Making Google Analytics Work in XHTML
I was moving my website, Google Voice for Outlook, over from HTML5 to XHTML5 today, and as soon as I did the basic content negotiation filters in PHP so that it would send the appropriate headers if the client supported XHTML as well as only outputting the <?xml if the client supported XHTML, I checked my developer tools to find a JavaScript error. It was Google Analytics, of course. document.write doesn’t exist in XHTML, after all.
The fix was simple, replace the current four line inclusion code with:
<script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); var script = document.createElement("script"); script.src = gaJsHost + "google-analytics.com/ga.js"; script.type = "text/javascript"; document.getElementsByTagName("head")[0].appendChild(script); </script>
This will work fine, unless of course you have no head tag. In which case you should replace getElementsByTagName(“head”) with getElementsByTagName(“html”).
Never Again (External JavaScript in the Body)
This is probably simply a personal taste, but I hate putting External JavaScript tags in the body of a web page. It feels and looks very unsightly to me. But as I learn more and more JavaScript, and really start to get a feel for the small language, I’ve realized that I don’t have to. That it’d be just as easy to place them directly into the header after the page is ready, by manipulating the DOM. Here is an excerpt from the beta turled website.
$(document).ready(function() { // Google Analytics var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); var script = document.createElement("script"); script.src = gaJsHost + "google-analytics.com/ga.js"; script.type = "text/javascript"; document.getElementsByTagName("head")[0].appendChild(script); try { var pageTracker = _gat._getTracker("CENSORED"); pageTracker._trackPageview(); } catch(err) { /* Do Nothing. */ } // Facebook Share var script = document.createElement("script"); script.src = "http://static.ak.fbcdn.net/connect.php/js/FB.Share"; script.type = "text/javascript"; document.getElementsByTagName("head")[0].appendChild(script); });
As you can see, I wait until the document is loaded using jQuery’s ready method, and then create elements for both Google Analytics and Facebook Share, before appending them directly to the <head> of the website. Keeping the code clean, reducing bandwidth usage for non-JavaScript users, and even making Google’s code cleaner. (By changing Google Analytic’s default code from document.write to DOM Manipulation.
So, Never again will I feel the need to insert external script tags at the bottom of the <body> just so that the rest of the page loads before them.
Note: If you’re not using jQuery, document.onload = function() { /* Code */ } works just as well, I promise.


