Tracking Consent Frontend is a solution intended to address the need for users visiting the public-facing HMRC tax platform (www.tax.service.gov.uk) to provide their explicit informed consent to the use of non-essential cookies.
Tracking consent provides a means to capture consent but is not itself responsible for ensuring this consent is correctly honoured by consuming services. Tracking consent does not actively allow or block cookies nor does it conditionally enable services such as Google Analytics or Optimizely.
Tracking consent provides:
- A Javascript asset intended to be included by all frontend microservices running under www.tax.service.gov.uk to
- provide an integration with Google Tag Manager (GTM), the service used to centrally control the enablement of Google Analytics on the tax platform
- inject a banner for tax users to accept or reject additional cookies, storing these preferences
in a
userConsent
cookie and notifying subscribed services on page load and following changes to them
- a cookie settings page that allows tracking preferences to be adjusted
If you have a public-facing microservice running under www.tax.service.gov.uk
, you should integrate with the
tracking-consent-frontend
microservice to provide an opt-in banner for cookie consent.
Tracking consent is designed to be used in conjunction with HMRC's frontend libraries.
Integration guidelines for play-frontend-hmrc can be found here.
Integration guidelines for older services using play-ui can be found here
If you are not able to use the above libraries, please contact #team-plat-ui for integration advice.
-
Use service manager 2 to spin up tracking consent locally on port 12345:
sm2 --start TRACKING_CONSENT_FRONTEND
-
If you are not using CSPFilter, make the required modifications to your CSP policy (see below).
-
Navigate to a page on your service. You should see the cookie banner at the top of the page, above the 'Skip to main content' link.
-
Toggle to the Welsh language, if applicable. You should see the cookie banner translated into Welsh.
-
Click 'Accept additional cookies', you should see a confirmation.
-
Click 'Change your cookie settings'. You should see the cookie settings page.
-
Click 'Save changes'. You should be scrolled to the top of the page and see a save confirmation.
When testing locally the 'Go back to the page you were looking at' link will either not display or will
navigate to /
which is likely to result in a 404 page not found error.
This is because:
- when running locally, tracking consent is running on a different port
- the back link uses
document.referrer
to identify the referring service url and thestrict-origin-when-cross-origin
referrer policy prevents the full path from being available
If you wish to satisfy yourself that the back link is operating correctly, you will need to deploy to an environment.
Because tracking consent depends on GTM, your service will need to have a CSP that is compatible with it.
If you're following the current platform security Content Security Policy guidance, you do not need to make any changes to your CSP as it will be configured by the bootstrap-play library.
To find out more about what the latest guidance is, check out the #event-content-security-policy in the HMRC Digital slack.
Tracking consent stores cookie preferences in the userConsent
cookie. Readable on the server
and client side, the contents are URL-encoded JSON with a structure described in
the next section. However, it‘s not intended that you inspect this cookie manually – helper methods have
been created for reading it in Scala and Javascript.
Your service can be made aware of the contents of this cookie either by inspecting it on demand or, on the client-side only, subscribing to updates.
For reading the cookie in server-side Scala, refer to the README in hmrc/tracking-consent-models
Your service will need to regularly update the version of this library in order to take advantage of changes to the underlying cookie model.
In Javascript, you can use the window.trackingConsent.UserPreferences
object that has methods for querying the userConsent cookie and
for subscribing to notifications for updates to it.
For example, if you need to determine if the user has accepted settings
cookies,
if (window.trackingConsent.userPreferences.getPreferences().settings) {
document.cookie = 'darkMode=true;path=/;Max-Age=31536000;';
}
If you want to perform an action only once the user has accepted settings cookies via the banner,
const communicator = {
sendPreferences: (userPreferences, event) => {
if (userPreferences.getPreferences().settings && event === 'CONSENT_UPDATED_EVENT') {
document.cookie = 'textSize=large;path=/;Max-Age=31536000;';
}
}
}
window.trackingConsent.userPreferences.subscribe(communicator);
In the above example, event is set to either SERVICE_PAGE_LOAD_EVENT
or CONSENT_UPDATED_EVENT
. The
SERVICE_PAGE_LOAD_EVENT
is sent on the initial page load. The CONSENT_UPDATED_EVENT
is sent when
a user explicitly changes their settings via the cookie banner or the cookie settings page.
Represented as a Typescript type, the structure of the URL-decoded userConsent cookie is as follows:
{
version: string, // 2021.1
datetimeSet: string, // e.g. 2021-03-04T15:16:47.077Z
preferences: {
measurement?: boolean, // e.g. true
settings?: boolean // e.g. false
}
}
A string of the form YYYY.N, where YYYY is the year and N is a positive integer e.g. 2022.5.
The version number allows consuming services to know exactly which version of the user consent cookie was in use at the time the user consented. Any breaking changes to the descriptions of the cookie categories on the cookie settings page should result in a new version number as it affects what exactly the user has consented to.
The date and time the cookie was set in UTC, ISO 8106 format e.g. 2021-03-04T15:16:47.077Z
A JSON object with the following optional keys:
- measurement: when set to true, this indicates the user has consented to measurement cookies being stored on their device.
- settings: when set to true, this indicates the user has consented to settings cookies being stored on their device.
Each preference setting should be interpreted as a strict boolean value. So-called ‘truthy’ values or even the literal string “true” should be interpreted as the user having rejected cookies.
In raw form the cookie value might look like:
{%22version%22:%222021.1%22%2C%22datetimeSet%22:%222021-03-10T13:48:19.321Z%22%2C%22preferences%22:{%22measurement%22:false%2C%22settings%22:false}}
This would result in the following URL-decoded value:
{"version":"2021.1","datetimeSet":"2021-03-10T13:48:19.321Z","preferences":{"measurement":false,"settings":false}}
This service is NOT intended for use on internal HMRC services which live on the internal domain. If you require user tracking for an internal service, please talk to your Performance Analyst to implement directly.
Tracking consent frontend provides a standardised GTM integration that means service teams do not need to add a separate GTM snippet in addition to tracking-consent-frontend tracking.js snippet. Tracking consent uses the GTM datalayer to send messages to GTM in the form of events and variables that allows analytics tags to be configured such that they will only be added when a user has properly consented.
On page load, tracking consent initialises the datalayer with the following variables:
Variable | Description | Possible values |
---|---|---|
trackingConsentLoaded |
Set to true if the service has integrated with tracking-consent-frontend | true or undefined |
trackingConsentMeasurementAccepted |
Set to true if the user has accepted measurement cookies or false otherwise |
true or false |
trackingConsentSettingsAccepted |
Set to true if the user has accepted settings cookies or false otherwise |
true or false |
When a user changes their cookie settings by accepting or rejecting cookies in the banner, or by
toggling different settings on the cookie settings page, the variables
trackingConsentMeasurementAccepted
and trackingConsentSettingsAccepted
are dynamically updated to
reflect the user's adjusted settings.
GTM has a special data layer variable called an event that can be used to initiate tag firing when a user performs some action on a service page, such as clicking on a button.
Tracking consent sends the following events to GTM via the datalayer:
trackingConsentMeasurementAccepted
is sent when
- a user clicks 'Accept additional cookies'
- clicks 'Save changes' on the cookie settings page having toggled the 'Use cookies that measure my website use' radio button.
- on page load, if the user has already accepted measurement cookies on a visit to any other service on the tax platform using one of the mechanisms above
trackingConsentSettingsAccepted
is sent when
- a user clicks 'Accept additional cookies'
- clicks 'Save changes' on the cookie settings page having toggled the 'Use cookies that remember my settings on services' radio button.
- on page load, if the user has already accepted settings cookies on a visit to any other service on the tax platform using one of the mechanisms above
Internally this mechanism is implemented via
gtmCommunicatorFactory.
Messages are sent to GTM for both SERVICE_PAGE_LOAD_EVENT
and CONSENT_UPDATED_EVENT
events.
Optimizely is a client-side solution for A/B testing that relies on cookies. It supports a mechanism for opting a user out of cookie and local storage that is implemented by tracking consent. However, for this to work correctly it is imperative that:
- tracking consent is loaded synchronously in the HEAD element – there must be no async attribute
- tracking consent is loaded before the Optimizely snippet
- the Optimizely snippet is wrapped in a conditional comment to prevent its inclusion on IE8 or IE9 browsers. Tracking consent does not support these browsers.
Due to the above complexities, it is highly recommended that consuming services using the Play framework use the tracking consent helpers provided in play-frontend-hmrc and play-ui
The following should be noted as consequences of the above:
- A/B testing will be disabled for users that have not accepted 'measurement' cookies before they navigated to the page under test.
- Users that accept additional cookies using the cookie banner will only see variations following a page reload or on subsequent pages in the user journey. They will not see the page change to a variation following acceptance.
Internally this mechanism is implemented via
optimizelyCommunicatorFactory.
An opt-out message is sent to Optimizely for both SERVICE_PAGE_LOAD_EVENT
and CONSENT_UPDATED_EVENT
events.
In order for analytics data relating to Optimizely experiments to be successfully communicated to Google Analytics, a special Universal Analytics GTM tag must be configured according to the instructions on the Optimizely website This configuration must be carried out once for each GTM container.
As a convenience, tracking consent hosts the custom integration code under
the endpoint https://www.tax.service.gov.uk/tracking-consent/tracking/optimizely.js needed by Step 9 of the above integration guide.
This means it is not necessary to carry out Step 9 - Custom HTML tag described in the above integration guide. The tracking consent
helpers in hmrc/play-frontend-hmrc
and hmrc/play-ui
add this snippet after the optimizely snippet,
to ensure the Optimizely object is available when it runs.
For auditing purposes, when cookie preferences are changed using the cookie banner or cookie settings page, tracking consent performs an XHR POST request to the
/tracking-consent/audit
endpoint with a payload containing the cookie preferences selected by the user. For example, clicking 'Accept additional cookies'
results in a request similar to the following (with some headers removed):
POST /tracking-consent/audit HTTP/1.1
Host: www.tax.service.gov.uk
Csrf-Token: nocheck
Content-type: application/json
Origin: https://www.tax.service.gov.uk
Cookie: ...
{"measurement":true,"settings":true}
This request results in tracking consent sending an implicit audit event to the datastream microservice via the audit filter in bootstrap-play that internally uses the audit connector from play-auditing library.
Internally this mechanism is implemented via
auditCommunicatorFactory, listening
to events of type CONSENT_UPDATED_EVENT
only.
When a user grants tracking consent, GTM will be loaded on the page and that will create Google Analytics cookies on the tax.service.gov.uk domain. If a user then revokes their consent, these cookies will remain, but their tracking preference will be updated and on future navigation GTM will not be loaded and no tracking data will be sent. The Google analytics cookies will remain in the users browser until they expire, you can view further details about the nature of the cookies within the google analytics documenation on cookie usage.
Maintenance documentation for the owning team, including architectural decision records (ADRs) can be found here.
This code is open source software licensed under the Apache 2.0 License.