Skip to main content

Cookie Consent Banner

Shopify provides a built-in cookie consent banner that helps your store comply with privacy regulations like GDPR, CCPA, and ePrivacy. In Hydrogen storefronts, this banner requires specific configuration to work correctly because the standard Liquid-based initialization is not available. This guide walks you through the complete setup, common pitfalls, and how to verify the banner is working.

How It Works

Shopify’s cookie consent system consists of two parts:
  1. Customer Privacy API (consent-tracking-api.js) — Manages visitor consent state and cookies
  2. Privacy Banner (storefront-banner.js) — The visible UI that collects consent from visitors
In a Hydrogen 2026.10 storefront, these scripts are loaded by the <ShopifyScripts> component from @shopify/hydrogen/react, which replaces classic Hydrogen’s <Analytics.Provider>. The banner’s appearance and behavior (text, regions, position) are configured in Shopify Admin under Settings → Customer privacy.
The banner configuration (text, regions, theme) is managed entirely in Shopify Admin — not in your Hydrogen code. Your code only needs to pass the correct credentials.

Setup

In your root loader’s critical data function (typically app/.server/root.ts), return the consent mode, the public Storefront API token, and the shop and i18n props for ShopifyScripts. Keep them per market, never per shopper, so the document stays cacheable:
storefront.i18n.currency is set by your Storefront client’s request context; see Pilot’s app/.server/root.ts for the full version.
The storefrontAccessToken must be your public Storefront API token (32 characters). Never use a private/admin API token (starts with shpat_).
In your root layout (app/root.tsx), render <ShopifyScripts> first in <head> and pass the consent mode:
useNonce comes from your theme’s CSP helpers (see Content Security Policy), and routeTemplates from createShopifyRouteTemplates(); see Step 10 of the v6 migration guide.

Step 3: Expose the Storefront Access Token to the Banner

This is the critical step that most setups miss. The banner script (storefront-banner.js) loads and self-initializes before React hydrates, and needs your public Storefront API token to authenticate with the Storefront API. Render the token in a #shopify-features JSON script in <head>, before <ShopifyScripts>, so it’s available before the banner script executes:
The suppressHydrationWarning attribute is needed because this script’s output can differ between server and client renders, which is expected and harmless.

Step 4: Configure the Banner in Shopify Admin

  1. Go to Shopify Admin → Settings → Customer privacy
  2. Under Cookie banner, click Set up or Edit
  3. Configure:
    • Banner position — Bottom center, bottom left, etc.
    • Banner text — Customize the consent message
    • Button labels — Accept, Decline, Manage preferences
    • Region visibility — Select which countries see the banner
    • Theme — Light or dark, custom colors
  4. Click Save

Step 5: Set Up Environment Variables

Ensure these variables are set in your .env file and deployment environment:
The PUBLIC_CHECKOUT_DOMAIN should be your custom checkout domain (e.g., checkout.yourdomain.com). If you don’t have a custom domain, use your .myshopify.com domain.

Verifying the Banner Works

Preview Mode

Add ?preview_privacy_banner=1 to any page URL to force the banner to display regardless of region or prior consent:
This is useful for testing during development. Without this parameter, the banner only appears for visitors in configured regions who haven’t yet given consent.

Checklist

Use this checklist to verify your setup:
  • consent.mode is "default-banner" in the root loader and reaches <ShopifyScripts consent={{ mode }}>
  • storefrontAccessToken is a valid 32-character public token
  • The #shopify-features script with the token is rendered in <head> before <ShopifyScripts>
  • Banner appears with ?preview_privacy_banner=1
  • Banner appears for visitors in configured regions (without preview param)
  • Accepting/declining sets the _tracking_consent cookie
  • window.Shopify.customerPrivacy is not null after page load

Browser Console Check

Open DevTools and verify the privacy API initialized:

Troubleshooting

”Error initializing banner: Missing access token”

Cause: The banner script loaded without finding the public Storefront API token. Fix: Add the #shopify-features script in Step 3 to <head>, before <ShopifyScripts>.

”Could not find liquid access token”

Cause: This is a harmless warning. The banner script first checks for a Liquid-based token (used in traditional Shopify themes). In Hydrogen, this path doesn’t exist, so the script falls back to the Storefront API path. Resolution: This warning can be safely ignored as long as the Storefront API token is correctly configured. Cause: The banner’s init() function failed silently because it couldn’t find the access token during initial load. With ?preview_privacy_banner=1, the script forces initialization and bypasses this check. Fix: Ensure Step 3 is implemented — the #shopify-features script must carry the token in the server-rendered HTML, before React hydrates.

window.Shopify.customerPrivacy is null

Cause: The banner script failed to initialize, which means it never set up the Customer Privacy API. This prevents the banner from showing and analytics consent from working. Fix: This is almost always caused by the missing access token (follow Step 3), or by a CSP nonce that doesn’t reach <ShopifyScripts>. Check the console for CSP violations. Cause: The region visibility configuration in Shopify Admin may not include the visitor’s country. Fix: Go to Shopify Admin → Settings → Customer privacy → Cookie banner and verify the region visibility list includes the target countries.

React Hydration Error (#418) Alongside Banner Errors

Cause: A hydration mismatch between server-rendered HTML and client-rendered output. This is separate from the banner issue but often appears together. Resolution: Use suppressHydrationWarning on the inline script tag (as shown in Step 3). For other hydration errors, check that your components render the same content on server and client.

How the Banner Initialization Flow Works

Understanding the initialization sequence helps with debugging:

Further Reading

Last modified on November 10, 2026