# Optimisation des conversions ChatGPT Ads : vos conversions entraînent les enchères

> Une campagne oCPC optimise vers un seul événement de conversion : doublons, commandes absentes et événements tardifs faussent les enchères.

Canonical: https://convrail.com/fr/blog/optimisation-conversions-chatgpt-ads/

En campagne optimisée pour la conversion (oCPC), ChatGPT Ads oriente la diffusion vers un seul événement de conversion suivi et facture toujours au clic valide : chaque commande envoyée à OpenAI, et chaque commande oubliée, façonne ce que le système d'enchères apprend. Les doublons gonflent le signal, les événements manquants l'affament, ceux de plus de 7 jours sont rejetés. Un pipeline dédupliqué, complet et ponctuel est le prérequis, pas un raffinement.

## Ce qu'OpenAI documente sur les enchères à la conversion

Cette section se limite à répéter ce que disent les pages officielles, parce que le reste de l'article en dépend et parce que les affirmations sur les enchères sont faciles à gonfler.

La [référence Campaigns](https://developers.openai.com/ads/api-reference/campaigns) définit un champ `bidding_type` à trois valeurs, `"impressions"`, `"clicks"` ou `"conversions"`, et précise qu'il « Defaults to `"impressions"` ». Juste à côté figure `conversion_event_setting_ids`, décrit ainsi : « For conversions, exactly one active standard event setting ID from this account. »

Le [guide Conversion-Optimized Campaigns](https://developers.openai.com/ads/conversion-optimized-campaigns) explique l'intention : « Use a conversion-optimized cost-per-click (oCPC) campaign when you want to optimize delivery toward one tracked conversion event while continuing to pay for valid clicks. » Il énonce les prérequis sans détour. Vous devez avoir « set up conversion tracking with the JavaScript Pixel, the Conversions API, or both », et « The Conversions API is a more reliable tracking source than the pixel alone. » Il vous faut « exactly one active standard conversion event to use as the optimization goal », et « Custom events cannot be oCPC optimization goals. »

L'enchère elle-même s'exprime au niveau du groupe d'annonces. La [référence Ad Groups](https://developers.openai.com/ads/api-reference/ad-groups) fixe `billing_event_type` à « `impression` for impression campaigns; `click` for click and conversion campaigns », et réinterprète l'enchère pour l'oCPC : « For an oCPC campaign, `max_bid_micros` is the CPA bid even though billing uses valid clicks. » L'exemple chiffré de la même référence : « 100000000 is a $100.00 CPA bid for a USD account. » La facturation ne bascule pas vers un paiement à la conversion. Selon les mots du guide, « OpenAI charges you only when a valid click occurs, and the auction determines the actual CPC. »

Deux phrases de plus tranchent la question des conversions qui comptent. Dans la [référence Insights](https://developers.openai.com/ads/api-reference/insights) : « View-through conversions are for reporting only. CPA, post-click CVR, bidding, billing, and conversion optimization remain click-through-based. » Et dans la [référence Measurement Pixel](https://developers.openai.com/ads/measurement-pixel) : « Click-through attribution uses the applicable configured click window. »

| Question | Réponse documentée | Où |
| --- | --- | --- |
| Une campagne peut-elle enchérir sur les conversions ? | Oui, `bidding_type: "conversions"` | Référence Campaigns |
| Quel événement est optimisé ? | Un paramètre d'événement standard actif, aucun événement personnalisé | Guide Conversion-Optimized Campaigns |
| Qu'est-ce que l'enchère ? | `max_bid_micros` comme enchère CPA, facturée au clic valide | Référence Ad Groups |
| Les conversions post-impression entraînent-elles les enchères ? | Non, post-clic uniquement | Référence Insights |
| Comment la phase d'apprentissage est-elle dimensionnée ou chronométrée ? | Non documenté sur les pages que nous avons lues | s. o. |
| Quelles caractéristiques le modèle utilise-t-il pour prédire la probabilité de conversion ? | Non documenté sur les pages que nous avons lues | s. o. |

Les deux dernières lignes comptent autant que les quatre premières. La documentation ne publie ni volume minimal de conversions, ni durée de phase d'apprentissage, ni les rouages de la prédiction. Quiconque vous cite un seuil devine. Ce que le guide dit, en revanche, est qualitatif : « Keep conversion tracking healthy. Incomplete or incorrectly configured tracking can make reporting and optimization less effective », et « Use a conversion event with enough volume to evaluate performance. »

## Pourquoi le signal de conversion est le seul levier que vous maîtrisez entièrement

Dans une campagne oCPC, vous fixez une enchère CPA, un budget et une création. Le système d'enchères fixe le CPC réel, et l'optimisation décide où et à qui votre annonce est diffusée en fonction de l'événement de conversion que vous avez désigné. Ce flux d'événements est la seule entrée qu'il vous revient entièrement de soigner, et il alimente à la fois l'optimisation de la diffusion, le CPA et le taux de conversion rapportés, et la colonne des conversions.

Parce que l'optimisation repose sur le clic, la chaîne passe par l'identifiant `oppref`. La référence Measurement Pixel indique que le pixel « captures `oppref` from the landing page URL » et « stores `oppref` in a first-party `__oppref` cookie so later page views can reuse it. » La [référence Conversions API](https://developers.openai.com/ads/conversions-api) décrit le même champ sur les événements serveur comme « An opaque, OpenAI-provided attribution identifier. Pass the original string without modification. » Une conversion qui atteint OpenAI sans moyen de la rattacher à un clic est une conversion dont l'optimisation ne peut rien apprendre, quoi que dise votre tableau de bord.

La bonne question n'est donc pas « mon pixel se déclenche-t-il ? » mais « chaque commande réelle atteint-elle OpenAI exactement une fois, dans la fenêtre, avec le contexte du clic attaché ? ». Les trois modes de défaillance ci-dessous sont les façons dont cette question reçoit une mauvaise réponse.

## Défaillance 1 : les doublons gonflent le signal

La règle de déduplication est courte. Référence Conversions API : « Deduplication uses your Pixel ID, `event_name`, and `id`. OpenAI uses the first event it receives for a matching key and ignores later duplicates. » Côté pixel, l'option `event_id` en est le miroir ; la référence Measurement Pixel la décrit ainsi : « Set a unique ID to identify the same event sent from the browser and server. »

Les doublons apparaissent quand cette clé n'est pas respectée :

- Le pixel envoie le passage en caisse avec un identifiant généré dans le navigateur, et le serveur envoie la même commande avec l'identifiant de base de données. Deux clés, deux conversions.
- Une nouvelle tentative après une erreur réseau génère un identifiant neuf au lieu de renvoyer le même.
- Un rechargement de la page de remerciement déclenche le pixel une seconde fois sans identifiant stable.

Des conversions gonflées font paraître la campagne moins chère qu'elle ne l'est et, en oCPC, apprennent à l'optimisation que les clics d'un certain type convertissent deux fois plus souvent qu'en réalité.

Le correctif tient en un identifiant déterministe par commande, partagé par toutes les sources. Convrail utilise `order_<orderId>` sur le pixel au passage en caisse et sur l'événement serveur construit à partir du webhook de commande payée, si bien que les deux copies se fondent en une seule chez OpenAI. Le raisonnement de conception est détaillé dans [Pixel OAIQ ou Conversions API](/fr/blog/pixel-oaiq-ou-conversions-api/).

## Défaillance 2 : les événements manquants affament le signal

Les événements se perdent dans le navigateur et sur le serveur, pour des raisons différentes.

Dans le navigateur, un pixel ne s'exécute que si un script est autorisé à s'exécuter et si une requête est autorisée à quitter l'onglet. Bloqueurs de publicité, bandeaux de consentement qui se déclenchent après que le visiteur est déjà parti, onglets fermés sur la page de remerciement et fonctions de confidentialité retirent tous des événements avant qu'ils n'atteignent OpenAI. Nous n'avons pas mesuré cette perte sur un ensemble de boutiques, nous ne publions donc aucun pourcentage. Le constat tient sans chiffre : une installation limitée au pixel sous-déclare, et une campagne oCPC nourrie par elle est optimisée vers un sous-ensemble de vos vrais acheteurs.

Sur le serveur, les pertes sont plus silencieuses et plus mécaniques :

- Le webhook de commande échoue ou n'est pas souscrit, la commande ne devient donc jamais un événement.
- Une réponse 4xx est traitée comme transitoire et réessayée indéfiniment, ou traitée comme définitive et jetée sans que personne ne regarde.
- Un seul événement malformé coule tout le lot. La référence Conversions API est explicite : « The API accepts batches of up to 1,000 events. If one event in the batch fails, the full batch fails. » Une seule commande avec un mauvais code devise ou un hashage mal formé peut entraîner 999 commandes valides dans sa chute.
- Le consentement est refusé et l'événement est retenu à bon droit, mais rien ne consigne qu'il l'a été, si bien que le trou ressemble à un bogue plutôt qu'à une décision.

Le manque est l'image miroir du gonflement : l'optimisation voit moins de conversions qu'il n'y en a eu, le CPA rapporté grimpe, et la campagne est jugée ou freinée sur des données incomplètes.

## Défaillance 3 : les horodatages tardifs sont rejetés

La référence Conversions API fixe une fenêtre stricte : le `timestamp_ms` « must be within the last 7 days and no more than 10 minutes in the future. »

Les deux bornes mordent en pratique. Côté passé, une réinjection des commandes du mois dernier est rejetée, et comme un lot échoue en bloc, mêler une seule commande périmée à un lot de commandes fraîches rejette aussi les fraîches. Une file qui se bloque une semaine puis se vide envoie des événements tous morts à l'arrivée. Côté futur, un serveur dont l'horloge dérive de plus de dix minutes, ou un traitement qui utilise « maintenant » au lieu de l'heure de la commande et prend de l'avance sur une réplique de base de données en retard, produit des événements qu'OpenAI refuse.

## À quoi ressemble un pipeline de conversion propre

Mettre les trois modes de défaillance côte à côte donne une courte spécification. Un pipeline qui satisfait chaque ligne est un pipeline vers lequel vous pouvez pointer une campagne oCPC sans douter des chiffres.

| Propriété | Ce que cela signifie en pratique |
| --- | --- |
| Un identifiant par conversion, toutes sources confondues | Le même `order_<orderId>` sur l'`event_id` du pixel et l'`id` de l'API, sous le même identifiant de pixel |
| Copie serveur issue du webhook de commande payée | Chaque commande devient un événement, que le navigateur se soit déclenché ou non |
| Contexte du clic transporté jusqu'au serveur | `oppref` lu dans l'URL d'atterrissage, conservé 7 jours dans le cookie `__oppref`, attaché à la conversion |
| Horodatages réels des commandes | `timestamp_ms` est l'heure de la commande, jamais l'heure d'envoi, et jamais plus ancien que 7 jours |
| Validation avant mise en lot | Chaque événement vérifié localement, pour qu'une mauvaise ligne ne fasse pas échouer un lot de 1 000 |
| Nouvelles tentatives avec un plancher | Backoff exponentiel sur 429 et 5xx, aucune nouvelle tentative sur 4xx, file des rebuts (dead-letter queue) après la dernière tentative, et une alerte |
| Données personnelles hashées | Emails et numéros de téléphone hashés en SHA-256 avant stockage ou transmission, jamais envoyés en clair |
| Mode test | `validate_only: true` pendant le câblage, pour que rien ne soit compté tant que les charges utiles ne sont pas acceptées |

Un événement serveur qui respecte la spécification ressemble à ceci :

```json
POST https://bzr.openai.com/v1/events?pid=<PIXEL-ID>
Authorization: Bearer <key>

{
  "validate_only": false,
  "integration_source": "convrail",
  "events": [
    {
      "id": "order_1001",
      "type": "order_created",
      "timestamp_ms": 1757001600000,
      "oppref": "<value read from the landing URL>",
      "source_url": "https://shop.example/checkouts/thank-you",
      "action_source": "web",
      "user": {
        "emails_sha256": ["<64 lowercase hex chars>"],
        "ip_address": "203.0.113.10",
        "user_agent": "Mozilla/5.0 ..."
      },
      "data": {
        "type": "contents",
        "amount": 12990,
        "currency": "EUR",
        "contents": [
          { "id": "sku-42", "quantity": 1, "amount": 12990, "currency": "EUR" }
        ]
      }
    }
  ]
}
```

Deux détails de cette charge utile sont faciles à rater. Le montant est un entier dans l'unité mineure de la devise (l'exemple de la référence elle-même : « use 4200 for $42.00 »), donc 129,90 € s'écrit `12990`, pas `129.9`. Et l'email hashé est le SHA-256 de l'adresse débarrassée de ses espaces et passée en minuscules, rendu sur 64 caractères hexadécimaux minuscules ; tout autre format n'est pas une clé de correspondance.

C'est le pipeline que Convrail fait tourner pour les boutiques Shopify et WooCommerce : événements navigateur via le pixel OAIQ, événements serveur issus du webhook `orders/paid` (ou des hooks de commande WooCommerce), lots de 1 000 événements au plus avec backoff et file des rebuts, hashage à la réception avec une garde automatique qui refuse toute charge utile sortante contenant des données personnelles en clair, et une alerte de santé quand un lot échoue définitivement. Le pas-à-pas Shopify se trouve dans [Comment suivre les conversions ChatGPT Ads sur Shopify](/fr/blog/suivre-conversions-chatgpt-ads-shopify/).

## Comment auditer votre propre pipeline avant de passer en oCPC

Vous n'avez pas à faire confiance à la description d'un éditeur, la nôtre comprise. Six contrôles, de quelques minutes chacun, vous disent si votre signal de conversion est apte à servir d'objectif d'enchère.

### 1. Suivre une commande de bout en bout

Prenez une commande passée dans la dernière heure. Retrouvez son événement navigateur et son événement serveur, et confirmez qu'ils portent le même identifiant sous le même identifiant de pixel. Si vous ne pouvez pas voir les deux copies côte à côte, vous ne pouvez pas savoir si elles se dédupliquent. L'écran Événements de Convrail liste chaque événement avec sa source, son statut et son horodatage précisément pour cette raison.

### 2. Confirmer que l'événement d'optimisation est un événement standard

Ouvrez vos paramètres d'événements. La [référence Conversion Setup](https://developers.openai.com/ads/api-reference/conversion-setup) montre un paramètre d'événement dont l'`event_type` est soit un « supported event or `custom` », accompagné d'un `attribution_window_days`. Votre objectif oCPC doit être un type standard comme `order_created`, puisque les événements personnalisés sont exclus, et il doit être celui que votre pipeline alimente réellement.

### 3. Vérifier que le pixel arrive en ce moment même

La même référence documente `GET /conversions/events` avec un paramètre `pid`, qui « Returns up to 50 conversion events from previous 15 minutes ». Parcourez votre boutique, déclenchez une vue de page et un ajout au panier, et confirmez qu'ils apparaissent. Si rien ne s'affiche dans le quart d'heure, la couche navigateur est cassée, quoi qu'en disent vos outils d'analyse.

### 4. Envoyer un lot en validation seule

Prenez les commandes d'hier, construisez le lot tel que vous l'enverriez, et postez-le avec `validate_only: true`. La référence décrit le drapeau ainsi : « Validates events without saving them when `true`. » Un lot rejeté ici est un lot qui aurait perdu des commandes en silence en production.

### 5. Comparer les décomptes sur une fenêtre fixe

Comptez vos commandes payées des sept derniers jours. Comparez avec la métrique `conversions` des mêmes jours dans l'Ads Manager ou le point de terminaison Insights, en gardant en tête que « `conversions` is always equal to `click_through_conversions` ». Le chiffre de l'Ads Manager doit être un sous-ensemble de vos commandes : celles attribuées à un clic dans la fenêtre. S'il est plus grand, vous avez des doublons. Si la part attribuée au clic bouge fortement d'une semaine à l'autre sans changement de dépense, vous avez probablement des trous intermittents.

### 6. Regarder l'horodatage le plus ancien de votre file

Si votre file d'envoi peut un jour contenir un événement de plus de quelques heures, demandez-vous ce qui se passe au septième jour. Une file sans alarme d'ancienneté est une file qui fera un jour échouer tout un arriéré d'un coup.

## Erreurs fréquentes

- Choisir `bidding_type: "conversions"` sur une boutique dont la seule source est le pixel. Les mots du guide : la Conversions API « is a more reliable tracking source than the pixel alone. »
- Générer l'`event_id` du pixel dans le navigateur avec une valeur aléatoire pendant que le serveur utilise le numéro de commande. Même vente, deux clés.
- Envoyer `amount` en unités majeures. `42`, pour l'API, c'est quarante-deux centimes, pas quarante-deux dollars.
- Horodater les événements à l'heure d'envoi plutôt qu'à l'heure de la commande, ce qui décale les commandes par rapport à la fenêtre de clic et, après un blocage de file, les fait sortir tout à fait de la fenêtre de 7 jours.
- Traiter une 4xx comme réessayable. Le lot échouera de la même façon à chaque fois ; le correctif est dans la charge utile, et l'événement a sa place dans la file des rebuts avec son erreur, pas dans une boucle infinie.
- Pointer l'optimisation vers un événement personnalisé. Ce n'est pas autorisé comme objectif oCPC, et une campagne créée ainsi n'optimise pas vers ce que vous croyez.

## Et maintenant

Si vous êtes sur le point de basculer une campagne ChatGPT Ads en enchères optimisées pour la conversion, exécutez d'abord les six contrôles ci-dessus, puis regardez comment [le suivi des conversions de Convrail](/fr/tracking-conversions/) envoie chaque commande une seule fois, depuis le navigateur et depuis le serveur, avec le contexte du clic attaché et rien de personnel en clair.