From b6e37a6ac81e86b1cd2c0d2caf591bbef08e3f7d Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Fri, 10 Jan 2020 11:02:17 +0000 Subject: [PATCH] Add event tracking to window.GOVUK.analytics app/assets/javascripts/errorTracking.js sent events to `window.ga`. This extends the API of `window.GOVUK.Analytics` to include support for sending events so all calls to `window.ga` can use it instead of direct access. This use of `window.ga` was missed from the initial work on `window.GOVUK.Anaytics`. --- app/assets/javascripts/analytics/analytics.js | 25 ++++++++++++- app/assets/javascripts/errorTracking.js | 16 ++++----- tests/javascripts/analytics/analytics.test.js | 36 ++++++++++++++++--- tests/javascripts/errorTracking.test.js | 13 ++++--- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/analytics/analytics.js b/app/assets/javascripts/analytics/analytics.js index 580ee382a..1b6f526d4 100644 --- a/app/assets/javascripts/analytics/analytics.js +++ b/app/assets/javascripts/analytics/analytics.js @@ -4,7 +4,7 @@ window.GOVUK = window.GOVUK || {}; // Stripped-down wrapper for Google Analytics, based on: - // https://github.com/alphagov/static/blob/master/app/assets/javascripts/analytics_toolkit/analytics.js + // https://github.com/alphagov/static/blob/master/doc/analytics.md const Analytics = function (config) { window.ga('create', config.trackingId, config.cookieDomain); @@ -34,6 +34,29 @@ }; + // https://developers.google.com/analytics/devguides/collection/analyticsjs/events + Analytics.prototype.trackEvent = function (category, action, options) { + + options = options || {}; + + var evt = { + eventCategory: category, + eventAction: action + }; + + if (options.label) { + evt.eventLabel = options.label; + delete options.label; + } + + if (typeof options === 'object') { + $.extend(evt, options); + } + + window.ga('send', 'event', evt); + + }; + window.GOVUK.Analytics = Analytics; })(window); diff --git a/app/assets/javascripts/errorTracking.js b/app/assets/javascripts/errorTracking.js index 3b7053841..b0ec16f27 100644 --- a/app/assets/javascripts/errorTracking.js +++ b/app/assets/javascripts/errorTracking.js @@ -1,22 +1,22 @@ -(function(Modules) { +(function(window) { "use strict"; - Modules.TrackError = function() { + window.GOVUK.Modules.TrackError = function() { this.start = function(component) { - if (!ga) return; + if (!('analytics' in window.GOVUK)) return; - ga( - 'send', - 'event', + window.GOVUK.analytics.trackEvent( 'Error', $(component).data('error-type'), - $(component).data('error-label') + { + 'label': $(component).data('error-label') + } ); }; }; -})(window.GOVUK.Modules); +})(window); diff --git a/tests/javascripts/analytics/analytics.test.js b/tests/javascripts/analytics/analytics.test.js index 6b357a1e8..224569ba2 100644 --- a/tests/javascripts/analytics/analytics.test.js +++ b/tests/javascripts/analytics/analytics.test.js @@ -37,7 +37,7 @@ describe("Analytics", () => { afterEach(() => { - window.ga.mockReset(); + window.ga.mockClear(); }); @@ -58,10 +58,15 @@ describe("Analytics", () => { describe("When tracking pageviews", () => { - test("It sends the right URL for the page if no arguments", () => { + beforeEach(() => { + // clear calls to window.ga from set up window.ga.mockClear(); + }); + + test("It sends the right URL for the page if no arguments", () => { + jest.spyOn(window, 'location', 'get').mockImplementation(() => { return { 'pathname': '/privacy', @@ -77,8 +82,6 @@ describe("Analytics", () => { test("It strips the UUIDs from URLs", () => { - window.ga.mockClear(); - jest.spyOn(window, 'location', 'get').mockImplementation(() => { return { 'pathname': '/services/6658542f-0cad-491f-bec8-ab8457700ead', @@ -94,4 +97,29 @@ describe("Analytics", () => { }); + describe("When tracking events", () => { + + beforeEach(() => { + + // clear calls to window.ga from set up + window.ga.mockClear(); + + }); + + test("It sends the right arguments to `ga`", () => { + + analytics.trackEvent('Error', 'Enter a valid email address', { + 'label': 'email_address' + }); + + expect(window.ga.mock.calls[0]).toEqual(['send', 'event', { + 'eventCategory': 'Error', + 'eventAction': 'Enter a valid email address', + 'eventLabel': 'email_address' + }]); + + }); + + }); + }); diff --git a/tests/javascripts/errorTracking.test.js b/tests/javascripts/errorTracking.test.js index 9b16b391f..c9db2aded 100644 --- a/tests/javascripts/errorTracking.test.js +++ b/tests/javascripts/errorTracking.test.js @@ -18,18 +18,23 @@ describe('Error tracking', () => { afterEach(() => { document.body.innerHTML = ''; + delete window.GOVUK.analytics; }); - test("It should send the right data to Google Analytics", () => { + test("If there is an analytics tracker set up, it should send details of the error to window.GOVUK.analytic", () => { - window.ga = jest.fn(() => {}); + window.GOVUK.analytics = { + 'trackEvent': jest.fn() + }; // start the module window.GOVUK.modules.start(); - expect(window.ga).toHaveBeenCalled(); - expect(window.ga.mock.calls[0]).toEqual(['send', 'event', 'Error', 'validation', 'missing field']); + expect(window.GOVUK.analytics.trackEvent).toHaveBeenCalled(); + expect(window.GOVUK.analytics.trackEvent.mock.calls[0]).toEqual(['Error', 'validation', { + 'label': 'missing field' + }]); });