Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add single cookie consent API #3854

Merged
merged 7 commits into from Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,8 @@
of the commit log.

## Unreleased

* Add single cookie consent API ([PR #3854](https://github.com/alphagov/govuk_publishing_components/pull/3854))
* Update popular links in super navigation header ([PR #3904](https://github.com/alphagov/govuk_publishing_components/pull/3904))
* Allow custom text for GA4 scroll tracker ([PR #3896](https://github.com/alphagov/govuk_publishing_components/pull/3896))
* Ensure analytics stops firing if a user disables usage cookies on our cookie settings page ([PR #3893](https://github.com/alphagov/govuk_publishing_components/pull/3893))
Expand Down
Expand Up @@ -10,10 +10,17 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};

CookieBanner.prototype.init = function () {
this.$module.hideCookieMessage = this.hideCookieMessage.bind(this)
this.$module.showCookieMessage = this.showCookieMessage.bind(this)
this.$module.showConfirmationMessage = this.showConfirmationMessage.bind(this)
this.$module.setCookieConsent = this.setCookieConsent.bind(this)
this.$module.rejectCookieConsent = this.rejectCookieConsent.bind(this)
this.setupCookieMessage()

if (window.GOVUK.useSingleConsentApi) {
window.addEventListener('hide-cookie-banner', this.$module.hideCookieMessage)
window.addEventListener('show-cookie-banner', this.$module.showCookieMessage)
window.GOVUK.singleConsent.init()
}
}

CookieBanner.prototype.setupCookieMessage = function () {
Expand All @@ -34,10 +41,13 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
this.$rejectCookiesButton.addEventListener('click', this.$module.rejectCookieConsent)
}

this.showCookieMessage()
if (!window.GOVUK.useSingleConsentApi) {
this.showCookieMessage()
}
}

CookieBanner.prototype.showCookieMessage = function () {
window.removeEventListener('show-cookie-banner', this.$module.showCookieMessage)
// Show the cookie banner if not in the cookie settings page or in an iframe
if (!this.isInCookiesPage() && !this.isInIframe()) {
var shouldHaveCookieMessage = (this.$module && window.GOVUK.cookie('cookies_preferences_set') !== 'true')
Expand All @@ -47,7 +57,9 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};

// Set the default consent cookie if it isn't already present
if (!window.GOVUK.cookie('cookies_policy')) {
window.GOVUK.setDefaultConsentCookie()
if (!window.GOVUK.useSingleConsentApi) {
window.GOVUK.setDefaultConsentCookie()
}
}

window.GOVUK.deleteUnconsentedCookies()
Expand All @@ -56,9 +68,12 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
}

CookieBanner.prototype.hideCookieMessage = function (event) {
window.removeEventListener('hide-cookie-banner', this.$module.hideCookieMessage)
if (this.$module) {
this.$module.hidden = true
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })
if (!window.GOVUK.useSingleConsentApi) {
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })
}
}

if (event.target) {
Expand All @@ -70,25 +85,37 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
if (this.$acceptCookiesButton.getAttribute('data-cookie-types') === 'all') {
this.$module.querySelector('.gem-c-cookie-banner__confirmation-message--accepted').hidden = false
}
window.GOVUK.approveAllCookieTypes()
if (window.GOVUK.useSingleConsentApi) {
window.GOVUK.singleConsent.setPreferences('accept')
} else {
window.GOVUK.approveAllCookieTypes()
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })
AshGDS marked this conversation as resolved.
Show resolved Hide resolved
}

this.$module.showConfirmationMessage()
this.$module.cookieBannerConfirmationMessage.focus()
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })

if (window.GOVUK.analyticsInit) {
window.GOVUK.analyticsInit()
}
if (window.GOVUK.globalBarInit) {
window.GOVUK.globalBarInit.init()
}
window.GOVUK.triggerEvent(window, 'cookie-consent')
if (!window.GOVUK.useSingleConsentApi) {
window.GOVUK.triggerEvent(window, 'cookie-consent')
}
}

