Search code examples
javascriptjqueryajaxgoogle-analyticshtml5boilerplate

How to extend google analytics to track AJAX etc (as per H5BP docs)


I am trying to install the google analytics augments identified in the extend.md file of H5BP (https://github.com/h5bp/html5-boilerplate/blob/v4.3.0/doc/extend.md)

It states that the "optimised" google analytics JS snippet includes the following code:

var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];

and that additional augments such as track jquery AJAX requests, track javascript errors and track page scroll should be added after _gaq is defined.

In fact, the snippet included with the current version of H5BP does not make reference to _gaq as a variable:

        (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
        function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
        e=o.createElement(i);r=o.getElementsByTagName(i)[0];
        e.src='//www.google-analytics.com/analytics.js';
        r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
        ga('create','UA-XXXXX-X');ga('send','pageview');

This creates an undefined error when trying to use any of the H5BP extensions. E.g.

if (typeof _gaq !== "undefined" && _gaq !== null) {
    $(document).ajaxSend(function(event, xhr, settings){
        _gaq.push(['_trackPageview', settings.url]);
    });
}

Will not work as _gaq is not defined.

How are these augments intended to be implemented? Can someone provide a working example showing a full implementation of all the extensions?

Thanks


Solution

  • The code you are trying to add will not work, as _gaq was an array used to push the tracking beacons to in the older Google Analytics (GA) version. But the HTML5 BoilerPlate (H5BP), in its latest version you seem to be using, has updated itself to make use of Universal Analytics (UA), the next version of GA which Google has released. This can be seen from the protocol-relative URL //www.google-analytics.com/analytics.js and also the docs for the latest version. Unfortunately, it seems the doc you mentioned hasn't been updated, as the link given at the H5BP for the source of the optimised GA code, has itself been updated with code for UA and that is what the H5BP source is now using.

    Consequently, your additional source code extending the use of the _gaq object will not work, as you are not using ga.js which has functions to process the data pushed to the _gaq object from GA, but the analytics.js for UA, which does not initialise any such object as _gaq or have functions to process the data pushed to _gaq.

    But, before upgrading itself to use analytics.js (UA), H5BP had a GA version of the script, like this (I got this, courtesy of a friend who used to work with H5BP):

    <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
        <script>
            var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']]; //here the _gaq was initialised
            (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
            g.src='//www.google-analytics.com/ga.js';
            s.parentNode.insertBefore(g,s)}(document,'script'));
        </script>
    

    Ideally, this should replace the lines of code you mentioned, namely

    (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
        function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
        e=o.createElement(i);r=o.getElementsByTagName(i)[0];
        e.src='//www.google-analytics.com/analytics.js';
        r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
        ga('create','UA-XXXXX-X');ga('send','pageview');
    

    If you did that, then your use of the code

    if (typeof _gaq !== "undefined" && _gaq !== null) {
    $(document).ajaxSend(function(event, xhr, settings){
        _gaq.push(['_trackPageview', settings.url]);
    });
    }
    

    and so on which use _gaq will work.

    Also remember that the H5BP code you are currently using is best, as Google is phasing out GA in a move to make Universal Analytics the future of analytics. The older code I have mentioned no longer works (or will stop working in the near future, depending on Google). Read more about this at UA Upgrade Center.

    Keep in mind that the current H5BP uses UA (analytics.js) code which is an optimised form of what Google provides, as found here.

    That explains why the scripts mentioned in extend.md won't work on the H5BP you seem to be working on, an a possible workaround by implementing the old code. What you need is a way to track AJAX etc. with the script you do have in place. For that, each time an AJAX request completes, you can simply record a virtual pageview. You can find a similar scenario here. There the asker applies the tracking to the opening of a modal. You can apply the same technique to track AJAX calls and retreives of a page or partial page. The VURL as I've specified in the answer can be, in your case, /virtual/ajax/url-of-page-retrieved-via-ajax.

    If you do not wish to send virtual pageviews, you can also send customised events for each AJAX request. Read more about event tracking in UA here.

    If you want to know what the arguments of the function you specified stand for, you can read here. This is where the script in the extend.md file you mentioned was taken. An attempt to modify the script for use with UA would probably look like this:

    (function ($) {
      // Log all jQuery AJAX requests to Google Analytics
      $(document).ajaxSend(function(event, xhr, settings){ 
        ga('send','pageview',settings.url.pathname);
      });
    })(jQuery);
    

    The ajaxSend() method is a callback which is fired every time a jQuery AJAX call is completed. Remember the word jQuery here. This only works for jQuery AJAX requests. xhr generally stands for XMLHttpRequest. I think it assumes one knows what a jQuery AJAX call is, I'm not very knowledgeable about that.

    To track Javascript errors using UA, a similar script would be:

    (function(window){
    var undefined,
        link = function (href) {
            var a = window.document.createElement('a');
            a.href = href;
            return a;
        };
    window.onerror = function (message, file, line, column) {
        var host = link(file).hostname;
        ga('send','event',
            (host == window.location.hostname || host == undefined || host == '' ? '' : 'external ') + 'error',
            message, file + ' LINE: ' + line + (column ? ' COLUMN: ' + column : ''),
            {'nonInteraction': 1});
        };
    }(window));
    

    This collects likewise: Event Category will be host+error, Action will be the error message, and label will point to where the error occurred (line no, filename, etc.).

    Tracking page scroll is also very similar:

    $(function(){
    var isDuplicateScrollEvent,
        scrollTimeStart = new Date,
        $window = $(window),
        $document = $(document),
        scrollPercent;
    
    $window.scroll(function() {
            scrollPercent = Math.round(100 * ($window.height() + $window.scrollTop())/$document.height());
            if (scrollPercent > 90 && !isDuplicateScrollEvent) { //page scrolled to 90%
    //If you want to track for page scroll for some other percentage of scroll, you
    //can edit the number 90, or write additional conditional ga('send',...) calls
    //inside this block and vary the label accordingly, specifying the percentage
    //of scroll.
                isDuplicateScrollEvent = 1;
                ga('send','event','scroll',
                'Window: ' + $window.height() + 'px; Document: ' + $document.height() + 'px; Time: ' + Math.round((new Date - scrollTimeStart )/1000,1) + 's',
                {'nonInteraction':1}
            );
            }
        });
    });
    

    Here, Event Category will be scroll, Action will be thw Window, height and document, and time. If you want to track scroll as an interactive event (which means if you want a user to be tracked as a non-bounce user if he scrolls) you can remove the line {'nonInteraction':1}

    Hope that helps! :)