The Diffen Blog • How a Progress bar for AJAX requests helped increase conversions by 38%

The NY Times published an interesting article this week about how progress bars can make it easier for people to wait for computers to respond. This idea is not new; usability experts have long advocated their use. Developers and designers have even tried to have some fun with progress bars.

When we launched the Get from Wikipedia feature on Diffen, we wanted to make the wait bearable for our users and hold their interest. Our first progress indicator was just a a loading GIF. Here’s how we replaced it with an actual progress bar and increased conversions by 38%.

First, for those who don’t know, Diffen is like Wikipedia for comparisons. If you compare two entities on Diffen and there is no information about either of them in our database, the system tries to get the information from Wikipedia infoboxes. Here’s a 20-second demo of how it works:

The page makes an AJAX request to get information about each entity. The back-end needs some time to respond because different variations and misspellings of the entity name may have to be tried before finding the right Wikipedia page for it. Also, the Wikipedia page must be parsed to tokenize the attribute/value pairs from the infobox. (We can do a separate blog post on how this is done if there is interest.) When both AJAX requests are completed successfully, the attributes are lined up side by side and shown to the user.

How we implemented the progress bar

First we benchmarked the time it took for a typical AJAX request for entity information and found that the time varies from 3-8 seconds. So we needed a progress bar that could last as long as 8-10 seconds. That’s a pretty long time, which means we needed lots of status messages. 

The status messages in the progress bar are based on what the server is likely doing, not what the server is actually doing at that time (more on that later). The status messages we use are:


var progressStatuses = [
    "Searching Wikipedia",
    "Scanning search results",
    "Reading the right Wikipedia page",
    "Scanning the information box",
    "Preparing the info",
    "Preparing the info",
    "Receiving the info",
    "Almost there"
];

The server doesn’t really send any progress report to the browser. The progress bar isn’t real; it is only meant to placate the user and tell her the system is working on her request.

A word about timing

The easy way to make progress is to increment to the next step at a set interval, say 1 second. But that is more likely to draw suspicion and give away our illusion of authenticity.

Another approach would be to progress through the initial 3 stages really fast to get the user hooked, and then gradually decelerate the pace of progress.

Instead we try and use intermittent variable rewards, known to be more pleasurable and addictive. The basic idea is that random reinforcement is more addictive (because it is more pleasurable) than consistent, predictable reinforcement for the same activity. We spend a random amount of time - between 500 and 1500 milliseconds - at each stage.

function makeProgress (reset){
    var div = $("#progressIndicator"),width=0;
    if(div.length==0)
        return; //Operation complete. Progress indicator is gone.
    if(reset)
        div.width(0);
    else
        width = div.width();
    if(width < 300){
        width += 45; //make the bar progress
        div.width(width);
        $("#progressStatus").html(progressStatuses[(width/45)-1]+'...');
        var delay = Math.floor(Math.random() * (1500 - 500 + 1)) + 500; //A random number between 500 and 1500
        setTimeout(makeProgress, delay, false);
    }
}

That’s pretty much all we need for the progress bar. The initialization code is somewhat like this:

    
function importFromWikipedia(){
    setTimeout(makeProgress,100,true); //start the progress bar
    $.getJSON("/call/to/backend/script/for/entity1",fnOnSuccess);
    $.getJSON("/call/to/backend/script/for/entity2",fnOnSuccess);
    function fnOnSuccess(data){ 
        //Did we get information about both entities or only one? 
        if(bothReceived){ 
            showTheComparisonChart(); 
            $('#progressIndicator').remove(); //helps us break out of the makeProgress() recursion
        }
        else {
            //Mark one entity as complete and wait for the other one         } 
    }); 
} 

First, we initialize the progress bar. Then we make the AJAX requests to the backend. When both requests are completed, we remove the progress indicator and show the comparison chart.

It is not necessary to loop through all 7 available progress status messages and “complete” the progress bar visually. If the user only sees the first 3 before the request completes, she is not going to care. In fact, if she notices it at all, she is likely to be delighted that the operation finished quicker than expected. 

It’s not very pretty, but this progress bar is quite functional. When this progress bar replaced a loading GIF we saw conversion rate (as measured by the weekly number of new entities imported from Wikipedia and saved to our database) increase 38%. 

Discuss on Hacker News