Status Update: Week 46

Done

It was a pretty slow week, I mainly just worked on patches for Mozilla Lab's Prospector and answering questions on the Google Analytics and Website Optimizer help forums this week.

Mozilla lab's Prospector

  • findSuggest: Clicking a word overwrites the last word in the find field instead of replacing the existing find field (Issue #33)
  • queryStats: Bug fix for an exception when running add-on (Issue #48)
  • queryStats: failed to work and disable itself when installing by proxy file or putting xpi into extensions folder manually (Issue #49)

Next

Still working on finding resolutions to the remaining bugs blocking Scriptish 0.1..

Skip Validation Of A/B GWO Tests

If you're like me and you get sick and tired of validating GWO A/B tests that you setup then this userscript is for you.

The "Skip GWO A/B Validation" userscript will turn the step 3 "Preview and start experiment" text near the top of the page into a link which will take you directly to step 3 (which is preview & launch), allowing you to skip/bypass the validation step (which is step 2). This userscript also adds a "Skip" button near the bottom of the page between the "Back" and "Continue" buttons (the "Continue" is disabled until you have validated your code).

Screen Shots

Before

After

How To Simulate An A/B Test With A Multivariate Test

A very common question I see on the Google Website Optimizer (GWO) Help Forum is how to perform an A/B test on page sets with dynamic urls. For example, if you want to perform an A/B test of different layouts across all of your product pages to determine which layout performs better, in which case the simple A/B test that GWO provides will not work, but you can achieve this by simulating an A/B test with a multivariate test (MVT) as I'll explain to you now.

First I want to explain how an A/B test works. When you setup an A/B test you provide Google with page A's url and page B's url, then Google will give you three tags/scripts: a control script, a tracking script, and a conversion script. The control script is what I want to focus your attention on, the difference between an A/B test's control script and a multivariate test's control script is a single line, the last line, which looks like this:

<script>utmx("url",'A/B');</script>

Now ask yourself what does this code do exactly? well if you were to grab the siteopt.js code, beautify it, and dig through it then you'll see that the code above uses the page B url that you provided to do the following when a visitor is meant to see page B.

<script>
window.location.replace( pageBURL );
</script>

Where pageBURL is the url for page B that you provided to Google in addition to any query string items and url hash that is in the url when your visitor hits page A.

This is how a GWO A/B test performs the redirection to page B. An important feature to notice here is that window.location.replace( ... ); is used and not window.location.href = ...; or window.location.assign( ... );. This is important because using the replace() method means that the user will not be able to use the back button to get back to page A. If GWO used window.location.href = pageBURL; then if the user pressed the back button they would be sent to page A which would redirect them to page B again, so they would have to go two pages back in order to get to the page they were at before landing on page A. This is obviously not desirable.

So now the question becomes how can one simulate a A/B test's redirection with a multivariate test? Well here are the steps that I give to anyone that asks:

  1. Create a multivariate test.
    1. Provide Google with any url in the set of urls that your wish to test. Google asks you for the test page's url is for two reasons, the first is so that they can scan the page and verify that the page has been 'tagged' properly, and the second reason is so that they can show you a preview of the test.
  2. Tag your pages with the control script, tracking script and conversion script all as you normally would.
  3. Now, put the section code directly below the control script and call the section whatever you want, let's call it "redirect" for example's sake. Make sure that the section code is surrounding nothing, white space, or blank space.
  4. Verify your pages and move on to step 3: Create variations.
  5. Create a new variation of your "redirect" section for each page variation that you desire (ie: if you just want a A/B test create one variation, if you want a A/B/C test make two variations, and so on). For each of these variations that you create, insert the following:

    <script>
    window.location.replace( window.location.protocol + "//" + page + window.location.search + window.location.hash );
    </script>

    Where page is something like www.yourdomain.com/product/123B.html, since you will likely be trying to implement a dynamic A/B test page will be dynamic, so it can either be a javascript variable that you define before/above the section code, or it can be derived from the window.location.href by using the replace() method. If page must contain a query string then you will want to modify the string above, which should be obvious. So I do not suggest that you copy and paste the code above, I suggest that you think about it to figure out how best to apply this principal to your use case. If your page variable must contain a query string then consider modifying window.location.search in the above code with window.location.search.replace(/^\?/,"&"), which will replace the '?' with '&' at the start of the string; this is likely be the only change you need to make, but in edge cases you may want to strip more data out of window.location.search, so think about it.

I hope this helps, happy testing!

BetterGA Is Dead (R.I.P)

As some of you may know, I developed a Firefox extension called BetterGA in 2008. Well today I have to tell you that the project is dead, and may it rest in peace.

[More]

Making All Internal Link Clicks a Conversion

A common use case of Google Website Optimizer (GWO) is to test (in order to optimize) a page's ability to have a user click an internal link, I like to call this the internal pass thru rate of a page. Meaning the click event of any internal link on a test page will count as a conversion for the test. This is not the opposite of the bounce rate which it is sometimes mistaken for, because the pass thru rate is oblivious to the difference between first time visits and other visits. The pass thru rate is not the same as the click thru rate either, because the pass thru rate relates to visits and the click thru rate relates to impressions. This is usually desired either because you have no other conversion to track -- although time on page is always another option, but the results typically take longer to acquire -- or because you wish to optimize the bounce rate, and this is as close as you can get at the moment.

Google doesn't have any documentation on how to track all internal links on a page, but they do provide a page on how to track an individual link, which any novice JavaScript programmer can follow in order to track all of the internal links, by simply repeating the process for every internal link on the test page(s). The main problem here is that Google's process requires that the onclick attribute of every link be set to "return false", albeit this can be done via JavaScript, it is not desirable. Google Website Optimizer's Technical Lead Engineer, Eric Vasilik, explained Google's method in a blog post from August 2009, called "Tracking Outbound Links -- The Right Way", and I wrote a follow up post in December 2009, called "Tracking Outbound Links - The Really Right Way" in which I describe a better method which is slightly harder to implement but does not require any use of the onclick attribute.

If you are at least a novice JavaScript programmer that wants to measure the pass thru rate of a page, then you can probably implement Google's method or mine with relative ease after reading the blog posts I mentioned.

If you are not a novice JavaScript programmer, or simply want to save some time implementing this type of conversion over and over again, then I would suggest you take a look at the JavaScript click track library that I released in early December '09, because with this javascript library you could simply add the following code to your page:

clickTrackingLib.addMatches([{
match: clickTrackingLib.getMatchPreset( "all-internal" ),
trackingFunc: function(e, link){
var gwoTracker=_gat._getTracker("UA-XXXXXXX-X");
gwoTracker._trackPageview("/YYYYYYYYYY/goal");
}
}]);
clickTrackingLib.attachTrackingFunctions(null,99);

The above code will tag all non-rel-external links or links with the internal hostname on the page; for just internal hostname links replace "all-internal" with "internal-hostname". I would recommend that you wrap the above into a function though, to be run on the DOM ready event or page loaded event, with jQuery that would look like:

$(document).ready(function(){
clickTrackingLib.addMatches([{
match: clickTrackingLib.getMatchPreset( "all-internal" ),
trackingFunc: function(e, link){
var gwoTracker=_gat._getTracker("UA-XXXXXXX-X");
gwoTracker._trackPageview("/YYYYYYYYYY/goal");
}
}]);
clickTrackingLib.attachTrackingFunctions(null,99);
});

The first line in the code above will setup a function to be executed when the DOM is ready, and all of the page's links have been added. The second line is the first of the function the be executed on DOM ready, and it is adding an array of match objects to the global clickTrackingLib object provided by the click tracking library that I wrote. The following 5 lines define a single match object for the input array, which consists of a preset match function to match internal links (as I said already this preset can be changed, and you can also define a custom match function), and a simple tracking function. When clickTrackingLib.attachTrackingFunctions(null,99); is executed, links are tested against the match functions in the clickTrackingLib object's match object array, and where there is a match the associated trackingFunc function is made in to a onclick event listener for the matched link. As for the two inputs, the null means try all links, and the 99 means use a 99 millisecond delay.

At this point you might be wondering, what if the page has dynamic content, which is changed via ajax, well in that case you can round up the new link(s) in to an array and run the clickTrackingLib.attachTrackingFunctions(links, delay) function again like so:

clickTrackingLib.attachTrackingFunctions(newLinksArray,99);

clickTrackingLib.attachTrackingFunctions(links, delay) will also accept a single link.

Tracking Outbound Links - The Really Right Way

About 5 months ago Eric Vasilik wrote a post on his GWO Tricks blog about Tracking Outbound Links -- The Right Way which was ment to point out a solution for the problem with the technique outlined in the Analytics Help Center article called "How do I manually track clicks on outbound links?", is that it suffers from a Race Condition which may mean the tracking doesn't take place. If you haven't read Eric's article, please do.

Well as readers of my blog would know, I recently wrote a JavaScript click tracking library which can be found at GitHub here. In the blog post I mention that I implemented Eric Vasilik's "Right Way" to track links, but today I started thinking about this some more.

I decided to do some searching on how to cancel a click event, and I found a great old blog post from 2006 by Ryan Campbell pretty quickly which mentions a method implemented by Prototype called Event.stop(). So I decided to dig in to the Prototype code to see what Event.stop() did exactly, so I could extract it, and I found that it does two things, one is to stop the event propagation, and the second is to stop the default behavior for the event. At the end of the post Ryan said that it not work for Safari 2.0.3, which is why it could not be relied on at the time, but today Safari 2.0.3 is dead, and I tested Safari 3 out which works. In fact I decided to do some PPK style testing and try test cases on every browser I could.

After seeing that Event.stop() had two purposes I wanted to find out why this was done, and found this documentation page for Event.stop(), which says this was done "because stopping one of those aspects means, in 99.9% of the cases, preventing the other one as well", but in the case of simply click tracking we don't really want to stop the event propagation, we just want to stop the default action from being triggered eventually. So here is what my update to Eric's example looks like:

<a id="example" href="http://www.example.com">Click me</a>
<script type="text/javascript">
function doGoal(e){
if(!e) var e = window.event;

var targ;
if ( e.target ) targ = e.target;
else if ( e.srcElement ) targ = e.srcElement;
// Safari..
if ( targ.nodeType == 3 ) targ = targ.parentNode;

setTimeout('document.location = "' + targ .href + '"', 100);

try{
var pageTracker=_gat._getTracker("UA-123456-1");
pageTracker._trackPageview("http://www.example.com");
}
catch(err){}

if (e.preventDefault) e.preventDefault(); // w3c
else e.returnValue = false; // for ie
}
if ( document.body.addEventListener ) {
// w3c
document.getElementById('example').addEventListener( "click", doGoal, false );
}
else if ( document.body.attachEvent ) {
// ie
document.getElementById('example').attachEvent( "onclick", doGoal );
}
</script>

To try the code above see the test page here. I have tested this out on IE6+, FF2+, Opera9+, Safari for the iPhone OS 3.0, Google Chrome, and Safari3+ on MacOSX and WindowsXP and they all work, so I am pretty confident that this is going to work for something like ~99% of web users today, and since it would not error even for a user using Safari 2 (which I wasn't able to test), and Safari 2 is so slow, there is a good chance the user would still be tracked anyhow.

If anyone else could try this out on some other browsers at let me know what they find good or bad that would be nice so that I can add them to the list above. The best way to test the test page is to comment out the setTimeout line, and make sure that clicking the link doesn't do anything.

The beautiful part about this method is that it is totally unobtrusive JavaScript code, and will work even if you are using the onclick attribute for other site functionality (even though you shouldn't ever use the onclick attribute).

Merry Clicking!

P.S. The Click Tracking JavaScript Library has been updated to use this really right method, check it out if you haven't already!

Click Tracking JavaScript Library Now Available

Purpose

To help web publishers easily track link clicks the correct way, across browser platforms, with tools like Google Analytics (GA) and Google Website Optimizer (GWO).

Typically a web publisher will want to do something like track all external links on a website with GA, setup a GWO test where the conversion is a click through, or do both on the same page for a few pages of their site. This javascript library was designed to make tasks such as these simple.

About

clickTrackingLib

Adding the click-tracking-lib.js or the click-tracking-lib-with-presets.js to a web page provides you with a clickTrackingLib javascript object. Once you provide clickTrackingLib with some match objects, you can then have clickTrackingLib scan a single, set, or all document links to determine if the link(s) should have tracking functions applied to it or not, and do so if needed. If one or more tracking functions are applied to a link, then a delay function will be applied to the link (this can be disabled too of course, and the delay can user defined but the default is 99 ms).

The Delay Function

The delay function is meant to delay the user from being redirected to a new page for just a bit to allow time for say a Google Analytics image request to complete, and avoid being canceled by the user's browser. It can be disabled, but it is added by with a 99 sec delay by default, which can be customized, as the very last onClick event listener, after all of the desired provided Match object trackingFunc's are applied.

The delay function technically only sets a timeout to redirect the user after x ms, but in order for the delay to work the link's default functionality, namely redirecting the user, needs to be disabled, if the link doesn't just open in a new tab (target="_blank" and target="_new" are checked for). To disable the default functionality the link's onclick attribute must be set to onclick="return false;" which I figured should be fine because all well made websites won't use that attribute except to make it equal to "return false;" anyhow. If your site is not well made, then you should think about fixing it or having it fixed for you, but you can still use this library by simply not using the delay function and implementing it by some other means.

Presets

There are a number of presets available if you use click-tracking-lib-with-presets.js or click-tracking-presets.js; presets are predefined match functions for common use cases, such as matching all internal links, or external links, or download links. They can be used as they written, you could cut out the ones you won't use, or simply use them as examples when you define your own custom match objects.

The can be accessed from the clickTrackingLib.getMatchPreset( name ) method. The possible name values and the meanings behind them are as follows:

  • 'rel-external': matches rel-external links
  • 'external-hostname': matches external hostname links
  • 'all-external': matches all rel-external and external hostname links
  • 'filetypes': matches file names: (docx*|xlsx*|pptx*|exe|zip|pdf|xpi|rar|xls)
  • 'non-rel-external': matches non-rel-external links
  • 'internal-hostname': matches internal hostname links
  • 'all-internal': matches non-rel-external links or internal hostname links

Match Objects

Any object that has a 'match(link):boolean' method and 'trackingFunc(event,link):void' method defined.

match(link):boolean

This method will take a link element as input, run some test on it and return true or false, if true is returned then the Match object's trackingFunc will be added to the link.

trackingFunc(event,link):void

This method will be provided with two input values; event is the click event object, and link is a reference to the link element. You can obtain a reference to this from the event object, but there is some cross browser logic you would need to implement, so I thought a direct reference to the link would be handy. The function should not return anything.

new clickTrackingLib._clickTrackingLib();

If you want to create multiple clickTrackingLib objects, that contain different sets of match object arrays, then you need to create a new one, like so:

var myNewClickTrackingObj = new clickTrackingLib._clickTrackingLib();

This will give you a new object, myNewClickTrackingObj, which is like clickTrackingLib in all but two ways. First myNewClickTrackingObj will not have a _clickTrackingLib() method, and second it will not have a getMatchPreset() method, even if clickTrackingLib.getMatchPreset() was defined. This is because you don't need a bunch of objects in memory with those two methods, only one, which is the singleton clickTrackingLib object.

How To Use

  1. Download either click-tracking-lib-with-presets.js or click-tracking-lib.js (see ABOUT fore more information) from the project repository at GitHub.
  2. Minify it with one of the following options:
  3. Upload the minified script to your site.
  4. Add <script src=".." type="text/javascript"></script> for the script to the desired pages.
  5. Write some code:
    • define some match objects (just an object with a match method and trackingFunc method)
    • Add match objects to your clickTrackingLib object
    • Call the clickTrackingLib.attachTrackingFunctions( links, delay ) when desired.
      • links: can be a single anchor element, an array of anchor elements, or falsely so that the default is used, which is document.links.
      • delay: should be a positive integer or falsey, in the latter case no delay function will be added to the links scanned, in the former case a delay function will be applied with the specified delay value.

[More]

Preview GWO MVT Combinations In A New Tab

If you dislike using the preview window that is provided by default for Google Website Optimizer, then I promise you will like this userscript, because it will provide you with means to preview your MVT combinations without following these instructions all of the time.

[More]

Google Website Optimizer Calculator Userscript

Back in November '08 VKI Studios won a Google Website Optimizer (GWO) "Design a Feature" Contest with the idea of adding an "Integrated Experiment Duration Calculator". Not long after I mentioned that I did not think it was a good idea, but there are obviously plenty of people that disagreed with me. It's even been a little joke at the office when we wanted to use the calculator and had to find the link, we would say "it would sure be nice to have a integrated calculator..".

Anyhow I promised back in November that I would write a greasemonkey script to hide the calculator, but they still haven't even gotten around to it, I wounder what they have planned.. Well, today I decided to write a userscript to add a link to the calculator which already exists, to the GWO interface, because I admit a link is handy, but I still don't think the GWO team's time should be spent on this.

In the screen shot above you can see a calculator icon has been added to the menu, press it and you will go to Google's Website Optimizer Duration Calculator

Installation Instructions

  1. Get Firefox.
  2. Get Greasemonkey.
  3. Install this userscript by clicking here.
  4. Login to GWO.

Details

Links

  1. Main page: - GWO Calculator
  2. Userscripts.org: - Preview GWO MVT combinations in new tab

Updates

ver 1.01 (2009-04-25): bugfix - removed dependency on the account select field, because is not present on every page.

Can You Execute The GWO Conversion Script With A IFrame Across Domains? or Subdomains?

Answer

I tested this on different subdomains about a week ago and that worked. Then I just recently tested this across different domains, and it turns out that it will only work if the user/visitor's browser allows third party cookies, which is obviously not good enough to rely upon. So it is not a good idea, and I recommend that you use a standard method of handling cross domain tracking, which I intend to blog about.

Aside

Having said that this is not a worth while idea, I do want to mention how to ensure that this method works for all browsers =] So if you are just so inclined, then I suggest you read this article on how to set third party cookies with an iFrame.

More Entries

© Erik Vold 2007-2012. Contact Erik Vold. Top ^