Happy New Year!
Last year was certainly a good one - 2010 is set to be even better. It'll be Spring soon - warmer weather, more daylight and more records to break.
Moneyspyder exceeded many targets last year. We were delighted with the resilience and scalability of all our clients' sites during the festive period (as were our clients!). The run up to Christmas saw new ground broken in terms of scalability, performance and transactional throughput.
Overall, 2009 saw 99.96% uptime across all our clients. Bearing in mind that the majority of that miserly amount of downtime was planned. Our twice monthly scheduled upgrades of sites are timed and performed with precision so as to maximise effect and return whilst minising interruption and downtime. We don't miss opportunities to introduce new A/B and Multivariate tests with Google Website Optimiser based on our deep dive analytics.
It has to be said that our infrastructure partners played a huge part in our success during 2009. A 'big shout out' to Site Confidence for the monitoring and uptime reporting and especially Engine Yard for the AWESOME Rails hosting. We're delighted to be part of Engine Yard's Select Partner Programme and look forward to moving onwards an upwards with all our client's and partners in 2010!
Monday, 4 January 2010
Moneyspyder exceeds targets in 2009.
Posted by
Doug Halll
at
01:20
0
comments
Links to this post
Wednesday, 16 December 2009
Google Analytics report bookmarking hacks
Help HiPPOs!
Even though Moneyspyder is firmly behind the anti-HiPPO movement we recognise it is still important to help HiPPOs. After all, they do rule the business world.
Generally speaking it is best to deliver insight to HiPPOs. Make the news - don't just deliver the news! However, there is merit (on occasion) to furnish them with 'vanity metrics' or 'outcome proxies' as we tend to think of them via the medium of 'the dashboard'.
Better Dashboards
The dashboard in the context of Google Analytics will likely take the form of a custom report. Custom reports rock. F.A.C.T. A custom report based dashboard can lift the value of the deliverable. You can move from report 'puking' to actually delivering insight by placing the report in context. You can do this in a few simple ways:
- Multi-tabbed
- Use advanced segments
- Use relevant date ranges
- Use comparison date ranges
Express delivery!
Okay, you have the dashboard setup - it offers context as well as just raw numbers. It yields actionable insight (so go do some insightful actions already!).
You'll probably want to schedule the delivery of this report via a monthly PDF attachment in an email. Simple in Google Analytics.
I suggest dropping a note in with the email via the description:

The note should start delivering context for the HiPPO. Help them already before they open the attachment! Now, the real meat of this post. Provide a link to the report.
Scary controversial opinion alert!
Invite the HiPPO into Google Analytics...Give them a specific read-only login to one profile that contains the dashboard/custom report.
Use the options in the report URL to customise and control what they see.
Here is a standard custom report link:
https://www.google.com/analytics/reporting/setup_email?id=4867638&seg0=-1&pdr=20091201-20091216&cmp=date_range&trows=50&gdfmt=nth_day&rpt=CustomReport&segkey=medium&tchcol=1&tst=0&tscol=v0&tsdir=0&mdet=WORLD&midx=0&gidx=0&cid=26&afs=false&seg=1&fmt=0
Here is the link with some easily customisable options in the URI:
https://www.google.com/analytics/reporting/custom?id=profile id&pdr=primary date range&cmp=advanced segments&trows=50&gdfmt=nth_day&cdr=comparison date range&segsegment number=-segment number&rpt=CustomReport&segkey=medium&tab=tab number&tchcol=1&tst=0&tscol=v0&tsdir=0&mdet=WORLD&midx=0&gidx=0&cid=Custom report id&afs=false
So, what are the customisable options? this is not an exhaustive list - these are just the ones I find useful right now - this list may grow.
Custom report id
Open your custom report. Write down the id in the url. Use it.
Primary date range
This is the date range that you want to look at. It's optional. If absent, the report will show the default last 30 days. It is in the format: yyyymmdd-yyyymmdd (eg. 20091101-20091116) where the first date must obviously be before the last... ;-)
Comparison date range
This is the date range to compare with - great context. Look at 'the same period last week/month'
Advanced Segments
How cool! Load a report showing only the segments you want to see! The format for the NVP is segn=-m. So, the default will show 'all users' would be ....&seg0=-1&...the default advanced segments follow the order in the drop down list so 'Non-bounce visits; would be seg0=-12. You can show multiple segments in the format: ...&seg0=-3&seg1=-5&seg2=-12&...which would show 'Direct Traffic','Visits with Conversions' and 'Non-bounce Visits'.
Tab number
Have you got a multi tab report? Do you want to default to a tab other than the first? Specify the default tab number here. Simples ;-)
Posted by
Doug Halll
at
01:09
1 comments
Links to this post
Wednesday, 2 December 2009
Statistical significance in A/B testing - a little tool to help
Rationale
I read a tweet recently by @tclaiborne about a great blog post on the subject of Easy Statistics For Adwords AB Testing And Hamsters. With a title like that, how could I not take a peek?
It so happened that I was working on a small project to build a tool in Javascript to enable easy analysis of two data sets to compare them for statisticaly significant differences, specifically in the context of A/B and MV Testing.
This post is introducing the prototype of that tool. Just to be clear, this tool is a mash up of Javascript snippets that have been published. I didn't write the whole thing so I'm not taking credit here - I'm just looking to share a cool tool!
A Simple Test to Introduce The Tool
Let's say we've run a test using Google Website Optimiser. We made a change to a page to increase the number of outcomes. We have 6 days worth of data. Here are the conversion rations for the 6 days for the original and the test variation:
| Test | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| Original | 6% | 6% | 5% | 6% | 7% | 6% |
| Test Page | 9% | 6% | 7% | 6% | 9% | 8% |
So, from 5 days worth of data, can we see if the difference in the conversion rates are significant? It's a small data set...the numbers seem to be different but as the blog post referred to earlier says, we humans are really bad at looking at data sets and making accurate judgements.
We need some stats. Enter jsstat.

