# Où les boutiques perdent leur signal ChatGPT : un audit en 5 contrôles

> Cinq contrôles repèrent la plupart des pannes de suivi ChatGPT : navigateur vs serveur, doublons, flux rejeté, lots API refusés, preuves d'attribution.

Canonical: https://convrail.com/fr/blog/audit-signal-chatgpt-5-controles/

La plupart des pannes de suivi ChatGPT suivent cinq schémas : un pixel navigateur qui a cessé de se déclencher pendant que le serveur continue de remonter, des commandes comptées deux fois parce que le pixel et le serveur ont utilisé des identifiants d'événement différents, des lignes de flux rejetées jusqu'à l'expiration du produit au bout de 14 jours, des lots Conversions API refusés en bloc, et des commandes attribuées sans preuve de la façon dont elles l'ont été. Chacun a un contrôle manuel, un correctif et un moniteur.

## Pourquoi un audit, et pas un coup d'œil au tableau de bord

L'Ads Manager rend compte du signal de conversion qu'il reçoit. Il ne vous dit pas ce qu'il n'a pas reçu, et la documentation OpenAI ne décrit aucun rapport d'erreur par ligne pour les lignes de flux dont l'ingestion échoue. Une boutique peut donc paraître saine du côté des rapports pendant que des achats n'arrivent jamais, ou arrivent deux fois. Les cinq contrôles ci-dessous partent de vos propres données, là où les pièces manquantes sont visibles. Aucun n'exige de modification de code, et chacun se termine par la façon dont les moniteurs de santé de Convrail détectent le problème, avec les seuils exacts utilisés.

## Contrôle 1 : événements navigateur vs événements serveur

Le pixel OAIQ tourne dans le navigateur de l'acheteur et envoie `page_viewed`, `contents_viewed`, `items_added`, `checkout_started` et `order_created` au fil de la session. Votre intégration côté serveur envoie l'appel Conversions API pour `order_created` quand la commande est payée, depuis un webhook ou un hook qui ne dépend pas du navigateur. Les deux sont censés fonctionner. Le rapport entre les deux est la première chose à lire.

### Comment vérifier à la main

Ouvrez votre boutique dans une fenêtre de navigation privée avec les outils de développement sur l'onglet Réseau, filtrez sur `bzr.openai.com`, puis parcourez une page produit, un ajout au panier et le tunnel de paiement. La documentation du pixel place le script à `https://bzrcdn.openai.com/sdk/oaiq.min.js` ; vous devez le voir se charger, puis une requête par événement. Comparez ensuite avec ce que votre serveur a envoyé pour la même session : l'appel Conversions API vers `https://bzr.openai.com/v1/events?pid=<PIXEL-ID>` dans les journaux de votre application.

Sur une fenêtre plus longue, comptez les deux côtés sur les dernières 24 heures. Si vous gardez votre propre copie des événements (Convrail conserve une copie relayée de chaque événement pixel à côté des événements serveur), c'est une seule requête.

### À quoi ressemble une situation saine

Les événements navigateur sont plus nombreux que les événements serveur, parce que la navigation produit beaucoup d'événements et que chaque commande produit un seul appel serveur. Les événements `order_created` côté serveur sont proches en nombre des `order_created` côté navigateur, le serveur étant légèrement au-dessus : certains acheteurs ferment l'onglet avant l'affichage de la page de remerciement, bloquent les scripts ou refusent le consentement (la documentation du pixel indique que lorsque le consentement est à false, il « doesn't send measurement-event pings »). Nous n'avons pas mesuré de ratio universel ; ce qui compte, c'est votre propre référence et les écarts par rapport à elle.

### À quoi ressemble une situation dégradée

Zéro événement navigateur en 24 heures pendant que les événements serveur continuent d'arriver est la panne la plus nette : le pixel ne se charge pas, parce qu'une mise à jour du thème a retiré le script, qu'un bandeau de consentement refuse désormais par défaut, qu'une politique de sécurité du contenu bloque `bzrcdn.openai.com`, ou que l'identifiant de pixel a changé. L'inverse (des événements navigateur mais aucun événement serveur) signifie que le webhook ne se déclenche pas ou que l'identifiant Conversions API a expiré.

### Le correctif

Réinstallez le pixel par un mécanisme qui survit aux changements de thème. Sur Shopify, un web pixel enregistré via la Web Pixel API se charge indépendamment du thème ; sur WooCommerce, un hook de plugin dans le pied de page fait la même chose. Confirmez que l'identifiant de pixel correspond à celui de l'Ads Manager. Puis confirmez le parcours de consentement : `oaiq("consent", false)` bloque les événements, `oaiq("consent", true)` les autorise, et la valeur par défaut est true sauf si un refus est mémorisé.

### Comment Convrail le détecte

