A different way to log your website usage

A-different-way-to-log-your-website-usageOur recently published whitepaper demonstrates some of the more business-orientated metrics that you can log so you can get a better insight into your interactions with customers.

There may also be some Sales & Marketing type interactions with potential customers that you’re not aware of. For example, do you know how long a customer opened a “more info” panel on your website for? Or how long someone hovered over the “Buy Me Now!” button without actually clicking the button?

Tools like Google Analytics are superb for getting a very good overview of your website’s traffic, demographics, referring websites etc, but do not capture the micro-interactions that someone might have. As far as you’re concerned, someone viewed a page on your site, but it’s hard to tell how they interacted with it – especially when more and more visitor interactions with a website are carried out by client side scripting rather than browsing to new pages. By logging this information and overlaying it with the other logs you can gather from your web server, you can get some rich data on your site’s usage.

Example 1: “More info” panel

Imagine you have a button that will display a panel on your page with some additional information – or perhaps a “Call To Action” like a sign-up / contact form. This may all be done using client side scripting, so it can be hard to track whether the content was viewed or not, and how long it was viewed for.

By using the Logentries JavaScript library, you can log this information with some pretty simple changes to your site. This will allow you to see if the content is popular, if there’s too much content for the average view duration, etc.

I have used JQuery in these examples, but the principles should apply to any framework you use.

Let’s get started

Sign in to your Logentries account (or sign-up for your free trial)

Add a new log from the left menu, and select “JavaScript” from the Libraries section.

Choose the Log set you want to create the log under and click the “Create Log Token” button.

You will be presented with a link to our JavaScript library, and the code you need to embed and use in your website