So, we can drop in our two samples of data as comma separated values. They don't have to be the same size or integer values. Let's hit that 'oh-so-tempting' import button to see what wonders we can find:

Ah, such insights, knowledge and power are ours! We can deliver meaning and value to our clients! Ahem, enough whimsy - what the heck does this mean?
I'm going to keep this high level:
- The differences could have happened by chance.
- The green text tells us the truth
- The results are conclusive.
- The new page converts 1.5% better than the old on average
Try the test yourself using '1,2,3,4,5,6,7,8,9' as both data sets. NOT SIGNIFICANT!
Moving swiftly on
It's a prototype okay? It might not work in crufty old browsers. Stick with a later version Chrome or FireFox to be safe. The graphing is adding little value right now but box plots are coming!
I'd really like a direct export from Google analytics or Website Optimiser into something like this...Hmmm.
Now, the new Google Analytics Intelligence functionality is very similar to this. It's great, don't get me wrong! Different in some ways but based on the same theory...mostly.
We are looking at taking this tool a lot further to supplement Multi-Variate testing results analysis and click stream data analysis.
I'll keep you posted.
Posted by
Doug Halll
at
09:10
2
comments
Links to this post
Friday, 20 November 2009
First/last click campaign attribution and onsite purchase trigger analysis techniques.
Overview
Understanding which traffic sources contribute to successful outcomes on your website is crucial to maximising Return On Investment. By default Google Analytics supports last click attribution. This means a customer who starts a session with a click on the Adwords Campaign 1 (see below) and then starts a new session with a click on Referrer 1 and ends in the purchase of four products will result in Referrer 1 being attributed with the 'credit' for all four sales.
See the Google Conversion University for more details.
We can add the utm_nooverride=1 parameter to the links in our campaigns to ensure the first campaign that is clicked is credited for sales and goal outcomes:
So, we can measure which marketing initiatives incentivise users to visit our sites but we can't so easily see what motivated a user to complete a goal or purchase while on the site – what is driving positive outcomes from user journeys during their visit? We can't easily see this with default techniques.
You can have your cake or eat it...but not both.
Moneyspyder has developed a technique that couples first or last click attribution data to measure brand engagement with last-click-before-purchase triggers on a 'per basket item' basis to reveal purchase or goal completion triggers.
We say you should have your cake, eat it and have extra sprinkles too!
Technique
We modified the Moneyspyder ecommerce engine such that the purchase trigger (last click before adding to basket/cart) is recorded in the Google Analytics clickstream data as well as being recorded against each order item in the basket such that the value can be used in the 'Category' field on the Google Analytics ecommerce tracking code.
Purchase triggers may include clicking on a feature product on the homepage, clicking on products in on-site search results, related product clicks, products in category listings, product clicks in email campaigns, organic search results and of course 'direct' visits from bookmarks. The limit here is your imagination!
Recording product clicks from on-site or external search engine results generates great purchase trigger data. Using the search term to supplement the data is a golden opportunity not to be missed. Likewise, related product clicks should record the product that was related to the purchased product and category list clicks should record the category.
This modification to our ecommerce engine was straightforward – it should simple be on your software too.
By now you will get a clear picture as to what extra data is being recorded. Now, what can you do with it?
Insights
First of all, let's take a look at the pure clickstream data:
From the standard content report in analytics we can see how clicks on the 'sky-lantern' product came from a multitude of different sources:
- search for lights
- email campaign
- linked from other products
- category links
- direct
We can see unique page views required for conversion metrics, average time on page, bounce rate, exit % and the super insightful $index. If the scope of this technique stopped here, we'd be pretty happy already with the extra insight we have on customer journeys. The extra sprinkles arrive when we consider the magical 'outcomes'.
As described above, of vital importance to getting maximum value from this technique is to record the last click before 'add to basket' in the clickstream data AND the transaction 'category' data. These sets of related data enable amazingly fine grained conversion metrics to be retrieved. For example, we can dig into the search listed above for 'lights' (the bottom row in the table). That's a pretty handy $index! Looking deeper we can see this search generated some pretty handy revenue over a short period of time:

Applying classic analytical techniques yields further insight:

If you're not convinced as to the merits of this technique by now, and indeed, you can get a lot of this data from the onsite search report then we shall take a mighty leap and look at category conversion metrics for the 'Best Sellers' category based on the landing page.
In the Google Analytics report below (Ecommerce → Product Performance → Categories), it looks at first glance that using the homepage as a landing page work pretty well. Sure, lots of revenue but that's not all!

When we take unique pageviews into account we can see the conversion rate for the best Sellers category when the homepage is the landing page is a respectable 4.8%. However, the Sale and Festive Season (Christmas) categories both out perform the homepage as landing pages at 5.4% conversion and the Best Seller category page as a landing page converts at 5.6%.
It's worth bearing in mind at this point exactly what this data means. A customer entered the site on a particular landing page, found their way to the Best Sellers category and put a product in their basket that they bought – the Best Sellers category page was a trigger to purchase. They liked the page and the products so much that they bought – just what site owners want to see and hear.
Conclusion
Through simple modification to our ecommerce engine, Moneyspyder has revealed finer grained, segmentable insights into the aspects of customer journeys that trigger positive outcomes – goal completions or purchases that include first and last click attribution.
This functionality is a great facility for conversion professionals to identify optimal customer journey paths and focus optimisation efforts with greater accuracy and effectiveness.
The modifications required for this technique are entirely portable and are in no way specific to the Moneyspyder ecommerce platform – we really encourage you to explore this technique.
Moneyspyder Biog:
We are a Google Conversion Professional and develop and host state-of-the-art ecommerce solutions using Ruby on Rails. We continuously improve customer experience using web analytics, split-testing and regular site enhancements based on web analytics data.
Posted by
Doug Halll
at
07:16
0
comments
Links to this post
Monday, 2 November 2009
Google Analytics: Expanded Mobile Tracking for Mobile Rails sites
Expanded Mobile Reporting - Introduction
Google recently announced expanded tracking for mobile apps using server side code. PHP, Perl, ASPX and JSP are supported as standard. As a dedicated 'Rails house' Moneyspyder has published a sample application for Mobile sites using Rails to broaden the usage of the product.
The need for this sample app is driven by the current use of javascript for tracking clickstream data. There are still a fair number of mobile devices out there that do not support client side javascript which can leave a sizable hole in your clickstream data. Using serverside code to reproduce the behaviour caters for these devices.
Preamble and cavets
The sample app is available for download. This is just a skeletal sample app and requires more thorough testing if deployed in the wild. We'd be keen to hear feedback of course as this is just a starting point....it ain't production ready!
Moneyspyder accepts no responsibility for loss or harm to data caused by using this sample app yadda yadda...
With that out of the way, some details.
Details
Download the app
Files
- routes.rb
- environment.rb
- ga_helper.rb
- ga_controller.rb
- index.html
Two routes are used, only one is really required. The utm_gif action (served by the ga_controller.rb controller) is responsible for sending basic request info to the action and the action builds the remainder of the request details and sends them to ga, returning a 1px transparent gif.
The GA Account idientifer is saved in environment.rb. You might want to store it in a configuration yml file, the db or whatever your favourite place is...
The utm_gif_url helper method builds the utm_gif request. This is used in index.html for demonstration purposes.
ga_controller.rb rquires cgi, digest and open-uri. CGI is used for urlencoding strings. digest is used for the MD5 stuff. open-uri is used to send the request to Google analytics.
utm_gif is the only public method needed. response headers are set appropriately and send_data is used to return the transparent gif image. Requesting the gif through the private track_pageview method is where the magic happens.
In summary, all the usual name value pairs that are appended to the _utm.gif request to Google Analytics by ga.js are collected and then sent to Google Analytics using the private send_request_to_ga method. open-uri allows us to send this request programmatically. This might well be a nice plave to build in some error handling...
Once the request is done, the gif data is returned and the page is rendered - sweet.
You should be able to spin upthis little rails app easily enough using webrick on your local machine i the standard rails way and hit http://localhost:3000. (no support is offered by Moneyspyder for this setup - it's pretty standard stuff)
You'll see something like:

