logo

Adding Google Analytics to DominoWiki - Nightmare!

The other week I added Google Analytics to all the web-facing applications I'd produced for a customer. They then asked if I'd mind adding it to a copy of DominoWiki they used. "Not at all" I said, knowing it to be a two minute copy-paste task.

The trouble is it turned in to a two hour job!

Google Analytics adds itself to a page using this line of code:

document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));

This adds a Script tag to the document and loads the required code from Google's site. That's the idea. On the DominoWiki page it didn't add a tag though. It just wrote the escaped string to document itself as visible text.

The first thing I did was add some more JavaScript lines to test the result of escape('<'), which it bizarrely returned as '&lt;'. Since when did escaping do that!?

After about an hour of messing about with charset settings and whatnot I started to reverse engineer the page to the point where I found that removing the reference to the wiki.js file solved the problem. Looking about in that file I found the following function:

/*
        unescape
        Decode an XML string
*/
function unescape(s)
{
        var n = s;
        n = n.replace(/&lt;/g, "<");
        n = n.replace(/&gt;/g, ">");
        n = n.replace(/&quot;/g, "\"");
        n = n.replace(/&amp;/g, "&");
        
        return n;
}

Whoever coded this part of the Wiki had re-written the built-in escape/unescape JavaScript functions. I'm sure I don't need to tell you how naughty that is. Not only bad practice but just plain annoying for the likes of me who come in afterward to do anything and spend half their morning struggling to work it all out.

The fix is simple enough. Just add the following two lines to the unescape() function in wiki.js:

//Following two lines required for Google Analytics to work
n = n.replace(/%3C/g, "<");
n = n.replace(/%3E;/g, ">");

Here's a massive list of "reserved" words you should avoid using in your own code as variables or function names.

If you really want a function called unescape then it's better defined within your own global object. For example the wiki.js file could contain this code:
var Wiki = {};

Wiki.unescape = function(s)
{
        var n = s;
        n = n.replace(/&lt;/g, "<");
        n = n.replace(/&gt;/g, ">");
        n = n.replace(/&quot;/g, "\"");
        n = n.replace(/&amp;/g, "&");
        
        return n;
}

There's then little to no chance of the code conflicting. Not just with others developers code but also with the inbuilt code of the browser.

Right then, back to what I should have been doing...

Comments

    • avatar
    • GazHay
    • Wed 11 Jun 2008 06:27 AM

    I would be tempted to change the whole function to use a switch, and have the default case return javascript's unescape of the passed string.

    (Using your scoping, however)

    • avatar
    • Rob
    • Wed 11 Jun 2008 12:34 PM

    This is a case of lazy or ignorant programming! The first rule (or at least one rule) of good programming is do not create global variables/code when local is all that's required.

    I try to keep all my code in my own objects. This way I create a single global object and everything else is inside of that.

    You can blame the DominoWiki programmer but the Google programmer could have done the same thing, knowing that his/her code will be loaded into a completely unknown environment.

    • avatar
    • Jake Howlett
    • Wed 11 Jun 2008 01:09 PM

    I don't think it's fair to point fingers at Google for expecting unescape to do what it does. Surely you wouldn't write all your code without using any of the inbuilt JavaScript functions just in case somebody has over-rode them?

    Jake

    • avatar
    • Domino Guy
    • Thu 12 Jun 2008 04:56 AM

    Hi All,

    Yes, I agree that built-in javascript function/keywords should be kept alone.

    Regards !

    Domino Guy

  1. I had the same problem with Google Analytics ... except different.

    I was using a setting doc (a method taken from one of Jake's templates) to store the Analytics code. I then inherited the code into the HTML head content using @DBLookup, a handy method if you're planning on using the same Analytics code on several forms.

    Then, in the HTML head content, I used @Text with the variable that I had set with the @DBLookup and got the same result... the script actually wrote to the page in plain text. After fiddling with some things (for 2 hours) I simply changed the @Text to @Implode and it worked.

    The nice thing about this method, no JavaScript.

    Another quick note: Google says that you shouldn't use both code versions on the same page, I.E. urchin.js with the new version that Google has put out. (I can't remember the new file name.)

    For me this was a bit of a pain because I was using two seperate programs for Analytics. Google's doesn't require the urchin.js, while my other service does. I don't remember how I came up with a fix for this, but when I do, I'll make sure and post it ... if anyone else has had the same problem.

  2. I disagree. Rewriting the escape/unescape function is a good practice for preventing an XSS attax - and those preventing an user to submit some js code that would be executed in some other user's context when he just open the site.

    And face it - that is exactly what yue have tryed to do - executing an additional javascript (that is loaded from an external server) when a user opens a page. Sounds pretty evil to me ;-)

  3. Yeah Gregory, but Jake's not just some user submitting javascript to a site...He's writing the damn thing!

    • avatar
    • Bob
    • Wed 25 Jun 2008 12:32 PM

    I really don't know much about Google Analytics, just that someone in our web marketing department asking me to paste the javascript onto a couple of my web forms. Is it sufficient for me to paste the content onto a form between <script>..</script> tags and make pass thru html?

    • avatar
    • Jake Howlett
    • Wed 25 Jun 2008 01:11 PM

    Yes Bob. Make sure it's right at the end of the form.

    • avatar
    • Bob
    • Wed 25 Jun 2008 02:46 PM

    Hi Jake, One more question - I pasted the script onto the form physically at the end, but when I view the source code of the web page there are some <Input> tags (fields) that appear between the </script> tag of the analytics and the </body> tag of the form, will this impact performance or should it be okay?

    Thanks for your very quick response here, as well as for all the indirect help you have given me throughout the years!!!

    • avatar
    • Jake Howlett
    • Wed 25 Jun 2008 03:07 PM

    Sounds like the form has "generate HTML for all fields turned on". Shouldn't be a problem though. There's only one way to find out though...

    • avatar
    • Bob
    • Wed 25 Jun 2008 03:11 PM

    Duh, that was it. Thanks so much once again!!!

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Wed 11 Jun 2008

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content