Back in the mists of the mid-to-late 2000s, life was simple. Users had a keyboard and a mouse. They had a screen that was wider than it was tall and usually had a resolution of at least this by that. And they were online. Of course they were – how else would they load your page?
Nowadays nothing is sacred. People browse on their phones, turn them sideways, shake them, swipe, pinch, tap and drop them in the toilet. You have to accommodate it all (well, perhaps not the last one), but nothing is trickier than connectivity. Most of the time users are online. But sometimes they’re offline. I saw a guy on the (underground, offline) subway today, paging through some tabs he’d preloaded onto his iPhone. His experience wasn’t great – he tried loading up a photo from its thumbnail, but the full-size version wasn’t cached offline. He was looking at some related links, but couldn’t tap any of them. He closed the tab and moved onto the next one.
Now, I know what you’re thinking (apart from “wow, you creepily stare at people’s phones on the subway?”) – he should just download an app! Offline storage, background syncing – it’s the ideal solution. Except he wasn’t using one. Maybe it’s ignorance. Maybe he doesn’t like apps. Either way, we’re in the business of catering to users, not telling them that they’re wrong, so it got me thinking – how many people do this? Should I worry about this? I have no idea.
Getting an idea: the OfflineTracker
So, let’s track this. Where to start? Well, the good news is that browsers have implemented some new events on the window object – online and offline. They’re far from perfect. The only truly reliable method is to regularly poll a remote resource to see if you can reach it – like offline.js does. However, firing up a cell data connection every 30 seconds will drain a phone’s battery, and is A Bad Thing. So we’ll make do. I made a quick gist:
(in CoffeeScript, see it in JS if you like) with a concept for this tracking. It’s more of a proof of concept than production-ready code, but the general flow is this:
- User goes offline. We record the current date and time as the ‘start’ of our track, and store it in localStorage.
- User comes back online. We stop tracking, update the end time to be the actual end time, and run the function provided to send this data wherever we want it to go.
Now, there are a few holes in this. So, we also do the following:
- Update the ‘end of tracking’ time every 30 seconds. In theory we should be able to catch any and all events that would signify the end of tracking, but we can’t (what if the browser crashes? What if the user turns off their phone?). So every 30 seconds we update the ‘end’ of the tracking, and save to localStorage. If all hell breaks loose, our numbers will only be up to 30 seconds off.
- Hook into the Page Visibility API. This is an event that tells us when the user moves away from our page (usually by changing tabs). This is pretty crucial because it’s going to stop us tracking time when we’re offline and in an inactive tab.
- Provide a callback to the save function. We’re dealing with bad connectivity – we can’t guarantee that our data will get saved correctly. So we don’t delete our tracking data until the function runs the callback provided.
- Check on page load for any saved data. So when subway guy views your page offline, closes the tab and moves onto the next thing you can still recapture that data the next time he visits your site.
So, now you have the start and end times of user offline browsing sessions. What you do with it is up to you – maybe only 0.5% of your users access your site this way and you shouldn’t care at all. But maybe your user base consists entirely of cave-dwellers. Either way it would be good to know, right?