CookieBanner.prototype.rejectCookieConsent = function () {
this.$module.querySelector('.gem-c-cookie-banner__confirmation-message--rejected').hidden = false
this.$module.showConfirmationMessage()
this.$module.cookieBannerConfirmationMessage.focus()
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })
window.GOVUK.setDefaultConsentCookie()
if (window.GOVUK.useSingleConsentApi) {
window.GOVUK.singleConsent.setPreferences('reject')
} else {
window.GOVUK.setDefaultConsentCookie()
window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 })
}
}

CookieBanner.prototype.showConfirmationMessage = function () {
Expand Down
@@ -0,0 +1,73 @@
window.GOVUK = window.GOVUK || {}
window.GOVUK.vars = window.GOVUK.vars || {}
window.GOVUK.vars.domains = [
{
// need to have this one at the start, see loadGa4 function
name: 'development',
domains: [
'localhost',
'127.0.0.1',
'0.0.0.0',
'dev.gov.uk'
],
initialiseGA4: true,
id: 'GTM-MG7HG5W',
auth: 'bRiZ-jiEHtw6hHpGd6dF9w',
preview: 'env-3',
gaProperty: 'UA-UNSET',
gaPropertyCrossDomain: 'UA-UNSET',
consentApiUrl: 'staging'
},
{
name: 'production',
domains: [
'www.gov.uk',
'www-origin.publishing.service.gov.uk',
'assets.publishing.service.gov.uk'
],
initialiseGA4: true,
id: 'GTM-MG7HG5W',
gaProperty: 'UA-26179049-1',
gaPropertyCrossDomain: 'UA-145652997-1',
consentApiUrl: 'production'
},
{
name: 'staging',
domains: [
'www.staging.publishing.service.gov.uk',
'www-origin.staging.publishing.service.gov.uk',
'assets.staging.publishing.service.gov.uk'
],
initialiseGA4: true,
id: 'GTM-MG7HG5W',
auth: 'oJWs562CxSIjZKn_GlB5Bw',
preview: 'env-5',
gaProperty: 'UA-26179049-20',
gaPropertyCrossDomain: 'UA-145652997-1',
consentApiUrl: 'staging'
},
{
name: 'integration',
domains: [
'www.integration.publishing.service.gov.uk',
'www-origin.integration.publishing.service.gov.uk',
'assets.integration.publishing.service.gov.uk'
],
initialiseGA4: true,
id: 'GTM-MG7HG5W',
auth: 'C7iYdcsOlYgGmiUJjZKrHQ',
preview: 'env-4',
gaProperty: 'UA-26179049-22',
gaPropertyCrossDomain: 'UA-145652997-1',
consentApiUrl: 'staging'
},
{
name: 'devdocs',
domains: [
'docs.publishing.service.gov.uk'
],
initialiseGA4: true,
id: 'GTM-TNKCK97',
consentApiUrl: 'production'
}
]
andysellick marked this conversation as resolved.
Show resolved Hide resolved
Expand Up @@ -12,31 +12,39 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
document.querySelector('form[data-module=cookie-settings]')
.addEventListener('submit', this.$module.submitSettingsForm)

this.setInitialFormValues()
if (window.GOVUK.useSingleConsentApi) {
window.GOVUK.singleConsent.init(this.setInitialFormValues.bind(this))
} else {
this.setInitialFormValues()
}
}

