Articles on: Integrations
This article is also available in:

Google Consent Mode in a Shopify custom pixel (Google Tag Manager)

Overview


Some stores load a Google Tag Manager (GTM) container from a Shopify custom pixel (Settings > Customer events) instead of, or as well as, from the storefront. This article shows how to apply Google Consent Mode Advanced to the tags that container fires.


With GTM there is very little code to write. Two lines at the top of the pixel hand the visitor's consent to the Pandectes CMP tag in your container, and the tag does the rest.


If you do not use GTM and load Google Analytics 4 or Google Ads directly with gtag.js, use Google Consent Mode in a Shopify custom pixel (gtag.js) instead. Use one approach or the other for a Google property, never both.


Before you start




A Shopify custom pixel runs in a sandboxed iframe with its own window and its own dataLayer. It is separate from the storefront page, and consent set in one is invisible to the other.


So a container loaded inside the pixel cannot see the consent that the storefront already has. The two lines below pass it in. Everything in this article applies inside the pixel only.


The two lines


Put these at the very beginning of the custom pixel, before the GTM snippet and before anything else:


window.pandectesPixelInit = init;
window.pandectesSubscribe = api.customerPrivacy.subscribe;


That is the whole consent setup. The Pandectes CMP tag in your container reads them, applies the right default consent state for the visitor, and updates it whenever the visitor changes their choice on the banner. You do not need to write default or update commands or keep a list of regions: the tag takes the policy from your banner settings.


Two placement rules:


  • The lines come first. The tag reads them when the container starts. If the GTM snippet runs before them, there is nothing to read.
  • The lines go in the same pixel as the container. Each custom pixel is its own sandbox. Setting them in one pixel does nothing for a container loaded in another.


Advanced mode and the pixel permission


This setup gives you Google Consent Mode Advanced: the container loads on every page view, its tags send cookieless pings while consent is denied, and they switch to full measurement once consent is granted.


For that, the pixel must be allowed to run before consent. In Shopify Admin, go to Settings > Customer events, open your custom pixel, and under Customer privacy set Permission to Not required. If you set it to Required, Shopify holds the pixel back until the visitor accepts, the container never loads, and no cookieless pings are sent.


If you want Basic mode instead (nothing loads until consent is given), set Permission to Required, select the categories you need, and let Shopify hold the pixel back.


The pixel code


  1. In Shopify Admin, go to Settings > Customer events and click Add custom pixel.
  2. Give the pixel a name and paste the code below.
  3. Replace GTM-XXXXXXX with your container ID.
  4. Add your own event subscriptions at the bottom.
  5. Set the permission as described above, click Save, then Connect.


/* Pandectes consent handover.
* Keep these two lines at the very top, above the GTM snippet.
* The Pandectes CMP tag in your container reads them. */
window.pandectesPixelInit = init;
window.pandectesSubscribe = api.customerPrivacy.subscribe;

/* START_MODIFY_FOR_YOUR_STORE */
const GTM_ID = "GTM-XXXXXXX"; // your container ID
/* END_MODIFY_FOR_YOUR_STORE */

/* Load the GTM container inside the pixel sandbox.
* This dataLayer is not shared with the storefront or other pixels. */
window.dataLayer = window.dataLayer || [];

(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;
f.parentNode.insertBefore(j, f);
})(window, document, "script", "dataLayer", GTM_ID);

/* YOUR EVENT SUBSCRIPTIONS GO HERE, IN THIS SAME PIXEL.
*
* The code above sets consent and loads the container. On its own it
* pushes nothing to the dataLayer.
*
* The example below is sample code only, adapted from Shopify's GTM
* tutorial. Adapt the events and fields to your own GTM triggers.
* Shopify's original also pushes email, phone and address. Those are
* left out on purpose: putting personal data in the dataLayer is a
* privacy decision you need to make for your own store. */

// analytics.subscribe("checkout_completed", (event) => {
// window.dataLayer.push({
// event: "checkout_completed",
// timestamp: event.timestamp,
// id: event.id,
// token: event.data?.checkout?.token,
// url: event.context.document.location.href,
// client_id: event.clientId,
// orderId: event.data?.checkout?.order?.id,
// currency: event.data?.checkout?.currencyCode,
// subtotal: event.data?.checkout?.subtotalPrice?.amount,
// shipping: event.data?.checkout?.shippingLine?.price?.amount,
// value: event.data?.checkout?.totalPrice?.amount,
// tax: event.data?.checkout?.totalTax?.amount,
// });
// });


Each event you push needs a matching Custom Event trigger in GTM with exactly the same name as the event key (checkout_completed in the sample).


Pandectes provides the consent layer only. The two lines set the consent state and nothing else. Which events you push, what data they carry, how your GTM tags and triggers are set up, and whether your Google Analytics or Google Ads reporting is accurate are your responsibility. Pandectes does not support or verify the tracking built on top of this code.


Every pixel that loads a container needs the two lines


You cannot put the two lines in one custom pixel and load the container in another. Each pixel is a separate sandbox. A container loaded in a pixel without the two lines has no consent state, and its tags fire under Google's defaults with no warning.


The same goes for your event subscriptions: they must be in the same pixel, below the GTM snippet.


Check that it works


Tag Assistant and GTM Preview cannot see the pixel


Neither Google Tag Assistant nor GTM Preview mode connects to a container that runs inside the pixel sandbox. They inspect the storefront page only, so they report nothing (or only the storefront's own tags) even when the pixel works correctly. This is expected and is not an error.


Check the dataLayer in the pixel's frame


  1. Open Chrome DevTools and go to the Console tab.
  2. In the console toolbar, open the frame dropdown (it normally shows top) and select the pixel's sandbox frame (its name starts with web-pixel). Shopify creates one frame per custom pixel, so pick the right one if you have several.
  3. Run the checks below.


In the top frame, dataLayer is the storefront's data layer, which tells you nothing about the pixel.


  • Are the two lines set? window.pandectesPixelInit and window.pandectesSubscribe should both be defined.
  • Does consent come before the tags? In dataLayer, the consent entries must appear before your tags fire.
  • Does the pixel load before consent? It must, for Advanced mode. If the container only appears after the visitor accepts, the pixel permission is set to Required and you are in Basic mode.
  • Do your events arrive? Place a test order and check that the event appears in dataLayer with the name your GTM trigger expects.


Common mistakes


Mistake

What happens

The two lines are placed after the GTM snippet

The tag has nothing to read when the container starts. Tags fire under Google's defaults.

The two lines are in one pixel and the container in another

Separate sandboxes. The container has no consent state.

The Pandectes CMP tag is not in the container

The lines are set but nothing reads them. No consent mode in GTM.

Pixel Permission set to Required

Shopify holds the pixel until consent, so the container never loads before it. That is Basic mode, not Advanced.

Testing with Tag Assistant or GTM Preview

They cannot see the pixel sandbox and report nothing, even when everything works.

Reading dataLayer in the top frame

That is the storefront's data layer, not the pixel's.

No GTM Custom Event trigger for a pushed event

The event reaches the dataLayer, but no tag fires.

Pasting Shopify's sample event unchanged

Event names and fields that do not match your triggers, and personal data in the dataLayer.

The same property loaded from this pixel and from a gtag.js pixel

Duplicate hits and two competing consent states.


Settings this article does not cover


Settings such as url_passthrough, ads_data_redaction, allow_enhanced_conversions and restricted_data_processing are set in GTM (on the Pandectes CMP tag or on your own tags), not in the pixel.


Pandectes cannot advise on these. The right values depend on your Google Ads and Analytics accounts, the modelling you rely on, and your business's legal position. Discuss them with whoever manages your Google setup, or with your legal advisor where there is a privacy question.

Updated on: 30/10/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!