Skip to content

Cookie Consent

Badger has its own cookie banner. On any site with Google Analytics or Hotjar set up, it asks visitors whether they accept analytics cookies, and neither tool loads until they accept. UK law (PECR) requires that consent before analytics cookies are set.

  • A site turns it on by applying the Cookie consent banner platform upgrade. It only appears on sites that have Google Analytics or Hotjar, or that hold back tracking code pasted into Site Text (see Tracking code pasted into Site Text). A site without analytics never shows it.
  • Visitors choose Accept analytics cookies or Reject analytics cookies. The two buttons look the same, because rejecting must be as easy as accepting.
  • A Cookie settings button opens the banner again, so visitors can change their mind at any time. Changing from accept to reject deletes the Google Analytics and Hotjar cookies.
  • When the cookies a site uses change, change the policy version and everyone is asked again.
  • A browser that sends Global Privacy Control (a "don't track me" setting in Firefox, Brave and some extensions) is treated as having rejected: the banner doesn't open and analytics stays off. The visitor can still accept through Cookie settings.
  • YouTube videos load only when clicked, on every site, whether or not the banner is on. Until then the page shows the block's poster image (chosen from the media library) or a plain dark panel, with a play button. Nothing loads from YouTube or Google, so no cookies are set for visitors who don't watch. A line under each video says "Plays from YouTube, which may set cookies", with a link to the cookie policy. It's left out for a visitor who has accepted cookies on a site with the banner on.
  • Every choice is logged as evidence of consent, without recording who made it (see The consent log).

Strictly necessary cookies never wait for consent: the basket, sign-in and session cookies, and Stripe's fraud-prevention cookies.

Setting it up

  1. Remove any other consent tool (such as Cookiebot). Remove tracking code pasted into Site Text or an HTML block, or mark it so the banner holds it back (see below).
  2. Apply Cookie consent banner under Settings → Platform upgrades. It turns the banner on and, if the site has no policy version yet, sets it to today's date.
  3. Set Cookie Policy Page to the page that explains your cookies.

The settings are under Settings → Store → Cookie consent:

Setting What it does
Ask for Cookie Consent (cookie-consent-enabled) Off until the platform upgrade turns it on. Leave it off if the site uses its own consent tool, such as Cookiebot.
Cookie Policy Version (cookie-consent-version) Any label for the current cookie policy, such as its date. Change it when the cookies you use change, and every visitor is asked again.
Cookie Policy Page (cookie-policy-url) Where the banner's "Read our Cookie Policy" link goes, such as /p/cookies. Empty uses the Privacy Policy URL from the legal entity settings, or shows no link if that's empty too.
Hold Back Pasted Tracking Code (cookie-consent-pasted-scripts) Turn on when the site's only tracking is code pasted into Site Text and marked as below. The banner then appears even though Google Analytics and Hotjar aren't set up in Badger.

By default a small Cookie settings button appears at the very bottom of every page. To put it with your other footer links instead, add a link to #cookie-settings (for example <a href="#cookie-settings">Cookie settings</a> in the footer's Site Text). Clicking it opens the banner, and the default button then stays hidden.

Wording

The banner text comes from the cookieConsent.* messages, so a site can change it through Site Text like any other storefront message.

Tracking code pasted into Site Text

The banner holds back the Google Analytics and Hotjar extensions by itself. A tracking script pasted straight into Site Text or an HTML block loads for everyone unless you mark it. Change its type to text/plain and add data-badger-consent="analytics":

<!-- before -->
<script async src="https://example-tracker.com/t.js"></script>
<script>startTracking();</script>

<!-- after -->
<script type="text/plain" data-badger-consent="analytics" async src="https://example-tracker.com/t.js"></script>
<script type="text/plain" data-badger-consent="analytics">startTracking();</script>

The browser doesn't run a text/plain script. Once a visitor has accepted, the banner's script swaps each marked script for a working copy, in page order. Visitors who reject or haven't chosen never run it.

The marked code runs only where the banner is active. On a site with no Google Analytics or Hotjar set up in Badger, turn on Hold Back Pasted Tracking Code, or the marked code never runs.

Using the extensions is still better where one exists: the server leaves their scripts out of the page entirely.

How it works

The visitor's choice

The choice lives in the visitor's bdgr_consent cookie for 12 months. The cookie holds:

  • a random consent id
  • whether they accepted analytics
  • when they chose
  • the policy version they answered

The server reads it on every page:

  • GoogleAnalyticsExtension and HotjarExtension render nothing unless the visitor has accepted the current version. The tracking scripts aren't in the page at all, rather than being present but disabled.
  • CookieConsentExtension, a global extension in the analytics slot that every theme's footer renders, shows the banner open when the visitor hasn't answered the current version. Otherwise it renders closed, ready for Cookie settings to open it.

A choice for an older version counts as no choice, so the banner opens and analytics stays off.

The banner also carries data-analytics="true|false", the same answer, for switching on marked pasted scripts. A visitor who hasn't chosen but whose browser sends Sec-GPC: 1 (Global Privacy Control) gets the banner closed rather than open. With no choice recorded, analytics stays off.

When a visitor clicks Accept or Reject, the page posts to POST /api/cookie-consent ({"analytics": true}). The endpoint logs the choice, sets the cookie, and the page reloads. It accepts JSON only, so another website can't accept cookies on a visitor's behalf.

Each choice adds an entry to the cookieConsentLog collection. An entry holds:

  • the consent id
  • the site
  • the policy version
  • the answer
  • the time

It deliberately holds no user id, IP address or browser details. It identifies no one, so it needs no erasure handling and doesn't appear in Subject Access Request packs. Mongo deletes each entry after 400 days, a little longer than the cookie lasts.

To show that a particular visitor consented, take the consent id from their bdgr_consent cookie (the first part of the value, before the first .) and look up its entries. The log also gives accept and reject counts for each policy version.

If the log can't be written, the visitor's choice still takes effect through their cookie.

Classes

Class Role
CookieConsentService / CookieConsentServiceImpl Whether the site asks, whether a choice allows analytics, recording a choice (commerce-core/.../consent/)
CookieConsentCookie Reads and writes the bdgr_consent cookie
CookieConsentRecord One consent log entry, with its 400-day TTL
CookieConsentExtension The banner (commerce-core/.../extensions/consent/)
CookieConsentController POST /api/cookie-consent (web-mvc)
CookieConsentUpgrade The platform upgrade that turns the banner on for a site
YoutubeVideoExtension + youtube-facade.js Click-to-load YouTube: the poster image or a plain panel until the visitor clicks, then the youtube-nocookie.com player
extensions/cookieConsentExtension/banner.html One template for every theme, styled by themes/shared/css/extensions/cookieConsent/cookie-consent.css

Limits

  • The banner appears wherever storefront extensions render: pages, products, collections, search and checkout. Pages without extensions, such as sign-in, don't show it, but analytics doesn't load on them either.
  • Global Privacy Control is read from the request header. Browsers that only expose it to scripts (navigator.globalPrivacyControl) aren't detected.
  • Consent is per browser. A shopper is asked again on a new device or browser.
  • There's one choice, analytics. A site that adds advertising or remarketing tags needs a separate marketing choice, which isn't built yet.