PicNet Custom Software Development

.Net and Javascript Development

Split Testing (A/B Testing) in ASP.Net Mvc

Posted on clock May 11, 2010 10:21 by author guido

Working on our website heat maps product, Mouse Eye Tracking, has allowed us to really get into some of the more lean and super agile approaches to developing software.  Something that we have loved doing recently is Split Testing (or A/B Testing). Its really amazing how much time you can save when using techniques like this.

Basically for our heat map product we try every deployment out before investing huge amount of time into it.  For example.  We wanted to see if the features video could be made more prominent.  So what we did is created a page for this approach, published it and compared results.  We realised that this in fact was a waste of time and left the page exactly as it was.

There are plenty of products out there that allow you to do AB testing but most of those are CMSs which is useless when your site is in a server side language so what we use is a custom ASP.Net Mvc solution that works a real treat.  It's this solution that I hope to describe in this post.

SplitABController

The brains of the whole operation is a new controller (descendant of System.Web.Mvc.Controller) that allows you to provide multiple views for each ViewResult.  This is kind of hard to explain so why not just show some code:

 

    using System;

    using System.Web;

    using System.Web.Mvc;

 

    public abstract class SplitABController : Controller

    {

        private static readonly Results results = new Results();

        private const string B_TEST_SUFFIX = "_B";

        private const string SPLIT_TEST_VIEW_COOKIE_NAME = "SPLIT_TEST_VIEW_COOKIE";

        private static ViewFilesCache cache;

 

        public static Results GetSplitTestResults() { return results; }

 

        protected over ride void OnActionExecuting(ActionExecutingContext filterContext)

        {

            AddSplitTestResultsToResultsMap(filterContext);

            base.OnActionExecuting(filterContext);

        }

 

        private void AddSplitTestResultsToResultsMap(ActionExecutingContext filterContext)

        {

// If last request was not for a split test view then just return

            if (Request.Cookies[SPLIT_TEST_VIEW_COOKIE_NAME] == null) return;

 

// Add this controller/action to the results of the split test

            ResultRow rr = ResultRow.FromString(Request.Cookies[SPLIT_TEST_VIEW_COOKIE_NAME].Value);

            results.RemoveOneFromResults(rr);

            rr.ToControllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;

            rr.ToAction = filterContext.ActionDescriptor.ActionName;

            results.AddOneToResults(rr);                        

        }                

 

/// <summary>

/// If the view has a _B counterpart then we mark this action as a 'Split Test' we

/// then record the results of this split view in the next request (OnActionExecuting).

/// 

/// This method also determines if we should supply the A or B view depending on the

/// 'ShouldRequestUseBView' algorithm.

/// </summary>

        protected override ViewResult View(string viewName, string masterName, object model)

        {            

            if (String.IsNullOrEmpty(viewName)) { viewName = (string) RouteData.Values["action"]; }

            bool isSplitTestingView = IsSplitTestingView(masterName, viewName);            

// If this view does not have a _B counterpart then we mark this request as non split test (by

// removing the 'SPLIT_TEST_VIEW_COOKIE_NAME' cookie) and just send control to base.View

            if (!isSplitTestingView)

            {

                Response.Cookies.Remove(SPLIT_TEST_VIEW_COOKIE_NAME);

                return base.View(viewName, masterName, model);

            }               

// Wether to use the A or B view depending on the 'ShouldRequestUseBView' algorithm

            bool useb = ShouldRequestUseBView();

// Lets create a results row and store it in the cookie (SPLIT_TEST_VIEW_COOKIE_NAME). This will let the 

// next request (OnActionExecuting) know that we just hit a split test view.

            ResultRow rr = new ResultRow {FromController = this, FromAction = viewName, UsedBView = useb};

            Response.Cookies.Add(new HttpCookie(SPLIT_TEST_VIEW_COOKIE_NAME, rr.ToString()));

            results.AddOneToResults(rr);            

 

// Display the appropriate view (A or B)

            return useb 

                ? base.View(viewName + B_TEST_SUFFIX, masterName, model)

                : base.View(viewName, masterName, model);            

        }        

 

/// <summary>

/// Returns wether the specified view has a _B counterpart. 

/// </summary>

        private bool IsSplitTestingView(string masterName, string viewName)

        {

            if (cache == null) { lock (GetType()) { if (cache == null) { cache = new ViewFilesCache(B_TEST_SUFFIX); } } }           

            return cache.HasSplitTestingAlternative(this, masterName, viewName);            

        }

 

/// <summary>

/// If odd IP then use 'B' view.  This will give a ~50% A / B split.

/// </summary>

        private bool ShouldRequestUseBView()

        {            

            return Int32.Parse(Request.UserHostAddress.Substring(Request.UserHostAddress.LastIndexOf('.') + 1)) % 2 == 1;

        }

    }

 

