There Is No Cat

The alternative to flowers!

Thursday, July 10, 2008

Working Around Omniture

The most recent site I developed at work had a couple of pages with lots of what would have once been called DHTML functionality, stuff like tabbed interfaces, modal windows and the like. In development, this stuff all worked really well, and I even did my level best to make it all accessible. But just before we deployed, we had to incorporate code from Omniture that tracks users as they move through a site. Omniture is widely used script for tracking the path users follow through sites. And here we ran into some problems.

The first problem was that Omniture's Javascript code is heavily obfuscated and optimized. All of the function names and variables use extremely brief and cryptic names, using one or maybe two characters, something that makes it extremely difficult to debug when you have a problem. Unlike an open source Javascript library like, say, jQuery, Omniture doesn't provide a development version of their library with reasonably named functions and variables, so if you've got a problem, you're stuck trying to figure out what function a and its variables x, y and z, are doing and what they're stomping on. And the stomping on is another problem; if you incorporate another minified library, like, say, the minified version of jQuery, some of those single-character-named functions or variables are going to conflict with the single-character-named functions or variables in Omniture's code. This could have been avoided if Omniture namespaced their code so it doesn't stomp on anything else and blow up your site (can you tell I've seen this happen more than once?) When we discovered this conflict, we wound up going with a slightly larger version of jQuery that doesn't create those functions and variables with the same names as the ones Omniture creates.

But the bigger problem we found is that Omniture's code is slow. Verrrrrrrry slow. On a tracked link, the Omniture code would do whatever it does (hard to tell what, exactly, because of the obfuscated code), and only when it was done would the default action of the link be triggered. So when you clicked on a tab in the tabbed interface, or on a link that would open up a modal window, links that were pretty much instantaneous on the development network and still extremely speedy on the staging server now took forever to activate, on the order of three or four seconds. This was really unacceptable from a user experience point of view, but from the client's perspective, the links had to be tracked. What to do? We could change the cursor to an hourglass and then change it back, but the link would still be slow to activate. Not good.

Omniture provided two possibilities for tracking links; the first was to add an id as part of a query string at the end of a link. This caused us problems in some cases, such as the tabs, because now links that were within a page and wouldn't cause the browser to reload the page, with the addition of the query string, now appeared to the browser to have different parameters from the originally loaded page, and so it would reload the page, bouncing users back to the default tab. That didn't work, so we tried their alternate syntax, which involved assigning one of their functions to the onclick event handler. That led to the above-mentioned slowing to a crawl.

In a conversation with the Omniture expert at work, I asked if it mattered if the id associated with a link were actually called by the page or if it could be called by another URL. The answer led to a solution. The id could be added to any URL, even, say, a 1×1 spacer GIF. (Finally, a justifiable use for a spacer GIF in modern code!) So we could make the onclick event handler call /images/x.gif?iid=page_identifier_here. Even better, we could call that URL asynchronously using Ajax. Since we were already using jQuery, all we had to do was to add a line like the following to the already existing (unobtrusively linked) onclick event handler:

$.get('/images/x.gif?iid=page_identifier_here');

This would send the call to the server that included the required Omniture tagging, but since the call was being executed with jQuery's Ajax get() function, the call was happening asynchronously, and the default actions could be triggered without waiting for a response. That restored the speedy user experience. But we found that once the asynchronous call was finished, whatever URL was in the href attribute would then reload, causing, for example, the tabs to once again bounce back to the default. So we had to define a callback function to be executed upon the completion of the Ajax request. Since we didn't want anything to happen at the completion of the request, the function is a simple return false:

$.get('/images/x.gif?iid=page_identifier_here',function(){return false});

Et voila, the client gets the tracking they require, and the user gets the experience they deserve. No longer does Omniture cause the interface to bog down.

If you're using any library other than jQuery, it's bound to have a similar function for asynchronous Ajax calls. If you're rolling your Javascript from scratch, such a call would look something like this:

function trackme(url,query) {
    // Native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();

    // ActiveX XMLHttpRequest object
    } else if (window.ActiveXObject) {
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }
    if (request) {
        request.onreadystatechange = function() { 
            return false; 
        };
        request.open("get", url, true);
        request.send(query);
    }
}

And then your onclick event handler would include something like this:

onclick="trackme('file.html','iid=page_identifier_here'); return false;"

The return false here is required to prevent the onclick from executing the default action of the href even before the Ajax request is returned.

Posted at 10:36 PM
Link to this entry || 6 comments || Trackbacks (0)

This site is copyright © 2002-2024, Ralph Brandi. (E-mail address removed due to virus proliferation.)

What do you mean there is no cat?

"You see, wire telegraph is a kind of a very, very long cat. You pull his tail in New York and his head is meowing in Los Angeles. Do you understand this? And radio operates exactly the same way: you send signals here, they receive them there. The only difference is that there is no cat."

- Albert Einstein, explaining radio


There used to be a cat

[ photo of Mischief, a black and white cat ]

Mischief, 1988 - December 20, 2003

[ photo of Sylvester, a black and white cat ]

Sylvester (the Dorito Fiend), who died at Thanksgiving, 2000.


Stylesheets


This site is powered by Missouri. Show me!

Valid XHTML 1.0!

Valid CSS!

XML RSS feed

Read Me via Atom

new host

Me!

Home Page
Resume
Married
Photographs
Flickr Photostream
Instagram Archive
Twitter Archive

last.fm

There Is No Cat is a photo Ralph Brandi joint.


Archives

Search



Family Blogs

Geneablogy
Jersey Girl Dance
Awakening
DullBlog
Mime Is Money

Blogs I Read

2020 Hindsight
AccordionGuy
Adactio
Allied
Apartment Therapy
Assorted Nonsense
Backup Brain
Burningbird
Chocolate and Vodka
Creative Tech Writer
Critical Distance
Daily Kos
Dan Misener likes the radio
Daring Fireball
Design Your Life
design*sponge
Doc Searls
Edith Frost
Elegant Hack
Emergency Weblog
Empty Bottle
Five Acres with a View
Flashes of Panic
Future of Radio
Groundhog Day
Hello Mary Lu
iheni
Inessential
Interllectual
Jeffrey Zeldman Presents
Jersey Beat
John Gushue ... Dot Dot Dot
john peel every day
JOHO The Blog
Kathryn Cramer
Kimberly Blessing
La Emisora de la Revolucion
Lacunae
Loobylu
mamamusings
Medley
mr. nice guy
MyDD
Orcinus
oz: the blog of glenda sims
Pinkie Style
Pinkie Style Photos
Pop Culture Junk Mail
Seaweed Chronicles
Shortwave Music
Slipstream
Talking Points Memo
The Unheard Word
Tom Sundstrom - trsc.com
Typographica
Unadorned
Vantan.org
WFMU's Beware of the Blog