Gotcha and thoughts
If bots are hitting your mobile site or you use this tracking code technique insteaqd of ga.js (Hmmm?!) then you'll likely get a lot of traffic from bots - better filter the requests that get tracked.
Posted by
Doug Halll
at
06:28
1 comments
Links to this post
Monday, 26 October 2009
Easier Website Optimiser tagging
Overview
In my previous posts I introduced the idea of externalised javascript libraries to abstract over Google Analytics page tracking and ecommerce transaction tracking.
This idea also transfers nicely into Google Website Optimiser where you can experience some interesting scripts on your first visit!
Caveat
These articles assume you are at least familiar with the concept of multivariate testing, javascript, Google Analytics tracking and the Live HTTP Headers plugin in FireFox.
As with the last posts - use these scripts at your own risk. Don't link to the script libraries directly, copy and tune to your own needs!
A Simple MV Test made simpler
A normal website optimiser multivariate (mv) test requires a control script, tracking script and goal script to be placed on your pages. The control script decides which experiment variation to show. The tracking script records which test variation was shown and the goal script records the experiment conversion.
Two cookies are also used in combination with the standard GA cookies.
Standard cookies
utma
utmb
utmc
utmv
.
.
.
etc (there are quite a few!)
Website Optimiser cookies
umtx
utmxx
The nature of the standard cookies is not the subject of this article. In summary, the utmx and utmxx cookies are used to remember which test variation a users sees.
If you inspect the cookies you have in your browser right now you probably won't have any utmx cookies for the moneyspyder.co.uk domain. If you go to the example page for this article and recheck your cookies, you should now see a utmx and utmxx cookie for the moneyspyder.co.uk domain.
You've just been tested!
You will have equal chances of seeing a very simple page with one of three different pieces of text and two links:
Original page
Test 1
Test 2
(and two links to goal and purchase)
Delete the utmx and utmxx cookies and reload the page to see different variations. This is standard Website Optimiser type development/testing/debugging.
You should also inspect the HTTP Headers output. Notice the request for siteopt.js? Notice the utmx and utmxx values? If you don't see these - it's broken. Simple. Check for javascript errors.
The source of the html page will reveal the how the test is rendered. As with the page tracking example we are including Moneyspyder javascript libraries:<script src="/javascripts/ms_ga.js" type="text/javascript"></script><script src="/javascripts/ms_wo.js" type="text/javascript"></script>
ms_wo.js gives us three methods to use:
ms_wo_ctrl
ms_wo_tracking
ms_wo_goal
All three methods take the experiment id as a parameter 'k'. You can get this value from the supplied script snippets when you set up your test.
The control script normally sits at the top of your content - ms_wo_ctrl replaces this script and so, sits in the same place. Feed it the test id to setup the test. Directly beneath the ms_wo_ctrl script, call the ms_wo_tracking method. Feed it the test id and Website Optimiser ua account value to track the test view.
Now, normal test scripting applies for a moment. Wrap the content you are testing with your utmx section and noscript tags as normal. At Moneyspyder, we are considering implementing later versions of this script library with the ability to 'document.write' the utmx sections based on matching dom elements by id or class. We'd be interested to hear your thoughts on this. Less code is better, right?
So, assuming your test is set up you should now have a page that mirrors the format of http://moneyspyder.co.uk/ms_ga.html:
Viewing this page and inspecting the HTTP Headers output will reveal the following requests:
ga.js (Google analytics script library from Google)
siteopt.js (Website Optimiser script library from Google)
utm.gif requests
The request to siteopt.js will pass in values of your utmx and utmxx cookies if you have them so that you can see the same test variation you saw last time or, if you don't have the cookies, your test variation and utmx values will be set.
Having displayed the test variation content, your page will track the test view with a utm.gif request to the Website Optimiser UA account and the utmp value of the test id follwed by the string 'test':
utmp=%2F0102111525%2Ftest&utmac=UA-11-56683-1
The goal page follows a very similar format but just calls ms_wo_goal in the same way as ms_wo_tracking with the UA and k values:
ms_wo_goal(['UA-11056683-1'],0102111525);
And so the page is tracked as you will see by inspecting the HTTP Headers output for the utmp and utmac values.
Wrap up
So, we have seen how the javascript supplied by Google for page tracking, transaction tracking and website optimiser testing is totally 100% fit for purpose and great to use. But with a little thought we can afford ourselves a little more power, maintainability and ease of use. We have cleaner pages and can handle change a little better.
If these articles help you implement good quality Google product integrations then we have a success. If you want to take this work further for your own sites, great but remember it's good to share! If you want to challenge this work, feel free to leave comments or drop us a line at info@moneyspyder.co.uk - we'd be happy to exchange ideas!
Posted by
Doug Halll
at
07:12
0
comments
Links to this post
Google analytics: easier transaction tracking
Overview
In my previous posts I introduced the idea of externalised javascript libraries to abstract over Google Analytics page tracking.
This idea also transfers nicely into Google Analytics transaction tracking where, it seems, most people seem to come unstuck.
We'll try and get you stuck back together!
Caveat
These articles assume you are at least familiar with the concept of javascript, Google Analytics tracking and the Live HTTP Headers plugin in FireFox.
As with the last posts - use these scripts at your own risk. Don't link to the script libraries directly, copy and tune to your own needs!
Simple transaction tracking made simpler
Take a peek at the transaction tracking example
Thanks for buying stuff! No, seriously, even though the page looks as unspectacular as the Page Tracking Example you have actually registered a (fake) transaction with Google Analytics for a t-shirt and an indoor frisbee.
Take a look at the page source. We're using ms_ga.js again. The method we are interested here is ms_ga_trans.
Notice the source does not track a page view! That'll be taken care of for us by the method.
ms_ga_trans takes three parameters: an array of UA accounts, a URL and a data structure representing the transaction.
The array of UA accounts enables us to track the transaction in any number of Google Analytics accounts. The URL is nullable so we can track the transaction page as a specific URI or just use the default. The transaction data structure mirrors the structure set out in the Google Analytics Transaction tracking documentation.
A transaction requires:
an order id
an affiliation
a shipping value
a tax value
a total value
a country, city and state
Clearly an order also requires one or more order items. Each item consists of:
the order id
a sku code
a name
optionally, a category (very useful)
a unit price (how much for one?!)
a quantity
Now, I'll stress this point about numerical values here. Do not include currency symbols. It is really important that when specifying a price or tax value or shipping value that you specify the value as a number to two decimal places. That is all. Not:
$45.00c
or
£345.567
or
[£9.99p]
or similar.
Just go for the simplest option which is (for example),
9.99
and stick it in quotes - everything is a string. Simple. No fuss. No complexity. If something is free, list it as 0. Don't miss out fields. You'll miss the wrong field and the script will fall over. With abstracted/externalised scripts and method calls you can build in more error handling and checking - handy!
So, inside the guts os ms_ga_trans we see a similar format to ms_ga_pagetrack where we iterate through the array of UA account values to track against:
ms_ga_trans(['UA-7862117-1'],'skeleton/thankyou',
{"order_id": "666666", "shipping": "5.95", "web": "moneyspyder.co.uk", "tax": "1.79", "total": "21.74", "country": "UK", "items": [
{"price": "6.00", "category": null, "name": "t-shirt", "sku": "t-1", "quantity": 1},
{"price": "8.00", "category": "home", "name": "indoor frisbee", "sku": "f-1", "quantity": 1}
]
}
);
We see that the page view is tracked here to - hence, we do not track the page separately. It is important to track the page view before recording the transaction.
The transaction is then added using the ga.js addTrans method. Each item in the transaction is then added and finally the transaction is tracked.
So, there isn't that much that is simplified here other than the order in which the steps happen and the opportunity to build in more error checking and handling. If you've got these basics right - well done. You want to know the transaction has registered though, right? Real time? Right, thought so.
Debugging/Checking/Testing
Reload the page with our new best friend Live HTTP Headers looking over our shoulder so we can review what happened under the hood.
First of all, no surprises, ga.js loaded.
Then we track the pageview with utm.gif
Take note of the third section in the HTTP Headers output - there is a new utm value called utmtid and it has our transaction id, '666666'. Cool - transaction being tracked with expected values! Okay, so we can see the total in utmtto, the tax in utmtx, shipping in utmtsp etc.
Each follwing section details each order item. utmut=item, utmipn for the item name, utmiqt for the quantity. Real self explanatroy stuff when you know where to look and what to look for.
Never have a transaction fail to track ever again!
Thats should do for this article - next time we Optimiser our website with Google Website Optimiser - but simpler. ;-)
Posted by
Doug Halll
at
07:10
0
comments
Links to this post