Description

So what is this code doing, basically it checks if a view has a '_B' counterpart, i.e.: If there is an Index.spark and an Index_B.spark.  If the view does have a _B counterpart then we mark the request as a split test and on the next request we save the results of that test.

To use this code simply extend this controller rather than the standard System.Web.Mvc.Controller.

Download

I have created a very simple test project (which uses Spark View Engine) that you can download here.  

Once you get the project set up simply navigation to Home.mvc/Index (which has a '_B' view also) and you can click around there for a while.  You can then navigation to Home.mvc/SplitTestResults to see a sample of how the results are stored.

Disclosure

This code was ripped quite aggressively from a much more comprehensive library and is intended only to illustrate the technique described here.  I highly suggest you do not use the code in production until you are happy with its stability.

Potential

I have been using this technique now for 2 months and have found it a fantastic way to measure true user acceptance of new features.  I also know that there is no other open source solution for asp.net mvc that allows you to do split testing efficiently so if you would like to work with me on getting this code production ready as an open source project let me know and I'll be more than happy to spend a bit more time making this code a bit more robust and creating a project for it,

Thanks

Guido Tapia

PicNet Pty Ltd


Automatic Google Page Position Report

Posted on clock March 10, 2010 06:38 by author guido

Overview

The position of your website in the Google organic search is quickly becomming one of the most critical marketting measures.  This page/script will allow you to automate this process.

