Google Consent Mode dans un pixel personnalisé Shopify (gtag.js)
Vue d’ensemble
Certaines boutiques chargent Google Analytics 4 (G-) ou Google Ads (AW-) directement avec gtag.js depuis un Shopify custom pixel (Settings > Customer events). Cet article vous fournit un code de pixel prêt à coller, qui applique Google Consent Mode Advanced à ces propriétés en utilisant le consentement que vos visiteurs donnent sur la bannière Pandectes.
Si vos propriétés Google sont chargées par un conteneur Google Tag Manager, utilisez plutôt Google Consent Mode dans un pixel personnalisé Shopify (Google Tag Manager).
Il s'agit d'un guide de mise en œuvre. Pour le contexte sur les commandes default et update et sur le mode Advanced, consultez Consent Mode avec gtag.js dans la documentation de Google.
Avant de commencer
Activez d'abord l'intégration Google Consent Mode
Ce pixel est l'une des deux moitiés d'une configuration en deux parties. Dans Shopify Admin, allez dans Apps > Pandectes GDPR > Integrations, cliquez sur Configure sur la carte Google Consent Mode et activez l'intégration. Voir Utiliser l'intégration Google Consent Mode. Google Consent Mode fonctionne à partir du forfait Plus.
Un pixel personnalisé Shopify s'exécute dans une iframe isolée, avec ses propres window, dataLayer et une copie de gtag.js. Il est séparé de la page de la boutique, et le consentement défini dans l'un est invisible pour l'autre. Chacun a donc besoin de sa propre configuration :
theme.liquid, votre conteneur GTM, balises d'autres applications | L'intégration Pandectes Google Consent ModeEnvironnement isolé du pixel | Le gtag.js que vous chargez dans le pixel et ses propriétés | Le code de cet articleUtilisez-vous Google Tag Manager ?
Si votre boutique a un conteneur GTM, vérifiez si vos propriétés Google y sont déjà chargées. C'est généralement le cas. Ajouter un pixel qui charge à nouveau la même propriété GA4 ou Google Ads duplique vos pages vues, sessions, achats et conversions, et crée deux états de consentement concurrents.
| GA4 ou Google Ads chargés par un conteneur GTM | Google Consent Mode dans un pixel personnalisé Shopify (Google Tag Manager) |Pas de GTM, propriétés chargées avec
gtag.js dans un pixel personnalisé | Cet articleCe que couvre ce code
Le code définit uniquement l'état du consentement. Il envoie à Google la politique par défaut de la boutique, applique le choix du visiteur, le maintient synchronisé avec la bannière et charge la balise Google pour que les signaux de consentement aient une destination. Il n'envoie pas à lui seul de données d'analyse ou de conversion.
Vos abonnements aux événements vont dans le même pixel
Envoyer les événements clients de Shopify à Google est la véritable raison d'être du pixel, et ces abonnements doivent se trouver dans le même pixel, sous le code de consentement. Les exemples de chaque snippet sont volontairement commentés. Décommentez-les ou remplacez-les par les vôtres.
Chaque pixel qui charge une propriété Google a besoin de sa propre copie
Vous ne pouvez pas mettre le code de consentement dans un pixel personnalisé et vos événements dans un autre. Chaque pixel est un environnement isolé. Un pixel qui charge GA4 ou Google Ads sans le code de consentement envoie tout avec les valeurs par défaut de Google, comme si aucun mode de consentement n'existait, et Shopify ne vous en avertit pas.
- Un seul pixel charge vos propriétés : une copie du code, avec les événements de ce pixel en dessous.
- Trois pixels chargent chacun une propriété Google : trois copies, une dans chaque pixel.
- Si plusieurs pixels chargent la même propriété, corrigez d'abord ce doublon.
Mode Advanced et autorisation du pixel
Ce code vous donne Google Consent Mode Advanced : la balise Google se charge à chaque affichage de page, envoie des pings sans cookie tant que le consentement est refusé, et passe à une mesure complète dès que le consentement est accordé. C'est ce qui permet à Google de modéliser les conversions des visiteurs qui ne consentent pas.
Pour cela, le pixel doit pouvoir s'exécuter avant le consentement. Dans Shopify Admin, allez dans Settings > Customer events, ouvrez votre pixel personnalisé et, sous Customer privacy, réglez Permission sur Not required. Si vous le réglez sur Required, Shopify retient le pixel jusqu'à l'acceptation du visiteur : la balise Google ne se charge donc jamais avant le consentement et aucun ping sans cookie n'est envoyé.
Si vous voulez Basic mode (rien ne se charge tant que le consentement n'est pas donné), vous n'avez pas besoin de ce code. Réglez Permission sur Required, sélectionnez les catégories dont vous avez besoin et laissez Shopify retenir le pixel.
Fonctionnement du code
Shopify transmet au pixel le consentement du visiteur dans init.customerPrivacy, mais n'indique pas s'il s'agit de la valeur par défaut de la boutique ou d'un choix déjà fait par le visiteur. Le code exécute donc toujours ces étapes, dans cet ordre :
consentdefault: la politique de la boutique, inscrite dans le code.consentupdate: ce que contientinit.customerPrivacy. S'il ne s'agit que de la valeur par défaut, rien ne change. S'il s'agit d'un choix enregistré, il s'applique avant le premier envoi.- Charger
gtag.jset configurer vos propriétés Google. - Écouter
visitorConsentCollectedet envoyer unupdatechaque fois que le visiteur modifie son choix.
Dans un pixel personnalisé, analytics, browser et init sont disponibles directement, mais customerPrivacy s'obtient via api. Appeler customerPrivacy.subscribe(...) sans api. génère une ReferenceError.
Les valeurs de consentement de Shopify correspondent aux types de consentement de Google comme suit :
Shopify | |
|---|---|
|
|
|
|
|
|
| Pas d'équivalent dans Consent Mode. Il s'agit d'un signal de vente ou de partage pour les États américains (voir |
(toujours) |
|
Quel snippet me faut-il ?
Politique de votre boutique | Utiliser |
|---|---|
Même politique partout : rien ne s'exécute tant que le visiteur n'a pas consenti | Snippet 1 (une seule commande par défaut) |
Consentement recueilli seulement dans certaines régions, autorisé ailleurs | Snippet 2 (commandes par défaut par région) |
Les deux snippets prennent en charge GA4, Google Ads, ou les deux.
- Dans Shopify Admin, allez dans Settings > Customer events et cliquez sur Add custom pixel.
- Donnez un nom au pixel et collez l'un des snippets.
- Indiquez vos identifiants entre
START_MODIFY_FOR_YOUR_STOREetEND_MODIFY_FOR_YOUR_STORE. - Ajoutez vos propres abonnements aux événements en bas.
- Réglez l'autorisation comme décrit plus haut, cliquez sur Save, puis sur Connect.
Snippet 1 : une commande par défaut
Une seule commande default sans région, qui s'applique donc à tous les visiteurs. Tout est refusé, sauf 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 : commandes par défaut par région
Pour les boutiques qui ne recueillent le consentement que là où la loi l'exige. Il y a deux commandes default : une globale qui accorde tout, et une pour les régions listées qui refuse tout sauf security_storage. Quand les deux correspondent à un visiteur, la région la plus précise l'emporte.
Le reste est identique au 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. */
Vérifiez que cela fonctionne
Tag Assistant ne voit pas le pixel
Google Tag Assistant n'inspecte que la page de la boutique. Le gtag, le dataLayer et les propriétés du pixel se trouvent dans une iframe isolée qu'il n'atteint pas. Il ne signale donc rien (ou seulement les balises propres à la boutique), même lorsque le pixel fonctionne correctement. C'est normal et ce n'est pas une erreur.
Vérifier le dataLayer dans le cadre du pixel
- Ouvrez les outils de développement de Chrome et allez dans l'onglet Console.
- Dans la barre d'outils de la console, ouvrez la liste déroulante des cadres (elle affiche normalement
top) et sélectionnez le cadre de l'environnement isolé du pixel (son nom commence parweb-pixel). Shopify crée un cadre par pixel personnalisé. Choisissez donc le bon si vous en avez plusieurs. - Effectuez les vérifications ci-dessous.
Dans le cadre top, dataLayer est le dataLayer de la boutique, qui ne vous renseigne pas sur le pixel.
- Les valeurs par défaut viennent-elles en premier ? Dans
dataLayer, les entréesconsentdoivent apparaître avant les entréesconfig. - Le consentement atteint-il la balise ? Réglez
DEBUG = true, décommentez un événement pour qu'il soit envoyé, puis ouvrez GA4 DebugView. Avecanalytics_storagerefusé, vous voyez un ping sans cookie au lieu d'un hit normal. - Le pixel se charge-t-il avant le consentement ? Il le doit en mode Advanced. Si la balise Google n'apparaît qu'après l'acceptation du visiteur, l'autorisation du pixel est réglée sur Required et vous êtes en mode Basic.
- La logique par région fonctionne-t-elle ? Testez avec un VPN à l'intérieur et à l'extérieur d'un pays listé.
- L'abonnement se déclenche-t-il ? Ajoutez un
console.logtemporaire dans le callbackvisitorConsentCollectedet modifiez votre choix sur la bannière.
Erreurs courantes
Erreur | Ce qui se passe |
|---|---|
Code de consentement dans un pixel, événements dans un autre | Le pixel des événements n'a pas de |
Plusieurs pixels chargent une propriété Google, un seul a le code de consentement | Les autres s'exécutent sans mode de consentement, sans avertissement. |
Pixel Permission réglé sur Required | La balise ne se charge jamais avant le consentement : pas de pings sans cookie et pas de modélisation. C'est le mode Basic. |
Événement Ads | Chaque commande est comptée deux fois dans Google Ads. |
|
|
Omettre le | Les visiteurs de retour dont le consentement est enregistré reçoivent des balises refusées dès leur première page vue. |
| Consent Mode ne s'applique pas aux premiers hits. |
Intégration Google Consent Mode non activée dans Pandectes | Seules les propriétés du pixel bénéficient du mode de consentement. Les balises Google de la boutique fonctionnent sans lui. |
Pixel créé alors que GTM charge déjà la même propriété | Pages vues, sessions, achats et conversions en double, plus deux états de consentement. |
Tester avec Tag Assistant ou lire | Aucun des deux ne regarde à l'intérieur de l'environnement isolé du pixel. |
| Affaiblit les signaux de prévention de la fraude sans aucun bénéfice de conformité. |
| La valeur par défaut et la mise à jour ne concordent pas. La mise à jour l'emporte et la politique par région est ignorée. |
Réglages non couverts par cet article
Les snippets ne couvrent pas les réglages au niveau du compte Google : ce sont donc les valeurs par défaut de Google qui s'appliquent :
| Si les identifiants de clic publicitaire, comme le GCLID, sont transmis dans l'URL d'une page à l'autre lorsque les cookies ne peuvent pas être définis |
|---|---|
| Si les identifiants de clic publicitaire sont supprimés des pings sans cookie lorsque |
| Si des données clients hachées peuvent être envoyées avec les conversions |
| La restriction de vente ou de partage des États américains, liée au |
| Combien de temps les balises attendent une mise à jour du consentement avant de se déclencher |
Pandectes ne peut pas vous conseiller sur ces points. Les bonnes valeurs dépendent de vos comptes Google, de la modélisation sur laquelle vous vous appuyez et de la position juridique de votre entreprise. Discutez-en avec la personne qui gère votre configuration Google, ou avec votre conseiller juridique en cas de question de confidentialité.
Si vous décidez d'en définir un, ajoutez-le comme un appel gtag("set", ...) avant les commandes consent default :
// gtag("set", "url_passthrough", true);
// gtag("set", "ads_data_redaction", true);
wait_for_update fait exception : il va dans une commande default. Ces snippets n'en ont pas besoin, car init.customerPrivacy est disponible immédiatement et l'envoi update part juste après les valeurs par défaut.
Mis à jour le : 30/10/2026
Merci !
