Configurer le pixel OpenAI Ads (ChatGPT Ads) avec Google Tag Manager
Mis à jour : lundi 14 septembre 2026
Introduction au tracking des publicités ChatGPT
OpenAI propose désormais de diffuser des publicités dans ChatGPT. Comme pour toute plateforme publicitaire, OpenAI ne peut pas savoir ce qui se passe sur votre site après un clic sur une annonce. Le Measurement Pixel est le script à installer sur votre site pour informer OpenAI des actions réalisées par vos visiteurs : pages vues, ajouts au panier, achats, leads, inscriptions.
Ces remontées servent à trois choses :
- Attribuer vos conversions : OpenAI relie chaque conversion à un clic sur une annonce (attribution post-clic) et, lorsque la fonctionnalité est disponible sur votre compte, à une impression (attribution post-vue, sur une fenêtre fixe d’un jour).
- Optimiser vos campagnes : l’enchère, le calcul du CPA et l’optimisation des conversions reposent sur les conversions post-clic remontées par le pixel.
- Mesurer vos performances dans Ads Manager, avec des montants et des devises fiables.
Plutôt que d’ajouter le snippet officiel dans une balise HTML personnalisée puis d’écrire vous-même chaque appel oaiq("measure", ...), nous allons utiliser la balise OpenAI Ads Measurement Pixel by DMS, que j’ai développée pour Google Tag Manager Web. Elle charge le SDK, lit votre dataLayer au format GA4, convertit les montants au format attendu par OpenAI et hache les données utilisateur dans le navigateur.
Consentement et législation
Le pixel OpenAI transmet des données personnelles (identifiants publicitaires, email et téléphone hachés). En fonction de votre législation et de vos visiteurs, il faudra conditionner cette balise au consentement du visiteur. Rendez-vous dans la section gestion du consentement de cet article.
Ajouter la balise OpenAI Ads Measurement Pixel by DMS
Téléchargez ici le fichier template.tpl de la balise.

Rendez-vous dans la section Templates de Google Tag Manager. Dans la section Tag Templates, cliquez sur New.

Cliquez sur les 3 petits points en haut à droite de l’éditeur de modèle, puis sur Import. Sélectionnez le fichier template.tpl que vous venez de télécharger puis cliquez sur Save.

La balise est désormais disponible dans la liste de vos modèles lorsque vous créez une nouvelle balise.
Récupérer votre Pixel ID
Dans OpenAI Ads Manager, rendez-vous dans Tools > Conversions, onglet Data Source, et créez une source de données web. OpenAI vous fournit un Pixel ID, une chaîne de 22 caractères qui ressemble à Xk3PqR8mZt2vLn7wHs5yBa, affichée sous le nom de la source.

C’est ce même Pixel ID qui sert au pixel navigateur et, si vous en avez besoin, à l’API de conversions côté serveur.
Configurer la balise
Rendez-vous dans la section Tags de Google Tag Manager, cliquez sur New et sélectionnez la balise OpenAI Ads Measurement Pixel by DMS.

Pixel ID(s)
Renseignez votre Pixel ID. Pour envoyer le même événement à plusieurs pixels, par exemple un pixel par marque ou un pixel pour votre agence, séparez les identifiants par une virgule : Xk3PqR8mZt2vLn7wHs5yBa, 7kPz2QxLm4Ns8vRtYb1cDw.
Chaque pixel est initialisé à chaque déclenchement et reçoit l’événement via la commande measureSingle du SDK. Contrairement à la commande measure, elle ne cible que le pixel indiqué : si un autre pixel OpenAI est déjà présent sur la page, il ne recevra pas vos événements.
Event Name Setup Method
Ce champ détermine le nom de l’événement OpenAI envoyé. Deux modes sont disponibles.
Inherit From dataLayer (par défaut) : la balise lit le nom de l’événement dataLayer sur lequel elle se déclenche et le convertit en événement OpenAI. Voir la table de correspondance des événements GA4 vers OpenAI. Un événement dataLayer qui n’a pas d’équivalent est envoyé en tant qu’événement custom, dont le nom est celui de l’événement dataLayer en minuscules, les caractères non autorisés étant remplacés par _. Un événement Newsletter Signup devient donc l’événement custom newsletter_signup côté OpenAI.
Override : vous choisissez vous-même l’événement. Le champ Event Type propose Standard Event, qui affiche la liste déroulante des événements standards d’OpenAI, ou Custom Event, qui affiche le champ Custom Event Name.

