new google analytics tracking code xhtml validation problems

Recently Google Analytics tracking code changed. New code is preferred as object oriented and providing more features (event tracking).

Unfortunately, new code doesn't validate as correct XHTML 1.1 (and possibly other XHTML versions). This is because JavaScript code contains illegal characters: < and >. Those characters are improperly escaped with backslashes. Backslashes escape characters in JavaScript, not in XML (which is a container format for JavaScript here).

W3C HTML Validator complains with message: document type does not allow element "script" here. This is a little bit misleading, because it's complaining about part of string inside JavaScript code, and not about any of four script tags.

There are multiple ways to fix this: you can replace < with &lt; and > with &gt;, but nicer way is to explicitly mark JavaScript code as CDATA section.

After a little bit of experimenting I've invented this:


<script type="text/javascript">
//<![CDATA[
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write("\<script src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'\>\</script\>" );
//]]>
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("AA-00000-00");
pageTracker._initData();
pageTracker._trackPageview();
</script>

It seems to work in Firefox 2.x, Internet Explorer and Opera, and it validates at validator.w3.org.

You'll have to replace 'AA-00000-00' with your tracking id of course.

There are multiple ways to fix tracking code and there seems no best way to accomplish that.
For example after changing extensions and content-types to XHTML, IE failed to show anything (it shows file download dialog) and Firefox shows JavaScript errors because document.write is not legal in XHTML 1.1 anymore.
One could fix Firefox problem with DOM-oriented approach (document.createElement, .setAttribute, appendChild), but it simply won't work in Internet Explorer.

This is so called browser compatibility hell...

One of the easier ways to go around the problem is to skip scheme detection part. If you know you'll be serving pages via simple http and you don't care about https, you could easily replace first JavaScript block with simple <script type="text/javascript" src="http://www.google-analytics.com/ga.js"></script>. It doesn't contain bad chars, so you don't have to escape anything, it doesn't do document.write, so you'll be XHTML-compliant.
If you know your pages will be served via HTTPS only you could do the opposite - hardcode static https url to ga.js.
If your page is dynamic you could do detect protocol server side and send correct code to client.

Browser wars and incompatibilities really make life harder. Next time instead of testing different browsers and analysing how bad they can behave with quite simple code, I'll just dive into W3C specs and follow standards. I guess my site won't be accessible to IE users after that, but oh well... maybe they just aren't worth it.