Artikelen over: Integraties
Dit artikel is ook beschikbaar in:

Google Consent Mode in een Shopify custom pixel (gtag.js)

Overzicht


Sommige winkels laden Google Analytics 4 (G-) of Google Ads (AW-) rechtstreeks met gtag.js vanuit een Shopify custom pixel (Settings > Customer events). Dit artikel geeft je kant-en-klare pixelcode die Google Consent Mode Advanced toepast op die eigenschappen, met de toestemming die je bezoekers geven in de Pandectes-banner.


Worden je Google-eigenschappen geladen via een Google Tag Manager-container, gebruik dan in plaats daarvan Google Consent Mode in een Shopify custom pixel (Google Tag Manager).


Dit is een implementatiegids. Voor achtergrond over default- en update-commando's en over de Geavanceerde modus, zie Google's Consent Mode met gtag.js.


Voordat je begint



Deze pixel is één helft van een opzet in twee delen. Ga in Shopify Admin naar Apps > Pandectes GDPR > Integrations, klik op Configure bij de kaart Google Consent Mode, en zet de integratie aan. Zie Google Consent Mode-integratie gebruiken. Google Consent Mode werkt vanaf het Plus-abonnement en hoger.


Een Shopify custom pixel draait in een afgeschermd iframe met zijn eigen window, dataLayer en een kopie van gtag.js. Die staat los van de storefront-pagina, en toestemming die in de ene is ingesteld, is in de andere niet zichtbaar. Elk heeft dus zijn eigen instelling nodig:


Waar

Wat daar draait

Wat de consent mode instelt

Storefront-pagina

Google-tags in theme.liquid, je GTM-container, tags van andere apps

De Pandectes Google Consent Mode-integratie

Pixel-sandbox

De gtag.js die je in de pixel laadt en de eigenschappen daarvan

De code in dit artikel


De pixel vervangt de integratie niet. Niets in de pixel kan de storefront-pagina bereiken, dus zonder de integratie heeft je storefront helemaal geen consent mode.


Gebruik je Google Tag Manager?


Als je winkel een GTM-container heeft, controleer dan of je Google-eigenschappen daar al worden geladen. Dat is meestal het geval. Een pixel toevoegen die dezelfde GA4- of Google Ads-eigenschap opnieuw laadt, dubbelt je paginaweergaven, sessies, aankopen en conversies, en maakt twee concurrerende toestemmingsstatussen.


Je opzet | Volg--- | --- |

GA4 of Google Ads geladen door een GTM-container

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

Geen GTM, eigenschappen geladen met gtag.js in een custom pixel

Dit artikel


Wat deze code dekt


De code stelt alleen de toestemmingsstatus in en verder niets. Ze stuurt het standaardbeleid van de winkel naar Google, past de keuze van de bezoeker toe, houdt die gelijk met de banner, en laadt de Google-tag zodat de toestemmingssignalen een bestemming hebben. Ze stuurt zelf geen analyse- of conversiedata.


Pandectes levert alleen de toestemmingslaag. Welke events je verstuurt, welke gegevens ze bevatten, hoe ze aansluiten op je GA4-eigenschap of Google Ads-conversies, en of je rapportage klopt, is jouw verantwoordelijkheid. Pandectes ondersteunt of verifieert de tracking die bovenop deze code is gebouwd niet.


Je event-abonnementen staan in dezelfde pixel


Het versturen van Shopify's klantevents naar Google is het echte doel van de pixel, en die abonnementen moeten in dezelfde pixel staan, onder de toestemmingscode. De voorbeelden in elk fragment staan bewust uitgecommentarieerd. Haal de commentaartekens weg of vervang ze door je eigen code.


Elke pixel die een Google-eigenschap laadt, heeft een eigen kopie nodig


Je kunt de toestemmingscode niet in de ene custom pixel zetten en je events in een andere. Elke pixel is een aparte sandbox. Een pixel die GA4 of Google Ads laadt zonder de toestemmingscode, vuurt alles af volgens de standaardwaarden van Google, alsof er geen consent mode bestaat, en Shopify waarschuwt je daar niet voor.


  • Eén pixel laadt je eigenschappen: één kopie van de code, met de events van die pixel eronder.
  • Drie pixels laden elk een Google-eigenschap: drie kopieën, één in elke pixel.
  • Als meerdere pixels dezelfde eigenschap laden, los die dubbeling dan eerst op.


