Last active
October 19, 2018 06:43
-
-
Save rmpel/b621b9bfbac819f2c2a411bd1cbcf15a to your computer and use it in GitHub Desktop.
Send event to Google Analytics on scrolling past certain points on a page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function($, w, d) { | |
| function autoDetectGA() { | |
| if (typeof _gaq !== 'undefined') { | |
| return 'ga'; | |
| } | |
| if (typeof ga === 'function') { | |
| return 'ua'; | |
| } | |
| if (typeof dataLayer !== 'undefined') { | |
| return 'gtm'; | |
| } | |
| return false; | |
| } | |
| var defaults = { | |
| elements: [], | |
| minHeight: 0, | |
| offset: 0, // Not used yet | |
| elem: 0, | |
| type: autoDetectGA(), // set type format in which the events should be send ('ga', 'ua' and 'gtm). Support for Google Analytics, (Google) Universal Analytics, and Google Tag Manager | |
| percentage: true, | |
| testing: false | |
| }, | |
| $w = $(w), | |
| $d = $(d), | |
| cache = []; | |
| /* | |
| * Plugin | |
| */ | |
| $.scrollDepth = function(options) { | |
| var startTime = +new Date; | |
| options = $.extend({}, defaults, options); | |
| if (false === options.type) { | |
| // in case of no analytics, revert to testing so we can see what would have been sent | |
| typeof console !== 'undefined' && typeof console.log === 'function' && console.log('Switching to testing mode, no Google Analytics found.'); | |
| options.testing = true; | |
| } | |
| // Return early if document height is too small | |
| if ( $d.height() < options.minHeight ) { | |
| return; | |
| } | |
| // Establish baseline (0% scroll) | |
| sendEvent('Percentage', 'Baseline'); | |
| /* | |
| * Functions | |
| */ | |
| function sendEvent(action, label, timing) { | |
| if (!options.testing && options.type == 'ga') { | |
| _gaq.push(['_trackEvent', 'Scroll Depth', action, label, 1, true]); | |
| if (arguments.length > 2) { | |
| _gaq.push(['_trackTiming', 'Scroll Depth', action, timing, label, 100]); | |
| } | |
| } | |
| else if (!options.testing && options.type == 'ua') { | |
| ga('send', 'event', 'Scroll Depth', action, label, 1, {'nonInteraction': 1}); | |
| if (arguments.length > 2) { | |
| ga('send', 'timing', 'Scroll Depth', action, timing, label); | |
| } | |
| } | |
| else if (!options.testing && options.type == 'gtm') { | |
| dataLayer.push({'event':'GAscroll', 'eventCategory':'Scroll Depth', 'eventAction': action, 'eventLabel': label, 'eventValue': 1, 'eventNonInteraction': true}); | |
| if (arguments.length > 2) { | |
| dataLayer.push({'event':'GAtiming', 'eventCategory':'Scroll Depth', 'eventAction': action, 'eventLabel': label, 'eventTiming': timing}); | |
| } | |
| } | |
| else { | |
| $('#console').html(action + ': ' + label + '</br>' + 'Timing: ' + timing); | |
| } | |
| if (options.testing) { | |
| typeof console !== 'undefined' && typeof console.log === 'function' && console.log('Testing mode; event to be sent: [type, action, label, timing]', options.type, action, label, timing); | |
| } | |
| } | |
| function calculateMarks(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 - 1 | |
| }; | |
| } | |
| function checkMarks(marks, scrollDistance, timing) { | |
| // Check each active mark | |
| $.each(marks, function(key, val) { | |
| if ( $.inArray(key, cache) === -1 && scrollDistance >= val ) { | |
| sendEvent('Percentage', key, timing); | |
| cache.push(key); | |
| } | |
| }); | |
| } | |
| function checkElements(elements, scrollDistance, timing) { | |
| $.each(elements, function(index, elem) { | |
| if ( $.inArray(elem, cache) === -1 && $(elem).length ) { | |
| if ( scrollDistance >= $(elem).offset().top ) { | |
| sendEvent('Elements', elem, timing); | |
| cache.push(elem); | |
| } | |
| } | |
| }); | |
| } | |
| /* | |
| * Scroll Event | |
| */ | |
| $w.on('scroll.scrollDepth', function() { | |
| /* | |
| * We calculate document and window height on each scroll event to | |
| * account for dynamic DOM changes. | |
| */ | |
| var docHeight = $d.height(), | |
| winHeight = parseInt(w.innerHeight ? w.innerHeight : $w.height(), 10), | |
| scrollDistance = $w.scrollTop() + winHeight, | |
| // Offset not being used yet | |
| offset = parseInt(winHeight * (options.offset / 100), 10), | |
| // Recalculate percentage marks | |
| marks = calculateMarks(docHeight), | |
| // Timing | |
| timing = +new Date - startTime; | |
| // If all marks already hit, unbind scroll event | |
| if (cache.length >= 4 + options.elements.length) { | |
| $w.off('scroll.scrollDepth'); | |
| return; | |
| } | |
| // Check specified DOM elements | |
| if (options.elements) { | |
| checkElements(options.elements, scrollDistance, timing); | |
| } | |
| // Check standard marks | |
| if (options.percentage) { | |
| checkMarks(marks, scrollDistance, timing); | |
| } | |
| }); | |
| }; | |
| })( jQuery, window, document ); | |
| jQuery.scrollDepth(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment