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.

Recent Features

  • By
    Serving Fonts from CDN

    For maximum performance, we all know we must put our assets on CDN (another domain).  Along with those assets are custom web fonts.  Unfortunately custom web fonts via CDN (or any cross-domain font request) don't work in Firefox or Internet Explorer (correctly so, by spec) though...

  • By
    CSS Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome...

Incredible Demos

  • By
    Style Textarea Resizers

    Modern browsers are nice in that they allow you to style some odd properties.  Heck, one of the most popular posts on this blog is HTML5 Placeholder Styling with CSS, a tiny but useful task.  Did you know you can also restyle the textarea resizer in WebKit...

  • By
    jQuery Countdown Plugin

    You've probably been to sites like RapidShare and MegaUpload that allow you to download files but make you wait a specified number of seconds before giving you the download link. I've created a similar script but my script allows you to animate the CSS font-size...

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!