Skip to content

Commit

Permalink
Merge pull request #819 from alphagov/fix-scroll-tracking-events
Browse files Browse the repository at this point in the history
Quick fix scroll tracking events for GA campaigns and cosmetic changes
  • Loading branch information
NickColley authored Aug 5, 2016
2 parents b3447f6 + 6289f90 commit 311b3a7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 174 deletions.
145 changes: 16 additions & 129 deletions app/assets/javascripts/analytics/scroll-tracker.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,9 @@
(function() {
"use strict";

window.GOVUK = window.GOVUK || {};
window.GOVUK = window.GOVUK || {};

var CONFIG = {
'/': [
['Heading', 'Services and information'],
['Heading', 'More on GOV.UK'],
['Percent', 80] //To track 'Services and information' section in footer
],
'/bank-holidays': [
['Percent', 25],
['Percent', 50],
['Percent', 75]
],
'/jobsearch': [
['Heading', 'Registration'],
['Heading', 'Help']
],
'/register-to-vote': [
['Percent', 25],
['Percent', 50],
['Percent', 75]
],
'/apply-uk-visa': [
['Percent', 25],
['Percent', 50],
['Percent', 75]
],
'/student-finance-register-login': [
['Heading', 'Log in problems'],
['Heading', 'Manage your student finance']
],
'/contact-the-dvla/y/driving-licences-and-applications': [
['Heading', 'Driving licencing enquiries'],
['Heading', 'When to contact DVLA']
Expand All @@ -44,76 +16,6 @@
['Heading', 'Vehicle registration enquiries'],
['Heading', 'When to contact DVLA']
],
'/using-the-civil-service-jobs-website': [
['Heading', 'Your Civil Service Jobs account'],
['Heading', 'Job alerts'],
['Heading', 'Applying for a job'],
['Heading', 'Civil Service Initial Sift Test'],
['Heading', 'Results and feedback'],
['Heading', 'Civil Service recruitment'],
['Heading', 'Technical Support'],
['Heading', 'Contact Information']
],
'/government/publications/spending-review-and-autumn-statement-2015-documents/spending-review-and-autumn-statement-2015': [
['Percent', 25],
['Percent', 50],
['Percent', 75]
],
'/guidance/universal-credit-how-it-helps-you-into-work': [
['Percent', 25],
['Percent', 50],
['Percent', 75],
['Heading', 'Opening up work'],
['Heading', 'Support from your work coach'],
['Heading', 'When you can claim Universal Credit'],
['Heading', 'More detailed advice']
],
'/openingupwork': [
['Heading', 'How Universal Credit makes work pay'],
['Heading', 'When you can claim Universal Credit'],
['Heading', 'Help and advice']
],
'/guidance/universal-credit-how-it-can-help-your-business': [
['Percent', 25],
['Percent', 50],
['Percent', 75]
],
'/government/publications/see-potential-case-studies-and-guidance-for-employers/see-potential-case-studies-and-guidance-for-employers': [
['Heading', 'Case studies'],
['Heading', 'The business benefits'],
['Heading', 'What people are saying'],
['Heading', 'Review your recruitment approach to make sure you’re not missing out on talent and potential']
],
'/government/groups/common-technology-services-cts': [
['Heading', 'Our products'],
['Heading', 'Our services'],
['Heading', 'Our priorities']
],
'/guidance/common-technology-services-cts-secure-email-blueprint': [
['Heading', '1. Understand government policy'],
['Heading', '2. Follow our technical specification'],
['Heading', '3. Change email domain names as required'],
['Heading', '5. Get CTS’ assurance'],
['Heading', '6. Maintain your documentation and end user policies'],
['Heading', '7. Buy the solution']
],
'/guidance/common-technology-services-cts-guide-to-implementing-the-secure-email-blueprint': [
['Heading', 'Email service prerequisites'],
['Heading', 'Transport Layer Security (TLS)'],
['Heading', 'Domain-based Message Authentication, Reporting and Conformance (DMARC)'],
['Heading', 'DomainKeys Identified Mail (DKIM)'],
['Heading', 'Sender Policy Framework (SPF)'],
['Heading', 'Other email sending services'],
['Heading', 'Making DNS changes'],
['Heading', 'Assurance']
],
'/government/publications/budget-2016-documents/budget-2016': [
['Percent', 20],
['Percent', 40],
['Percent', 60],
['Percent', 80],
['Percent', 100]
],
'/government/collections/disability-confident-campaign': [
['Heading', 'Become a Disability Confident employer'],
['Heading', 'Aims and objectives'],
Expand All @@ -138,7 +40,7 @@

function ScrollTracker(sitewideConfig) {
this.config = this.getConfigForCurrentPath(sitewideConfig);
this.SCROLL_TIMEOUT_DELAY = 500;
this.SCROLL_TIMEOUT_DELAY = 10;

if ( !this.config ) {
this.enabled = false;
Expand All @@ -152,13 +54,15 @@
this.trackVisibleNodes();
};

ScrollTracker.prototype.getConfigForCurrentPath = function getConfigForCurrentPath(sitewideConfig) {
ScrollTracker.prototype.getConfigForCurrentPath = function (sitewideConfig) {
for ( var path in sitewideConfig ) {
if ( window.location.pathname == path ) return sitewideConfig[path];
if (this.normalisePath(window.location.pathname) == this.normalisePath(path)) {
return sitewideConfig[path];
}
}
};

ScrollTracker.prototype.buildNodes = function buildNodes(config) {
ScrollTracker.prototype.buildNodes = function (config) {
var nodes = [];
var nodeConstructor, nodeData;

Expand All @@ -171,12 +75,16 @@
return nodes;
};

ScrollTracker.prototype.onScroll = function onScroll() {
ScrollTracker.prototype.normalisePath = function (path){
return path.split("/").join("");
};

ScrollTracker.prototype.onScroll = function () {
clearTimeout(this.scrollTimeout);
this.scrollTimeout = setTimeout($.proxy(this.trackVisibleNodes, this), this.SCROLL_TIMEOUT_DELAY);
};

ScrollTracker.prototype.trackVisibleNodes = function trackVisibleNodes() {
ScrollTracker.prototype.trackVisibleNodes = function () {
for ( var i=0; i<this.trackedNodes.length; i++ ) {
if ( this.trackedNodes[i].isVisible() && !this.trackedNodes[i].alreadySeen ) {
this.trackedNodes[i].alreadySeen = true;
Expand All @@ -189,26 +97,7 @@
}
};



ScrollTracker.PercentNode = function PercentNode(percentage) {
this.percentage = percentage;
this.eventData = {action: "Percent", label: String(percentage)};
};

ScrollTracker.PercentNode.prototype.isVisible = function isVisible() {
return this.currentScrollPercent() >= this.percentage;
};

ScrollTracker.PercentNode.prototype.currentScrollPercent = function currentScrollPercent() {
var $document = $(document);
var $window = $(window);
return( ($window.scrollTop() / ($document.height() - $window.height())) * 100.0 );
};



ScrollTracker.HeadingNode = function HeadingNode(headingText) {
ScrollTracker.HeadingNode = function (headingText) {
this.$element = getHeadingElement(headingText);
this.eventData = {action: "Heading", label: headingText};

Expand All @@ -220,19 +109,17 @@
}
};

ScrollTracker.HeadingNode.prototype.isVisible = function isVisible() {
ScrollTracker.HeadingNode.prototype.isVisible = function () {
if ( !this.$element ) return false;
return this.elementIsVisible(this.$element);
}

ScrollTracker.HeadingNode.prototype.elementIsVisible = function elementIsVisible($element) {
ScrollTracker.HeadingNode.prototype.elementIsVisible = function ($element) {
var $window = $(window);
var positionTop = $element.offset().top;
return ( positionTop > $window.scrollTop() && positionTop < ($window.scrollTop() + $window.height()) );
};



$().ready(function() {
window.GOVUK.scrollTracker = new ScrollTracker(CONFIG);
});
Expand Down
63 changes: 18 additions & 45 deletions spec/javascripts/analytics/scroll-tracker-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,30 @@ describe("GOVUK.ScrollTracker", function() {
});

describe("enabling on correct pages", function() {
var FIXTURE = "<h1>A heading</h1>";

beforeEach(function() {
setFixtures(FIXTURE);
spyOn(GOVUK.ScrollTracker.HeadingNode.prototype, 'elementIsVisible');
});

it("should be enabled on a tracked page", function() {
var config = {}
config[window.location.pathname] = [ ['Percent', 50] ];
config[window.location.pathname] = [ ['Heading', 'A heading'] ];

expect( (new GOVUK.ScrollTracker(config)).enabled ).toBeTruthy();
});

it("should not be enabled on an untracked page", function() {
var config = {
'/some/other/path': [
['Percent', 50]
['Heading', 'A heading']
]
};
expect( (new GOVUK.ScrollTracker(config)).enabled ).toBeFalsy();
});
});

describe("tracking by scrolled percentage", function() {
beforeEach(function() {
spyOn(GOVUK.ScrollTracker.PercentNode.prototype, "currentScrollPercent");
});

it("should send an event when the page scrolls to >= the percentage specified", function() {
var config = buildConfigForThisPath([
['Percent', 25],
['Percent', 50],
['Percent', 75]
]);
new GOVUK.ScrollTracker(config);

scrollToPercent(60);

expect(GOVUK.analytics.trackEvent.calls.count()).toBe(2);
expect(GOVUK.analytics.trackEvent.calls.argsFor(0)).toEqual(["ScrollTo", "Percent", {label: "25", nonInteraction: true}]);
expect(GOVUK.analytics.trackEvent.calls.argsFor(1)).toEqual(["ScrollTo", "Percent", {label: "50", nonInteraction: true}]);
});
});

describe("tracking by headings", function() {
var FIXTURE = "\
<h1>This is the first <span>heading</span></h1>\
Expand All @@ -59,15 +45,14 @@ describe("GOVUK.ScrollTracker", function() {
beforeEach(function() {
setFixtures(FIXTURE);
spyOn(GOVUK.ScrollTracker.HeadingNode.prototype, 'elementIsVisible');
});

it("should send an event when the user scrolls so the heading is visible", function() {
var config = buildConfigForThisPath([
['Heading', "This is the first heading"],
['Heading', "This is the third heading"]
]);
new GOVUK.ScrollTracker(config);
});

it("should send an event when the user scrolls so the heading is visible", function() {
scrollToShowHeadingNumber(1);

expect(GOVUK.analytics.trackEvent.calls.count()).toBe(1);
Expand All @@ -82,40 +67,28 @@ describe("GOVUK.ScrollTracker", function() {
expect(GOVUK.analytics.trackEvent.calls.count()).toBe(2);
expect(GOVUK.analytics.trackEvent.calls.argsFor(1)).toEqual(["ScrollTo", "Heading", {label: "This is the third heading", nonInteraction: true}]);
});
});

it("should not send duplicate events", function() {
spyOn(GOVUK.ScrollTracker.PercentNode.prototype, "currentScrollPercent");

var config = buildConfigForThisPath([
['Percent', 25]
]);
new GOVUK.ScrollTracker(config);
it("should not send duplicate events", function() {
scrollToShowHeadingNumber(1);
scrollToShowHeadingNumber(3);
scrollToShowHeadingNumber(1);

scrollToPercent(30);
scrollToPercent(35);
expect(GOVUK.analytics.trackEvent.calls.count()).toBe(1);
expect(GOVUK.analytics.trackEvent.calls.count()).toBe(2);
});
});


function buildConfigForThisPath(thisPathData) {
var config = {};
config[window.location.pathname] = thisPathData;
return config;
}

function scrollToPercent(percent) {
GOVUK.ScrollTracker.PercentNode.prototype.currentScrollPercent.and.returnValue(percent);
$(window).scroll();
jasmine.clock().tick(510);
};

function scrollToShowHeadingNumber(headingNumber) {
var elementScrolledTo = $('h1, h2, h3, h4, h5, h6')[headingNumber-1];
GOVUK.ScrollTracker.HeadingNode.prototype.elementIsVisible.and.callFake(function($element) {
return ( $element[0] == elementScrolledTo );
});
$(window).scroll();
jasmine.clock().tick(510);
jasmine.clock().tick(20);
};
});

0 comments on commit 311b3a7

Please sign in to comment.