app/assets/javascripts/govuk/analytics/analytics.js in govuk_frontend_toolkit-7.2.0 vs app/assets/javascripts/govuk/analytics/analytics.js in govuk_frontend_toolkit-7.3.0
- old
+ new
@@ -1,14 +1,23 @@
;(function (global) {
'use strict'
var GOVUK = global.GOVUK || {}
+ var EMAIL_PATTERN = /[^\s=/?&]+(?:@|%40)[^\s=/?&]+/g
+ var POSTCODE_PATTERN = /[A-PR-UWYZ][A-HJ-Z]?[0-9][0-9A-HJKMNPR-Y]?(?:[\s+]|%20)*[0-9][ABD-HJLNPQ-Z]{2}/gi
// For usage and initialisation see:
// https://github.com/alphagov/govuk_frontend_toolkit/blob/master/docs/analytics.md#create-an-analytics-tracker
var Analytics = function (config) {
+ this.stripPostcodePII = false
+ if (typeof config.stripPostcodePII !== 'undefined') {
+ this.stripPostcodePII = (config.stripPostcodePII === true)
+ // remove the option so we don't pass it to other trackers - it's not
+ // their concern
+ delete config.stripPostcodePII
+ }
this.trackers = []
if (typeof config.universalId !== 'undefined') {
var universalId = config.universalId
delete config.universalId
this.trackers.push(new GOVUK.GoogleAnalyticsUniversalTracker(universalId, config))
@@ -18,10 +27,49 @@
delete config.govukTrackerUrl
this.trackers.push(new GOVUK.GOVUKTracker(govukTrackerUrl))
}
}
+ Analytics.prototype.stripPII = function (value) {
+ if (typeof value === 'string') {
+ return this.stripPIIFromString(value)
+ } else if (Object.prototype.toString.call(value) === '[object Array]') {
+ return this.stripPIIFromArray(value)
+ } else if (typeof value === 'object') {
+ return this.stripPIIFromObject(value)
+ } else {
+ return value
+ }
+ }
+
+ Analytics.prototype.stripPIIFromString = function (string) {
+ var emailStripped = string.replace(EMAIL_PATTERN, '[email]')
+ if (this.stripPostcodePII === true) {
+ return emailStripped.replace(POSTCODE_PATTERN, '[postcode]')
+ } else {
+ return emailStripped
+ }
+ }
+
+ Analytics.prototype.stripPIIFromObject = function (object) {
+ for (var property in object) {
+ var value = object[property]
+
+ object[property] = this.stripPII(value)
+ }
+ return object
+ }
+
+ Analytics.prototype.stripPIIFromArray = function (array) {
+ for (var i = 0, l = array.length; i < l; i++) {
+ var elem = array[i]
+
+ array[i] = this.stripPII(elem)
+ }
+ return array
+ }
+
Analytics.prototype.sendToTrackers = function (method, args) {
for (var i = 0, l = this.trackers.length; i < l; i++) {
var tracker = this.trackers[i]
var fn = tracker[method]
@@ -34,33 +82,44 @@
Analytics.load = function () {
GOVUK.GoogleAnalyticsUniversalTracker.load()
GOVUK.GOVUKTracker.load()
}
+ Analytics.prototype.defaultPathForTrackPageview = function () {
+ // Ignore anchor, but keep query string as per default behaviour of
+ // GA (see: https://developers.google.com/analytics/devguides/collection/analyticsjs/pages#overview)
+ // we ignore the possibility of there being campaign variables in the
+ // anchor because we wouldn't know how to detect and parse them if they
+ // were present
+ return this.stripPIIFromString(window.location.href.split('#')[0])
+ }
+
Analytics.prototype.trackPageview = function (path, title, options) {
- this.sendToTrackers('trackPageview', arguments)
+ arguments[0] = arguments[0] || this.defaultPathForTrackPageview()
+ if (arguments.length === 0) { arguments.length = 1 }
+ this.sendToTrackers('trackPageview', this.stripPII(arguments))
}
/*
https://developers.google.com/analytics/devguides/collection/analyticsjs/events
options.label – Useful for categorizing events (eg nav buttons)
options.value – Values must be non-negative. Useful to pass counts
options.nonInteraction – Prevent event from impacting bounce rate
*/
Analytics.prototype.trackEvent = function (category, action, options) {
- this.sendToTrackers('trackEvent', arguments)
+ this.sendToTrackers('trackEvent', this.stripPII(arguments))
}
Analytics.prototype.trackShare = function (network, options) {
- this.sendToTrackers('trackSocial', [network, 'share', global.location.pathname, options])
+ this.sendToTrackers('trackSocial', this.stripPII([network, 'share', global.location.pathname, options]))
}
/*
The custom dimension index must be configured within the
Universal Analytics profile
*/
Analytics.prototype.setDimension = function (index, value) {
- this.sendToTrackers('setDimension', arguments)
+ this.sendToTrackers('setDimension', this.stripPII(arguments))
}
/*
Add a beacon to track a page in another GA account on another domain.
*/