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
})