SiteKickr Web Development

The back button cache – taming it with HTML 5

As a user, the browser back button is one of the most handy features of a web client. As developers, we wish it never existed.

Using the back button, in it's simplest definition, means to go back to the page we visited before the one we are currently on. But what exactly does this mean?

In the real world, it depends on the application. One of the most common areas of concern when it comes to the back button is within the shopping cart on e-commerce sites. When a user adds an item to the shopping cart, the number of items in the cart is typically shown in the header of the website, and updated with each item added to the cart.

But, what happens when a user adds an item to the shopping cart, watches the cart count increment by one, then they hit the back button. The cart count will be back to it's original number. This is because the browser has loaded the entire previous page from it's cache.

We're not talking about the browser's usual page cache, where it stores images and scripts in case you visit the website at a later date. This is a dedicated cache which specifically serves back/forward requests. Hence, the back button serves a page that is cached even "stronger" than a normal page cache.

If you're experiencing this issue on your site and think you're the only one, check out Amazon.com. Add an item to the cart, then hit the back button. Yep, it happens to the best of 'em!

Now, after you hit the back button on Amazon's site, hover your mouse over the cart count. You'll notice at that point that the count is updated. This will also happen after a few seconds, once the page has fully loaded. 

Amazon uses AJAX to update the shopping cart count. This technique has been around for a long time, and does the job well. But, it does it at the cost of another HTTP call. As there is no direct way to determine when the back button is clicked, that HTTP call needs to be run on every page request.

Luckily, there is another way.

 

Leverage HTML 5 Storage

We talked about how browsers using a stronger caching mechanism for back/forward operations, which usually involves going beyond storing the HTML, CSS & JavaScript, but actually saving the state of the DOM when the page was left (unloaded). So how do we get around this? Two things make this technique possible:

The usual AJAX technique that Amazon.com uses leverages point number 1 above. Because JavaScript is always executed (regardless of where it is loaded from), AJAX calls that are part of that script are executed as well. This allows JavaScript to update any page, even one that was pulled from the browser's back/forward cache.

As you may have guess from reading point number two above, our goal is to replace an AJAX call with a simple read/write to session storage. 

I'll present a very specific example that demonstrates this technique. In this example, we're tackling the issue above, where the back button shows an inaccurate shopping cart count.

  1. When an e-commerce site user adds an item to a shopping cart, they are then directed to the shopping cart page.
     
  2. The shopping cart page contains JavaScript which stores the current number of items in the cart to window.sessionStorage.
     
  3. All pages except the shopping cart contain JavaScript which retrieves the current number of items from window.sessionStorage.

     

 

Example

HTML in the site's header:

<div id="cart"><span id="cart-count">6</span> items</div>


JavaScript (jQuery)

(function() { 
    var items; 
    
    if (typeof Storage !== 'undefined') { 

        if (location.href.indexOf('/cart') !== -1) { 
            // on the shopping cart page only, store the text inside 
            // the cart-count element to sessionStorage

            items = $('#cart-count').text(); 

            window.sessionStorage.setItem('cartCount', items); 
        
        } 
        else { 

            if (sessionStorage.getItem('cartCount')) { 
                // on all other pages, load the cart count from
                // sessionStorage and drop it into the cart-count element

                items = window.sessionStorage.getItem('cartItems'); 

                $('#cart-count').text(items); 

            } 

        } 
    } 
})();