diff --git a/app/controllers/cookies_controller.rb b/app/controllers/cookies_controller.rb index 50d874e92..0e78fa1bc 100644 --- a/app/controllers/cookies_controller.rb +++ b/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 diff --git a/app/frontend/application.js b/app/frontend/application.js index ff4bae81a..36b730098 100644 --- a/app/frontend/application.js +++ b/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') diff --git a/app/frontend/cookie-banner.js b/app/frontend/cookie-banner.js new file mode 100644 index 000000000..e39414f72 --- /dev/null +++ b/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', '') + }) +} diff --git a/app/views/cookies/_banner.html.erb b/app/views/cookies/_banner.html.erb new file mode 100644 index 000000000..7885bad47 --- /dev/null +++ b/app/views/cookies/_banner.html.erb @@ -0,0 +1,48 @@ +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 2e5f66da1..c52b587f3 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -25,15 +25,15 @@ <% gtm_container = get_gtm_container %> <% gtm_id = get_gtm_id %> - - - - <% if cookies[:accept_analytics_cookies] == "on" %> + + + + <% else %> - - <% if cookies[:accept_analytics_cookies] %> + <% if cookies[:accept_analytics_cookies] == "on" %> + <% end %> + <% unless cookies[:accept_analytics_cookies] || current_page?(cookies_path) %> + <%= render "cookies/banner" %> + <% end %> + <%= govuk_skip_link %> <%= govuk_header( diff --git a/spec/views/layouts/application_layout_spec.rb b/spec/views/layouts/application_layout_spec.rb new file mode 100644 index 000000000..2ee571e09 --- /dev/null +++ b/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 = /