O'Reilly

Track AJAX Link Clicks Using Google Analytics

By on  

4/22/2011: This blog post was completely rewritten to describe page tracking with Analytics' asynchronous loading method.

With more and more websites becoming completely AJAX-driven, the typical "do this every time a page loads" strategy isn't always enough. This is especially try if you're using Google Analytics or other analytics tracking software. Google is, of course, forward-thinking so they've provided a way to easily track page views of AJAX requests.

The Google Analytics JavaScript

The current standard for loading Google Analytics is the asynchronous method:

var _gaq=[["_setAccount","UA-#######-#"],["_trackPageview"]];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1;
g.src=("https:"==location.protocol?"//ssl":"//www")+".google-analytics.com/ga.js";
s.parentNode.insertBefore(g,s)}(document,"script"));

That bit tracks the initial page load but not subsequent AJAX calls. Any time you want to track a page load, place add the following snippet:

// "_trackEvent" is the pageview event, 
_gaq.push(['_trackPageview', '/some-page']);

_trackPageview is used again but this time we provide the URL of the AJAX address that was loaded. Using the small JavaScript snippet above allows you to keep track of pageviews just as you would if the entire page reloaded. I'd recommend using this snippet with MooTools' History plugin.

The Old Method

If you're still using the synchronous method of loading Google Analytics, the following snippet will accomplish the same task:

pageTracker._trackPageview('/some-page');

It's great to know that Google Analytics is as dynamic as your web applications. Allowing developers to track AJAX page clicks prevents the need to code apps just to keep track of statistics.

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • Create a CSS Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

  • 5 Ways that CSS and JavaScript Interact That You May Not Know About

    CSS and JavaScript:  the lines seemingly get blurred by each browser release.  They have always done a very different job but in the end they are both front-end technologies so they need do need to work closely.  We have our .js files and our .css, but...

Incredible Demos