<script src="/js/le.min.js"></script>
<script>
	LE.init('YOUR_LOG_TOKEN_HERE);
</script>

Once I’ve embedded the library, I can log my messages easily by simply adding a line of code to the JavaScript:

LE.log("hello world!")

But I want to log several values together, so I can query my data to get more detailed results. I’ve written a JavaScript function that takes in a number of parameters, creates a JSON object and then logs that object to Logentries.

function sendLog(msg, obj, duration) {
        var filename;
        try {
            filename = window.location.pathname.match(/.*\/([^/]+)\.([^?]+)/i)[1];
        } catch (err) {
            filename = "root"
        }

        var msgObj = new Object();

        $(msgObj).prop("message", msg);

        if (obj) {
            $(msgObj).prop("elementid", $(obj).attr("id"));
        }
        if (duration) {
            $(msgObj).prop("duration", duration);
        }

        $(msgObj).prop("page", filename);
        LE.log(msgObj);
    }

 (function($) {
 $.fn.logme = function(msg, obj, duration) {
 sendLog(msg, obj, duration);
 }
 }(jQuery));

I’ve also wrapped it as a JQuery function, so I can easily combine it with native JQuery functions.

$("#myContent").show().logme("Send a message", $(this), null);

This function expects the following: A message, the HTML entity that triggered the log entry and finally the duration that I want to log. If the latter 2 are not passed in, then I will just exclude these from the message I send to Logentries. I also send the current page to Logentries so I can group my queries by the pages that the messages originated from.

Tracking the content section being opened

Now I have a function which I can call, which will send in a more detailed log message – so I want to be able to trigger it.

For this example, I have a div element that contains some content. The div is hidden until someone clicks a button to view it – this is done by using standard .show() and .hide() JQuery functions.

My page might look a bit like this:

Wevsite mockup

And when someone clicks the “more info” button, the extra content is displayed:

Website Mockup 2

To track the duration that it’s open for, I need to save the current time as soon as it’s opened, and subtract that from the time at which it’s closed. You can do this in a number of ways: add a new function when someone clicks the show and hide buttons or add a callback function to the .show() and .hide() JQuery calls.

I decided to override the native JQuery functions so I don’t have to update my JavaScript that’s already in place to show and hide the content. As the logging is triggered whenever the div is hidden, I don’t have to worry about writing extra script for every button or key press that closes the div.

However, as this will apply to any element that is displayed or hidden using JavaScript, this could end up in a lot of entries being sent that don’t really matter to you. So the functions will look for a specific CSS class to be present before the time is tracked – I just need to add class=”logme” to the div (you can use this with existing CSS classes – e.g. class=”content logme darktheme”)

 var startTimer = 0;
    var _oldshow = $.fn.show;
    $.fn.show = function(speed, callback) {
        if ($(this).hasClass("logme")) {
            $(this).starttimer();
        }
        $(this).trigger('show');
        return _oldshow.apply(this, arguments);
    }

    var _oldhide = $.fn.hide;
    $.fn.hide = function(speed, callback) {
        if ($(this).hasClass("logme")) {
            $(this).endtimer();
        }
        $(this).trigger('hide');
        return _oldhide.apply(this, arguments);
    }

 (function($) {
        $.fn.starttimer = function(reset) {

            var startTime = $(this).attr("timer");
            if (!startTime || startTime == 0 || reset) {
                startTime = new Date();
                startTime = startTime.getTime();
                $(this).attr("timer", startTime);
            }

        }
    }(jQuery));

    (function($) {
        $.fn.endtimer = function() {

            startTime = $(this).attr("timer");
            endTime = new Date();
            endTime = endTime.getTime();
            $(this).attr("timer", 0);
            var timeSpent = (endTime - startTime) / 1000;
            sendLog($(this).attr("logger"), $(this), timeSpent);
        }
    }(jQuery));

What exactly happens when someone clicks on the button?

  1. The button has a click event that shows the content div
  2. The updated show() JQuery function checks to see if the div has a CSS class of “logme”
  3. In this case, it does, so the function sets the start time, storing it in a custom attribute of the div
  4. When the viewer chooses to close the div, the new hide() function is called and the timer is stopped
  5. The duration is calculated and a log message is sent to Logentries
    • You’ll see that the script looks for another HTML attribute called “logger” – this is where I put the human-readable message I want to send in

Want to apply this to a second div? Now the JavaScript is in place, all you need to do is add the 2 attributes to the HTML markup; a CSS class of “logme” and an attribute of “logger” that contains the  log message.

As the function will automatically detect the ID of the HTML element, you can query your log data in Logentries to group by which div is being viewed – there’s no additional JavaScript required.

Sample HTML:

<div id="divForm" style="border: solid green 1px; width: 400px; display: none" class="nicemodal anothermodal logme" logger="Opened more info modal">
	<h2>Read more about our company</h2>
	text of my content goes here...
	<br/><br/>
	<input type="button" id="btnCloseForm" value="close" />
</div>

Log message as seen in Logentries:
28 Apr 2016 21:30:18.238 { "event": { "message": "Opened info modal", "elementid": "divForm", "duration": 3.126, "page": "root" }, "trace": "w37ri6s2", "level": "LOG" }

And here’s what it looks like in our new Tableview:

Table View

Example 2: Hovering over “Buy me now!” button

The second example I mentioned above, was tracking to see how long someone hovered over a “Buy me now” button but did not ultimately click it – are there some small changes you can make to get more sales over the line?

I can use some of the script I implemented earlier – I just need to start the timer as I did before, and make sure I don’t log if the button is clicked (or maybe log a different message when it is clicked, so I can run a comparison within Logentries). I do this by setting a custom attribute when the button is clicked – if that attribute is present when the mouse is moved off the button, then I know not to log it.

Here’s the HTML:

<input type="button" id="btnBuyNow" value="Add to Cart" logger="Add to cart button hovered over, but not clicked" />

And the JavaScript:

 $("#btnBuyNow").click(function() {
            $(this).attr("didclick", true);          
            // action for the button - e.g. addToCart();
        })
        .mouseover(function() {
            $(this).starttimer();
        }).mouseout(function() {
            if ($(this).attr("didclick")) {
                $(this).attr("didclick", null);
                $(this).attr("timer", null);
            } else {
                $(this).endtimer();
            }
        });

The endtimer() function includes sending the message to Logentries, so there’s really not that much extra script required.

Example 3: Timing the checkout process

Suppose you have 4 stages in your checkout process: view cart, shipping details, payment details and confirmation.

By using a variation of the scripts above, you can track the duration that a customer spends on each step of the process by starting a timer when the page loads, and stopping it when they press the “next” button – which is when you’ll send the log message to Logentries.

When you query these results and group by the stage, you can calculate the average / median / 99th percentile duration  per stage to see which pages take the longest for the customer to complete. Or if you calculate the count per stage, you can also work out where people are typically dropping out of the process.

By overlaying this information with the metrics you’re gathering from the other components of your application (webserver access logs, database logs etc) you can start to build a very clear picture of where the bottlenecks are that you may want to address.

Sample queries and charts in LE

Now I have this information being logged to my Logentries account, I can easily write some LEQL to query my data.

This will calculate the average duration that someone opened a content div, and it will group the results by the ID of the div:

where(event.duration > 0) groupby(event.elementid) calculate(average:event.duration)

I can count the number of times that a button was hovered over but not clicked:

where("Add to cart button hovered over, but not clicked") groupby(event.elementid)

Or get the average duration of the hover:

where("Add to cart button hovered over, but not clicked") groupby(event.elementid) calculate(average:event.duration)

Or simply count the occurrences that a specific button was clicked:

where(event.elementid = btnCTA) groupby(event.page)

Summary

While web access logs and other analytics tools provide a good insight into your website’s usage, there are most likely still some interactions that are not being logged. By extending your logging to include these, you’ll gain better insight into how your site is being used.


Ready to start getting insights from your applications? Sign up for a Logentries free trial today.

Tagged with: , , , ,
Posted in Application Performance Monitoring, Business Metrics, Development, How To, Log Analysis, Log Management, Logentries, Monitoring

Leave a Reply