Browse Source

CLDC-1618 Add cookie banner (#973)

* CLDC-1618 Add cookie banner

* CLDC-1618 Add analytics script inclusion tests

* CLDC-1618 Include cookie banner JS

* CLDC-1618 Appease JS Standard
pull/1003/head^2
Sam 2 years ago committed by GitHub
parent
commit
9c5d52c78b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      app/controllers/cookies_controller.rb
  2. 7
      app/frontend/application.js
  3. 57
      app/frontend/cookie-banner.js
  4. 48
      app/views/cookies/_banner.html.erb
  5. 24
      app/views/layouts/application.html.erb
  6. 57
      spec/views/layouts/application_layout_spec.rb

6
app/controllers/cookies_controller.rb

@ -18,6 +18,12 @@ class CookiesController < ApplicationController
redirect_to cookies_path
end
format.json do
render json: {
status: "ok",
message: %(You’ve #{analytics_consent == 'on' ? 'accepted' : 'rejected'} analytics cookies.),
}
end
end
end

7
app/frontend/application.js

@ -4,18 +4,19 @@
// files to reference that code so it'll be compiled.
// Polyfills for IE
import '@stimulus/polyfills'
import '@webcomponents/webcomponentsjs'
import 'core-js/stable'
import 'regenerator-runtime/runtime'
import '@stimulus/polyfills'
import 'custom-event-polyfill'
import 'intersection-observer'
import 'regenerator-runtime/runtime'
//
import { initAll as GOVUKFrontend } from 'govuk-frontend'
import { initAll as GOVUKPrototypeComponents } from 'govuk-prototype-components'
import './styles/application.scss'
import './controllers'
import './cookie-banner'
import './styles/application.scss'
require.context('govuk-frontend/govuk/assets')

57
app/frontend/cookie-banner.js

@ -0,0 +1,57 @@
const cookieBannerEl = document.querySelector('.js-cookie-banner')
if (cookieBannerEl) {
const cookieFormEl = document.querySelector('.js-cookie-form')
cookieFormEl.addEventListener('click', (e) => {
if (e.target.tagName !== 'BUTTON') {
return
}
const body = new window.FormData(cookieFormEl)
body.append('cookies_form[accept_analytics_cookies]', e.target.value)
fetch(cookieFormEl.action, {
method: 'PUT',
headers: {
Accept: 'application/json'
},
body
})
.then((res) => {
if (res.status >= 200 && res.status < 300) {
return res
}
throw new Error(res)
})
.then((res) => res.json())
.then(({ message }) => {
const messageEl = cookieBannerEl.querySelector('.js-cookie-message')
messageEl.textContent = message
cookieBannerEl
.querySelector('.js-cookie-banner__form')
.setAttribute('hidden', '')
cookieBannerEl
.querySelector('.js-cookie-banner__success')
.removeAttribute('hidden')
})
const gaSrc = window.analyticsScript
if (e.target.value === 'on' && gaSrc) {
const scriptEl = document.createElement('script')
scriptEl.src = gaSrc
document.body.appendChild(scriptEl)
}
e.preventDefault()
})
const hideBannerEl = document.querySelector('.js-hide-cookie-banner')
hideBannerEl.addEventListener('click', (e) => {
e.preventDefault()
cookieBannerEl.setAttribute('hidden', '')
})
}

48
app/views/cookies/_banner.html.erb

@ -0,0 +1,48 @@
<div class="govuk-cookie-banner js-cookie-banner" role="region" aria-label="Cookies on CORE">
<div class="govuk-cookie-banner__message govuk-width-container js-cookie-banner__form">
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h2 class="govuk-cookie-banner__heading govuk-heading-m">Cookies on CORE</h2>
<div class="govuk-cookie-banner__content">
<p class="govuk-body">We use some essential cookies to make this service work.</p>
<p class="govuk-body">We’d like to use analytics cookies so we can understand how you use the service and make improvements.</p>
</div>
</div>
</div>
<%= form_with url: cookies_path, class: "js-cookie-form", method: :put do |f| %>
<div class="govuk-button-group">
<button type="submit" class="govuk-button" name="cookies_form[analytics_consent]" value="on">
Accept analytics cookies
</button>
<button type="submit" class="govuk-button" name="cookies_form[analytics_consent]" value="off">
Reject analytics cookies
</button>
<%= govuk_link_to "View cookies", cookies_path %>
</div>
<% end %>
</div>
<div class="govuk-cookie-banner__message govuk-width-container js-cookie-banner__success" role="alert" hidden>
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<div class="govuk-cookie-banner__content">
<p class="govuk-body">
<span class="js-cookie-message">
You’ve set your cookie preferences.
</span>
You can <%= govuk_link_to "change your cookie settings", cookies_path %> at any time.
</p>
</div>
</div>
</div>
<div class="govuk-button-group">
<button class="govuk-button js-hide-cookie-banner">
Hide this message
</button>
</div>
</div>
</div>

24
app/views/layouts/application.html.erb

@ -25,15 +25,15 @@
<% gtm_container = get_gtm_container %>
<% gtm_id = get_gtm_id %>
<!-- Google Tag Manager (doesn't store personal info until permission given) -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<%= gtm_container %>');</script>
<!-- End Google Tag Manager -->
<% if cookies[:accept_analytics_cookies] == "on" %>
<!-- Google Tag Manager (doesn't store personal info until permission given) -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<%= gtm_container %>');</script>
<!-- End Google Tag Manager -->
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= gtm_id %>"></script>
<% else %>
<script>
@ -72,13 +72,17 @@
document.body.className = ((document.body.className) ? document.body.className + " js-enabled" : "js-enabled");
</script>
<!-- Google Tag Manager (noscript) -->
<% if cookies[:accept_analytics_cookies] %>
<% if cookies[:accept_analytics_cookies] == "on" %>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=<% gtm_container %>" height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<% end %>
<% unless cookies[:accept_analytics_cookies] || current_page?(cookies_path) %>
<%= render "cookies/banner" %>
<% end %>
<%= govuk_skip_link %>
<%= govuk_header(

57
spec/views/layouts/application_layout_spec.rb

@ -0,0 +1,57 @@
require "rails_helper"
RSpec.describe "layouts/application" do
shared_examples "analytics cookie elements" do |banner:, scripts:|
define_negated_matcher :not_match, :match
it "#{banner ? 'includes' : 'omits'} the cookie banner" do
banner_text = "We’d like to use analytics cookies so we can understand how you use the service and make improvements."
if banner
expect(rendered).to match(banner_text)
else
expect(rendered).not_to match(banner_text)
end
end
it "#{scripts ? 'includes' : 'omits'} the analytics scripts" do
gtm_script_tag = /<script.*googletagmanager/
gtm_iframe_tag = /<iframe.*googletagmanager/
if scripts
expect(rendered).to match(gtm_script_tag).and match(gtm_iframe_tag)
else
expect(rendered).to not_match(gtm_script_tag).and not_match(gtm_iframe_tag)
end
end
end
context "with no cookie set" do
before do
cookies[:accept_analytics_cookies] = nil
render
end
include_examples "analytics cookie elements", banner: true, scripts: false
it "sets window.analyticsScript for the JS to refer to if the user accepts" do
expect(rendered).to match(/window\.analyticsScript = "https:\/\/www\.googletagmanager\.com\/gtag\/js\?id=G-[\w\d]+"/)
end
end
context "with analytics accepted" do
before do
cookies[:accept_analytics_cookies] = "on"
render
end
include_examples "analytics cookie elements", banner: false, scripts: true
end
context "with analytics rejected" do
before do
cookies[:accept_analytics_cookies] = "off"
render
end
include_examples "analytics cookie elements", banner: false, scripts: false
end
end
Loading…
Cancel
Save