Le moniteur « Pixel cassé » se déclenche quand il y a zéro événement navigateur sur les dernières 24 heures alors que les événements serveur continuent d'arriver, sévérité avertissement. Le moniteur « Chute de volume » couvre la version plus douce : événements des dernières 24 heures sous 30 % de la référence quotidienne (la moyenne des 7 jours précédents), évalué seulement une fois que la référence atteint au moins 50 événements par jour, pour ne pas noyer les petites boutiques sous le bruit. Les deux tournent toutes les 15 minutes, et chacun ouvre exactement une alerte par boutique et par type, résolue automatiquement quand la condition disparaît.

## Contrôle 2 : commandes en double

Une commande envoyée deux fois gonfle les conversions et le chiffre d'affaires dans l'Ads Manager et fait paraître le ROAS meilleur qu'il n'est. La référence de la Conversions API donne un seul mécanisme pour l'empêcher : la déduplication sur « Pixel ID, `event_name`, and `id` », avec la règle « OpenAI uses the first event it receives for a matching key and ignores later duplicates ». La documentation du pixel dit la même chose de l'autre côté : « If you send the same conversion from both the Measurement Pixel and a server-side integration, reuse the same event_id in both places. »

### Comment vérifier à la main

Prenez dix commandes récentes. Pour chacune, retrouvez l'`event_id` envoyé par le pixel sur la page de remerciement (onglet Réseau, la requête `order_created`) et l'`id` envoyé par votre serveur dans la charge utile Conversions API pour la même commande. Les deux chaînes doivent être identiques. Si votre pixel génère un UUID aléatoire et que votre serveur utilise le numéro de commande, chaque commande compte deux fois.

Regardez ensuite les conversions de l'Ads Manager pour une journée dont vous connaissez le nombre de commandes. Un compte proche du double de vos commandes payées est le symptôme.

### Le correctif

Dérivez l'identifiant d'événement de la commande des deux côtés, pour qu'aucun n'ait besoin de savoir ce que l'autre a généré. Convrail utilise `order_<orderId>` comme identifiant d'événement sur le pixel et sur le webhook serveur pour la même commande ; une intégration sur mesure peut adopter la même convention. Une subtilité : la clé de déduplication inclut l'identifiant de pixel et, pour les événements personnalisés, `custom_event_name`, donc une commande envoyée vers deux identifiants de pixel fait deux événements, pas un doublon.

### Comment Convrail le détecte

Il n'y a pas de moniteur distinct pour les doublons, parce que l'identifiant d'événement partagé supprime la cause à la source. L'export des commandes attribuées liste chaque commande une seule fois avec son identifiant, donc la comparaison avec le compte de l'Ads Manager est une simple jointure.

## Contrôle 3 : rejets de flux et expiration à 14 jours

Un produit absent du flux ne peut être ni recommandé, ni affiché en publicité, ni acheté via le paiement intégré. Le côté flux perd du signal de façon plus discrète que le suivi : les lignes sont rejetées sans rapport, et le produit disparaît avec un délai. La vue d'ensemble du dépôt de fichiers indique qu'« OpenAI retains its most recently processed record for up to 14 days ». Une ligne rejetée aujourd'hui garde son produit visible pendant deux semaines grâce au dernier instantané accepté, puis le produit expire.

### Comment vérifier à la main

Ouvrez votre dernier fichier de flux livré et validez-le vous-même contre la spécification. Les neuf champs obligatoires sont `item_id`, `title`, `description`, `url`, `brand`, `seller_name`, `image_url`, `availability` et `price`. Vérifiez ensuite les formats qui échouent le plus souvent : le prix en `amount CURRENCY` (« a decimal amount in major units, a space, and an uppercase three-letter ISO 4217 currency code »), la disponibilité parmi `in_stock`, `out_of_stock`, `pre_order`, `backorder`, `unknown`, les booléens en chaînes minuscules, le GTIN avec « Exactly 8, 12, 13, or 14 digits, including a valid check digit », et aucune valeur de substitution (« Do not use placeholder strings such as `null`, `unknown`, or `n/a` »).

Comparez le nombre de lignes du fichier avec le nombre de produits actifs de votre boutique, puis avec le fichier de la semaine dernière : les lignes présentes alors et absentes maintenant ont entamé leur décompte de 14 jours. La vue d'ensemble nomme les causes habituelles : « Missing required fields, Outdated or non-spec field names, Malformed field values. »

### Le correctif

Validez avant la livraison, pas après : chaque ligne contrôlée contre la spécification de votre côté, les lignes rejetées listées avec le champ et la règle, pour que le produit puisse être corrigé dans la boutique et repris à l'exécution suivante. Utilisez des noms de fichiers stables et des instantanés complets (« Keep the same file name on every update and overwrite it with the latest snapshot »). Pour retirer un produit volontairement, mettez `is_eligible_search=false` au lieu de supprimer la ligne ; la vue d'ensemble décrit cela comme la façon de rendre un produit inéligible au prochain instantané traité.