Discussion

  1. Christof Haemmerle

    you want to change want to check on the parent object(here window) if it has a function called pageTracker otherwise it will break your app.

    if(window.pageTracker)

  2. Chris Bowyer

    Interesting, but, the current (and it has been for some time) Google Analytics JavaScript (that should be placed immediately before the closing head tag) is as follows…

      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXX-YY']);
      _gaq.push(['_trackPageview']);
    
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    
    • What is this in reference to?

    • In my view I think he only give refrence for puttinh google analytics codes in Head section,,, But don’t know what he exactly mean.

  3. nice tuts keep up sometimes i am viewing your tuts and it’s usefull.

  4. Hi David,

    To clarify – does this

    _gaq.push(['_trackPageview', '/some-page']);

    go on the page being loaded, or is it added to the main page which is doing the loading? If it goes on the page being loaded, does it replace the original trackPageview or get added to the original tracking code?

    Thanks!

    • Ryan Mac

      You would call the original GA Code your head when the page first loads. Then on completion of subsequent ajax calls use:
      _gaq.push(['_trackPageview', '/some-page']);
      Use jquery as an example:

      $.ajax({
        url: "test.html",
        context: document.body,
        success: function(){
          _gaq.push(['_trackPageview', '/text.html']);
        }
      });
      
  5. Hey, im not sure I get it. I have a 100% Ajax webapp and in google analytics I only get information for woojah.com/ But that page hardlly has anything. Everything is generated dynamically so my question is, do I have to put _gaq.push([‘_trackPageview’, ‘woojah.com/#mysubpage’]) for every subpage I have in my woojah.html?

    • You should never use # tags to control content/pages of your site. It’s really bad for SEO.

      change everything to use dynamic paths like woojah.com/mysubpage/

      It looks nicer and plays nicer.

  6. Hi Fernando,

    _trackPageView generates a virtual page but is otherwise similar to _trackEvent.

    Since it is just Javascript it can be called whenever an Ajax “page” loads. If, for example, you are using a WordPress site and want to track the loading of content on some plugins that use Ajax, you can modify the plugins Ajax calls to also call the _gaq.push() function. The “pages” that are recorded on Google Analytics are really just labels for the Ajax event (or any other event you like), so you should make the parameters obvious to anyone reading a GA report.

    Here is an example straight from Google Code in which a user plays a specific video using _trackEvent:

    _gaq.push([‘_trackEvent’, ‘Videos’, ‘Play’, ‘Gone With the Wind’]);

    See the similarity?

  7. _trackPageView generates a virtual page but is otherwise similar to _trackEvent. Since it is just Javascript it can be called whenever an Ajax “page” loads. If, for example, you are using a WordPress site and want to track the loading of content on some plugins that use Ajax, you can modify the plugins Ajax calls to also call the _gaq.push() function. The “pages” that are recorded on Google Analytics are really just labels for the Ajax event (or any other event you like), so you should make the parameters obvious to anyone reading a GA report. Here is an example straight from Google Code in which a user plays a specific video using _trackEvent: _gaq.push(['_trackEvent', 'Videos', 'Play', 'Gone With the Wind']);

    See the similarity?

  8. Matt

    Could _gaq.push(…)also be called with click event?

  9. bursinka

    Hi, Matt. Sure, there’s example at GA reference:
    onclick="_gaq.push(['_trackEvent', 'name', value]);"

    • I would advise against inline JS like that, instead take it to your js file:

          myLink.onclick = function (event) {
            //prevent normal link action
            event.preventDefault();
            _gaq.push(['_trackPageView', '/page/url']);
            //Your ajax loading code
          };
      

      You’ll probably only want to call the _gaq push part after you’ve loaded your new content though, otherwise you’re tracking pageviews that didn’t happen.

  10. I’m a bit puzzled by how this approach is meant to work. From what I’ve gathered, you normally first populate the _gaq array with whatever you want to track and with your account code, then ga.js is loaded which sends the information to Google’s servers.

    Now if I push an extra element onto _gaq.js after that happened without further ado, how would it actually know to send a new request to Google? Does ga.js check _gaq for changes with an interval or something?

    • Never mind that, I just fiddled a bit with the console and figured out that ga.js actually converts the _gaq array to an object with a push method in its prototype, which clearly takes care of it. Disregard my last comment! :-)

  11. Thanks for the info!

    Typo: especially try -> especially true

  12. I have another google analytics script code :

        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    
        ga('create', 'UA-#######-#', 'my web site');
        ga('send', 'pageview');
    

    any help ??

    • Hi Najih,
      I had the same problem, since the Goog is handing out that code currently and offering no alternatives. However if you insert the previous GA tracking code:

      var _gaq=[["_setAccount","UA-#######-#"],["_trackPageview"]];
      (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1;
      g.src=("https:"==location.protocol?"//ssl":"//www")+".google-analytics.com/ga.js";
      s.parentNode.insertBefore(g,s)}(document,"script"));
      

      And insert your tracking number, then in that case, I could get it to work. I attempted to get it to work with the “i,s,o,g,r,a,m” version as well without success.

      If anyone can get it to work with the “i,s,o,g,r,a,m” version, please reply.

    • That is the newer Google Universal Analytics, and you can find a tutorial here about how to apply it to Ajax pages:
      https://mjau-mjau.com/blog/ajax-universal-analytics/

  13. Mik

    According to the following documentation you no longer add to the array but call the function with the appropriate functions: https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced

    So just add the tracking code google gives you and every time you want to log a pageview, instead of the old command:

    _gaq.push(['_trackPageview', '/some-page']);
    

    use the following code instead:

    ga('send', 'pageview', {
      'page': '/my-new-page',
      'title': 'My New Page Title'
    });
    

    So instead of adding to the array you just call the function with the extra options.

  14. Hi David!

    Thanks for sharing this trick.

    It seems that we have to use another syntax with the newer analytics.js API.
    The following code works:


    ga('send', 'pageview', '/some-page');

    Source: https://developers.google.com/analytics/devguides/collection/analyticsjs/pages

    Cheers,
    Thomas.

    • I’ll have a look, but the _gaq.push(['_trackPageview', '/some-page']); method does still work!

    • Sure!

      I wasn’t enough clear.
      It still work, but there is a different syntax if you use the Google Analytics API.

      It was just an additional information ;)

      Cheers,
      Thomas.

  15. For the Javascript I’m writing that might be deployed in various places, I use this:

          if (typeof _gaq !== 'undefined') {
            _gaq.push(['_trackPageview', location.pathname]);
          }
          else if (typeof ga !== 'undefined') {
            ga('send', 'pageview', {'page':location.pathname,'title':document.title});
          }
    

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Prevent Chrome from Translating a Page

    A while back I shared my favorite Google Chrome extension:  Google Art Project.  I've enjoyed seeing beautiful art when I open a new tab -- it's brought genuine happiness to my day, however small that happiness may be.  About a week ago, however, the art presented had...

  • Create Any Type Of Website With These Multi-Purpose Themes

    We have selected what we believe are the very best multipurpose WordPress themes on the market today. Our list contains a number of best sellers, several newcomers that are proving to be highly popular, and a few themes that are ideal for creating the types of...

  • An Introduction to Static Site Generators

    Static site generators seem to have been becoming more and more popular recently, but they’re not one of those ephemeral novelty things that grow in popularity as quickly as they fall into oblivion shortly after. For over a decade, many different projects — 394 of...

  • Automated Tests for Visual Responsive Layouts

    Today it's all about testing. In 2015, many developers knows about TDD and I personally think that testing is one of the key for quality products. But what about testing in a Front-end environment? How do you guys write your tests for a responsive page or...

  • Getting Dicey With Flexbox

    What if you could build complex CSS layouts in minutes? Flexbox is a new CSS layout spec that makes it easy to construct dynamic layouts. With flexbox, vertical centering, same-height columns, reordering, and direction agnosticism are a piece of cake. There's a popular myth floating around that...