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

  • From Webcam to Animated GIF: the Secret Behind chat.meatspac.es!

    My team mate Edna Piranha is not only an awesome hacker; she's also a fantastic philosopher! Communication and online interactions is a subject that has kept her mind busy for a long time, and it has also resulted in a bunch of interesting experimental projects...

  • fetch API

    One of the worst kept secrets about AJAX on the web is that the underlying API for it, XMLHttpRequest, wasn't really made for what we've been using it for.  We've done well to create elegant APIs around XHR but we know we can do better.  Our effort to...

Incredible Demos

  • Create Your Own Dijit CSS Theme with LESS CSS

    The Dojo Toolkit seems to just get better and better.  One of the new additions in Dojo 1.6 was the use of LESS CSS to create Dijit themes.  The move to using LESS is a brilliant one because it makes creating your own Dijit theme...

  • Sexy Album Art with MooTools or jQuery

    The way that album information displays is usually insanely boring. Music is supposed to be fun and moving, right? Luckily MooTools and jQuery allow us to communicate that creativity on the web. The XHTML A few structure DIVs and the album information. The CSS The CSS...

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

  • Open Files from Command Line on OS X

    I'm as much of a fan of application UIs as anyone else but I'm finding myself working more and more from the command line lately.  Much of that is becoming obsessed with media manipulation but I'm forcing myself to use less UIs so that I...

  • Get Stock Quotes From Command Line

    When I conned my way into my first professional programming gig, I didn't really think much about money -- just that I was getting my foot in the door.  But as my career has gone on, I've been more aware of money, investing, and retirement.  I've recently...

  • Geolocation API

    One interesting aspect of web development is geolocation; where is your user viewing your website from? You can base your language locale on that data or show certain products in your store based on the user's location. Let's examine how you can...

  • Create an Image Preview from a Video

    Visuals are everything when it comes to media.  When I'm trying to decide whether to watch a video on Netflix, it would be awesome to see a trailer of some kind, but alas that isn't available.  When I'm looking to download a video on my computer,...

  • New:  Webdesigner News!

    A new and exciting website has recently been launched for web designers and developers. You likely spend hours every morning browsing through hundreds of posts on your RSS feeds, hoping to stumble across relevant stories. Webdesigner News was built to provide web designers and developers with...