views:

1212

answers:

5

Does anyone know why Google Analytics requires two separate script tags?

Specifically, their instructions advise users to embed the following snippet of code into a web page for tracking purposes:

<!-- Google Analytics -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-8720817-1");
pageTracker._trackPageview();
} catch(err) {}</script>

Why couldn't users use only one script block like this:

<!-- Google Analytics -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
try {
var pageTracker = _gat._getTracker("UA-8720817-1");
pageTracker._trackPageview();
} catch(err) {}</script>
A: 

I suspect it's an attempt to avoid obscure browser issues with the use of document.write to deploy a script tag.

chaos
I doubt it's obscure; I believe browsers will only parse the written script tag after the current script block finishes... Something to do with predictable single-threaded javascript execution...
Stobor
@Stobor: You should write that up as an answer. I'd vote for it. :)
chaos
A: 

For what it's worth, we make substantial use of the onclick="pageTracker._trackPageview(%filename%)" mechanism to track direct file downloads, but still don't want to track the actual pageview until the page has completely loaded. We have to include the 1st tag at the top of the page to enable that, but leave the final _trackPageview() call at the end (well, we much with the var pageTracker bit too).

Not necessarily why they break it up that way, but it makes it a little easier for our purposes.

cori
You can put all the code at the bottom, and set the onclick handlers in code just afterwards.
Draemon
+1  A: 

The first block is actually using JavaScript to write a whole new script tag inline to replace that script tag. It is doing a check to see if you are using "https" on the page being requested and if so, to use their secure url to request the script, or your browser may display a "Portions of this page are unsecure--display secure items?" or refuse the make the call at all.

If the second script tag were included in the first, it would be blown away and/or not be a well-formed script tag and your code would have to intermix with theirs.

This way, you can just do all your calls to trackPageView and set properties, etc. in your own blocks cleanly and still work properly over http and https.

So, when the page renders, the DOM will look like this after the first script executes (regular http):

<!-- Google Analytics -->
<script src='http://www.google-analytics.com/ga.js' type='text/javascript'></script>

<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-8720817-1");
pageTracker._trackPageview();
} catch(err) {}</script>

And this (https):

<!-- Google Analytics -->
<script src='https://ssl.google-analytics.com/ga.js' type='text/javascript'></script>

<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-8720817-1");
pageTracker._trackPageview();
} catch(err) {}</script>

More details: http://code.google.com/apis/analytics/docs/tracking/gaTrackingOverview.html

Tony Heupel
thanks for the answer. correct and insightful but not as succinct as the one i selected. thanks, though!
Crashalot
+4  A: 

document.write occurs as soon as it is executed in code. So if we used your "one script block" example, the actual generated source code would end up looking like this:

<!-- Google Analytics -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
try {
var pageTracker = _gat._getTracker("UA-8720817-1");
pageTracker._trackPageview();
} catch(err) {}</script>
<script src='http://www.google-analytics.com/ga.js' type='text/javascript'></script>

Hence the var pageTracker = _gat._getTracker("UA-8720817-1"); pageTracker._trackPageview(); code would fail because _gat wouldn't be defined until the ga.js file is loaded.

Does that make sense?

Jason Berry
thanks for the answer. correct and insightful but not as succinct as the one i selected. thanks, though!
Crashalot
+11  A: 

<script> tags are executed in sequence. A <script> block cannot execute if the previous one isn't done executing.

The first <script> tag is in charge of creating the Google <script> tag which will load the external js. After the first <script> is finished executing, the DOM looks like the following:

<script></script> <!-- First Script Tag -->
<script></script> <!-- Google Injected Script -->
<script></script> <!-- Second Script Tag -->

This guarantees that the second <script> tag will not execute until the .js is done loading. If the first and second <script> would be combined, this would cause the _gat variable to be undefined (since the Google injected script will not start loading until the first script is done executing).

Andrew Moore