Scroll Tracker
This file contains 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
// Replace CATEGORY and ACTION with the names that you desire for your events. | |
<script type="text/javascript"> | |
/** | |
* @name jQuery.trackScrolls | |
* @desc Watch for scrolling past certain positions. | |
* | |
* @example: | |
* | |
* $(".track").trackScrolls({ | |
* onLandmark: function($el, progress) { | |
* _gaq.push('_trackEvent', $el.attr("data-track-scrolls"), progress); | |
* } | |
* }); | |
* | |
* @require jQuery | |
*/ | |
(function() { | |
/* Extracted from Underscore */ | |
var throttle = function(func, wait, options) { | |
var context, args, result; | |
var timeout = null; | |
var previous = 0; | |
options || (options = {}); | |
var later = function() { | |
previous = options.leading === false ? 0 : new Date; | |
timeout = null; | |
result = func.apply(context, args); | |
}; | |
return function() { | |
var now = new Date; | |
if (!previous && options.leading === false) previous = now; | |
var remaining = wait - (now - previous); | |
context = this; | |
args = arguments; | |
if (remaining <= 0) { | |
clearTimeout(timeout); | |
timeout = null; | |
previous = now; | |
result = func.apply(context, args); | |
} else if (!timeout && options.trailing !== false) { | |
timeout = setTimeout(later, remaining); | |
} | |
return result; | |
}; | |
}; | |
var triggerNearestLandmark = function(el, scroll, options) { | |
var $el = $(el); | |
var info = $el.data("trackScrolls") || { current: -1, shown: false } | |
var progress = 1; | |
// Already tracked past 100%? Skip this element | |
if (info.current >= 1) return; | |
// Height using complete box model (without margin) | |
var height = $el.outerHeight(false); | |
// Offset from the top of the page to the bottom of the element | |
var top = height + $el.offset().top; | |
while (progress > 0) { | |
if (progress > info.current && top - height * (1 - progress) <= scroll) { | |
if (!info.shown) { | |
options.onShow($el, info); | |
info.shown = true; | |
} | |
info.current = progress; | |
options.onLandmark($el, progress * 100, info); | |
break; | |
} | |
progress -= 0.25; | |
} | |
// Remember how far we've tracked, so that we don't repeat | |
// events. | |
$el.data("trackScrolls", info); | |
}; | |
$.fn.trackScrolls = function(options) { | |
var settings = $.extend({ | |
onShow: function() {}, | |
onLandmark: function() {} | |
}, options); | |
var trackers = $(this); | |
var isFrame = window.location !== window.parent.location; | |
var $window = $(isFrame? window.parent : window); | |
var $frame = $(window.frameElement); | |
$window.on('scroll.trackScrolls', throttle(function() { | |
var scroll = $window.scrollTop() + $window.height(); | |
// If we're dealing with an iFrame then offset by the frame's position | |
// on the page. | |
if (isFrame) { | |
scroll -= $frame.offset().top; | |
} | |
trackers.each(function() { | |
triggerNearestLandmark(this, scroll, settings); | |
}); | |
}, 10)); | |
} | |
}(window.jQuery)); | |
$(document).ready(function() { | |
$("body").trackScrolls({ | |
onLandmark: function($el, progress) { | |
_gaq.push(['_trackEvent', 'CATEGORY', 'ACTION', progress.toString(), 0, true]); | |
} | |
}); | |
}) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment