La plus grande partie d’un flux Google Shopping passe dans le flux produit OpenAI : identifiants, titres, descriptions, prix, GTIN, marque et état ont tous un équivalent direct. Ce qui casse, c’est ce que Google n’a jamais demandé : un seller_name sur chaque ligne, des booléens en chaînes minuscules pour l’éligibilité à la recherche, aux publicités et au paiement, target_countries, et l’orthographe pre_order. Ce guide fait la correspondance champ par champ.
Deux spécifications, un seul catalogue
Google Merchant Center et OpenAI veulent tous deux une liste plate de produits avec un identifiant stable, un prix dans une devise, une image et une page de destination. Le vocabulaire diffère. Google appelle l’identifiant id et la page de destination link ; OpenAI les appelle item_id et url. Google regroupe les variantes avec item_group_id ; OpenAI utilise group_id. Les valeurs sont en général les mêmes données, donc une couche de correspondance fait l’essentiel du travail.
Les différences qui comptent ne sont pas des renommages. Ce sont des champs exigés par OpenAI qui n’ont aucune source dans un flux Google, des valeurs qu’OpenAI orthographie autrement, et des valeurs par défaut qui se comportent différemment quand une colonne manque. Le reste de cet article passe chacune d’elles en revue.
OpenAI accepte aussi un second format qui conserve les noms de colonnes Google. La spécification le décrit à part et ajoute une condition : « Use this format only after OpenAI confirms it for your registered feed. » Il existe donc en réalité trois chemins : convertir votre flux Google vers le format natif OpenAI, enregistrer un flux compatible Google, ou générer les deux à partir d’un seul catalogue. La dernière option est celle que Convrail applique, et les raisons apparaissent dès que la table de correspondance est posée.
Correspondance champ par champ
Le tableau ci-dessous associe chaque attribut Google courant à son équivalent OpenAI. « Passe » signifie que la valeur se copie telle quelle. « Renommer » signifie que seul le nom de colonne change. « Convertir » signifie que la valeur elle-même demande du travail.
| Attribut Google | Champ OpenAI | Statut | Remarques |
|---|---|---|---|
id | item_id | Renommer | OpenAI : « Stable ID, unique per item or variant within your feed. Never reuse it for a different item. » Google limite id à 50 caractères ; OpenAI accepte encore id et sku comme alias hérités. |
item_group_id | group_id | Renommer | Les deux désignent un identifiant parent partagé, distinct de l’identifiant de chaque article. OpenAI accepte item_group_id comme alias. |
title | title | Passe | Les deux autorisent 150 caractères et veulent la variante nommée dans le titre. |
description | description | Passe, vérifier le contenu | Les deux autorisent 5 000 caractères. OpenAI veut du texte brut ; le HTML laissé par l’éditeur de la boutique doit être retiré. |
link | url | Renommer | Les deux exigent une URL absolue en HTTP ou HTTPS. OpenAI : « Product detail page for the item, with the variant selected when possible. » |
image_link | image_url | Renommer, vérifier le format | Google accepte JPEG, WebP, PNG, GIF, BMP et TIFF. OpenAI veut un lien direct vers un JPEG ou un PNG ; une image .webp acceptée par Google ne convient pas. |
availability | availability | Convertir | Google : in_stock, out_of_stock, preorder, backorder. OpenAI natif : in_stock, out_of_stock, pre_order, backorder, unknown. Le tiret bas de pre_order est le piège. |
availability_date | availability_date | Passe | ISO 8601 des deux côtés. |
price | price | Passe | L’exemple de Google est 15.00 USD ; celui d’OpenAI est 79.99 USD. Même forme : montant décimal, espace, code ISO 4217 en majuscules. |
sale_price | sale_price | Passe, vérifier la valeur | OpenAI : « greater than zero, strictly less than price, and in the same currency. » Un prix promotionnel égal au prix passe chez Google et échoue chez OpenAI. |
sale_price_effective_date | (absent du format natif) | Convertir | Le format natif OpenAI veut le prix courant : « Submit the current price; update the feed when a sale starts or ends. » Le format compatible Google conserve la paire début/fin. |
gtin | gtin | Passe, vérifier les chiffres | OpenAI : « Exactly 8, 12, 13, or 14 digits, including a valid check digit. » Google autorise jusqu’à 50 caractères numériques, donc une valeur tolérée par Google peut échouer ici. |
mpn | mpn | Passe | Les deux conservent la ponctuation et la casse. |
brand | brand | Passe | Les deux limitent à 70 caractères. OpenAI ajoute : « Use a real brand and seller name, not placeholders. » |
condition | condition | Passe | Mêmes trois valeurs : new, refurbished, used. |
product_type | product_category | Renommer | Le Home > Women > Dresses > Maxi Dresses de Google a exactement la forme voulue par OpenAI : « Your category path, from broad to specific, separated by >. » |
google_product_category | (aucun) | Supprimer ou replier | OpenAI n’a aucun champ pour l’identifiant de taxonomie Google. Gardez-le dans la projection Google seulement. |
shipping | shipping_price, shipping | Convertir | OpenAI : « Nonnegative amount; zero means no charge. Omitted or empty means unknown, not free shipping. » Un flux Google qui s’appuie sur les réglages de livraison du compte n’envoie rien ici. |
| (aucun) | seller_name | Ajouter | Exigé par OpenAI sur chaque ligne. Google identifie le vendeur par le compte Merchant Center, pas par le flux. |
| (aucun) | is_eligible_search | Ajouter ou omettre | « Omitted or empty: true. » Mettez false pour retirer un produit des résultats. |
| (aucun) | is_ads_eligible | Ajouter | « Set true for products Ads should process. Omitted or empty: disabled unless a feed-level Ads default applies. » |
| (aucun) | is_eligible_checkout | Ajouter, avec les URL de politiques | « Omitted, empty, or false: disabled. Search set to false overrides this flag. » Quand il vaut true, seller_privacy_policy et seller_tos deviennent obligatoires. |
| (aucun) | target_countries | Ajouter | Codes ISO 3166-1 alpha-2 en majuscules. « Omitted or empty does not mean worldwide. » |
| (aucun) | variant_dict | Ajouter pour les variantes | « Map option names to the selected values. » Google a des colonnes séparées color, size, material ; OpenAI les accepte aussi et ajoute le dictionnaire. |
Trois lignes de ce tableau méritent un examen plus attentif, parce que c’est là qu’un flux Google qui fonctionne se transforme en rejets silencieux.
L’orthographe de la disponibilité
La spécification OpenAI est explicite au sujet du format compatible Google : la disponibilité « must be in_stock, out_of_stock, preorder, or backorder. Use preorder, not the OpenAI spelling pre_order; unknown is not accepted. » Relisez-la deux fois. Dans le format natif OpenAI vous écrivez pre_order ; dans le format compatible Google vous écrivez preorder. Quel que soit le format enregistré, l’autre orthographe est une valeur invalide pour cette ligne. Et unknown, que le format natif autorise, n’est pas valide dans le format compatible Google.
Des booléens que Google n’a jamais eus
Un flux Google Shopping ne contient presque aucune colonne booléenne, donc les exportateurs qui le construisent n’ont aucune convention pour elles. OpenAI en a une : « For boolean fields, use JSON true or false, or the lowercase strings true and false in delimited files. » Une cellule CSV contenant TRUE, 1 ou yes est une valeur malformée, et la vue d’ensemble du dépôt de fichiers cite « Malformed field values » parmi les échecs d’ingestion courants.
Des valeurs par défaut qui vont dans le mauvais sens
Deux valeurs par défaut d’OpenAI sont l’inverse de ce qu’un marchand devinerait. Un shipping_price omis signifie inconnu, pas gratuit. Un target_countries omis ne signifie pas monde entier. Et un is_ads_eligible omis signifie que le produit n’est pas traité pour les publicités, sauf si une valeur par défaut existe au niveau du flux. Un flux Google ne transporte aucune de ces colonnes, donc un simple renvoi tel quel atterrit dans l’interprétation la moins favorable de chacune.
Le mode d’ingestion compatible Google d’OpenAI
La spécification documente un format qui conserve les noms de colonnes Google pour qu’un marchand puisse réutiliser un export existant. Ses colonnes obligatoires sont id, title, description, link, image_link, availability, price et brand. Les variantes utilisent item_group_id, décrit comme « Shared parent ID, different from each id. Enables grouping. » availability_date est « Required for preorder and backorder. Use YYYY-MM-DD or ISO 8601 timestamp. » sale_price_effective_date garde la forme de Google : « start/end with ISO 8601 dates or timestamps. »
Deux choses que ce mode ne supprime pas. D’abord, l’identité du vendeur et les réglages d’éligibilité doivent toujours exister quelque part ; le format n’a pas de colonne seller_name, donc ils vivent dans l’enregistrement du flux côté OpenAI plutôt que dans le fichier. Ensuite, la condition d’entrée : « Use this format only after OpenAI confirms it for your registered feed. » Un fichier au format Google déposé sur un point de livraison SFTP enregistré pour le format natif est un fichier rempli de noms de champs obsolètes, ce que la vue d’ensemble du dépôt de fichiers cite aussi parmi les échecs courants (« Outdated or non-spec field names »).
La conséquence pratique : le mode compatible Google est une décision d’enregistrement, pas une décision de fichier. Choisissez-le délibérément, ou convertissez vers le format natif.
Ce qui casse quand vous renvoyez simplement un flux Google
Supposons qu’un marchand exporte son CSV Google Shopping, ne renomme rien, et le pousse vers un point SFTP enregistré pour le format natif OpenAI. Voici ce que la spécification dit qu’il se passera, ligne par ligne.
| Symptôme dans l’export Google | Effet sous le format natif OpenAI |
|---|---|
Colonnes nommées id, link, image_link, item_group_id | id et item_group_id sont acceptés comme alias hérités. link et image_link ne sont pas listés comme alias, donc url et image_url manquent : deux champs obligatoires absents, ligne rejetée. |
Aucune colonne seller_name | Champ obligatoire manquant sur chaque ligne. C’est tout le fichier qui est rejeté, pas quelques lignes. |
availability = preorder | Pas l’une des cinq valeurs natives. Ligne rejetée. |
image_link pointant vers un fichier .webp | OpenAI veut un JPEG ou un PNG direct. Ligne rejetée. |
sale_price égal à price après une promotion terminée | Échoue la règle « strictly less than price ». Ligne rejetée. |
gtin avec un chiffre de contrôle erroné, toléré par Google | Échoue la règle du chiffre de contrôle. Ligne rejetée. |
Description avec des balises <br> et <strong> | Pas du texte brut. Ligne à risque. |
Aucune colonne is_ads_eligible | Les produits ne sont pas traités pour les publicités, sauf valeur par défaut au niveau du flux. Les lignes sont acceptées ; la campagne publicitaire n’a rien à afficher. |
Aucun target_countries | « Omitted or empty does not mean worldwide. » Lignes acceptées, visibilité sur vos marchés non garantie. |
shipping vide parce que la livraison vit dans les réglages Merchant Center | Interprété comme inconnu, pas comme gratuit. |
La partie inconfortable, c’est ce que vous voyez ensuite : rien. La vue d’ensemble du dépôt de fichiers décrit comment les instantanés sont traités et combien de temps un enregistrement persiste, mais la spécification ne documente aucun rapport d’erreur par ligne pour les lignes rejetées. Les produits absents d’un instantané sont conservés « for up to 14 days », puis disparaissent. Un marchand qui renvoie un flux Google a donc deux semaines de normalité apparente avant que des produits jamais acceptés cessent d’exister dans ChatGPT, sans aucun message entre-temps. L’article frère sur les produits absents des résultats shopping de ChatGPT détaille le chemin de diagnostic.
Comment garder un seul catalogue pour les deux canaux
Le schéma sûr n’est ni « renvoyer le flux Google » ni « maintenir deux flux à la main ». C’est un seul catalogue avec deux projections, chacune validée contre sa propre spécification.
La projection native OpenAI
Convrail synchronise votre catalogue Shopify ou WooCommerce par webhook, avec un délai de regroupement de 30 secondes pour qu’une modification en masse ne déclenche qu’une seule reconstruction. Chaque produit devient une ligne native OpenAI : le HTML est retiré des descriptions, le prix est formaté en amount CURRENCY dans la devise de la boutique, les variantes sont regroupées sous un group_id distinct de item_id, et seller_name, target_countries et les indicateurs d’éligibilité viennent des réglages de votre flux plutôt que d’une colonne à inventer. Un GTIN dont le chiffre de contrôle est faux est omis plutôt qu’envoyé, de sorte que la ligne reste valide au lieu d’être écartée pour une faute de frappe dans un code-barres.
Chaque ligne est ensuite validée : les neuf champs obligatoires, le format de chaque champ conditionnel présent, les valeurs de substitution telles que n/a ou unknown là où elles ne sont pas autorisées, sale_price par rapport à price, is_eligible_checkout par rapport à ses URL de politiques. Les lignes rejetées n’atteignent jamais le fichier. Elles sont écrites dans le journal d’exécution avec l’article, le champ et la règle, de sorte que le contrôle que la spécification ne vous donne pas se fait de votre côté, avant la livraison.
La projection compatible Google
Le même catalogue est aussi conservé sous forme de projection compatible Google : id, link, image_link, item_group_id, preorder au lieu de pre_order, aucune disponibilité unknown, product_type là où OpenAI a product_category. Rien n’est modifié deux fois. Un changement de prix dans votre boutique met à jour les deux projections à la reconstruction suivante.
Une livraison conforme à la vue d’ensemble
Le flux natif est exporté en parquet, jsonl.gz, csv.gz ou tsv.gz, découpé en fragments de 500 000 articles ou environ 450 Mo (sous les repères de la vue d’ensemble : « Up to 500k items per shard » et « under ~500MB »), avec des noms stables tels que feed-organic-000.jsonl.gz pour que chaque livraison SFTP quotidienne écrase l’instantané précédent comme la vue d’ensemble le demande : « Keep the same file name on every update and overwrite it with the latest snapshot instead of creating a new name each run. » Les livraisons en échec sont réessayées, puis ouvrent une alerte de santé. Si vous hésitez entre les formats d’export, la comparaison parquet, JSONL ou CSV pour le flux OpenAI détaille les compromis.
Erreurs fréquentes
Prendre l’acceptation par Google pour une preuve de validité. Google est plus permissif sur la longueur des GTIN, les formats d’image et les prix promotionnels. Une ligne que Google affiche depuis des mois peut enfreindre trois règles OpenAI à la fois.
Copier item_id dans group_id. OpenAI veut un « Stable parent-listing ID shared by all variants » qui diffère de chaque identifiant d’article. Les exportateurs qui remplissent la colonne de groupe avec l’identifiant du produit quand celui-ci n’a qu’une variante produisent des lignes où les deux sont égaux.
Écrire TRUE dans une colonne booléenne. Les tableurs mettent les booléens en majuscules à l’enregistrement. OpenAI veut la chaîne en minuscules. Vérifiez le fichier après le dernier outil qui l’a touché, pas avant.
Supposer qu’une colonne vide veut dire « la valeur raisonnable par défaut ». Pour shipping_price, target_countries et is_ads_eligible, la valeur par défaut d’OpenAI est la plus restrictive.
Ajouter utm_medium=feed au flux Google mais pas au flux OpenAI. La page de bonnes pratiques suggère des paramètres d’attribution de flux sur url « when you need feed-specific click tracking ». Si vous le faites, faites-le dans les deux projections, et lisez le guide de l’attribution pour comprendre comment ces clics sont ensuite rapprochés des commandes.
Commencer avec tout le catalogue. La vue d’ensemble recommande de « Start with a small sample (around 100 items). » Corrigez la correspondance sur 100 lignes, puis montez en volume.
Que faire ensuite
Connectez votre boutique au flux produit de Convrail et lisez le premier journal d’exécution : il liste chaque ligne issue de Google que la spécification OpenAI rejetterait, avec le champ et le correctif, avant toute livraison. L’article la spécification du flux produit OpenAI expliquée couvre chaque champ plus en profondeur.
Sources
Questions fréquentes
Puis-je envoyer mon flux Google Shopping tel quel à OpenAI ?
Uniquement en mode compatible Google, et seulement une fois qu'OpenAI a confirmé ce mode pour votre flux enregistré. La spécification y liste huit colonnes obligatoires (id, title, description, link, image_link, availability, price, brand) et exige toujours un nom de vendeur et des réglages d'éligibilité configurés côté OpenAI.
Faut-il écrire pre_order ou preorder pour la disponibilité ?
Cela dépend du format que vous avez enregistré. Le format natif OpenAI utilise pre_order ; le format compatible Google utilise preorder et n'accepte pas unknown. Les mélanger fait rejeter la ligne.
OpenAI a-t-il un équivalent de google_product_category ?
Pas de taxonomie obligatoire. OpenAI propose un champ optionnel product_category qui prend votre propre chemin, du général au particulier, séparé par un signe supérieur : il ressemble davantage au product_type de Google qu'à la taxonomie Google.
Faut-il deux catalogues pour servir Google Shopping et ChatGPT ?
Non. Un seul catalogue peut être projeté dans les deux formats. Convrail valide le flux OpenAI contre la spécification et conserve une projection compatible Google des mêmes lignes : vous ne maintenez qu'une seule source.
Comment savoir rapidement pourquoi OpenAI rejette une ligne issue de Google ?
La documentation OpenAI ne décrit aucun rapport d'erreur par ligne, donc le contrôle se fait de votre côté, avant la livraison. Le journal d'exécution de Convrail liste chaque article rejeté avec le champ concerné et la règle enfreinte.