Datalicious Blog - Data Driven Marketing
Filed under

web

 

Testing Javascript code live in production without affecting live traffic

Save yourself some time, reduce your frustration, remove code deployment risk and improve your insight by using our technique to quickly test and deploy new web analytics code on your site without the need for staged testing.

Fear driven motivation ...

Quite frequently we needed to test site updates on a staging server for fear of breaking the production site, upsetting customers and losing revenue. This seems like a really good idea, except that when the files are pushed live things don't always happen quite as expected. Staging sites are never the same as production, we've seen perfect copies have issues with cookies due to the different domain, poor version control, different asset location and other network issues like load balancing amongst a range of other problems, the bottom line is they are never the same, period. 

In addition to the testing issues, we also need to deal with the fact that assets like Javascript are cached by some browsers. Code roll outs are not immediate, but dribble out over a period of up to a month as browsers invalidate their cache. This is a scary proposition for people relying on the analytics data, especially when frequent updates are required. 

Efficiency driven motivation ...

In addition to this, for many of our clients (e.g. banks) we have rare deployment windows as far as 6 months in the future (yes this is not an exaggeration) and aren't allowed to test code outside their building. We have other clients where we need to send them code and wait for a testing response when they can allocate the resources. The feedback loop becomes very slow and sometimes very minor code issues can cause significant deployment delays. The loss in revenue and general inability to find answers to key business questions in a timely manner cannot be underestimated.

Our background is in analytics and strategy, so we're usually dealing with Javascript files for tracking purposes, but the same issues occur with all asset based code updates. We want a simple means to test and deploy new code without making any on page changes or requiring testing in a staging environment. Maybe i'm lazy, but i don't want to test the same code twice! This initially sounds a bit ambitious, but it's actually pretty simple.

The solution ...

We use a single controlling file to include all other Javascript assets. The single file has the ability to switch between different Javascript file versions based on the existence of a cookie (created from a URL parameter when testing is required). This single file is also utilised to control the file version of the asset files without making any on page changes.

Advantages

  1. No on-page changes are required for Javascript updates EVER
  2. All updated files roll out instantly to everyone, there is no caching lag. Roll backs are just as easy.
  3. Testing on the live site can be performed without ever affecting a single other user. Staging sites are not required.
  4. Testing can be performed remotely (wherever the production site is accessible).
  5. Risk of web site down time or customer irritation is greatly reduced.
  6. Time to go live is significantly reduced.
  7. Development costs are significantly reduced.
  8. Javascript file names can include a version number, this greatly reduces confusion around version control.

Implementation

If you know Javascript and you're looking for an example, check out below. If you need more explanation, then drop us a line.

A. CONFIG
- Production server base location (e.g. www.client-site.com/js/)
- Test Server A base loca tion (e.g. www.your-live-test-site.com/client-folder/js/)
- Test Server B base location (e.g. www.client-site.com/js/live-test/). Maybe they want to test too!
- File version (or name, e.g. scode-v1.js)

B. DEFINE INCLUDE FUNCTION and OTHER BASE FUNCTIONS
These functions include setting and retrieving cookies, reading URL parameters into variables and including other javascript files.