Geavanceerde modus en de pixel-toestemming


Deze code geeft je Google Consent Mode Advanced: de Google-tag laadt bij elke paginaweergave, stuurt cookieloze pings zolang de toestemming is geweigerd, en schakelt over op volledige meting zodra de toestemming is verleend. Daardoor kan Google conversies modelleren voor bezoekers die niet instemmen.


Daarvoor moet de pixel vóór toestemming mogen draaien. Ga in Shopify Admin naar Settings > Customer events, open je custom pixel, en stel onder Customer privacy Permission in op Not required. Als je het op Required zet, houdt Shopify de pixel tegen tot de bezoeker accepteert, dus de Google-tag laadt nooit vóór toestemming en er worden geen cookieloze pings verstuurd.


Als je Basic mode wilt (niets laadt tot er toestemming is gegeven), heb je deze code niet nodig. Zet Permission op Required, selecteer de categorieën die je nodig hebt, en laat Shopify de pixel tegenhouden.


Hoe de code werkt


Shopify geeft de pixel de toestemming van de bezoeker in init.customerPrivacy, maar zegt niet of dat het standaardbeleid van de winkel is of een keuze die de bezoeker al heeft gemaakt. De code voert dus altijd deze stappen uit, in deze volgorde:


  1. consent default: het beleid van de winkel, in de code geschreven.
  2. consent update: wat init.customerPrivacy ook bevat. Als het alleen de standaard was, verandert er niets. Als het een opgeslagen keuze was, wordt die toegepast vóór de eerste hit.
  3. Laad gtag.js en configureer je Google-eigenschappen.
  4. Luister naar visitorConsentCollected en stuur elke keer een update als de bezoeker zijn keuze wijzigt.


In een custom pixel zijn analytics, browser en init direct beschikbaar, maar customerPrivacy bereik je via api. Het aanroepen van customerPrivacy.subscribe(...) zonder api. geeft een ReferenceError.


De toestemmingswaarden van Shopify worden als volgt aan Google's toestemmingstypen gekoppeld:


Shopify

Google

analyticsProcessingAllowed

analytics_storage

marketingAllowed

ad_storage, ad_user_data, ad_personalization

preferencesProcessingAllowed

functionality_storage, personalization_storage

saleOfDataAllowed

Geen Consent Mode-equivalent. Het is een signaal voor verkoop of delen in een Amerikaanse staat (zie restricted_data_processing).

(altijd)

security_storage is altijd granted


Welke snippet heb ik nodig?


Het beleid van je winkel | Gebruik--- | --- |

Zelfde beleid wereldwijd: niets draait tot de bezoeker toestemming geeft

Snippet 1 (één standaardcommando)

Toestemming alleen in sommige regio's verzameld, elders toegestaan

Snippet 2 (standaardcommando's per regio)


Beide snippets ondersteunen GA4, Google Ads, of beide.


  1. Ga in Shopify Admin naar Settings > Customer events en klik op Add custom pixel.
  2. Geef de pixel een naam en plak een van de snippets.
  3. Vul je ID's in tussen START_MODIFY_FOR_YOUR_STORE en END_MODIFY_FOR_YOUR_STORE.
  4. Voeg onderaan je eigen event-abonnementen toe.
  5. Stel de toestemming in zoals hierboven beschreven, klik op Save, en daarna op Connect.


Snippet 1: één standaardcommando


Eén default-commando zonder regio, zodat het voor elke bezoeker geldt. Alles is geweigerd behalve security_storage.


/* START_MODIFY_FOR_YOUR_STORE */
const GA4_ID = ""; // e.g. "G-XXXXXXXXXX", leave empty if not used
const AW_ID = ""; // e.g. "AW-XXXXXXXXXX", leave empty if not used
const DEBUG = false; // true sends GA4 hits to DebugView while testing
/* END_MODIFY_FOR_YOUR_STORE */

const GRANTED = "granted";
const DENIED = "denied";
const GOOGLE_URL = "https://www.googletagmanager.com/gtag/js?id=";
const DEVELOPER_ID = "dMTZkMj";

/* Shopify customerPrivacy -> Google consent state */
const toConsentState = (cp) => ({
ad_storage: cp.marketingAllowed ? GRANTED : DENIED,
ad_user_data: cp.marketingAllowed ? GRANTED : DENIED,
ad_personalization: cp.marketingAllowed ? GRANTED : DENIED,
analytics_storage: cp.analyticsProcessingAllowed ? GRANTED : DENIED,
functionality_storage: cp.preferencesProcessingAllowed ? GRANTED : DENIED,
personalization_storage: cp.preferencesProcessingAllowed ? GRANTED : DENIED,
security_storage: GRANTED,
});

/* The pixel sandbox has its own dataLayer. */
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}

