A rails engine for managing cookie consent in Citizens Advice websites and applications.
This engine can be integrated into host apps and used to manage cookies
based on the consent types of essential, analytics and video players
The engine provides a cookie preferences page, cookie banner, cookie confirmation banner and cookie management logic.
The engine uses a combination of Rails and JavaScript to manage cookie consent, and has fallbacks for users without JavaScript enabled.
Add this snippet to your application's Gemfile, updating the tag to the latest published version of the engine:
gem "citizens_advice_cookie_preferences",
github: "citizensadvice/cookie-preferences",
tag: "v0.4.0"And then execute:
$ bundle installMount the engine in your routes.rb file. You do not need to include (/:country) if your
host app doesn't support multiple countries:
mount CitizensAdviceCookiePreferences::Engine, at: "(/:country)/cookie-preferences"Import the helpers from the gem into application_controller.rb
include CitizensAdviceCookiePreferences::HelpersAdd cookie banner to application.html.haml:
- unless cookies_preference_page?
= render CitizensAdviceCookiePreferences::CookieBanner.newor to the erb file:
<% unless cookies_preference_page? %>
<%= render CitizensAdviceCookiePreferences::CookieBanner.new %>Include cookies javascript in application.html.haml:
= javascript_include_tag "citizens_advice_cookie_preferences/application", nonce: trueor to the erb file:
<% javascript_include_tag "citizens_advice_cookie_preferences/application", nonce: true %>Add to your main .scss file:
@import "citizens_advice_cookie_preferences/components/cookie-banner";
@import "citizens_advice_cookie_preferences/components/cookie-preferences";In package.json, add the following to your build css script:
--load-path=$(bundle show citizens_advice_cookie_preferences)/app/assets/stylesheets
Exact commands will vary according to those defined in your application's package.json.
Example from energy-apps:
yarn build && yarn build:cssAdd a new data layer variable analyticsCookiesAccepted. We use it in GTM to trigger overriding consent mode.
In data_layer.rb (or equivalent file)
# e.g. from energy-apps
def default_data_layer_properties
properties = {
#data layer properties go here
}
if allow_analytics_cookies?
properties.merge({ analyticsCookiesAccepted: "True" })
else
properties
end
endSeparate setting data layer from GTM snippet, and only render GTM snippets if user has accepted analytics cookies.
In the no script tag:
- if allow_analytics_cookies?
%noscript
%iframe{ src: "https://www.googletagmanager.com/ns.html?id=<GTM container id>",
height: "0", width: "0", style: "display:none;visibility:hidden" }In the head analytics tag:
%script{ id: "script-data-layer", nonce: content_security_policy_nonce }
window.dataLayer = window.dataLayer || [];
- if data_layer_properties.present?
dataLayer.push(#{data_layer_properties.to_json.html_safe})
- if allow_analytics_cookies?
%script{ id: "script-google-tag-manager", nonce: content_security_policy_nonce }
(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;var n=d.querySelector('[nonce]');
n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<GTM container id>>');We use LOCAL_RETURN_HOST for the return url functionality of the success message banner on the preferences page.
It needs to be configured to point to the localhost host for local development. It is also configurable for feature tests running in GitHub Actions.
The host apps don't need the env var set up for production - we also check if .citizensadvice.org.uk part the host, which also allows using subdomains.