views:

51

answers:

1

I am attempting to track events when links are clicked on my site in a method similar to the following.

<a href="/example" class="track">Example</a>

<script type="text/javascript">
    jQuery(function($) {
        // track clicks on all anchor tags that require it
        $('a.track').live('click', function(e) {
            // send an AJAX request to our event tracking URL for the server to track it
            $.get('/events/track', {
                    url: $(this).attr('href'),
                    text: $(this).text()
            });
        });
    });
</script>

The problem that I'm having is that a new page load interrupts the AJAX request, and so sometimes these events aren't being tracked. I know Google Analytics has a _trackPageview function that can be attached to onclick events though, and this doesn't seem to be an issue for that. I'm wondering what's different about their call vs. mine that I'm seeing this race condition, and GA isn't. e.g.:

<a href="/example" onclick="javascript:pageTracker._trackPageview('/click/example');">Example</a>

Note that I'm not worried about the result of the AJAX request...I simply want it to ping the server with the fact that an event happened.

(Also, I expect I'll get at least one answer that says to simply track the new page load from the server side, not the client side. This is not an acceptable answer for this question. I'm looking for something like how Google Analytics' trackPageview function works on the click event of anchor tags regardless of a new page being loaded.)

+3  A: 

Running Google's trackPageview method through a proxy like Charles shows that calls to trackPageview( ) request a pixel from Google's servers with various parameters set, which is how most analytics packages wind up implementing such pieces of functionality (Omniture does the same).

Basically, to get around ansynchronous requests not completing, they have the client request an image and crunch the parameters passed in those requests on the server side.

For your end, you'd need to implement the same thing: write a utility method that requests an image from your server, passing along the information you're interested in via URL parameters (something like /track.gif?page=foo.html&link=Click%20Me&bar=baz); the server would then log those parameters in the database and send back the gif.

After that, it's merely slicing and dicing the data you've collected to generate reports.

ajm
How is this preventing the race condition? Is the pixel loaded in a non-AJAX fashion? For example, is it loaded into the page in an image tag via `document.write`? Or is the Javascript Image() object used similar to how preloading images for rollovers used to be done back in the day? I just want to make sure I implement this correctly such that I don't have the same race condition occurring in a new way. Thanks! :)
Matt Huggins
Well, essentially the work is all being done on the server side. The client's only responsibility is sending the request; it could insert the image into the page if necessary, but the real action is hitting the server and allowing the server to record what's been sent to it. In this case, you could create a new Image, send an Ajax request, load a script, etc. as long as you're making a request to the server.
ajm
Well that brings me back to my problem in the first place. I'm making an AJAX get request, but sometimes it's not making it to the server before the requested page on the anchor tag is being loaded. How can I ensure the image loading won't have the same problem?
Matt Huggins
I tried to dig through the GA code, and it looks like their using the Javascript `Image` object. i.e.: `var image = new Image(1,1); image.src="tracking_pixel_url.gif";`
Matt Huggins
The image loading on the client isn't really doing anything here; rather, it's the request to the server that does all the magic.
ajm