chatgpt.com/merchants, and after approval OpenAI assigns you a private delivery channel (SFTP or API) where you upload the file. There is no URL to submit, no crawler to wait for. The two fields that decide what ships are brand and the primary image. We built the generation-and-validation half as an open-source plugin and ran it on real catalogs — numbers below.1. The model: push, not pull
The single most common misconception: that OpenAI will crawl a feed URL on your site. It won't. The pipeline is:
- Generate a complete snapshot of your catalog in the OpenAI Product Feed format — one JSONL row per product or variant, validated field by field.
- Apply at
chatgpt.com/merchants— store URL, business contact, product categories, order volume. This is a per-merchant application: approval attaches to the store, not to whatever software generated the file. - After approval, OpenAI assigns your delivery channel — typically SFTP credentials to their endpoint (an API path also exists). You push the file there. During onboarding they validate a sample (~100 products) before the full catalog goes live.
- Refresh: a full snapshot at least daily, same filename every time; the system accepts uploads as frequent as every 15 minutes for fast-moving inventory. Because every upload is a complete snapshot, products removed from your catalog disappear from discovery automatically.
Your feed URL — if your tooling exposes one — is a convenience for you to download and inspect the file. It is not the delivery channel.
2. What the spec actually requires
The format is JSONL (one JSON object per line), UTF-8, gzip-compressed for delivery. The fields that trip people up in practice:
| Field | Rule | Real-world gotcha |
|---|---|---|
item_id | Required, ≤100 chars, stable and unique | Derive it from the product ID (wc-123), never from mutable data like SKUs that get edited |
brand | Required by the spec, ≤70 chars | The #1 blocker on real stores — see section 3 |
image_url | Required, HTTPS | Products without a featured image cannot ship a usable row; visual shopping needs the picture |
additional_image_urls | Comma-separated string | A string, not a JSON array — an easy validator failure |
gtin | 8–14 digits when present | Malformed barcodes are better omitted than shipped |
price, availability | Required | Sale prices are separate fields; availability is an enum, not free text |
seller_name, seller_url, return_policy, store_country, target_countries | Required merchant-level context | seller_name ≤70 chars; target countries should mirror where you actually sell |
| Variants | One row per purchasable variant | A 300-product fashion catalog is often a 1,000+ row feed once sizes and colors expand |
3. Brand: the field that decides your feed size
On paper, brand is just another required field. On real WooCommerce stores it is the gatekeeper, because most Woo stores have never filled a brand taxonomy — the data lives in product titles ("Wolford Velvet 66…") and in category names, not in a machine-readable field. Shopify sidesteps this structurally: its product model has a vendor field that defaults to the store name, so every Shopify product has something in that slot by construction.
What we learned running this on a real multi-brand catalog (~1,100 SKUs, luxury lingerie and beachwear):
- The Woo core
product_brandtaxonomy existed but was empty — while 20+ real brands lived as top-level product categories. - The honest fix is on the data side, under the merchant's authority: assign the real brands (the merchant did — 22 brands, 1,129 product assignments, sourced from their own category names). No inference, no guessing by the tooling.
- For genuinely own-label or unbranded stores, "seller as brand" is legitimate — it is literally how Shopify's vendor default and most Etsy listings work. For a multi-brand retailer it would be false data on the exact field shoppers search by. Tooling should offer it only as an explicit, merchant-declared opt-in.
- For the remainder with no brand data at all, there is a defensible middle path: ship the row without the brand field — absent, never an empty string, never fabricated — and let OpenAI's ingestion enforce its own requirement. The merchant sees a count and a warning and knowingly assumes that risk. Omission is honest; fabrication is not.
4. Numbers from real generations
What the validator reports on actual catalogs (our plugin validates every row against the spec before it enters the file, and regenerates atomically — the previous good snapshot is never destroyed by a failed run):
- A small mixed catalog (~110 products, food and apparel): 86 conformant rows, 28 rows excluded for missing primary image, 0 schema errors.
- The ~1,100-SKU multi-brand catalog above, after the merchant assigned real brands: full-catalog feed with real brand values, 39 rows excluded for missing images, 0 schema errors — first pass.
- Generation cost matters at scale: a naive per-product implementation took ~20 seconds on 1,100 SKUs (thousands of N+1 queries) and would hit PHP execution limits near 5,000 SKUs; batch-priming product, meta and term caches collapsed it to a few seconds. If you build your own generator, budget for this.
5. Discovery-first: the checkout stays yours
OpenAI's commerce strategy has shifted away from in-chat instant checkout toward discovery-first: your products appear in ChatGPT's shopping answers, and the buyer clicks through to your product page and buys on your store. You remain the merchant of record; there is no transaction fee to OpenAI for this tier. Ranking is stated to be by relevance — data quality, not ad spend. (It also means the quality of your titles, descriptions and structured fields is your ranking lever.)
6. The honest disclaimers nobody writes
- Approval is entirely OpenAI's decision, per merchant, with no published timeline. Being on the waitlist costs nothing; nobody can promise you acceptance.
- Shopping-surface availability varies by market. The feed format is region-neutral; where results actually show is OpenAI's call.
- A conformant feed is necessary, not sufficient. It gets you to the door with clean data; relevance does the rest.
- Products excluded from the feed (missing image, for instance) are not invisible to AI in general — agents that read your site directly, or structured catalog APIs, still see them. The feed is one channel among several.
7. What you can do today
WooCommerce has announced native ACP/UCP/MCP integrations are being built, with no ship date yet. Until then, the pipeline above is available now: KaliCart Bridge (open source, on WordPress.org) generates and validates the feed, shows you exactly which products are excluded and why — with one-click access to a pre-filtered product list and a CSV export for bulk fixing — and prepares the file you will deliver once your application is approved. The application itself, and the decision, remain between you and OpenAI, as they should.
The one-line takeaway: getting into ChatGPT is not a growth hack — it is a data-quality exercise with a well-defined spec. Read the spec, fix brand and images, generate, apply, and keep the snapshot fresh.