/* Pandectes developer ID. Identifies the implementation to Google,
* has no effect on your data. Leave it as it is. */
gtag("set", `developer_id.${DEVELOPER_ID}`, true);

/* STEP 1: store policy, before gtag.js loads. Applies to everyone. */
gtag("consent", "default", {
ad_storage: DENIED,
ad_user_data: DENIED,
ad_personalization: DENIED,
analytics_storage: DENIED,
functionality_storage: DENIED,
personalization_storage: DENIED,
security_storage: GRANTED,
});

/* STEP 2: visitor state, always sent. If it is only the default,
* nothing changes. If it is a saved choice, it lands before the first hit. */
gtag("consent", "update", toConsentState(init.customerPrivacy));

/* STEP 3: load the Google tag once and configure each property. */
const TAG_IDS = [GA4_ID, AW_ID].filter(Boolean);

if (TAG_IDS.length) {
gtag("js", new Date());

if (GA4_ID) {
gtag("config", GA4_ID, {
send_page_view: false,
...(DEBUG ? { debug_mode: true } : {}),
});
}

if (AW_ID) {
gtag("config", AW_ID);
}

const script = document.createElement("script");
script.async = true;
script.src = GOOGLE_URL + TAG_IDS[0];
document.head.appendChild(script);
}

/* STEP 4: follow the visitor's choices. Note the api. prefix. */
api.customerPrivacy.subscribe("visitorConsentCollected", (event) => {
gtag("consent", "update", toConsentState(event.customerPrivacy));
});

/* YOUR EVENT SUBSCRIPTIONS GO HERE, IN THIS SAME PIXEL.
* The examples are commented out on purpose. What you send is yours
* to own and verify. */

/* Page view: only if the storefront does not already send page_view
* for the same property, or it is counted twice. */
// analytics.subscribe("page_viewed", (event) => {
// gtag("event", "page_view", {
// page_path: event.context.document.location.pathname,
// page_title: event.context.document.title,
// page_location: event.context.window.location.href,
// });
// });

/* Purchase: if GA4 and Google Ads are linked, import the GA4 purchase
* as a conversion in Google Ads and delete the conversion block below,
* or every order is counted twice. */
// analytics.subscribe("checkout_completed", (event) => {
// const checkout = event.data.checkout;
// const items = checkout.lineItems.map((line) => ({
// item_id: "shopify_" + line.variant.product.id + "_" + line.variant.id,
// item_name: line.title,
// item_variant: line.variant.title,
// price: line.variant.price.amount,
// quantity: line.quantity,
// }));
//
// gtag("event", "purchase", {
// transaction_id: checkout.token,
// currency: checkout.currencyCode,
// value: checkout.totalPrice.amount,
// tax: checkout.totalTax.amount,
// shipping: checkout.shippingLine ? checkout.shippingLine.price.amount : 0,
// items: items,
// });
//
// // Google Ads conversion, ONLY when GA4 and Google Ads are NOT linked.
// // Use the conversion label from your Google Ads conversion action.
// gtag("event", "conversion", {
// send_to: "AW-XXXXXXXXXX/AbC-D_efGhIjKlMnOp",
// transaction_id: checkout.token,
// currency: checkout.currencyCode,
// value: checkout.totalPrice.amount,
// });
// });


Snippet 2: standaardcommando's per regio


Voor winkels die alleen toestemming vragen waar dat wettelijk verplicht is. Er zijn twee default-commando's: een globaal commando dat alles toestaat, en een voor de vermelde regio's dat alles weigert behalve security_storage. Als beide op een bezoeker van toepassing zijn, wint de specifiekere regio.


De rest is gelijk aan Snippet 1.


/* START_MODIFY_FOR_YOUR_STORE */
const GA4_ID = ""; // e.g. "G-XXXXXXXXXX", leave empty if not used
const AW_ID = ""; // e.g. "AW-XXXXXXXXXX", leave empty if not used

