Skip to content

Commit

Permalink
feat: Disable tracking/Google Analytics when DNT is enabled (fix #2792)
Browse files Browse the repository at this point in the history
  • Loading branch information
tofumatt committed Jul 13, 2017
1 parent db8fcd6 commit f84ac9b
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 11 deletions.
5 changes: 4 additions & 1 deletion src/core/server/base.js
Expand Up @@ -79,7 +79,10 @@ export function getPageProps({ noScriptStyles = '', store, req, res }) {
noScriptStyles,
sriData,
store,
trackingEnabled: convertBoolean(config.get('trackingEnabled')),
trackingEnabled: (
convertBoolean(config.get('trackingEnabled')) &&
req.header('dnt') !== '1' // A DNT header set to "1" means Do Not Track
),
};
}

Expand Down
32 changes: 30 additions & 2 deletions src/core/tracking.js
@@ -1,5 +1,6 @@
/* global window */
/* global navigator, window */
/* eslint-disable no-underscore-dangle */
import { oneLine } from 'common-tags';
import config from 'config';

import { convertBoolean } from 'core/utils';
Expand Down Expand Up @@ -105,8 +106,35 @@ export function getAction(type) {
}[type] || TRACKING_TYPE_INVALID;
}

export function isDoNotTrackEnabled({
_log = log,
_navigator = typeof navigator !== 'undefined' ? navigator : null,
_window = typeof window !== 'undefined' ? window : null,
} = {}) {
if (!_navigator || !_window) {
return false;
}

// We ignore things like `msDoNotTrack` because they are for older,
// unsupported browsers and don't really respect the DNT spec. This
// covers new versions of IE/Edge, Firefox from 32+, Chrome, Safari, and
// any browsers built on these stacks (Chromium, Tor Browser, etc.).
const dnt = _navigator.doNotTrack || _window.doNotTrack;
if (dnt === '1') {
_log.log(oneLine`[TRACKING]: Do Not Track Enabled; Google Analytics not
loaded and tracking disabled.`);
return true;
}

// Known DNT values not set, so we will assume it's off.
return false;
}

export default new Tracking({
trackingEnabled: convertBoolean(config.get('trackingEnabled')),
trackingEnabled: (
convertBoolean(config.get('trackingEnabled')) &&
doNotTrackEnabled()
),
trackingId: config.get('trackingId'),
trackingSendInitPageView: config.get('trackingSendInitPageView'),
});
82 changes: 74 additions & 8 deletions tests/unit/core/test_tracking.js
@@ -1,6 +1,7 @@
/* global window */
import { oneLine } from 'common-tags';

import { Tracking, getAction } from 'core/tracking';
import { Tracking, isDoNotTrackEnabled, getAction } from 'core/tracking';
import {
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
Expand Down Expand Up @@ -31,7 +32,7 @@ describe('Tracking', () => {
info: sinon.stub(),
},
});
expect(tracking._log.info.calledWith(sinon.match(/OFF/), 'Tracking init')).toBeTruthy();
expect(tracking._log.info.calledWith(sinon.match(/OFF/), 'Tracking init')).toBe(true);
});

it('should log OFF when not enabled due to missing id', () => {
Expand All @@ -44,7 +45,7 @@ describe('Tracking', () => {
});
expect(
tracking._log.info.secondCall.calledWith(sinon.match(/OFF/), 'Missing tracking id')
).toBeTruthy();
).toBe(true);
});

it('should send initial page view when enabled', () => {
Expand All @@ -56,7 +57,7 @@ describe('Tracking', () => {
info: sinon.stub(),
},
});
expect(window.ga.calledWith('send', 'pageview')).toBeTruthy();
expect(window.ga.calledWith('send', 'pageview')).toBe(true);
});

it('should not send initial page view when disabled', () => {
Expand All @@ -68,7 +69,7 @@ describe('Tracking', () => {
info: sinon.stub(),
},
});
expect(window.ga.calledWith('send', 'pageview')).toBeFalsy();
expect(window.ga.calledWith('send', 'pageview')).toBe(false);
});

it('should throw if page not set', () => {
Expand All @@ -79,7 +80,7 @@ describe('Tracking', () => {

it('should call ga with setPage', () => {
tracking.setPage('whatever');
expect(window.ga.called).toBeTruthy();
expect(window.ga.called).toBe(true);
});

it('should throw if category not set', () => {
Expand All @@ -101,7 +102,7 @@ describe('Tracking', () => {
category: 'whatever',
action: 'some-action',
});
expect(window.ga.called).toBeTruthy();
expect(window.ga.called).toBe(true);
});

it('should call _ga when pageView is called', () => {
Expand All @@ -110,7 +111,7 @@ describe('Tracking', () => {
dimension2: 'whatever2',
};
tracking.pageView(data);
expect(window.ga.calledWith('send', 'pageview', data)).toBeTruthy();
expect(window.ga.calledWith('send', 'pageview', data)).toBe(true);
});
});

Expand All @@ -127,3 +128,68 @@ describe('getAction', () => {
expect(getAction('whatever')).toEqual('invalid');
});
});

describe('Do Not Track', () => {
it('should respect DNT when enabled', () => {
expect(isDoNotTrackEnabled({
_navigator: { doNotTrack: '1' },
_window: {},
})).toBe(true);
expect(isDoNotTrackEnabled({
_navigator: {},
_window: { doNotTrack: '1' },
})).toBe(true);
});

it('should respect not enabled DNT', () => {
expect(isDoNotTrackEnabled({
_navigator: { doNotTrack: '0' },
_window: {},
})).toBe(false);
expect(isDoNotTrackEnabled({
_navigator: {},
_window: { doNotTrack: '0' },
})).toBe(false);
});

it('should treat unknown values as no DNT', () => {
expect(isDoNotTrackEnabled({
_navigator: { doNotTrack: 'leave me alone' },
_window: {},
})).toBe(false);
expect(isDoNotTrackEnabled({
_navigator: {},
_window: { doNotTrack: 'leave me alone' },
})).toBe(false);
});

it('should handle missing navigator and window', () => {
expect(isDoNotTrackEnabled({ _navigator: null })).toBe(false);
expect(isDoNotTrackEnabled({ _window: null })).toBe(false);
});

it('should log that DNT disabled tracking', () => {
const fakeLog = { log: sinon.stub() };
isDoNotTrackEnabled({
_log: fakeLog,
_navigator: { doNotTrack: '1' },
_window: {},
});

sinon.assert.calledWith(fakeLog.log, oneLine`[TRACKING]: Do Not Track
Enabled; Google Analytics not loaded and tracking disabled.`);
sinon.assert.calledOnce(fakeLog.log);

// Check with `window.doNotTrack` as well, just for completeness.
fakeLog.log.reset();
isDoNotTrackEnabled({
_log: fakeLog,
_navigator: {},
_window: { doNotTrack: '1' },
});

sinon.assert.calledWith(fakeLog.log, oneLine`[TRACKING]: Do Not Track
Enabled; Google Analytics not loaded and tracking disabled.`);
sinon.assert.calledOnce(fakeLog.log);
});
});

0 comments on commit f84ac9b

Please sign in to comment.