2

Here is Google's Asynchronous Analytics tracking code:

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXX-Y']);
  _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);
  })();
</script>


If you ask me it's pretty ugly. It could be condensed into this (Credit: Mathias):

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


But why can't we just use the HTML5 async attribute and a protocol-relative URL?

<script src="//www.google-analytics.com/ga.js" async></script>
<script>var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];</script>

With the protocol-relative URL we avoid having to check for the location.protocol, and the async attribute should take care of unobtrusive loading in modern browsers, and will gracefully degrade in others.

Isn't this better?

3 Answers 3

4

You could do this:

<script src="//www.google-analytics.com/ga.js" async></script>
<script>var _gaq= _gaq || [];
_gaq.push(['_setAccount','UA-XXXXX-X'],['_trackPageview']);
</script>

Anything shorter and you risk overwriting the _gaq that ga.js loads, and specifically the _gaq.push function that GA overwrites.

The problem with hardcoding script[async], rather than using the DOM injection method, is that script[async] isn't the only mechanism by which the injection is made asynchronous. In older browsers, the JS-based inject can result in asynchronous injection even without script[async] support.

However, the above code should work in all browsers, but ga.js will block on older browsers. The extra bytes saved aren't worth the performance hit, but if you do this, you should put the script in the footer.

(Note: Protocol relative URL will work here because https://www.google-analytics.com/ga.js has been setup by Google to work.)

3
  • Note that the protocol check alone here is not a good idea. For SSL the subdomain also changes.
    – Eduardo
    Commented May 10, 2012 at 4:04
  • 1
    I acctually tried it and it seems that both https://ssl.google-analytics.com/ga.js and https://www.google-analytics.com/ga.js.
    – Eduardo
    Commented May 10, 2012 at 4:06
  • 2
    @EduardoCereto yep, for a while, there was no https://www service, but they (silently?) added it around a year ago.
    – Yahel
    Commented May 10, 2012 at 4:12
1

Notice that while the async tag would be enough for modern compliant browsers it doesn't do the trick to old non-compliant browser. Sure they degrade gracefully. But they degrade by not been asynchronous at all and just ignoring the async attribute. If you use dynamic insertion like they use on the other hand will make non-compliant browsers behave much like it is asynchronous.

Another important point is that if you just redefine the _gaq object it can cause problems if the ga.js file has been loaded previously. It shouldn't happen most of the times, but there are sites that end up including the tag multiple times for various reasons or just by mistake, That's why its a good idea to keep the _gaq = _gaq || [] logic.

Google analytics goal is not to be pretty, it's to be cross browser not just in the sense that it degrades gracefully but also in the sense that it works exactly the same way on all browsers as much as possible. If it works in a slightly different way on each browser it could skew the metrics for one browser and that's something you don't want. The first golden rule for data analysis is data consistency. Even if it means that you need to support ie5.5 for Mac.

0

I see this breaking in older browsers, assuming async is ignored.

By making the script inline, you are caused non-async browsers to download an execute it immediately. At this point, it will parse the _gaq, which up until now is an array, and execute the stored commands. It then rewrites the push method, and moving forward uses that as a function for executing requests (e.g. _trackEvent).

So by getting the script synchronously, and then defining _gaq as an array, you are overwriting the changes Google makes to the _gaq, and will prevent pageviews from being tracked.

Not the answer you're looking for? Browse other questions tagged or ask your own question.