Articles sur : Intégrations
Cet article est aussi disponible en :

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



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 :


Emplacement | Ce qui s'y exécute | Ce qui définit le mode de consentement--- | --- | --- |Page de la boutique | Balises Google dans 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 article


Le pixel ne remplace pas l'intégration. Rien dans le pixel ne peut atteindre la page de la boutique : sans l'intégration, votre boutique n'a donc aucun mode de consentement.


Utilisez-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.


Votre configuration | Suivez--- | --- |
| 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 article


Ce 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.


Pandectes fournit uniquement la couche de consentement. Les événements que vous envoyez, les données qu'ils contiennent, leur correspondance avec votre propriété GA4 ou vos conversions Google Ads, et l'exactitude de vos rapports relèvent de votre responsabilité. Pandectes ne prend pas en charge et ne vérifie pas le suivi construit au-dessus de ce code.


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 :


  1. consent default : la politique de la boutique, inscrite dans le code.
  2. consent update : ce que contient init.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.
  3. Charger gtag.js et configurer vos propriétés Google.
  4. Écouter visitorConsentCollected et envoyer un update chaque 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

Google

analyticsProcessingAllowed

analytics_storage

marketingAllowed

ad_storage, ad_user_data, ad_personalization

preferencesProcessingAllowed

functionality_storage, personalization_storage

saleOfDataAllowed

Pas d'équivalent dans Consent Mode. Il s'agit d'un signal de vente ou de partage pour les États américains (voir restricted_data_processing).

(toujours)

security_storage est toujours granted


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.


  1. Dans Shopify Admin, allez dans Settings > Customer events et cliquez sur Add custom pixel.
  2. Donnez un nom au pixel et collez l'un des snippets.
  3. Indiquez vos identifiants entre START_MODIFY_FOR_YOUR_STORE et END_MODIFY_FOR_YOUR_STORE.
  4. Ajoutez vos propres abonnements aux événements en bas.
  5. 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


  1. Ouvrez les outils de développement de Chrome et allez dans l'onglet Console.
  2. 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 par web-pixel). Shopify crée un cadre par pixel personnalisé. Choisissez donc le bon si vous en avez plusieurs.
  3. 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ées consent doivent apparaître avant les entrées config.
  • Le consentement atteint-il la balise ? Réglez DEBUG = true, décommentez un événement pour qu'il soit envoyé, puis ouvrez GA4 DebugView. Avec analytics_storage refusé, 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.log temporaire dans le callback visitorConsentCollected et 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 gtag ni d'état de consentement. Ses événements n'aboutissent nulle part.

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 conversion envoyé alors que l'achat GA4 est aussi importé comme conversion

Chaque commande est comptée deux fois dans Google Ads.

customerPrivacy.subscribe(...) sans api.

ReferenceError. Le consentement ne se met jamais à jour après la bannière.

Omettre le update parce que init.customerPrivacy ressemble à la valeur par défaut

Les visiteurs de retour dont le consentement est enregistré reçoivent des balises refusées dès leur première page vue.

default envoyé après config

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 dataLayer dans le cadre top

Aucun des deux ne regarde à l'intérieur de l'environnement isolé du pixel.

security_storage refusé

Affaiblit les signaux de prévention de la fraude sans aucun bénéfice de conformité.

RESTRICTED_REGIONS ne correspond pas aux régions de la bannière

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 :


Réglage | Ce qu'il contrôle--- | --- |

url_passthrough

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

ads_data_redaction

Si les identifiants de clic publicitaire sont supprimés des pings sans cookie lorsque ad_storage est refusé

allow_enhanced_conversions

Si des données clients hachées peuvent être envoyées avec les conversions

restricted_data_processing

La restriction de vente ou de partage des États américains, liée au saleOfDataAllowed de Shopify

wait_for_update

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

Cet article a-t-il répondu à vos questions ?

Partagez vos commentaires

Annuler

Merci !