A cookie consent banner decides what your tracking is allowed to see. Set it up well, and GA4, Google Ads and Meta get every signal they’re allowed to have. Set it up badly, and you get purchases in Direct, landing pages that look like they lose everyone, Meta landing page views falling, and sometimes tags that fire before anyone agreed. This guide covers how to set up a consent management platform (CMP) properly on Shopify: the choice of banner, where to load it, what happens to the first page view before consent, how to share consent with the checkout, and how to debug it.
This is a tracking guide, not legal advice. What your banner must show, and where, is a question for your lawyer or DPO.
What a CMP has to do on Shopify
On most websites, a CMP shows a banner and tells your tags what the visitor chose. On Shopify, it has four jobs:
- Collect and store the choice, by category: analytics, marketing, preferences, and sale of data where it applies.
- Tell Google tags through Consent Mode v2:
analytics_storage,ad_storage,ad_user_dataandad_personalization. - Block or allow every other tag: the Meta Pixel, TikTok, Pinterest, Clarity, Hotjar, and scripts added by apps.
- Pass the choice to Shopify through the Customer Privacy API, so Shopify’s own pixels, app pixels, your custom pixel and the checkout all know what the visitor accepted.
Most broken setups I audit do the first two and forget the last two. The banner looks fine, Google tags respect it, and the checkout knows nothing.
Choosing your banner type
There are three ways to present consent, and each one has a direct effect on your data.
1. A blocking banner
The banner covers the page, or blocks scrolling and clicks, until the visitor chooses. Done properly, “Reject all” is as easy to find as “Accept all”.
- For tracking: almost every visitor decides on the landing page. Your landing page hit is sent with a known consent state, so the session keeps its source: the campaign, the
gclid, the UTMs. Direct and Unassigned stay low. - The cost: some visitors leave at the banner. They’re link clicks without landing page views in Meta, and bounces in your analytics if their page view was sent before they left.
- Best for: stores in strict markets that want clean attribution and accept a bit of friction.
2. An optional banner
The banner sits at the bottom of the page. Visitors can browse without choosing, and many never do. In the EU, no choice means no consent.
- For tracking: a large share of sessions stays denied the whole time. Visitors who accept on their second or third page start a tracked session there, without the landing page and often without its source. That’s one of the main causes of purchases attributed to Direct or Unassigned, and of landing page reports where your home page “loses” everyone.
- The benefit: less friction on the first page.
- Best for: stores that care more about the first impression than attribution. If you choose it, advanced Consent Mode and
url_passthroughmatter even more.
3. No banner
Some stores sell only in regions where consent isn’t required before tracking, or use an opt-out model such as the “Do not sell or share my personal information” link in some US states.
- For tracking: everything is granted by default, so tracking is complete. In regions with opt-out rules, the Global Privacy Control signal and opt-out choices must still be honoured, and Shopify handles
sale_of_dataseparately. - The risk: a store that sells in the EU, the UK or Switzerland without a banner is exposed legally, and Google requires consent signals for EEA traffic to use its ads features fully.
- Best practice: use one CMP with rules by region: a banner for the EEA, the UK and Switzerland, granted defaults or an opt-out model elsewhere.
Where to load the CMP
| Method | How it loads | Pros | Cons |
|---|---|---|---|
| Shopify’s own cookie banner | Settings → Customer privacy | Free, built into the Customer Privacy API and the checkout | Few design and category options, no Consent Mode for tags in your theme by itself |
| A CMP app | Theme app embed | No code, usually integrated with the Customer Privacy API, survives theme changes | Load order isn’t always under your control, quality of the Shopify integration varies |
In theme.liquid | CMP script at the top of <head> | Loads first, before GTM and apps, predictable order | Tied to the theme, you connect the Customer Privacy API yourself if the CMP doesn’t |
| Through GTM | CMP tag on the Consent Initialization trigger | No theme edits, Consent Mode handled by the CMP’s template | Can’t block scripts outside GTM, shows later, disappears if GTM is blocked |
Loading it in theme.liquid
The CMP and the Consent Mode defaults must come before GTM in the <head>:
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('consent', 'default', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'denied',
wait_for_update: 500
});
gtag('set', 'url_passthrough', true);
</script>
<!-- your CMP script -->
<!-- Google Tag Manager -->
If the CMP reads the visitor’s saved choice and sends a consent update before GTM fires its first tags, returning visitors are tracked from their first hit. If the defaults come after GTM, the first tags fire without any consent state: either they’re blocked by mistake, or they send data they shouldn’t.
Loading it through GTM
Most CMPs (Cookiebot, Didomi, Axeptio, OneTrust, Usercentrics and others) have a GTM template. Put it on the Consent Initialization – All Pages trigger so it sets defaults and restores saved choices before any other tag. Three limits to know:
- It only controls GTM. Scripts in your theme, app embeds and Shopify’s own pixels don’t go through GTM. Your CMP must still tell Shopify about the choice, and app pixels must be controlled through the Customer Privacy API.
- The banner appears later, after GTM loads, so more visitors scroll or leave before they see it.
- If GTM is blocked, by an ad blocker for example, there’s no banner. Your GTM tags don’t run either, but anything outside GTM does.
If you use a CMP app on Shopify, check whether it already sets Consent Mode. Don’t also add its GTM template: two sources of consent updates produce conflicting states.
Consent Mode for GA4 and Google Ads
Consent Mode has two modes, and the difference is what happens before the visitor chooses:
- Basic: Google tags don’t load until consent is granted. Nothing is sent before, not even the consent state. Visitors who refuse are invisible, and there’s nothing to model.
- Advanced: Google tags load with consent denied and send cookieless pings: no cookies, no persistent ID, marked as denied. GA4 and Google Ads use them for modeling. Once the visitor accepts, the tags send full data.
For most Shopify stores, advanced mode with denied defaults in the EEA, the UK and Switzerland is the right choice. Two settings help it:
url_passthroughkeeps ad click identifiers in your internal links whenad_storageis denied, so a conversion can still be attributed to the click after a later accept.ads_data_redactionremoves ad click identifiers from pings whenad_storageis denied, for stores that want to be stricter.
Use region-specific defaults if you sell outside Europe: denied for EEA countries, the UK and Switzerland, granted elsewhere if that’s legal for you. Consent Mode uses the most specific region that matches.
GA4’s behavioral modeling needs enough volume: Google’s guidance is at least 1,000 events a day with analytics consent denied for 7 days, and at least 1,000 daily users with consent granted on 7 of the last 28 days. Smaller stores won’t be modeled, but advanced mode still gives Google Ads more signals than basic.
Tags that aren’t Google
Meta, TikTok, Pinterest, Clarity and most other tags don’t understand Consent Mode the way Google tags do. They must be blocked until the right consent, then fired.
- In GTM, set each tag’s consent settings to require
ad_storage(oranalytics_storagefor analytics tools). - Add a trigger on the consent update for page-level tags such as the Meta Pixel’s
PageView. GTM doesn’t fire a blocked tag again when consent changes. Without that trigger, a visitor who accepts on the landing page sends noPageViewfor that page, which is a common cause of a Meta landing page view rate drop. - Some tags have their own consent API, such as
fbq('consent', 'revoke')andfbq('consent', 'grant')for Meta. If you use them, the pixel can load early and hold events until consent. - App pixels on Shopify, such as the Facebook & Instagram app or TikTok’s app, follow the Customer Privacy API. If your CMP doesn’t write to it, they follow Shopify’s default for the visitor’s region, which may not match the banner.
What happens to the first page view before consent?
This is where most of the damage happens. A visitor lands from a campaign, the page loads, the banner appears. What does each tool see?
| Scenario | GA4 | Google Ads | Meta (blocked until consent) |
|---|---|---|---|
| Accepts on the landing page, basic mode | Nothing until accept. The page view is sent only if a tag fires on the consent update. | Same: no click data until accept. | PageView only if a tag fires on the consent update. |
| Accepts on the landing page, advanced mode | Cookieless ping, then full data after accept. Tests by practitioners show the Google tag can resend the page’s hits after consent is granted, but Google doesn’t document it: test it. | Cookieless ping, then the click is stored once ad_storage is granted. | PageView only if a tag fires on the consent update. |
| Accepts on a later page | The tracked session starts on that page. The landing page and often its source are lost: Direct, Unassigned or a self-referral. | The click can still be attributed if url_passthrough kept the gclid in the URL. | Landing page view lost for that click. |
| Never chooses | Advanced: cookieless pings only. Basic: nothing. | Advanced: pings for modeling. Basic: nothing. | Nothing. |
| Refuses | Same as never chooses. | Same as never chooses. | Nothing. |
Does GA4 resend the page view in the background once consent is granted? Not in a way you should rely on. In practice:
- Returning visitors: the CMP must restore their saved choice before GTM’s first tags. Then their landing page hit is complete. Check it with GTM Preview: the consent state on the first event must already be granted.
- New visitors who accept on the landing page: make sure the page view, and the Meta and TikTok page events, fire on the consent update when they haven’t fired with consent yet. Test that it isn’t sent twice.
- New visitors who accept later: keep campaign information on internal links with
url_passthrough, and accept that some attribution is lost. A blocking banner reduces this case.
Sharing consent with the checkout
Your theme’s banner doesn’t run in the checkout, and neither does GTM from your theme. The checkout only knows what the visitor chose if your CMP wrote it to Shopify.
- The CMP calls the Customer Privacy API with
setTrackingConsentwhenever the visitor chooses, for analytics, marketing and preferences, andsale_of_datawhere it applies. Many CMP apps do this for you. Check it, don’t assume it. The code is in Consent Mode v2 on Shopify with the Customer Privacy API. - Your custom pixel reads it from
init.customerPrivacywhen it loads, and listens for changes withcustomerPrivacy.subscribe("visitorConsentCollected"). It sets Consent Mode defaults and updates from those values before GTM loads. - Choose the pixel’s customer privacy setting consciously. If it requires consent, Shopify only loads the pixel once the visitor accepts, so there are no cookieless pings in the checkout. If it doesn’t, the pixel always loads, and your code must apply Consent Mode itself.
Visitors who reach the checkout without visiting your store pages, from an abandoned cart email or a Shop Pay link for example, never saw your banner. They get Shopify’s default for their region. Decide whether that’s what you want.
Don’t read or write Shopify’s consent cookies directly. Shopify says their format can change. Use the API.
How to debug consent
In the browser console
// what Shopify knows
Shopify.customerPrivacy.currentVisitorConsent();
// what Google tags know (latest consent commands)
dataLayer.filter((e) => e[0] === "consent");
In GTM Preview
Click the first event, Consent Initialization, then the Consent tab. You should see the defaults set there, before any tag fires. After accepting, the consent update event should show the new state. On each tag, the consent column shows whether it was blocked, and why.
In network requests
Filter the Network tab on collect for GA4. The gcs parameter shows ad_storage and analytics_storage:
G100: both deniedG110: ads granted, analytics deniedG101: ads denied, analytics grantedG111: both granted
The gcd parameter is sent on every request and encodes all four signals, including whether each one came from a default or an update.
In the checkout
Use the Shopify Pixel Helper, and log init.customerPrivacy from your custom pixel during testing. On the purchase, check gcs: it should match what the visitor chose on your store pages.
The test matrix
Run each case in a new private window, from a campaign URL with UTMs and a test gclid:
- No choice, then browse two pages.
- Reject on the landing page.
- Accept on the landing page.
- Accept on the second page.
- Accept, then change your mind in the banner settings.
- Accept, then complete a test order.
- From another region with a VPN, if you use region-specific rules.
For each case, check GA4 DebugView, the Meta Pixel Helper and the purchase. The quick version of this test is in does your cookie banner actually reach your pixels?
Symptoms of a broken CMP
| Symptom | Likely cause |
|---|---|
| Purchases attributed to Direct or Unassigned | Consent not passed to the checkout, or sessions starting after a late accept without the landing page. See Shopify purchases attributed to Direct or Unassigned. |
| High bounce rate, many one-page sessions | The page view fires again on consent update with a new client ID, splitting one visit into two sessions, or the landing page hit is missing so sessions look like they start and end on one page. |
| Landing pages that look like the second page of a visit | Tracked sessions start after a late accept on a non-blocking banner. |
| Meta landing page view rate drops | The pixel is blocked on page load and never fired after consent, or a new banner lowers acceptance. |
| Google Ads conversions drop after a banner change | Basic mode or missing ad_user_data, so conversions and enhanced conversions are lost for consented users too. Check Consent Mode status in Google Ads diagnostics. |
| GA4 traffic falls in some countries only | Wrong region-specific defaults. |
| Purchases consented on the store, denied in the checkout | The CMP doesn’t call setTrackingConsent. |
| Tags fire before any choice | The CMP or the defaults load after GTM, or app scripts aren’t blocked. This is a legal problem, not only a data one. |
| Numbers that didn’t change at all after adding the banner | Tags ignore consent. Also a legal problem. |
The setup I recommend for most Shopify stores
- A CMP with a real Shopify integration that writes to the Customer Privacy API, or Shopify’s own banner if your needs are simple.
- Loaded before GTM, through its app embed or at the top of
theme.liquid, with Consent Mode defaults set before any tag. - Advanced Consent Mode with denied defaults in the EEA, the UK and Switzerland,
url_passthroughon, and region rules elsewhere. - Non-Google tags blocked until consent, with a consent update trigger for their page events.
- A custom pixel that reads
init.customerPrivacyand applies Consent Mode in the checkout. - A blocking or prominent banner if attribution matters more to you than first-page friction, with “Reject all” as easy as “Accept all”.
- The test matrix after every change to the banner, the theme or GTM.
Frequently asked questions
Should I use Shopify’s cookie banner or a third-party CMP?
Shopify’s banner is enough for simple setups and is always connected to the checkout. A third-party CMP gives you more control over categories, design, regions and Consent Mode, but check that it writes to the Customer Privacy API.
Is it better to load the CMP in GTM or in theme.liquid?
Before GTM, through an app embed or theme.liquid, is safer: it loads first and can control scripts outside GTM. GTM works if everything you track goes through GTM.
Does GA4 send the page view again after consent is granted?
Google doesn’t document it. Practitioner tests show some hits are resent or reprocessed in advanced mode, depending on the setup. Make sure your page view fires with consent on the landing page, and test it.
Does a blocking cookie banner hurt conversions?
It can increase bounces on the first page. It also keeps attribution clean, because visitors decide on the landing page. Test both on your own store.
Why does the checkout ignore my visitor’s consent?
Your CMP isn’t writing it to Shopify’s Customer Privacy API. The checkout can’t read your banner’s own cookies.
Do I need a banner if I only sell in the US?
Not a consent banner before tracking in most states, but some states require an opt-out of selling or sharing data, and Global Privacy Control signals must be honoured. Check with your lawyer.
Want it checked?
Consent is the part of tracking that breaks most quietly. A Shopify tracking audit (from 800€) runs the full test matrix on your store and checks the banner, Consent Mode, the pixels and the checkout. My Starter package (1,300€) sets up GA4 with GTM and Consent Mode v2. Book a free 30-minute call to talk about your setup.