Using JavaScript to estimate connection speed

Orde Saunders' avatarPublished: by Orde Saunders

An item very high up on the wish list for people building responsive sites is information about connection speed. This information is not made available to us by browsers but, by using JavaScript and timing information in the page, we can estimate it. Once we have this information we can then selectively load larger assets such as images.

This article walks through the approach developed during the responsive redesign of Tesco Bank and the implementation used on this site.

Tools

There are a number of tools that are used in this approach and, although not fully supported across all browsers, we can combine what's available to get the best result.

The Navigation Timing API gives us access to metrics of page load provided by the browser, including information about what happens before the page starts loading. This is by far the best source of data available to us and, in this instance, we will be using the difference between the request start and DOM ready which will give a good indication of a combination of network latency and time taken to download the page itself.

In page timers

As JavaScript date objects provide millisecond level precision we can put timers in the page to measure elements of page load with reasonable accuracy. The obvious disadvantage of this approach when compared to the Navigation Timing API is that it does not give us information on what happens before the page starts rendering. To get round this limitation I have done some research into how long an HTTP request takes so we can apply a reasonable approximation of adding 0.5 seconds to the in page timers to estimate the request time.

Connection type

Android exposes information on the connection type to the browser via navigator.connection.type. This provides us with a value that is one of 2G, 3G, WiFi, wired or unknown. Whilst this does not tell us directly about the connection speed we can use it to tell if we are on a mobile connection which is likely to be slow or bandwidth capped.

Session storage

The session storage API allows us to store information between page loads so, if it's available, we can use this to compare the connection speed over a number of page loads to get a better value. We could use cookies to fulfil this role if session storage is not available but I have chosen not to.

Methodology

First of all we need to set a threshold for the request time above which we class it as a slow load. I collect RUM data on a number of my sites and have used this to set a value of 2.5 seconds which I feel is reasonable. You should look at similar data from your own sites to determine the value you use for the cut off time.

Once we have the threshold time we gather the information from the page using the Navigation Timing API if present. If not, we use in page timers as discussed above to estimate the equivalent data.

We start with a default of a slow load time and then compare the time we measured for the request with our threshold time. If it is less than the threshold then we class it as a fast page load.

If session storage is available then we use it to store the last known page load speed. We set a threshold for a number of page loads over which we compare the load speeds. I have set mine to four so if the first four page loads are slow then the connection is classed as slow for the remainder of the session.

Finally, if the connection type is known, an override is set forcing 2G and 3G connections to be registered as a slow speed. Whilst this may not be completely accurate, we do know that the browser is using a network that typically has limited bandwidth and increased latency. When on a wired or WiFi connection we still rely on the timing information and do not assume a fast connection as they may be using a 3G to WiFi router or using a contested or limited broadband connection such as WiFi in a café or conference venue.

We now have a value for the connection speed as either fast or slow so we add this as a class hook to the <html> element and store it as an item in the profile which allows us to use this information to make decisions about which resources to load, either as part of our client side scripts or to send optimised content from the server.

Conclusion

By using timing information provided by the browser or calculated from in page timers we can estimate the speed of a user's connection and use that to modify the assets we request and serve. This means we do not try to send large assets (typically images) to users on slow connections thus providing them with a faster page load. When we know the connection is faster we can make use of this to send larger assets providing a richer experience where we know it will not significantly hamper the fundamental aspect of load speed.

Resources