Les événements appointment_scheduled, subscription_created et trial_started n’ont pas d’équivalent dans le standard GA4 : utilisez le mode Override pour les envoyer. Les événements app_installed et app_opened ne sont pas pris en charge par le pixel navigateur, ils passent uniquement par l’API de conversions.
Un nom d’événement custom doit contenir entre 1 et 64 caractères (lettres, chiffres, tirets ou underscores), commencer et finir par une lettre ou un chiffre, et ne pas reprendre le nom d’un événement standard. Sinon la balise échoue et explique pourquoi dans la console de la preview.
Ecommerce Data
Lorsque la case Read e-commerce data from the dataLayer est cochée (par défaut), la balise lit l’objet ecommerce de votre dataLayer : ecommerce.value devient le montant de l’événement, ecommerce.currency sa devise et ecommerce.items la liste des contenus.
Les champs Amount, Currency et Plan ID permettent de forcer une valeur. Un champ renseigné l’emporte toujours sur la valeur du dataLayer.
Montants en unité mineure
OpenAI attend des montants entiers exprimés dans l’unité mineure de la devise : 2599 pour 25,99 USD. Vous n’avez rien à convertir : renseignez le montant comme dans GA4 (25.99) et la balise applique l’exposant ISO 4217 de la devise. 25.99 USD devient 2599, 1250 JPY reste 1250 et 1.250 KWD devient 1250. Un montant sans devise valide n’est pas envoyé.
Le type de données de l’événement est choisi automatiquement à partir de son nom : les événements lead_created, registration_completed et appointment_scheduled n’acceptent qu’un montant et une devise, jamais de contenus. Plan ID n’est envoyé qu’avec subscription_created, trial_started et les événements custom.
Items Data
Cette section pilote la construction du tableau contents envoyé à OpenAI.
- Contents : une variable renvoyant un tableau d’items. Elle remplace
ecommerce.itemslorsqu’elle est renseignée. - Item ID Key, Item Name Key, Quantity Key, Price Key : les clés lues dans chaque item pour alimenter
id,name,quantityetamount. Par défaut,item_id,item_name,quantityetprice, c’est-à-dire le schéma GA4. - Content Type Key : optionnel, la clé lue pour
content_type, par exempleitem_category. - Default Content Type : la valeur envoyée lorsque aucune clé n’est définie ou que l’item n’en a pas.
productpar défaut.

Les clés acceptent la notation pointée, par exemple product.sku, ce qui permet d’utiliser la balise avec un dataLayer dont les produits ne suivent pas le schéma GA4, sans passer par une variable de transformation. Le prix de chaque item est lu dans l’unité principale puis converti en unité mineure avec la devise de l’événement.
User Data
Lorsque la case Read user data from the dataLayer est cochée (par défaut), la balise lit l’objet user_data du dataLayer. Elle accepte aussi bien le format GA4 imbriqué (user_data.address.first_name) qu’un format aplati (user_data.first_name), et reconnaît plusieurs alias de clés. Voir la table des clés lues.
Les champs Email Address, Phone Number, External ID, First Name et Last Name permettent de renseigner une valeur manuellement. Les champs Country, City, Region et Postal Code sont transmis en clair, comme le prévoit OpenAI.
Hachage dans le navigateur
L’email, le téléphone, l’identifiant externe, le prénom et le nom ne quittent jamais le navigateur en clair. La balise les normalise puis les hache en SHA-256 avec exactement les mêmes règles que le SDK d’OpenAI : email en minuscules, téléphone réduit à ses chiffres avec l’indicatif pays, nom sans espaces ni ponctuation. Une valeur déjà hachée (64 caractères hexadécimaux, ou une clé sha256_email_address dans le dataLayer) est transmise telle quelle. Une valeur que le SDK refuserait, comme un email invalide ou un téléphone de moins de 8 chiffres, est ignorée et signalée dans la console.
Pensez à pousser les numéros de téléphone avec l’indicatif international (+353 1 555 0123). Un numéro national perd son zéro initial lors de la normalisation et ne correspondra pas au même utilisateur saisi avec l’indicatif.
Event ID Deduplication
Si vous envoyez le même événement à la fois côté navigateur (via cette balise) et côté serveur (via l’API de conversions d’OpenAI), OpenAI risque de compter deux fois la même conversion. Pour l’éviter, on transmet un Event ID identique dans les deux envois : OpenAI conserve le premier événement reçu pour un même Pixel ID, nom d’événement et Event ID, et ignore le doublon.
Renseignez le champ Event ID avec une variable qui génère un identifiant unique et stable pour un même événement, par exemple la variable Event Id de mbaersch disponible dans la galerie GTM Web. Lorsque le champ est vide, aucun Event ID n’est envoyé.
Transmettez la même variable dans le paramètre event_id de vos balises GA4 envoyées au conteneur serveur : la balise OpenAI CAPI d’Addingwell by Didomi réutilise automatiquement ce paramètre comme identifiant d’événement, et OpenAI peut alors dédupliquer les deux envois.

Pixel Options
- Opt Out This Event From User-Level Personalization : envoie
opt_out: trueavec l’événement, pour l’exclure de la personnalisation au niveau utilisateur. - Enable SDK Debug Mode : active le mode debug du SDK, qui journalise son activité dans la console du navigateur avec le préfixe
[oaiq]. Pratique pendant vos tests, à désactiver en production.
Déclencher la balise
La façon de déclencher la balise dépend du format de votre dataLayer : une seule balise en mode Inherit From dataLayer s’il respecte le standard GA4, une balise par événement en mode Override sinon.
Méthode 1 : avec un dataLayer au format standard GA4
Si votre dataLayer respecte le standard GA4, une seule balise suffit. Renseignez votre Pixel ID, laissez Inherit From dataLayer sélectionné et les deux cases de lecture du dataLayer cochées.
Déclenchez ensuite la balise sur l’ensemble des événements que vous souhaitez envoyer à OpenAI, sans oublier les pages vues. Dans cet exemple, je la déclenche sur gtm.init (déclencheur Initialization - All Pages), view_item, add_to_cart, begin_checkout, purchase et generate_lead.
Méthode 2 : avec un dataLayer custom
Si votre dataLayer est custom, créez une balise par événement OpenAI en mode Override, et faites vous-même la correspondance entre vos événements dataLayer et les événements OpenAI.
Exemple avec un événement dataLayer custom AddToCart
dataLayer.push({
event: "AddToCart",
cart: {
currency: "EUR",
total: 30.03,
products: [
{
sku: "SKU_12345",
title: "Stan and Friends Tee",
category: "Apparel",
unit_price: 10.01,
qty: 3
}
]
},
user_data: {
email: "[email protected]",
phone: "+353 1 555 0123",
first_name: "Jane",
last_name: "Doe"
}
});Configurez la balise ainsi :
| Champ | Valeur |
|---|---|
| Event Name Setup Method | Override, Standard Event, items_added |
| Read e-commerce data from the dataLayer | décochée |
| Amount | {{DLV - cart.total}} |
| Currency | {{DLV - cart.currency}} |
| Contents | {{DLV - cart.products}} |
| Item ID Key | sku |
| Item Name Key | title |
| Quantity Key | qty |
| Price Key | unit_price |
| Content Type Key | category |
| Read user data from the dataLayer | cochée |
Gérer le consentement
La balise n’appelle jamais la commande oaiq("consent", ...) du pixel : c’est votre déclencheur GTM qui décide si elle se déclenche, en fonction du choix exprimé par le visiteur dans votre CMP (plateforme de gestion du consentement).
Le pixel OpenAI est un vendor publicitaire. Conditionnez donc le déclenchement de la balise à l’acceptation du vendor OpenAI dans votre CMP ou, si votre CMP ne gère pas ce vendor, à l’acceptation de la catégorie de finalités qui le représente : Targeting, Advertising, Performance, ou par exemple la catégorie C0004 (Targeting Cookies) avec OneTrust.
Quelle que soit votre CMP, la logique est la même :
- Une variable GTM qui retourne
grantedlorsque le vendor OpenAI ou sa catégorie est accepté,deniedsinon. - Un déclencheur pour la page vue, branché sur l’événement que votre CMP pousse dans le dataLayer lorsque le consentement est connu ou mis à jour, avec la condition variable égale à
granted. Il remplace le déclencheur Initialization - All Pages de la méthode 1, de façon à ne pas perdre la page vue lorsque le visiteur accepte après le chargement de la page. - La même condition ajoutée à vos déclencheurs d’événements dataLayer (
add_to_cart,purchase,generate_lead…).
Prérequis indispensable
OpenAI doit être déclaré comme vendor dans l’interface de votre CMP, ou rattaché à une catégorie de finalités publicitaires. Sans cette déclaration, le vendor ne sera jamais présent dans la liste des consentements accordés et votre variable GTM retournera systématiquement denied.
Voici comment procéder avec Axeptio, Didomi et OneTrust. Adaptez la même logique à votre CMP.
Pour vérifier, ouvrez la preview GTM sur une page de votre site avant d’avoir fait votre choix dans la bannière : la balise ne doit pas apparaître dans les balises déclenchées et aucune requête vers bzr.openai.com ne doit partir. Acceptez ensuite le vendor OpenAI ou sa catégorie : la balise doit se déclencher sur l’événement de votre CMP et la requête events apparaître dans l’onglet Network.
Si votre site utilise déjà la commande de consentement du pixel OpenAI, elle reste entièrement sous votre contrôle : la balise ne la modifie pas.
Vérifier sa configuration
Avant de publier, vérifiez que les événements partent correctement. Trois outils sont utiles : la preview GTM, l’onglet Network du navigateur et l’Event Stream d’Ads Manager.
Preview GTM
Cliquez sur Preview en haut à droite de GTM et naviguez sur votre site. Pour chaque événement dataLayer concerné, la balise doit apparaître avec le statut Succeeded.