### Comment Convrail le détecte

Deux couches. D'abord, le validateur : chaque ligne est validée avant l'export, et le journal de chaque exécution enregistre `itemsTotal`, `itemsValid`, `itemsRejected`, le différentiel par rapport à l'exécution précédente (ajoutés, retirés, modifiés) et une entrée d'erreur par article rejeté avec `item_id`, champ et message. Ensuite, le moniteur « Livraison de flux en échec » : au moins une exécution de flux n'a pas pu être livrée dans les dernières 24 heures, sévérité critique, une fois les tentatives de livraison épuisées. Un produit qui disparaîtrait en silence au bout de deux semaines devient une ligne de journal le jour où il commence à échouer. Le guide sur les [produits absents des résultats shopping de ChatGPT](/fr/blog/produits-absents-resultats-shopping-chatgpt/) approfondit chaque motif de rejet.

## Contrôle 4 : lots Conversions API en échec

Les événements serveur voyagent par lots. La référence est directe sur ce qu'un mauvais événement fait à ses voisins : « The API accepts batches of up to 1,000 events. » et « If one event in the batch fails, the full batch fails. » Une seule commande avec un horodatage malformé ou un `source_url` manquant peut entraîner jusqu'à 999 commandes valides dans sa chute, et l'Ads Manager n'en voit tout simplement aucune.

### Comment vérifier à la main

Cherchez dans les journaux de votre intégration les réponses autres que 2xx à `POST https://bzr.openai.com/v1/events`. Vérifiez ensuite les règles par événement qui trébuchent le plus souvent : `timestamp_ms` « must be within the last 7 days and no more than 10 minutes in the future » (un décalage d'horloge ou un rattrapage d'anciennes commandes échoue ici), `source_url` est obligatoire pour les événements web avec un schéma et un hôte, `data.amount` est « an integer in the currency's standard minor unit » (`4200` pour 42,00 $, jamais `42.00`), et les champs utilisateur hashés doivent être des SHA-256 en hexadécimal minuscule de 64 caractères.

Si vous n'êtes pas sûr qu'une charge utile soit valide, la référence propose `validate_only`, qui « Validates events without saving them when `true`. » Une passe de validation sur un lot d'échantillon vous dit si la forme est bonne sans rien enregistrer.

### Le correctif

Réessayez avec une temporisation exponentielle sur les réponses 429 et 5xx, qui sont transitoires. Après la dernière tentative, déplacez le lot vers une file des rebuts (dead-letter queue) plutôt que de le jeter, pour que les événements puissent être inspectés, corrigés et renvoyés dans la fenêtre d'horodatage de 7 jours. Et traitez un lot définitivement en échec comme un incident : les commandes qu'il contient ne sont pas dans l'Ads Manager.

### Comment Convrail le détecte

Les lots sont envoyés avec jusqu'à 1 000 événements, réessayés avec une temporisation exponentielle sur 429 et 5xx, et placés en file des rebuts après la dernière tentative. Le moniteur « Erreurs Conversions API » se déclenche quand au moins un lot a échoué définitivement dans la dernière heure après toutes les tentatives, sévérité critique. Le mode test utilise `validate_only` pour qu'une nouvelle boutique puisse vérifier la forme de ses charges utiles avant d'envoyer des données réelles. Le pas-à-pas d'installation pour Shopify est dans [suivre les conversions ChatGPT Ads sur Shopify](/fr/blog/suivre-conversions-chatgpt-ads-shopify/).

## Contrôle 5 : couverture des preuves d'attribution

La dernière fuite n'est pas dans ce qui atteint OpenAI mais dans ce que vous pouvez prouver de votre côté. Une commande attribuée à ChatGPT doit porter sa raison : l'identifiant de clic `oppref` issu d'une publicité, un `utm_source` sur la page de destination, ou un référent. Si l'attribution est une étiquette sans preuve, vous ne pouvez ni la rapprocher de l'Ads Manager, ni distinguer la publicité de l'organique.

### Comment vérifier à la main

Prenez vos commandes attribuées sur une période et classez chacune selon la preuve disponible sur la commande telle qu'enregistrée par votre plateforme. Convrail applique ces règles, la première qui correspond l'emporte :

| Preuve sur la commande | Verdict |
| --- | --- |
| L'URL de destination contient `oppref=<id>` | Publicité ChatGPT |
| `utm_source` parmi chatgpt, openai ou chatgpt.com, avec `utm_medium` parmi cpc, ppc, paid ou ads | Publicité ChatGPT |
| Même `utm_source`, tout autre medium | ChatGPT organique |
| Le référent est chatgpt.com, chat.openai.com ou openai.com (ou un sous-domaine) | ChatGPT organique |
| Aucun des cas ci-dessus | Non attribuée |

