From 0ecbff6a8be5021e0ab7860ed4ea86935d13dd0e Mon Sep 17 00:00:00 2001 From: Tom Byers Date: Sun, 15 Dec 2019 19:36:29 +0000 Subject: [PATCH] Add consent tracking to cookie functions Taken from GOVUK components: https://github.com/alphagov/govuk_publishing_components/blob/master/app/assets/javascripts/govuk_publishing_components/lib/cookie-functions.js Also includes: - make new cookie functions handle notify domains - addition of hasConsentFor function to allow easy checking of consent for categories of cookie --- app/assets/javascripts/consent.js | 15 ++ .../javascripts/govuk/cookie-functions.js | 157 ++++++++++++++---- 2 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 app/assets/javascripts/consent.js diff --git a/app/assets/javascripts/consent.js b/app/assets/javascripts/consent.js new file mode 100644 index 000000000..e5953974d --- /dev/null +++ b/app/assets/javascripts/consent.js @@ -0,0 +1,15 @@ +(function (window) { + "use strict"; + + function hasConsentFor (cookieCategory) { + const consentCookie = window.GOVUK.getConsentCookie(); + + if (consentCookie === null) { return false; } + + if (!(cookieCategory in consentCookie)) { return false; } + + return consentCookie[cookieCategory]; + } + + window.GOVUK.hasConsentFor = hasConsentFor; +})(window); diff --git a/app/assets/javascripts/govuk/cookie-functions.js b/app/assets/javascripts/govuk/cookie-functions.js index fdabe48e3..5fa15bee7 100644 --- a/app/assets/javascripts/govuk/cookie-functions.js +++ b/app/assets/javascripts/govuk/cookie-functions.js @@ -1,8 +1,17 @@ -(function () { - "use strict"; +// used by the cookie banner component - var root = this; - if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; } +(function (root) { + 'use strict'; + window.GOVUK = window.GOVUK || {}; + + var DEFAULT_COOKIE_CONSENT = { + 'analytics': false + }; + + var COOKIE_CATEGORIES = { + '_ga': 'analytics', + '_gid': 'analytics' + }; /* Cookie methods @@ -19,38 +28,129 @@ Deleting a cookie: GOVUK.cookie('hobnob', null); */ - GOVUK.cookie = function (name, value, options) { - if(typeof value !== 'undefined'){ - if(value === false || value === null) { - return GOVUK.setCookie(name, '', { days: -1 }); + window.GOVUK.cookie = function (name, value, options) { + if (typeof value !== 'undefined') { + if (value === false || value === null) { + return window.GOVUK.setCookie(name, '', { days: -1 }); } else { - return GOVUK.setCookie(name, value, options); + // Default expiry date of 30 days + if (typeof options === 'undefined') { + options = { days: 30 }; + } + return window.GOVUK.setCookie(name, value, options); } } else { - return GOVUK.getCookie(name); + return window.GOVUK.getCookie(name); } }; - GOVUK.setCookie = function (name, value, options) { - if(typeof options === 'undefined') { - options = {}; + + window.GOVUK.getConsentCookie = function () { + var consentCookie = window.GOVUK.cookie('cookies_policy'); + var consentCookieObj; + + if (consentCookie) { + try { + consentCookieObj = JSON.parse(consentCookie); + } catch (err) { + return null; + } + + if (typeof consentCookieObj !== 'object' && consentCookieObj !== null) { + consentCookieObj = JSON.parse(consentCookieObj); + } + } else { + return null; } - var cookieString = name + "=" + value + "; path=/"; - if (options.days) { - var date = new Date(); - date.setTime(date.getTime() + (options.days * 24 * 60 * 60 * 1000)); - cookieString = cookieString + "; expires=" + date.toGMTString(); - } - if (document.location.protocol == 'https:'){ - cookieString = cookieString + "; Secure"; - } - document.cookie = cookieString; + + return consentCookieObj; }; - GOVUK.getCookie = function (name) { - var nameEQ = name + "="; + + window.GOVUK.setConsentCookie = function (options) { + var cookieConsent = window.GOVUK.getConsentCookie(); + + if (!cookieConsent) { + cookieConsent = JSON.parse(JSON.stringify(DEFAULT_COOKIE_CONSENT)); + } + + for (var cookieType in options) { + cookieConsent[cookieType] = options[cookieType]; + + // Delete cookies of that type if consent being set to false + if (!options[cookieType]) { + for (var cookie in COOKIE_CATEGORIES) { + if (COOKIE_CATEGORIES[cookie] === cookieType) { + window.GOVUK.cookie(cookie, null); + + if (window.GOVUK.cookie(cookie)) { + document.cookie = cookie + '=;expires=' + new Date() + ';domain=' + window.location.hostname.replace(/^www\./, '.') + ';path=/'; + } + } + } + } + } + + window.GOVUK.setCookie('cookies_policy', JSON.stringify(cookieConsent), { days: 365 }); + }; + + window.GOVUK.checkConsentCookieCategory = function (cookieName, cookieCategory) { + var currentConsentCookie = window.GOVUK.getConsentCookie(); + + // If the consent cookie doesn't exist, but the cookie is in our known list, return true + if (!currentConsentCookie && COOKIE_CATEGORIES[cookieName]) { + return true; + } + + currentConsentCookie = window.GOVUK.getConsentCookie(); + + // Sometimes currentConsentCookie is malformed in some of the tests, so we need to handle these + try { + return currentConsentCookie[cookieCategory]; + } catch (e) { + console.error(e); + return false; + } + }; + + window.GOVUK.checkConsentCookie = function (cookieName, cookieValue) { + // If we're setting the consent cookie OR deleting a cookie, allow by default + if (cookieName === 'cookies_policy' || (cookieValue === null || cookieValue === false)) { + return true; + } + + if (COOKIE_CATEGORIES[cookieName]) { + var cookieCategory = COOKIE_CATEGORIES[cookieName]; + + return window.GOVUK.checkConsentCookieCategory(cookieName, cookieCategory); + } else { + // Deny the cookie if it is not known to us + return false; + } + }; + + window.GOVUK.setCookie = function (name, value, options) { + if (window.GOVUK.checkConsentCookie(name, value)) { + if (typeof options === 'undefined') { + options = {}; + } + var cookieString = name + '=' + value + '; path=/'; + if (options.days) { + var date = new Date(); + date.setTime(date.getTime() + (options.days * 24 * 60 * 60 * 1000)); + cookieString = cookieString + '; expires=' + date.toGMTString(); + } + if (document.location.protocol === 'https:') { + cookieString = cookieString + '; Secure'; + } + document.cookie = cookieString; + } + }; + + window.GOVUK.getCookie = function (name) { + var nameEQ = name + '='; var cookies = document.cookie.split(';'); - for(var i = 0, len = cookies.length; i < len; i++) { + for (var i = 0, len = cookies.length; i < len; i++) { var cookie = cookies[i]; - while (cookie.charAt(0) == ' ') { + while (cookie.charAt(0) === ' ') { cookie = cookie.substring(1, cookie.length); } if (cookie.indexOf(nameEQ) === 0) { @@ -59,4 +159,5 @@ } return null; }; -}).call(this); +}(window)); +