Ouvrez ensuite l’onglet Console de la preview. La balise y journalise chaque envoi avec le préfixe OpenAI Measurement Pixel, en indiquant le nom de l’événement, les Pixel ID ciblés, les données de l’événement et l’objet utilisateur haché. C’est le moyen le plus rapide de vérifier que le montant a bien été converti et que les identifiants ont bien été hachés.

Onglet Network
Dans les outils de développement du navigateur, filtrez les requêtes sur bzr. Vous verrez trois requêtes : le chargement du SDK oaiq.min.js, la configuration de votre pixel (un fichier JSON nommé d’après votre Pixel ID) et la requête events qui porte vos conversions. Le SDK regroupe les événements proches dans le temps et les envoie en POST vers /v1/sdk/events. Les événements openai::sdk_init et oai::diagnostic qui accompagnent les vôtres sont émis par le SDK lui-même, c’est normal. Le corps de la requête contient vos événements, l’identifiant de clic oppref s’il est présent, et un objet user avec deux blocs possibles :
in: les identifiants que vous avez transmis via la balise (empour l’email,phpour le téléphone,fnetlnpour le prénom et le nom,eidpour l’identifiant externe).fm,htoujs: les identifiants détectés automatiquement par le pixel dans vos formulaires, votre HTML ou vos scripts, lorsque la correspondance avancée automatique est activée sur votre pixel.