How To

  • Sign up for a google Ajax API Key (http://code.google.com/apis/ajaxsearch/signup.html)

- You will get a jsapi key from google, something like this

            'ABQIAXFEakaXw3_Fd-

zqqMhjDLzqaRTTser7lsytcEDBoz0jKRWQmOpxexR7x409podV88a5eoPr2KIvw8Ub3B'

 

 

            (Note this is not a valid key)

  • Download this html page/script and rename to .html (remove .txt extension)

  • Open this page in a text editor (note pad is just fine)

  • Replace <YOUR JSAPI KEY> (Line 53) with, you guessed it, your jsapi key.

  • On line 59 you will see the configuration for this file, you will need to change the following items

- lookfor (Line 66, 78, 87).  These tell the script what to look for in the url and youtube title.

 

- On line 75, replace "Sydney, NSW" with a location that you think some of your clients would be searching from. 

  • On line 228 the lookup table rows begin.  You can add as many rows as you wish here.  The rows must be in the format (replace <Search term or phrase>):


<tr><td><Search term or phrase></td></tr>

  • You can have headers by adding rows in this format:


<tr class='header'><th>This is a header row</th></tr>

  • Open the file in your browser and click 'Run Report'


Thats it, when the table is working you will get something that looks like this:

 

Let me know if you have any problems with this.

 

Thanks

Guido Tapia

Manager - Custom Software Development

PicNet Pty Ltd


How to make money from your website or blog using adsense and intelligent add placement

Posted on clock February 15, 2010 10:11 by author guido

Overview

This article will try to show you how best to maximize the income generating potential of a blog or a website by focusing on placement and settings of your advertisements. We will be using a new free service called Mouse Eye Tracking. This service allows you to see exactly how users interact with your website so it's a great tool for analyzing the placement of your AdSense adds.

Background

Making money from a popular blog post or website used to be fairly straight forward, you concentrated on having great content and the high revenue per click of online advertisement used to do the rest. Now days making a few dollars from a blog or a hobbyist web site is much harder and we have to start considering such things as:

  • Add placement, size, location
  • Look and Feel of the adds
  • The way the adds interact with the site content
  • Etc

Add Placement

If you are serious about making a few dollars from your website you unfortunately will need to invest some time trying out different placements for your adds, there is unfortunately no way around this. I will try however to show you that this can be a pretty easy process and hopefully help some of you make a dollar or two.

Analyzing your current add strategy

The first thing you need to do is register for a free account for the PicNet Mouse Eye Tracking Service. This will give you a code that needs to be inserted somewhere inside the body tag of your page. Note: This code does display a small message 'Mouse Eye Tracking by PicNet...' so ensure you style this message in such a way that it does not intrude on your content. Now let's look at the analysis of my blog with this tool.







As we can see, I had my add placed at the bottom of my screen and I was just using the standard look and feel of the AdSense adds. We can also see that NO ONE paid the adds any attention at all this day (this heat map shows a 24 hours period). So looking at the heat maps we can see that most of the activity is at the top of the screen and the right column.

Now I think I will try placing the add on the right hand side of the screen. This will allow the main content of the blog to still be the main player in the page but also make the adds more effective.

I left this for another 24 hours and this is the results



We can clearly now see much more activity in the adds now.
Now, I think I am happy with the position of these adds however they are taking way too much room and they are actually making it harder for users to use my side bar (you can see that by the lower activity in the side bar). So lets make the adds smaller, better looking and lets wait another 24 hours.



We can now see a lot more activity around this area. It appears that the smaller advertisement has made the add blend in a bit better with its surrounds. This may be why there is much more activity around the add region. In fact doing a click only analysis shows us that we have indeed had a few clicks.



Well, thats it. Hopefully this article helps you make a few more dollars from your blog/website. Please let me know how it goes with the usage of the Mouse Eye Tracking service as any feedback is welcome at the moment.

 

Guido Tapia

Manager - Custom Software Development

PicNet Pty Ltd


GWT in a .Net environment

Posted on clock February 3, 2010 04:11 by author guido

Hi All,

As you know we have recently release the PicNet Mouse Eye Tracking service. This project is by far the largest Javascript centric application that PicNet has developed. This led us to do a lot of research on what technologies we would use for generating a maintainable javascript project.

We were restricted to having a .Net backend as that is what our existing infrastructure supports and its the technology where we live most comfortably. So the decision for the backend was simple, ASP.Net Mvc (w/ Spark View Engine) + NHibernate.

But now came the more complex decision of the client code (javascript). Do we stick to standard jquery code minified in our continous build? do we create our own bootstrapping js framework to easily allow OO in js? Do we leverage other such frameworks?

We ended up investigating a lot of different options but this article focuses on one of these which is GWT.

Javascript development is hard, anyone that tells you otherwise thinks javascript development is for creating roll over buttons. JS development is hard for various reasons.
  • The language is very flexible and it gives you all the rope in the world to ...
  • At the heart of the language is the function. This is a concept that is difficult for most OO devs to wrap their heads around
  • Performance is such a huge issue, compared to server languages
  • Code size (and design) is a big issue
  • Finally and most importantly is: The tools for javascript development are useless in comparison to other languages
The last item is huge. I mean with Java you use Eclipse or IntelliJ to manage your projects, builds, deployments, code analysis, error reporting, debugging, syntax highlighting, unit testing, code completion, refactoring, etc, etc, etc. For .Net you have Visual Studio giving the same support. Now try this as an experiment. Write a simple app in Java or .Net using notepad! That is what javascript development is like, regardless of language features, performance, etc. The tools issue is a killer.

GWT is a great framework and I would comfortably say, its the best framework for javascript development available. The reason it is the best framework is the fact that you can use good tools (Eclipse, IntelliJ, etc), it also removes alot of the Javascript hacky mentality required for writing fast javascript (but thats a secondary benefit in my opinion). Now for .Net developers learning to use Eclipse, etc is a bit of a pain but from a maintainability issue, if you were developing a solely javascript application it is definatelly worth the effort. HOWEVER!! Having a client (javascript) / server (.Net) application written in GWT / .Net has huge drawbacks. It is actually so painful that we finally decided to abandon the attempt.

How do you do it
Well our service is a very complex html page with a very large javascript component. The html file we generate using Spark View Engine. This lets us modularise the html into nice little controls that are easy to work with. This is where we encounter our first GWT hurdle. To use GWT you have to have the html in the hosted server, well that's not true you could compile the javascript and stick it in your ASP.Net application and not have html in Java however if you cannot use GWT in hosted mode it is not worth using (My own opinion).

What does this mean? Well, basically it means that you have to view the source of your html and copy into your GWT environment. Thats correct, change html you need to remember to copy paste into GWT env every time. We tried doing crazy things like having iframes pointing to the ASP.Net app from GWT environment with cross domain policies, etc but this always failed.

Ok, this is a huge maintenance issue, however if this were the only issue I think we still would have used GWT given its previously described benefits.

Second issue!! Talking to the server. This issue actually has a few parts, the first is serialisation. GWT offers a few optimised serialisation mechanisms such as XML and JSON (and a custom one). Since our application used plain strings for its communications, rolling up our own XmlHttpRequests from GWT was no problem (we do this for performance reasons). So this was no big issue at all. The second issue is authentication. To use our application you must be logged in so in development mode we had to add a hack that would recognise GWT development requests and simulate a user, Ughh!! Still not a huge issue but getting bigger. And finally the last issue is the fact that to use GWT with a .Net backlend in development you have to use a proxy server. No problem here is a great article describing how to set this up. Now it is difficult to describe the development process here but I will try.
  • Start the hosted mode server
  • Oh forgot to copy the new html
  • Copy the html
  • Restart hosted mode
  • Crash!!
  • Hughh?
  • Oh, a crash on the .net side
  • Done, try again
  • Hmmm yes it does look better with that border
So you get my pain?

So my conclusions. GWT is awesome!! Enough cannot be said about how good this toolkit is but it is still too painful to be a real alternative in a .net application.

Guido Tapia

Manager - Custom Software Development

PicNet Pty Ltd


Mouse Tracking vs. Eye Tracking

Posted on clock February 3, 2010 02:28 by author guido

Note: I tried to make this article as unbiased as possible but being the father of a newborn mouse tracking service I highly doubt I achieved this. So please read this with an open mind and feel free to research both solutions.

Since the limited release of our Mouse Eye Tracking service we have had great feedback and we are now more excited than ever in future of this product. However some criticism has been raised over the statistics quoted on our product page, this critisism however came from employees of Eye Tracking companies so I take their comments with a grain of salt. These comments however led met to investigate the differences and benefits of each technology, that is, eye tracking and mouse (virtual eye) tracking. This blog is the result of that research.

Note: I will not describe the ultimate goals of both these approaches which is improved usability and increased marketing value of your online presence.

Firstly let me try to illustrate what I believe to be the pros/cons of each technology (Please comment if you believe I have missed anything):

 Eye-TrackingMouse [Virtual Eye] Tracking (MET)
Cost Prohibitive to SME Free
Sample Group Small sample group of people who may not be the regular users of your site. If you want targeted sample group the costs are significantly higher (and sample group smaller). Real users to your site
Environment Sample group in a research room, conscious of their actions being monitored. Some eye tracking companies still use tracking glasses which make the sample group even more conscious of their environment. Even when not using glasses current technology means that the head has to remain relatively still and within a reasonable location (Don't lean back!!). Real users using the site normally with no knowledge their usage is being studied
Interpretation These companies usually provide analysis of results which is another addition to cost but it does provide you with insight that you may miss. Usually left to up to you. However PicNet does offer these services to customers that require it but since this is a technology comparison I will leave this red.
Used in mockups Huge costs Yes, for free and set up instantly.
Easy to set up Needs to be done by third party, requires expertise Can be up and running almost instantly
Accuracy Close to 100% Accurate representation of what the sample group is viewing. 84%-88% According to the only independent - scientific research I have found (http://portal.acm.org/citation.cfm?id=634067.634234).


Now, I think this table is redundant as it illustrates the obvious. But what I really want to do is dig into is the sample group issue. I think research done on a small unrelated group of uni students or unemployed people (huge costs otherwise) is a huge drawback to traditional eye tracking methodologies. For example. Let's say you sell integrated controllers for onboard computers. Do you think that an untrained sample group will ever show you how your real customers (engineers) navigate through your web site? Offcourse not, all they will do is show you the standard usability glitches such as banner blindness, Inattentional blindness, etc. You do not need to use any system to show you this, just read a usability book or a free Google search.

In a week of usage we have had web sites that have upwards of 2000 recorded user interactions on some pages. This is 2000 real customers showing you how they use your website in a real day-to-day environment. Now whether this is 88% accurate or 60% accurate or whatever figure you can find in the statistical abyss that is Google it does not matter. This is highly valuable information. Information that will allow you to make marketing and usability decisions with a very high level of confidence.

Now, don't get me wrong I still think that eye tracking is a very valuable technique for some companies out there but to say that mouse tracking is a 'lesser' offering I think is wrong. I initially did not think they competed (I actually thought it was the lesser/poorer option) but after researching this article I am now sure they do compete and my biased view is that the free alternative is better due to the 'real users' issue discussed here.

References:

http://glinden.blogspot.com/2008/01/cheap-eyetracking-using-mouse-tracking.html
http://research.microsoft.com/en-us/um/people/ryenw/proceedings/WISI2007.pdf
http://googleblog.blogspot.com/2009/02/eye-tracking-studies-more-than-meets.html
http://www.seobythesea.com/?p=874
http://www.tobii.com/archive/files/20040/EyeWatch_Using+eye+tracking+to+optimize+the+attention+path+of+advertisements.pdf.aspx
http://www.iua.upf.es/~jblat/material/hci/students09/topic1/SusanEyeMouseTrack.pdf
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.5691&rep=rep1&type=pdf
http://www.gmi-mr.com/documents/bylines/Quirks_Click-Testing_0408.pdf

Guido Tapia

Manager - Custom Software Development

PicNet Pty Ltd