CookieSettings.prototype.setInitialFormValues = function () {
if (!window.GOVUK.cookie('cookies_policy')) {
window.GOVUK.setDefaultConsentCookie()
if (!window.GOVUK.useSingleConsentApi) {
window.GOVUK.setDefaultConsentCookie()
}
}

var currentConsentCookie = window.GOVUK.cookie('cookies_policy')
var currentConsentCookieJSON = JSON.parse(currentConsentCookie)
if (currentConsentCookie) {
var currentConsentCookieJSON = JSON.parse(currentConsentCookie)

// We don't need the essential value as this cannot be changed by the user
delete currentConsentCookieJSON.essential
// We don't need the essential value as this cannot be changed by the user
delete currentConsentCookieJSON.essential
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention this. Here you're deleting the essential cookie but not reintroducing it into the cookie object when the user submits the form.

Saving cookies isn't working properly in IE11 on this branch - it saves sucessfully, but then when I go to the homepage, the cookie settings I have in document.cookie are different to the ones that I saved.

Could this be because essential is missing from the cookie when the form is saved, causing something odd?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a problem with this branch, or more generally? I don't think I introduced this change. Would it be alright to log this as an issue and for it to not block this change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries - I've just tried it again and I think it's actually a weird IE11 caching thing. If I update my cookies, and go back to the homepage, the homepage gives me the old cookie state unless I add a cachebust query string to the URL. So don't worry about it


for (var cookieType in currentConsentCookieJSON) {
var radioButton
for (var cookieType in currentConsentCookieJSON) {
var radioButton

if (currentConsentCookieJSON[cookieType]) {
radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=on]')
} else {
radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=off]')
}
if (currentConsentCookieJSON[cookieType]) {
radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=on]')
} else {
radioButton = document.querySelector('input[name=cookies-' + cookieType + '][value=off]')
}

if (radioButton) {
radioButton.checked = true
if (radioButton) {
radioButton.checked = true
}
}
}
}
Expand All @@ -62,13 +70,15 @@ window.GOVUK.Modules = window.GOVUK.Modules || {};
}
}

window.GOVUK.setConsentCookie(options)
window.GOVUK.setCookie('cookies_preferences_set', true, { days: 365 })
if (window.GOVUK.useSingleConsentApi) {
window.GOVUK.singleConsent.setPreferences(null, options)
AshGDS marked this conversation as resolved.
Show resolved Hide resolved
} else {
window.GOVUK.setConsentCookie(options)
window.GOVUK.setCookie('cookies_preferences_set', true, { days: 365 })
}

this.fireAnalyticsEvent(options)

this.showConfirmationMessage()

return false
}

Expand Down
Expand Up @@ -163,7 +163,7 @@

YoutubeLinkEnhancement.prototype.campaignCookiesAllowed = function () {
var cookiePolicy = window.GOVUK.getConsentCookie()
return cookiePolicy !== null ? cookiePolicy.campaigns : true
return cookiePolicy !== null ? cookiePolicy.campaigns : false
}

YoutubeLinkEnhancement.nextId = function () {
Expand Down
@@ -0,0 +1,59 @@
/* global GovSingleConsent */
// = require govuk-single-consent/dist/singleconsent.iife.js

(function (root) {
'use strict'
window.GOVUK = window.GOVUK || {}

window.GOVUK.singleConsent = {
init: function (callback) {
if (!window.GOVUK.useSingleConsentApi) {
return
}
callback = callback || this.apiCallback
// determine where we are and set the consent api URL accordingly
if (!this.url) {
this.url = 'staging'
var environment = window.GOVUK.loadAnalytics.getEnvironment(window.GOVUK.analyticsGa4.core.trackFunctions.getHostname())
AshGDS marked this conversation as resolved.
Show resolved Hide resolved
if (environment) {
this.url = environment.consentApiUrl
}
}
// create the consent API object
this.consentApiObj = new GovSingleConsent(callback, this.url)
},

apiCallback: function (consents, consentsPreferencesSet, error) {
if (error) {
console.error('Single consent error: ', error, window.location)
return
}
if (consentsPreferencesSet) {
if (consents && consents.usage) {
window.GOVUK.triggerEvent(window, 'cookie-consent')
}
} else {
window.GOVUK.triggerEvent(window, 'show-cookie-banner')
}
},

setPreferences: function (type, options) {
if (window.GOVUK.useSingleConsentApi) {
try {
switch (type) {
case 'accept':
this.consentApiObj.setConsents(GovSingleConsent.ACCEPT_ALL)
break
case 'reject':
this.consentApiObj.setConsents(GovSingleConsent.REJECT_ALL)
break
default:
this.consentApiObj.setConsents(options)
}
} catch (e) {
console.error('Single consent ' + type + ' error: ', e, window.location)
}
}
}
}
}(window))