Stephen Ostermiller's Blog

Send Google Analytics event when loading a new page

It is often desirable to send an event to Google Analytics to track when somebody clicks on a link or submits a form. This is not easy to implement properly.

Problem 1 -- The page unloads

Here is a problematic approach:

$('a').click(function(){
     ga('send',  'event',  'outbound',  'click',  $(this).attr('href'))
})

Clicking on the link causes the current page to unload. The call to ga won't happen because the page unloads first.

Problem 2 -- setTimeout won't work

You might be tempted to stop the click from unloading the page by return false, call ga, and change the page after a second of setTimeout.

$('a').click(function(){
    var url=$(this).attr('href')
     ga('send',  'event',  'outbound',  'click',  url)
     setTimeout(function(){
        document.location=url
     }, 1000)
     return false
})

This records some data, but the call to ga could take more than one second. This is also bad user experience because it introduces a delay for the user. Those two problems are at odds. The longer you make the delay, the more data will get collected, but the worse the user experience will be.

Problem 3 -- Callbacks get blocked

Google Analytics documentation suggests using a callback for this situation:

$('a').click(function(){
    var url=$(this).attr('href')
     ga('send',  'event',  'outbound',  'click',  url), {
        'hitCallback': function(){
            document.location = url;
        }
     })
     return false
})

This will break the functionality of the link for some users. It is becoming increasingly common for browser plugins to block Google Anaytics for privacy reasons. If ga isn't loaded, the callback won't happen. Nothing will happen when users click on the link.

Solution -- Use callbacks and check for Google Anyltics

The solution is to use a callback, but also to check to see if ga is loaded and call the callback ourselves if it is not.

This can be encapsulated in a re-usable JS method.

function gaevent(category, action, label, value, callback, nonAction){
    var event = {
        'eventCategory': category,
        'eventAction': action
    };
    if (label) event['eventLabel'] = label;
    if (value) event['eventValue'] = value;
    if (callback) event['hitCallback'] = callback;
    if (nonAction) event['nonInteraction'] = 1;
    if (hasgoogleanalaytics()) {
        ga('send', 'event', event);
    } else if (callback) {
        callback.call();
    }
}

function hasgoogleanalaytics(){
    return (typeof ga == 'function' && ga.hasOwnProperty('loaded') && ga.loaded === true);
}

$('a').click(function(){
    var url=$(this).attr('href')
    gaevent('outbound',  'click',  url, null,  function(){
        document.location = url;
     })
     return false
})

Leave a comment

Your email address will not be published.