Scroll Tracking with Google Tag Manager

Almost a year ago LunaMetrics posted a great scroll tracking script for Google Analytics. I won’t get into details why to implement this tracking and what are the benefits from it (you can read that in the original LunaMetrics article). Instead I’ll show you how to implement this scroll tracking with Google Tag Manager step by step.

Step One – the Scroll Tracking Script

First – we start with an HTML tag, containing the JavaScript for the scroll Tracking. I borrowed the Lunametrics script and modified it to work with Google Tag Manager.

Copy the following script and paste it in new HTML Tag:

  (function (window) {
    'use strict';

        var cache = [];
        /* inArray function borrowed from:
         * jQuery 1.10.1
         * */
        function inArray(elem, array) {
            var i, length;
            for (i = 0, length = array.length; i < length; i++) {
                if (array[i] === elem) {
                    return i;
            return -1;

        /* Each function borrowed from:
         * jQuery 1.10.1
         * */
        function each(object, callback) {
            var name;

            for (name in object) {
                if (object.hasOwnProperty(name) &&[name], name, object[name]) === false) {
        /* Throttle function borrowed from:
         * Underscore.js 1.5.2
         * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
         * Underscore may be freely distributed under the MIT license. */
        function throttle(func, wait) {
            var context, args, result;
            var timeout = null;
            var previous = 0;
            var later = function () {
                previous = new Date;
                timeout = null;
                result = func.apply(context, args);
            return function () {
                var now = new Date;
                if (!previous) {
                    previous = now;
                var remaining = wait - (now - previous);
                context = this;
                args = arguments;
                if (remaining <= 0) {
                    timeout = null;
                    previous = now;
                    result = func.apply(context, args);
                } else if (!timeout) {
                    timeout = setTimeout(later, remaining);
                return result;
        function calculatePercentages(docHeight) {
            return {
                '25%': parseInt(docHeight * 0.25, 10),
                '50%': parseInt(docHeight * 0.50, 10),
                '75%': parseInt(docHeight * 0.75, 10),
                // 1px cushion to trigger 100% event in iOS
                '100%': docHeight - 5
        function checkPercentages(percentages, scrollDistance) {
            each(percentages, function (key, val) {
                if (inArray(key, cache) === -1 && scrollDistance >= val) {
                  var gtmScrollDistance = 'Scrolled ' + key;
                  dataLayer.push({'event':'scrollTracking','scrollDepth': gtmScrollDistance});
        window.onscroll = throttle(function () {
           * We calculate document and window height on each scroll event to
           * account for dynamic DOM changes.

            var body = document.body,
                html = document.documentElement,
                docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
                winHeight = window.innerHeight || html.clientHeight,
                scrollTop = body.scrollTop || html.scrollTop,
                // recalculate percentages on every scroll
                percentages = calculatePercentages(docHeight),
                // see how far we've scrolled
                scrollDistance = scrollTop + winHeight;
            // if we've fired off all percentages, then return
            if (cache.length >= 4) {
            // check for percentage scrolled and see if it matches any of our percentages
            checkPercentages(percentages, scrollDistance);
        }, 500);


The default setup of the script is tracking 0%(Baseline), 25%, 50%, 75% and 100% scroll activity. If you want to use other fractions (for example – 10, 20, 30…) you just need to modify rows 67-69.

Step Two- the Scroll Tracking Trigger

While in most cases your guts tell you to add “All Pages” as a trigger for your HTML tags – I prefer to use the Windows Loaded event, so the script won’t slow down your website loading speed. Doing that is easy – just create a new trigger with the built-in Windows Loaded option:

gtm.load trigger in Google Tag Manager

I use gtm.load as name of the trigger, but you could give it another one. You can save the tag now.

Step Three- the Scroll Tracking Variable

Now, as you have your HTML tag it’s time to send the data to Google Analytics. To do that you first need to setup a variable which collects the percentage of the scroll, that is pushed on rows 4 and 88 of the scroll tracking script. Create a new Data Layer variable and use ‘scrollDepth’ as Data Layer Variable Name:

GTM Scroll Tracking - varible

Step Four- the Scroll Tracking Trigger

That’s an easy one – you just need to create a Custom Event trigger to fire the Scroll Tracking Event:
GTm Scroll Tracking trigger The name of the event should be ‘scrollTracking’, as it’s defined in the script. If you want to use another name you should tweak the script in row 4 and 88.

Step Five- the Scroll Tracking Event

Now you have everything ready to send to Google Analytics. You just need to create Google Analytics Event tag and fill the fields as follows:
Scroll Tracking Event in Google Tag Manager You can put any name in Event Category, for Event Action add the Data Layer Variable you just created earlier and for trigger of the tag use the previously added custom event trigger. For Event Label you can add anything (or nothing at all). I always add the GTM Built-in variable {{Page URL}} as a back up of the Page Dimension.

Don’t forget to add ‘True’ in the ‘Non-Interaction Hit’ Dropdown, as if it’s set to the default “False” this event will disrupt your Bounce Rate.

Publish your Scroll Tracking!

If you did everything from this article your scroll tracking should be ready now. Debug the tags and if everything works properly just Hit the “PUBLISH” button.
Happy Analyzing!

Check these related articles:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.