No product dropped in silence
A title in capital letters, HTML in a description or a price written “25,99” is caught before OpenAI sees it, with the correction to make.
Product feed
OpenAI drops a malformed product without telling you, and the product never shows up. Convrail keeps your catalog in sync, checks every row of your product feed against the official specification before delivery, sends the accepted rows in the format OpenAI expects, and lists each rejection with its fix.
Today’s feed, 9,987 products
✓ 9,974 ready for ChatGPT 13 to fix before delivery
Delivered to OpenAI at 04:00, full run log available
A title in capital letters, HTML in a description or a price written “25,99” is caught before OpenAI sees it, with the correction to make.
Product changes in your store reach OpenAI within the hour, and your full catalog is sent again once a day.
Each delivery is logged: products read, accepted and rejected, what changed since the last one, and whether the file arrived.
Product webhooks on Shopify and batched sync on WooCommerce keep the feed current, with a full resync on demand.
The 9 required fields and their exact limits, price format, image files, identifiers and placeholder values, checked on every row.
Each rejected product is listed with the field, the rule it broke and the correction to make.
HTML is stripped from descriptions, prices use your store currency and variants are grouped under one product.
Store name, target countries and eligibility for ChatGPT search and ads, set once and applied to every product.
A GTIN with a wrong check digit is left out rather than sent, so the product stays in the feed.
Compressed JSON Lines by default, or Parquet, CSV or TSV, with files split under the size limits of the specification.
Once your ChatGPT Ads account is linked, Convrail creates your feed at OpenAI and uploads every delivery, with retries and an alert if it keeps failing.
Accepted and rejected counts, what was added, removed or changed since the previous run, and the delivery status.
On Shopify or WooCommerce. Your catalog syncs on its own.
Store name and target countries. Link your ChatGPT Ads account and your feed is created at OpenAI, with nothing else to enter.
Accepted products are delivered within the hour; rejected ones wait for the fix shown in the app.
For technical teams and agencies: the required fields and their limits, how a catalog becomes a delivered file, and what each run records.
The OpenAI feed ingestion does not return an error report per row. A title in capital letters, HTML left in a description or a price written as "25,99" means the product is skipped, and nothing tells you. Merchants discover it weeks later when a product they sell every day never appears in ChatGPT. Convrail moves that check to your side of the fence: every row is validated before delivery, and every rejection is written to the run journal with the field, the rule and the correction.
✗ "25,99" as a price: the row is gone and so is the product
✓ caught before delivery: price must be "25.99 EUR"
These are the rules Convrail enforces, taken from the OpenAI product feed specification. Each one is covered by an automated test.
| Field | Rule | Typical rejection |
|---|---|---|
| item_id | Required, stable, 100 characters max | Variant ID that changes on re-import |
| title | Required, 150 characters max, not all capital letters | "WIRELESS HEADPHONES XL" |
| description | Required, 5,000 characters max, plain text | HTML tags left from the store editor |
| url | Required, valid http(s) URL | Relative path |
| brand | Required, 70 characters max | Empty vendor field |
| image_url | Required, direct HTTP(S) link to a JPEG or PNG, HTTPS recommended | .webp file, URL with credentials |
| price | "<amount> <ISO-4217>", greater than 0 | "25,99", "25.99", "€25.99" |
| availability | in_stock, out_of_stock, pre_order, backorder or unknown | "available" |
| seller_name | Required, real seller name, 70 characters max | Missing, "unknown" |
Conditional and recommended fields are checked the same way when they are present, because a malformed optional field also drops the row.
| Field | Rule | Typical rejection |
|---|---|---|
| is_eligible_search | Lowercase "true" or "false"; omitted means true | Boolean, "TRUE", "yes" |
| is_ads_eligible | Lowercase "true" or "false"; required for ads processing | "1", "yes" |
| target_countries | Uppercase ISO 3166-1 alpha-2 codes, configured with your OpenAI setup | "France", "USA" |
| gtin | 8, 12, 13 or 14 digits with a valid check digit | Typo in the barcode, dashes |
| sale_price | Same currency, strictly less than price | Sale price equal to price |
| group_id | Stable and different from item_id | group_id copied from item_id |
| brand, seller_name | Real values, never placeholders | "n/a", "null", "unknown" |
Also checked when present: mpn (70 characters max), availability_date (ISO 8601), star_rating and popularity_score (0 to 5), review_count and return_deadline_in_days (positive integers). When neither GTIN nor MPN exists, identifier_exists is set to "no". A GTIN with a wrong check digit is omitted rather than sent, so the row stays valid.
Product webhooks keep Convrail’s copy of your catalog current. Changes are debounced for 30 seconds so a bulk edit triggers one rebuild, not a hundred. A full sync is available on demand.
HTML is stripped from descriptions, prices are formatted with the store currency, variants are grouped under group_id, and your seller name, target countries and eligibility flags are applied from the feed settings.
Accepted rows go into the file. Rejected rows are journaled with the field and the rule they broke. The count of rejections is visible in the app before the file leaves.
Formats: jsonl.gz by default, or parquet, csv.gz or tsv.gz. Files are split at 500,000 items or roughly 450 MB, under the limits of the specification, with stable names (feed-organic-000.jsonl.gz) so each delivery overwrites the previous snapshot.
Convrail creates your feed at OpenAI, with its own upload access, and delivers the files there: product changes within the hour, at most one delivery per hour so OpenAI can finish processing the previous one, and the full catalog once a day. Failed deliveries retry, then open a health alert.
Each run records the number of items read, accepted and rejected, the diff against the previous run (added, removed, changed) and the delivery status. The per-row errors are kept with the run, so you can trace when a product disappeared from the feed and why.
| Run field | Meaning |
|---|---|
| itemsTotal, itemsValid, itemsRejected | How many rows were built, kept and dropped |
| added, removed, changed | Diff against the previous run, computed from a hash of each row |
| errors | One entry per rejected item: item_id, field, message |
| deliveryStatus | pending, delivered or failed, with the attempt count |
Most fields transfer, some do not. OpenAI expects is_eligible_search, is_ads_eligible and target_countries that Google never asked for, uses seller_name instead of a merchant account, and formats booleans as lowercase strings. Convrail keeps a Google-compatible projection of your feed as well, so the same catalog serves both channels without maintaining two exports.
Parquet (recommended for large catalogs), gzipped JSON Lines, CSV and TSV. Convrail exports all four: gzipped JSON Lines (jsonl.gz) is the default, and another format can be chosen in the advanced feed settings.
Changes to your products go out within the hour, with at most one delivery per hour so OpenAI can finish processing the previous one, and your full catalog is sent again once a day. Filenames stay stable, so each delivery replaces the previous one.
It is excluded from that delivery and listed in the run journal with the field and the rule it broke. Fix the product in your store and the next run picks it up.
No. OpenAI uses one product feed for organic results and ads: each row says whether it can be used in ads with the is_ads_eligible flag. Convrail sets it from your feed settings.
Files are sharded at 500,000 items or about 450 MB each, within the limits of the specification. In our automated test, a 10,000-product catalog is validated, exported and delivered to SFTP in under a minute.
The upload access created at OpenAI for your feed is encrypted at rest with AES-256-GCM, like every secret Convrail stores, and decrypted only at delivery time.
Convrail starts with a Free plan, and paid plans begin with a free trial. Leave your email and we send the install link when your spot opens.