Comptez combien de commandes attribuées tombent dans chaque ligne. Une répartition saine a des commandes publicitaires qui portent `oppref` : la référence de la Conversions API le décrit comme « An opaque, OpenAI-provided attribution identifier », et le pixel « stores oppref in a first-party `__oppref` cookie so later page views can reuse it », donc il devrait survivre du clic sur la publicité jusqu'à la commande. Si vos commandes attribuées à la publicité reposent surtout sur les UTM ou le référent, l'`oppref` se perd quelque part entre la page de destination et la commande.

### Ce qui casse la preuve

Les redirections qui retirent les paramètres de requête (un sélecteur de pays, une redirection de `www` vers le domaine nu, une application qui réécrit l'URL de destination), une plateforme qui enregistre le référent à la première page vue mais pas sur la commande, et des parcours de consentement qui effacent les cookies avant le paiement. Le référent est la preuve la plus faible : souvent présent sur la première page, disparu à la page de remerciement.

### Le correctif

Préservez `oppref` tout au long de la chaîne d'atterrissage et attachez-le aux événements de conversion ; le pixel le fait quand il se charge sur la page de destination, et la Conversions API accepte `oppref` sur l'événement, donc l'appel serveur le porte aussi. Ajoutez `utm_source` et `utm_medium` aux URL de vos publicités et de votre flux comme seconde ligne de preuve (la page de bonnes pratiques suggère des paramètres tels que `utm_medium=feed` sur `url`). Stockez la preuve avec la commande, pas seulement le verdict.

### Comment Convrail le rapporte

Il n'y a pas de moniteur automatisé pour la couverture des preuves ; c'est une revue, pas un seuil. Convrail stocke la règle appliquée et la preuve avec chaque commande attribuée, et exporte les commandes attribuées en CSV avec identifiant de commande, montant, medium, méthode et preuve, de sorte que le décompte ci-dessus tient dans un tableau croisé. L'ensemble des règles et leurs limites sont sur la [page attribution](/fr/attribution/).

## L'audit en un tableau

| Contrôle | Signal manuel | Correctif | Moniteur Convrail et seuil |
| --- | --- | --- | --- |
| 1. Navigateur vs serveur | Zéro requête pixel vers bzr.openai.com alors que des commandes arrivent côté serveur | Pixel indépendant du thème, identifiant de pixel correct, parcours de consentement | Pixel cassé : 0 événement navigateur en 24 h alors que des événements serveur arrivent (avertissement). Chute de volume : dernières 24 h sous 30 % de la moyenne quotidienne sur 7 jours, référence d'au moins 50 événements/jour (critique) |
| 2. Commandes en double | L'`event_id` du pixel diffère de l'`id` serveur pour la même commande | Dériver l'identifiant de la commande des deux côtés (`order_<orderId>`) | Empêché à la source ; audit via l'export des commandes attribuées |
| 3. Rejets de flux et expiration | Lignes manquantes ou malformées ; produits disparus après 14 jours | Valider chaque ligne avant livraison ; journaliser les rejets ; `is_eligible_search=false` pour retirer volontairement | Journal d'exécution avec erreurs par ligne. Livraison de flux en échec : au moins une exécution non livrée en 24 h (critique) |
| 4. Lots CAPI en échec | Réponse autre que 2xx sur POST /v1/events ; lot entier refusé | Temporisation sur 429/5xx, file des rebuts après la dernière tentative, `validate_only` en test | Erreurs Conversions API : au moins un lot en échec définitif dans la dernière heure (critique) |
| 5. Preuves d'attribution | Commandes publicitaires sans `oppref` | Préserver les paramètres de requête, ajouter des UTM, stocker la preuve avec la commande | Aucun moniteur ; colonne de preuve dans l'export CSV |

Tous les moniteurs sont évalués toutes les 15 minutes par boutique. Chaque condition ouvre au plus une alerte, envoyée une fois par email si les notifications sont activées, et résolue automatiquement quand la condition disparaît.

## Erreurs fréquentes

**Prendre l'Ads Manager pour la source de vérité du volume.** Il rapporte ce qui est arrivé. L'écart n'est visible que de votre côté.

**Rattraper d'anciennes commandes via la Conversions API.** Les événements de plus de 7 jours échouent la règle d'horodatage et, dans un lot, entraînent les commandes fraîches dans leur chute.

**Supprimer une ligne produit pour le masquer.** Le produit reste visible jusqu'à 14 jours de toute façon. `is_eligible_search=false` est la méthode documentée pour le retirer au prochain instantané.

## Que faire ensuite

Faites les cinq contrôles une fois à la main, puis laissez les [alertes de santé de Convrail](/fr/alertes-sante/) en exécuter quatre toutes les 15 minutes et conservez la preuve du cinquième dans l'export des commandes attribuées.