views:

950

answers:

3

I'm using the following code to load my Google Analytics (external javascript) in a way that is meant to not block rendering.

However, using both YSlow and Safari Web Inspector - the network traffic clearly shows that the ga.js script is still blocking rending.

/*
http://lyncd.com/2009/03/better-google-analytics-javascript/
Inserts GA using DOM insertion of <script> tag and "script onload" method to
initialize the pageTracker object. Prevents GA insertion from blocking I/O!

As suggested in Steve Souder's talk. See:
http://google-code-updates.blogspot.com/2009/03/steve-souders-lifes-too-short-write.html
*/

/* acct is GA account number, i.e. "UA-5555555-1" */
function gaSSDSLoad (acct) {
  var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."),
      pageTracker,
      s;
  s = document.createElement('script');
  s.src = gaJsHost + 'google-analytics.com/ga.js';
  s.type = 'text/javascript';
  s.onloadDone = false;
  function init () {
    pageTracker = _gat._getTracker(acct);
    pageTracker._trackPageview();
  }
  s.onload = function () {
    s.onloadDone = true;
    init();
  };
  s.onreadystatechange = function() {
    if (('loaded' === s.readyState || 'complete' === s.readyState) && !s.onloadDone) {
      s.onloadDone = true;
      init();
    }
  };
  document.getElementsByTagName('head')[0].appendChild(s);
}

/* and run it */
gaSSDSLoad("UA-5555555-1");

Any ideas on how I can use JavaScript to delay the loading of the ga.js file, because the code above doesn't appear to do as it intends, until the entire page has been rendered so that I don't block rendering?

+2  A: 
/* and run it */
gaSSDSLoad("UA-5555555-1");

Don't “run it” until the page has finished rendering. That is: onload or elsewhere further along. Don't include the above lines in your inline script block itself, or you won't gain anything.

bobince
gaSSDSLoad("UA-5555555-1") is the last line of my HTML. I don't understand, what should I do different?
mp_
How do I not "run it" until the page has finished rendering?
mp_
Put ‘gaSSDSLoad("UA-5555555-1");’ in your body onload, not in inline script.
bobince
How would I do that? Would it be something like: window.onload = function () { gaSSDSLoad("UA-3631080-1"); }; ?
mp_
@mp_: Use the "load" event: window.addEventListener("load", function() { /* and run it */ gaSSDSLoad("UA-5555555-1"); }, false);
Steve Harrison
@mp_: That would work, but it's best to use "window.addEventListener" rather than "window.onload". See https://developer.mozilla.org/en/DOM/element.addEventListener#Why_use_addEventListener.3f.
Steve Harrison
mp: yes, exactly like that. As long as you only have one thing to listen for, stick with window.onload. addEventListener is needed when you have multiple scripts all wanting the event, but if you want to use that you have to deal with IE's lack of DOM Event support. That means branching code to attachEvent, or using a higher-level event handling framework.
bobince
A: 

You can add a listener to the window, document or body's onload event and execute your gaSSDSLoad function at that time.

Kyle Jones
How would I do that? Would it be something like: window.onload = function () { gaSSDSLoad("UA-3631080-1"); }; ?
mp_
If it's like how I described with using window.onload - that still blocks rendering as seen by YSlow
mp_
+1  A: 

If you use jQuery you can include the run it part in (which is the same as the body onLoad() event):

$(window).load(function() {
    /* and run it */
    gaSSDSLoad("UA-5555555-1");
});

and if that is not good enough, you run it a second later (for example...):

$(window).load(function() {
    setTimeout("run_it()", 1000);
});

function run_it() {
    /* and run it */
    gaSSDSLoad("UA-5555555-1");
}

Shouldn´t be necessary though...

jeroen
what's the equivalent of "$(window).load(function() {" using standard JavaScript (no framework)?
mp_
@mp_: See my comment(s) on bobince's answer.
Steve Harrison
I'm not familiar with the methods discussed there, but a long time ago, before jQuery, etc. you just put it in your body tag: <body onLoad="some_function()">
jeroen
By the way, the methods discussed under bobince's answer do seem better, it´s best to avoid inline scripts.
jeroen