/* ISO 3166-2 codes where the store collects consent: EEA + UK below.
* Add US states ("US-CA", "US-CO", ...) if you treat them as opt-in.
* This list MUST match the regions where your banner collects consent. */
const RESTRICTED_REGIONS = [
"AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
"DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
"PL", "PT", "RO", "SK", "SI", "ES", "SE", "GB", "LI", "NO", "IS",
];

const DEBUG = false; // true sends GA4 hits to DebugView while testing
/* END_MODIFY_FOR_YOUR_STORE */

const GRANTED = "granted";
const DENIED = "denied";
const GOOGLE_URL = "https://www.googletagmanager.com/gtag/js?id=";
const DEVELOPER_ID = "dMTZkMj";

/* Shopify customerPrivacy -> Google consent state */
const toConsentState = (cp) => ({
ad_storage: cp.marketingAllowed ? GRANTED : DENIED,
ad_user_data: cp.marketingAllowed ? GRANTED : DENIED,
ad_personalization: cp.marketingAllowed ? GRANTED : DENIED,
analytics_storage: cp.analyticsProcessingAllowed ? GRANTED : DENIED,
functionality_storage: cp.preferencesProcessingAllowed ? GRANTED : DENIED,
personalization_storage: cp.preferencesProcessingAllowed ? GRANTED : DENIED,
security_storage: GRANTED,
});

/* The pixel sandbox has its own dataLayer. */
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}

/* Pandectes developer ID. Identifies the implementation to Google,
* has no effect on your data. Leave it as it is. */
gtag("set", `developer_id.${DEVELOPER_ID}`, true);

/* STEP 1a: policy for everyone outside the listed regions. */
gtag("consent", "default", {
ad_storage: GRANTED,
ad_user_data: GRANTED,
ad_personalization: GRANTED,
analytics_storage: GRANTED,
functionality_storage: GRANTED,
personalization_storage: GRANTED,
security_storage: GRANTED,
});

/* STEP 1b: policy for the listed regions. Google resolves the region
* from the IP address, so test it with a VPN. */
gtag("consent", "default", {
ad_storage: DENIED,
ad_user_data: DENIED,
ad_personalization: DENIED,
analytics_storage: DENIED,
functionality_storage: DENIED,
personalization_storage: DENIED,
security_storage: GRANTED,
region: RESTRICTED_REGIONS,
});

/* STEP 2: visitor state, always sent. Shopify has already applied your
* regional settings to init.customerPrivacy, so this matches 1a or 1b. */
gtag("consent", "update", toConsentState(init.customerPrivacy));

/* STEP 3: load the Google tag once and configure each property. */
const TAG_IDS = [GA4_ID, AW_ID].filter(Boolean);

if (TAG_IDS.length) {
gtag("js", new Date());

if (GA4_ID) {
gtag("config", GA4_ID, {
send_page_view: false,
...(DEBUG ? { debug_mode: true } : {}),
});
}

if (AW_ID) {
gtag("config", AW_ID);
}

const script = document.createElement("script");
script.async = true;
script.src = GOOGLE_URL + TAG_IDS[0];
document.head.appendChild(script);
}

/* STEP 4: follow the visitor's choices. Note the api. prefix. */
api.customerPrivacy.subscribe("visitorConsentCollected", (event) => {
gtag("consent", "update", toConsentState(event.customerPrivacy));
});

/* YOUR EVENT SUBSCRIPTIONS GO HERE, IN THIS SAME PIXEL.
* Use the same page view and purchase examples as in Snippet 1. */


Controleer of het werkt


Tag Assistant kan de pixel niet zien


Google Tag Assistant inspecteert alleen de storefront-pagina. De gtag, dataLayer en eigenschappen van de pixel staan in een afgeschermd iframe waar het niet bij kan, dus het meldt niets (of alleen de eigen tags van de storefront), ook als de pixel correct werkt. Dit is normaal en geen fout.


Controleer de dataLayer in het frame van de pixel


  1. Open Chrome DevTools en ga naar het tabblad Console.
  2. Open in de consolebalk het frame-menu (dat meestal top toont) en selecteer het sandbox-frame van de pixel (de naam begint met web-pixel). Shopify maakt één frame per custom pixel, dus kies het juiste frame als je er meerdere hebt.
  3. Voer onderstaande controles uit.


