If users consent to cookies on GOV.UK we can use Google Analytics to help improve our services and content for the millions of people that visit every day. We look at data on things like page views, link clicks and some element interactions, such as when a user clicks something to show or hide text.
For some high traffic pages, we also use scroll tracking. This blog post is about how we identified some problems with the existing scroll tracker and went about building a new one.
What is scroll tracking?
Scroll tracking is commonly used to show how much of a page has been read. Our scroll tracking can either tell us how many users have scrolled a certain percentage of the page or which headings they’ve reached.
This data can help us identify problems with content - for example, is the whole page being read, or just the first part? Are users missing out on important information that could be positioned more prominently? Do users engage differently on desktop and mobile?
Problems with the existing scroll tracker
We were looking at improving our foreign travel advice pages and adding scroll tracking to get more usage information was a sensible first step. Unfortunately this highlighted some problems with the way our current scroll tracker worked.
This was an untenable way to do scroll tracking both now and in the future, so we started thinking about how to make a new scroll tracker that would use a different approach.
How does scroll tracking work?
Determining whether an element like a heading is currently visible in the window or not is computationally expensive, and scrolling even a little way down a page can cause the scroll event to happen hundreds of times. Combined without consideration, these things could make scrolling down a page on GOV.UK unbearably slow for some users, which we had to avoid.
Instead, when the scroll tracker starts it begins by storing the positions of headings (and percentage positions) and using those numbers inside a throttled scroll event listener to reduce the load. Our new scroll tracker worked, but there were still some problems that we had to consider.
Problems to solve
If we pre-determine the position of things on a page (headings or percentage positions), we need to take account of the fact that the height of a page (and therefore the position of those things) can change after the page has finished loading. This can happen when the browser window is resized, or if a device is rotated, or if the font size or zoom level in the browser is changed. It can also happen when the user interacts with the page, for example by expanding a collapsed element or dismissing the cookie banner.
We only wanted to track headings in the page content, not headings in the footer or other common elements. We also needed to consider that headings might appear or disappear after a page has loaded, for example if they are inside collapsible content like an accordion.
We wanted to make sure that tracking occurs for any headings that are visible when the page loads, before scrolling occurs. This might be a different set of headings depending on what size device or browser window is being used. This would also be a different set of headings if the user was following a jump link to a point on the page that wasn’t the top.
Finally, for both heading and percentage tracking, we didn’t want to track things more than once, so we needed a mechanism for remembering what had already been tracked.
Our new scroll tracker
It also detects changes in page height and resizing of the browser, and recalculates everything appropriately. Finally, it uses fewer lines of code than the list of URLs to track in the old scroll tracker.
We successfully tested our new scroll tracker on the foreign travel advice pages and discovered that some users were missing important information, which led to some content changes. We then carried out a complete review of scroll tracking across GOV.UK. This resulted in the removal of scroll tracking that either wasn’t needed or wasn’t working properly, as well as some further improvements to the new scroll tracker.