P3PC: Google Analytics

March 3, 2010 7:25 pm | 16 Comments

P3PC is a project to review the performance of 3rd party content such as ads, widgets, and analytics. You can see all the reviews and stats on the P3PC home page. This blog post looks at Google Analytics. Here are the summary stats:

impact on page Page Speed YSlow doc.
total reqs total xfer size JS ungzip DOM elems median Δ load time
small 91 99 n 2 18 kB 24 kB 2 19 ms
column definitions
Click here to see how your browser performs compared to the median load time shown above.

Google Analytics recently had a nice performance upgrade. The old snippet used document.write and thus blocked other resources and rendering, making pages feel slower. On Dec 1, 2009, Google announced the launch of their new asynchronous snippet. The old snippet still works, but sites that want a significant speedup should use the new async snippet.

My analysis focuses on the new async snippet for Google Analytics.

Snippet Code

Let’s look at the actual snippet code:

1: <script type=”text/javascript”>
2: var _gaq = _gaq || [];
3: _gaq.push([‘_setAccount’, ‘UA-15026169-1’]);
4: _gaq.push([‘_trackPageview’]);
6: (function() {
7: var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
8: ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
9: (document.getElementsByTagName(‘head’)[0] || document.getElementsByTagName(‘body’)[0]).appendChild(ga);
10: })();
11: </script>
snippet code as of March 3, 2010

A quick walk through the snippet code:

  • lines 2-4 – Push commands onto a queue to be executed once the async script finishes loading.
  • lines 6-10 – Create a script DOM element and set the src to fetch ga.js.

Performance Analysis

This HTTP waterfall chart was generated by WebPagetest.org using IE 7 with a 1.5Mbps connection from Dulles, VA. Notice how the image in the main page (google-analytics-waterfall.png) is not blocked by ga.js – they both download in parallel.

Here are the most important performance issues along with recommended solutions.

1. 24 kB seems like a lot of JavaScript for sending a tracking beacon.

My example is very straightforward and doesn’t use much Google Analytics functionality. The three sites I run that use Google Analytics are all simple. I’d like to see a “lite” version of ga.js for sites like mine and whittle that 24 kB down to 5 kB or so.

2. The beacon returns a 200 HTTP status code.

I recommend returning a 204 (No Content) status code. A 204 response has no body and browsers will never cache them, which is exactly what we want from a beacon. In this case, no body only saves 35 bytes, and the beacon’s HTTP headers prevent it from being cached. Although the savings are minimal, using a 204 response for beacons is a good best practice.

What you can do now: The new async version of the Google Analytics snippet is pretty slim. Even YSlow and Page Speed can’t find much wrong with it. My main advice would be to switch over to this async version if you’re still using the old document.write snippet. Cruising through the Alexa U.S. top 50 web sites I found two web sites that use the new async snippet: Huffington Post and Answers.com. But these web sites haven’t moved over yet: Twitter, FOXNews.com, Reference.com, Photobucket, Hulu, DoubleClick.com, and (ahem) Blogger. To be fair, the new snippet was launched as Beta just a few months ago, but all of these sites should switchover to the async snippet and speed things up for their users.

16 Responses to P3PC: Google Analytics

  1. Why does the async Analytics snippet still use document.getElementsByTagName('body')[0]) instead of simply document.body?

  2. hey steve, always doing a great job around perfs :)

    I didnt knew about the 204 response code
    I made something to track user actions in JS, but instead of calling a beacon image, I’m using an XHR with HEAD instead of GET
    I was thinking that since the browser knows that he doesnt have to wait for a body response, he wont cache it (and it seems to be the case) and it wont spend any time interpretating the answser

    do you think that an image with 204 response is better ?

  3. I don’t really think 24kb is a problem – especially considering the widespread use (=caching) of this particular JS file.

    And it does have a lot more, than just being a beacon – screen size, color depth, flash, java, etc detection does have it’s cost.

    Though looking at beautified code… I can see that there is space left for improvement.

    Captcha: four plus tin <– tin?

  4. OK. Now I understand the captcha thing :) Smart :)

  5. Awesome series! Have you heard anything from the owners of any of these? I’d love to see them implement your recommendations – it’s basically free consulting for them.

  6. @Mathias

    Frankly, I don’t see a reason not to use `document.body` here. Theoretically, there’s a chance that true XHTML documents would need `getElementsByTagName` (if `document.body` was missing). From what I can see, this is explicitly allowed in DOM L2 (http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-5353782642), where it says that interfaces are intended to work with HTML 4.01 _only_ and not XHTML. But then it would be strange if HTMLDocument interface implemented `getElementsByTagName` method but not `body` property.

    In any case, last time I tested, I couldn’t find a browser that would lack `document.body` when served as true XHTML.

    And by the way, one of GA devs (https://twitter.com/briankuhn) said they wouldn’t have time to retest new snippet, which is why `document.body` didn’t make it in.

  7. @Mathias @kangax

    We’re still considering document.body, but we’re currently more interested in another replacement for that line, which we’re testing right now. DM me on twitter if you’d like to discuss.

  8. I’ve been using the aSync gA since day dot. Very happy to see instant performance improvements.

    Even more excited to to see the new, Google-endorsed Pion.app tagless gAnalytics integration. (http://www.atomiclabs.com/pion-web-analytics/index.php)

    Would love Steve, and any of you performance Gurus, to voice your thoughts on this, so that we followers can learn. I’m actually unable to get the app to run on my Mac – anyone else tried it yet?

  9. @jpvincent: I think 204 image response is better than XHR because it works across domains, is less code to implement, and its behavior is in the spec.

    @Pat: Hi! Everyone – if you’re not using Pat’s WebPagetest.org go check it out. One of the best tools in the past year. To answer your question: Yes, I usually end up talking to these teams, either before or after. I always say that no one starts off with the goal to build a slow web site, many times they just don’t know or don’t have time to do the analysis. Generally, I’ve found web site owners to be very receptive to my free consulting advice. And what a cool company Google is to let me do it!

    @Brian: Great to hear from you. Thanks for being so willing to answer questions about the new GA snippet.

  10. @Cracks: we found a problem with the 3.0.1 Mac installer and fixed it probably shortly after you downloaded. If you re-download it should work fine, but this fix should work as well:

  11. It would be great to see tests on the snippets from some of the other large analytics vendors, especially Omniture. Maybe it would help them put a little more emphasis on performance. :)

  12. @Steve, very interesting post. Two related questions…

    a) How much of an impact on performance would moving from a 1*1 beacon to a 2*1 (or 2*2) have?

    List of sites that use 2*2 beacons
    http://112.2o7.net/b/ (omniture)

    List of sites that use 1*1 beacons

    b) Is their any benefit in setting a p3p or Etag for the ga.js & utm.gif as these are present on Yahoo Analytics but not GA.
    e.g. P3P policyref=”/w3c/p3p.xml”, CP=”xxx” and Etag “xxx”



  13. @shawn: I wasn’t able to sign up for Omniture. Can you post a URL that’s using their default snippet, and point me to documentation about their snippet? (Use the “contact Steve” link if you want to do that offline.)

    @Phil: A 204 No Content is the preferred status code to use, making the size of the beacon a non-issue. ETag and P3P response headers don’t help. In fact, they might hurt in that they had more bytes to the response.

  14. I’m happy to see that Blogger is now using the Google Analytics async snippet!

  15. I’ve been using GA async for months, but I don’t recognize Line 9 in your snippet. I don’t see it on the Google Code page either.

  16. @Eric: The new GA code was added after this blog post.