In het top-frame is dataLayer de dataLayer van de storefront, die niets over de pixel vertelt.


  • Komen de standaardwaarden eerst? In dataLayer moeten de consent-regels vóór de config-regels komen.
  • Bereikt de toestemming de tag? Stel DEBUG = true in, zet een event aan zodat er iets wordt verstuurd, en open GA4 DebugView. Met analytics_storage geweigerd zie je een cookieloze ping in plaats van een normale hit.
  • Laadt de pixel vóór toestemming? Dat moet, voor de Geavanceerde modus. Als de Google-tag pas verschijnt nadat de bezoeker accepteert, staat de pixel-toestemming op Required en werk je in de Basismodus.
  • Werkt de regiologica? Test met een VPN binnen en buiten een vermeld land.
  • Wordt het abonnement uitgevoerd? Voeg tijdelijk een console.log toe binnen de visitorConsentCollected-callback en wijzig je keuze in de banner.


Veelgemaakte fouten


Fout

Wat er gebeurt

Toestemmingscode in de ene pixel, events in een andere

De events-pixel heeft geen gtag en geen toestemmingsstatus. De events verdwijnen.

Meerdere pixels laden een Google-eigenschap, maar slechts één heeft de toestemmingscode

De andere vuren af zonder consent mode, zonder waarschuwing.

Pixel Permission ingesteld op Required

De tag laadt nooit vóór toestemming: geen cookieloze pings en geen modellering. Dat is de Basismodus.

Ads-conversion-event verstuurd terwijl de GA4-aankoop ook als conversie wordt geïmporteerd

Elke bestelling wordt dubbel geteld in Google Ads.

customerPrivacy.subscribe(...) zonder api.

ReferenceError. De toestemming wordt na de banner nooit bijgewerkt.

De update overslaan omdat init.customerPrivacy de standaard lijkt

Terugkerende bezoekers met opgeslagen toestemming krijgen geweigerde tags bij hun eerste paginaweergave.

default verstuurd na config

Consent Mode wordt niet toegepast op de eerste hits.

Google Consent Mode-integratie niet ingeschakeld in Pandectes

Alleen de eigenschappen van de pixel krijgen consent mode. Google-tags op de storefront draaien er zonder.

Pixel gebouwd terwijl GTM dezelfde eigenschap al laadt

Dubbele paginaweergaven, sessies, aankopen en conversies, plus twee toestemmingsstatussen.

Testen met Tag Assistant of dataLayer lezen in het top-frame

Geen van beide kijkt in de pixel-sandbox.

security_storage geweigerd

Breekt de signalen voor fraudepreventie zonder enig nalevingsvoordeel.

RESTRICTED_REGIONS komt niet overeen met de regio's van de banner

De standaard en de update spreken elkaar tegen. De update wint en het regiobeleid wordt genegeerd.


Instellingen die dit artikel niet behandelt


De snippets laten Google's accountbrede instellingen weg, dus gelden Google's standaardwaarden:


Instelling | Wat die bepaalt--- | --- |url_passthrough | Of advertentieklik-ID's zoals GCLID tussen pagina's in de URL worden doorgegeven wanneer cookies niet kunnen worden geplaatstads_data_redaction | Of advertentieklik-ID's uit cookieloze pings worden verwijderd terwijl ad_storage is geweigerdallow_enhanced_conversions | Of gehashte klantgegevens mogen worden meegestuurd bij conversiesrestricted_data_processing | De beperking voor verkoop of delen in Amerikaanse staten, gerelateerd aan Shopify's saleOfDataAllowedwait_for_update | Hoe lang tags wachten op een toestemmingsupdate voordat ze afvuren


Pandectes kan hierover geen advies geven. De juiste waarden hangen af van je Google-accounts, de modellering waarop je vertrouwt, en de juridische positie van je bedrijf. Bespreek ze met degene die je Google-instellingen beheert, of met je juridisch adviseur als er een privacyvraag speelt.


Als je besluit er een in te stellen, voeg die dan toe als gtag("set", ...)-aanroep vóór de consent default-commando's:


// gtag("set", "url_passthrough", true);
// gtag("set", "ads_data_redaction", true);


wait_for_update vormt de uitzondering: die gaat binnen een default-commando. Deze snippets hebben het niet nodig, omdat init.customerPrivacy meteen beschikbaar is en de update direct na de standaardinstellingen wordt verstuurd.

Bijgewerkt op: 30/10/2026

Was dit artikel nuttig?

Deel uw feedback

Annuleer

Dankuwel!