Si le même email apparaît dans in et dans un formulaire de la page, le SDK ne l’envoie qu’une fois : sa disparition du bloc fm est le signe que le hachage de la balise est identique à celui du pixel.
Event Stream dans Ads Manager
Dans OpenAI Ads Manager, la section Conversions propose un onglet Event Stream qui liste les derniers événements reçus par votre pixel. C’est la confirmation finale que vos conversions arrivent bien avec le bon nom, le bon montant et la bonne devise.
Erreurs fréquentes
| Message dans la console | Cause | Solution |
|---|---|---|
no Pixel ID configured | Le champ Pixel ID(s) est vide ou ne contient que des virgules. | Renseignez au moins un Pixel ID. |
Invalid custom event name | Le nom custom contient des caractères interdits ou dépasse 64 caractères. | Utilisez uniquement lettres, chiffres, _ et -. |
matches a standard event name | Le nom custom reprend un événement standard. | Sélectionnez l’événement standard dans la liste. |
No event name found in the dataLayer | Mode Inherit sans clé event dans le dataLayer. | Déclenchez la balise sur un événement dataLayer nommé, ou passez en mode Override. |
amount ignored because no valid currency is available | Un montant est présent sans devise ISO 4217 à 3 lettres. | Renseignez ecommerce.currency ou le champ Currency. |
skipped, value rejected by normalization | Email invalide, téléphone trop court ou sans indicatif, nom composé uniquement de chiffres. | Corrigez la valeur poussée dans le dataLayer. |
could not hash | Le navigateur ne fournit pas SubtleCrypto, généralement parce que la page n’est pas en HTTPS. | Testez sur une page sécurisée. |
Tables de correspondance GA4 => OpenAI
Table de correspondance des événements dataLayer
Cette table est utilisée par la balise uniquement lorsque le champ Event Name Setup Method est configuré en Inherit From dataLayer.
| Nom de l’événement dataLayer | Nom de l’événement OpenAI | Type de données |
|---|---|---|
gtm.init_consent (Consent Initialization) | page_viewed | contents |
gtm.init (Initialization) | page_viewed | contents |
gtm.js (Container Loaded) | page_viewed | contents |
gtm.dom (DOM Ready) | page_viewed | contents |
gtm.load (Window Loaded) | page_viewed | contents |
page_view | page_viewed | contents |
view_item | contents_viewed | contents |
view_item_list | contents_viewed | contents |
add_to_cart | items_added | contents |
begin_checkout | checkout_started | contents |
purchase | order_created | contents |
generate_lead | lead_created | customer_action |
sign_up | registration_completed | customer_action |
| Tout autre événement | custom | custom |
Table de correspondance des paramètres e-commerce
Cette table est utilisée par la balise uniquement lorsque la case Read e-commerce data from the dataLayer est cochée, avec les clés d’items par défaut.
| Chemin du paramètre GA4 | Champ OpenAI | Transformation |
|---|---|---|
ecommerce.value | amount | Converti en unité mineure |
ecommerce.currency | currency | Mis en majuscules |
ecommerce.items[item_id] | contents[].id | |
ecommerce.items[item_name] | contents[].name | |
ecommerce.items[quantity] | contents[].quantity | Converti en entier |
ecommerce.items[price] | contents[].amount | Prix unitaire converti en unité mineure |
| Valeur fixe | contents[].content_type | product par défaut |
Table des clés user_data
Cette table est utilisée par la balise uniquement lorsque la case Read user data from the dataLayer est cochée. Chaque clé est cherchée dans user_data.address puis à la racine de user_data, dans l’ordre indiqué.
| Champ OpenAI | Clés déjà hachées | Clés en clair (hachées par la balise) |
|---|---|---|
email_sha256 | sha256_email_address, sha256_email | email_address, email |
phone_number_sha256 | sha256_phone_number, sha256_phone | phone_number, phone |
external_id_sha256 | sha256_external_id, sha256_customer_id, sha256_user_id | external_id, customer_id, user_id, puis user_id à la racine du dataLayer |
first_name_sha256 | sha256_first_name | first_name |
last_name_sha256 | sha256_last_name | last_name |
country | country | |
city | city | |
region | region | |
postal_code | postal_code, zip, zip_code, postcode |
Content Security Policy
Si votre site applique une Content Security Policy, autorisez https://bzrcdn.openai.com dans script-src et connect-src, ainsi que https://bzr.openai.com dans connect-src et img-src. Sans cela, le SDK ne se chargera pas ou ne pourra pas envoyer les événements.
Conclusion
La balise OpenAI Ads Measurement Pixel by DMS vous permet d’installer le pixel des publicités ChatGPT sans écrire une ligne de code : elle exploite votre dataLayer GA4 existant, respecte les formats attendus par OpenAI pour les montants et les identifiants, et prépare la déduplication avec l’API de conversions. Le code source est disponible sur GitHub sous licence Apache 2.0 : n’hésitez pas à ouvrir une issue si vous rencontrez un cas non couvert.
FAQ - Pixel OpenAI Ads
Faut-il installer le snippet OpenAI en plus de la balise ?
oaiq.min.js depuis le CDN d'OpenAI, une seule fois par page, et initialise vos Pixel ID à chaque déclenchement. Ajouter le snippet officiel en plus est inutile et risquerait de créer des doublons.La balise fonctionne-t-elle sans dataLayer au format GA4 ?
Les données utilisateur sont-elles envoyées en clair à OpenAI ?
Peut-on envoyer un même événement à plusieurs Pixel ID ?
measureSingle dédiée, ce qui évite d'envoyer l'événement à d'autres pixels OpenAI éventuellement présents sur la page.Comment gérer le consentement avec cette balise ?
Discutons de votre tracking
Une question sur cet article, besoin d'un audit de votre configuration ou migration server-side ? Écrivez-moi, je réponds sous 24h.


