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 < and > with
>, 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.