function gqp(name){name=name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");var regexS="[\\?&]"+name+"=([^&#]*)";var regex=new RegExp(regexS);var results=regex.exec(window.location.href);if(results==null)return"";else return results[1];}
function setCookie(c_name,value,expiredays){var exdate=new Date();exdate.setDate(exdate.getDate()+expiredays);document.cookie=c_name+"="+escape(value)+((expiredays==null)?"":";expires="+exdate.toGMTString());}
function getCookie(c_name){if(document.cookie.length>0){c_start=document.cookie.indexOf(c_name+"=");if(c_start!=-1){c_start=c_start+c_name.length+1;c_end=document.cookie.indexOf(";",c_start);if(c_end==-1)c_end=document.cookie.length;return unescape(document.cookie.substring(c_start,c_end));}}return"";}
function include(filename){document.write(unescape("%3Cscript src='" + filename + "' type='text/javascript'%3E%3C/script%3E"));}


C. ADD LIVE TESTING FUNCTIONALITY
Some example code is shown below. The test URL parameter we're looking for is called "datalicious". So a URL like http://www.client-site.com/?datalicious=test will trigger the code to include from the test location instead of the production server. The default production code base is stored in a variable called "datClientCodebase"

var datURL=document.location.href.toLowerCase();
datTest = gqp('datalicious');
if (datTest == 'test') {
    setCookie('datCookie', 'test', 1);
}
if (datTest == 'client-name') {
    setCookie('datCookie', 'client-name', 1);
}
datCookieValue = getCookie('datCookie');
if (datCookieValue == 'test' || datTest == 'test' || datCookieValue == 'client-name' || datTest == 'client-name') {
    // This will use the test files on your server folder livetest
    if(datCookieValue == 'test' || datTest == 'test'){
        var datCodebase = '//www.your-server.com/client-name/js/livetest/';
    }else{
        // This will use the test files on the client-name server folder livetest
        var datCodebase = '//www.client-name.com.au/js/livetest/';
    }
} else {
    // Your server will use the production dir (this is done so you don't need a different file version on your
    //site), otherwise the client code base is used, which is the default normally
    if (datURL.indexOf('your-server.') > -1) {
        var datCodebase = '//www.your-server.com/client-name/js/';   
    } else {
        var datCodebase = datClientCodebase;   
    }
}

D. INCLUDE THE FILE
The following line of code takes the base file location and the file name (version), combines them and requests the desired file.

include(datCodebase + datScode);

E. TRIGGER
Now the file has been included, if there are any analytics functions, like with the Omniture scode, or google analytics page tracker, this part of the code can decide when these functions are executed. Normally we have conditions here so the function can be triggered at either the top or the bottom of the body.

F. CALL THE CONTROLLING FILE
Your web sites can now include this base file, but we recommend you use a cachebuster to ensure any updates you make the to base file propagate in a timely manner (we use 24 hours, but you can set to whatever you want). A code example is shown below, this would appear on all site pages:

<!-- BEGIN CACHE BUSTER -->
<script type="text/javascript">
var cacheBuster="";
var cbd=new Date();
var cbm=new Date();
var cby=new Date();
cbd=cbd.getUTCDate();
cbd=cbd.toString();
cbm=cbm.getUTCMonth()+1;
cbm=cbm.toString();
cby=cby.getUTCFullYear();
cby=cby.toString();
cacheBuster=cbd+":"+cbm+":"+cby;
</script>
<!-- END CACHE BUSTER -->

<!-- BEGIN INCLUDES -->
<script type="text/javascript">document.write('<scr'+'ipt type="text/javascript" src="//www.client-site.com/js/datalicious.js?cb='+cacheBuster+'"></scr'+'ipt>')</script>
<!-- END INCLUDES -->

Email Hamish at hogilvy@datalicious.com if you need help with your implementation.

Loading mentions Retweet
Email this post
Filed under  //   analytics   best practice   code   customization   google analytics   hamish   javascript   ogilvy   omniture   site catalyst   tips   web  
Posted by Hamish Ogilvy 

Comments [0]

How to ensure Google Analytics goal values are accurate when using Windows IIS web servers

When running Windows IIS as your web server, you might find that the issue of upper and lower case URLs can very annoying and troublesome.

Windows is a case insensitive OS, meaning test.html and Test.html are actually physically the same file in Windows. However, in Google Analytics they will by default be recorded as two different pages if you don't do something about it. The following screenshot shows an example of the folder '/candidates/' and how it is tracked as two different folders simply because of the case sensitive issue.

It's very easy to fix the problem. All you need to do is to setup a filter in your Google Analytics profile to convert all the URLs into lower case or upper case. To do that, login to Google Analytics and click on Filter Manager, then add a filter as shown in the following screenshot. This filter will turn all URLs in Google Analytics to lowercase eliminating the duplication on the content and goal reports. Please note, this only works form the moment you create the filter and not in retrospect.

We recommend that all websites running on Windows IIS should have such a filter to avoid the problem caused by case sensitivity.

Loading mentions Retweet
Email this post
Filed under  //   goals   google   google analytics   how to   iis   server   tutorial   URLs   web  
Posted by Chaoming Li 

Comments [0]

Alertbox: Content consumption on the web vs. TV, what to consider

Another awesome article form Jakob Nielsen's Alertbox, especially the stats on how many decisions we make online vs. when watching TV which has serious implications for online advertising and website usability.

Today, of course, we're in the opposite scenario: everything we write competes with trillions of Web pages, all a few clicks away. As a result, most people actually read very few words on the Web.

The velocity of media consumption has increased dramatically. Readers no longer linger over lovingly described passages detailing a lord's style of dress. They click here, they click there, they click everywhere. But they don't stay.

People's consumption of print media is different than their use of websites, leading to the many differences in designing for print versus the Web.

Compared to TV, the Web also has a much finer granularity of user control:

When watching TV, you make one decision every 30–120 minutes: pick a show or movie to watch, and then it's lean-back time. Ah, easy.

When surfing the Web, you make a decision every 10–120 seconds: leave or stay on this page; leave or stay on this site. Where to click now? Where to click next? A bit stressful.

Adding up all these differences explains the fast pace of Web use: the velocity is much higher than we see for TV use.

Read the original Alertbox article here
http://www.useit.com/alertbox/media-velocity.html


Loading mentions Retweet
Email this post
Filed under  //   alertbox   christian bartens   consumption   content   trends   tv   usability   web  

Comments [0]

InteractionConsortium: Great interactive visualisation of Australian' web history

Check out the below interactive visualisation of Australian' web history form the InteractionConsortium to see how traffic volumes and audience sizes have changed for major Australian sites over the years.

http://avant.interactionconsortium.com/australian_internet/


Loading mentions Retweet
Email this post
Filed under  //   australia   christian bartens   history   interactionconsortium   online   traffic   trends   visualisation   web  

Comments [0]

MultichannelMetrics: Cool interactive flow-chart to trouble shoot drop in traffic or conversions

Check out MultichannelMetrics's interactive flowchart if you're experiencing issues with a drop in traffic or conversion rates, it's a great starting point to figure out what to do.

Click on the below link to get to the interactive version of the chart

http://multichannelmetrics.com/WebAnalyticsQuestionSupportSystem/WebAnalyticsQSS.html

Loading mentions Retweet
Email this post
Filed under  //   analytics   conversion   flowchart   guide   multichannelmetrics   optimisation   tools   tutorial   web  

Comments [0]

Top five tips for deploying Omniture Site Catalyst Javascript

Below are some pretty basic tips to Site Catalyst setup, they may seem straight forward, but i am continually surprised at how poorly Omniture is set up, so maybe they're not so obvious!

1. Have one scode file

Duplicating the scode file is painful and you will eventually make mistakes. Keep all your code in one file.

2. Use a cachebuster

This will ensure your javascript code updates propagate quickly. Otherwise your existing users may not reflect the changes, which can complicate and confuse reporting. A cachebuster automatically adds a parameter to the end of the javascript file reference, which forces it to be reloaded. i.e. scode.js?cb=1234

3. Make it protocol independent

Don't put "http:" in your file reference, this will allow the javascript to work for either http or https. i.e src="//www.example.com/js/scode.js"

4. Use the s.pageName variable properly
This is by far the most important thing to set, i can't even stress that enough. Any extra effort to get it right is worth it. Your pageName should preferably follow a set structure so your javascript can utilise it fully. If you get this right, your reports will immediately become more powerful. We typically follow a structure like the following:
site:sub-section:sub-sub-section:sub-sub-sub-section

This should follow the site directory structure where possible. i.e. www.site.com/sub-section/sub-sub-section/sub-sub-sub-section

By breaking this up and putting it into several props and eVars, you will be able to look at success events at a site, sub section, sub sub section and sub sub sub section level, which is very useful. You will also be able to trigger certain events based on these values. Code example below, which should also be copied from props to eVars:

var scSection=s.split(s.pageName,':');
s.prop1 = scSection[0];
if (typeof scSection[1] != 'undefined')
s.prop2 = s.prop1 + ":" + scSection[1];
if (typeof scSection[2] != 'undefined')
s.prop3 = s.prop2 + ":" + scSection[2];
if (typeof scSection[3] != 'undefined')
s.prop4 = s.prop3 + ":" + scSection[3];


The output of the above will be:
s.prop1 = site
s.prop2 = site:sub-section
s.prop3 = site:sub-section:sub-sub-section
s.prop4 = site:sub-section:sub-sub-section:sub-sub-sub-section

5.
Minimise the on page javascript
Any logic you can use to trigger events based on the pageName, the URL or section variables, will make things so much easier. If you can get code off the individual pages and keep all the logic in the scode file, you will greatly simplify any deployments and rollbacks. For some things you can't avoid putting code on individual pages, but it's suprising how often it can be avoided.

An example might be a segmentation rule that will label someone once they have stayed for at least 2 pages in a particular site section. For things like this, very small changes to the scode can be very powerful, if you paid attention to tip 1 above, they're also immediately site wide!

If you need help with your implementation, email Hamish at hogilvy@datalicious.com.

Loading mentions Retweet
Email this post
Filed under  //   analytics   code   customisation   hamish   javascript   ogilvy   omniture   scode   site catalyst   tips   web  
Posted by Hamish Ogilvy 

Comments [7]

Omniture Site Catalyst and Google Analytics custom variable comparison

Many online businesses don't really need the complex capabilities of Omniture Site Catalyst, Google Analytics is good enough to meet their requirements, or almost good enough. Omniture's custom variables are very powerful, but i would think the average utilisation that i observe (when we're not setting it up!) is less than 10%, which is interesting considering the cost. I've experienced the frustration of Google Analytics limitations, but I can also appreciate that for free it is a pretty nice piece of software. Both have their rightful place, so I thought it would be appropriate to illustrate the differences you need to consider before deciding which to deploy.

One of the interesting features of Google Analytics is the custom variable, which can be set to any value and then later used for custom segmentation. The functionality of this variable is different to Omniture though and unlike with Omniture's variables, it is not configurable. The key difference is is the way the value sticks. With Google, although it can be changed during a session, the value associated with reports does not change for the rest of that session, so it can effectively only be one value per session. If it's changed again during that session, subsequent sessions will reflect this new value, but the current session will not. For some things this is ok, but for other applications it is quite frustrating.

Summary of key characteristics

Omniture Variables

- Can be related to pageviews (i.e. they don't have to stick). These are called props
- Can be related to success events, like purchases, registrations. These are called eVars
- Can change during the session (or not if you prefer, first or last setting can be configured)
- Can be made to expire
- Can be configured to be stacked (this stores a sequence of values)
- Many variables available, so you can customise lots of different things at the same time

Google Analytics Variable
- Cannot change during a session (can change between sessions)
- Can be stacked using javascript
- Has nice custom segmentation tools which are easy and instant, unlike Omniture ASI segments

Which to choose?

If you have the cash and the resources to use Site Catalyst properly, their custom variables are far beyond Google Analytics, the two aren't even close. If you also consider many variables are important to your business, then Google will probably not get you where you need to go. But if you just want standard usage information and possibly only require one variable to perform some basic segmentation, then Google Analytics is for you. You can also stack the custom variable, which will buy you a little extra capability, but it's pretty clunky. If you need some advice, drop Hamish a line at hogilvy@datalicious.com.

Loading mentions Retweet
Email this post
Filed under  //   analytics   custom   google   hamish   ogilvy   omniture   site catalyst   tracking   variable   web  
Posted by Hamish Ogilvy 

Comments [0]

Adobe to Buy Omniture For $1.8 Billion

Adobe has announced the planned acquisition of Omniture, a leading web analytics software / solution provider. This is an interesting purchase for Adobe and a lot of analytics people out there will be wondering how this is going to change their landscape. Traditionally tracking flash has been a bit of a pain, you can bet that will change if this deal goes through. If it doesn't go through, Omniture will be paying $64 million for the privilege of withdrawing from the deal, but seeing as it's already progressed to a public announcement, you can probably bet it's going to go through.

Loading mentions Retweet
Email this post
Filed under  //   acquire   adobe   analytics   buy   hamish   ogilvy   omniture   software   web  
Posted by Hamish Ogilvy 

Comments [0]