Channel comparison
Meta vs OpenAI: feed requirements compared
A Meta catalogue feed and an OpenAI product feed describe the same catalogue in incompatible shapes. Five core fields are renamed, price carries its currency inside the value, variants are rebuilt around group_id and variant_dict, and the file is pushed over SFTP instead of fetched.
Where the two specifications diverge
The 9 attributes one channel treats differently from the other. Everything else is identical and is listed further down.
| Attribute | Meta | OpenAI | What that means |
|---|---|---|---|
| brand | Recommended | Required | Stricter on OpenAI. |
| condition | Required | Optional | Stricter on Meta. |
| custom_label_0 | Optional custom_label_0 | Optional ads_metadata | The field is named differently on each channel. |
| google_product_category | Not supported | Optional | Only OpenAI accepts it. |
| gtin | Recommended | Optional | Stricter on Meta. |
| id | Required id | Required item_id | The field is named differently on each channel. |
| image_link | Required image_link | Required image_url | The field is named differently on each channel. |
| item_group_id | Required in some cases item_group_id | Optional group_id | Stricter on Meta. The field is named differently on each channel. |
| link | Required link | Required url | The field is named differently on each channel. |
Differences a table cannot show
Requirement levels are the easy part. These are the differences in values, structure and delivery that break a feed copied from one channel to the other.
Delivery is a push, not a fetch
Meta fetches a URL you host, as often as hourly, and can also take pushed updates through the Catalog Batch API. OpenAI issues an SFTP endpoint and expects full catalogue snapshots pushed to it at least daily. The difference is not cadence but direction, and it means adding a delivery step rather than changing a setting.
Five core fields change name
id becomes item_id, link becomes url, image_link becomes image_url, item_group_id becomes group_id and custom labels move into ads_metadata. Meta and OpenAI both accept a product category, but Meta ignores the Google taxonomy attribute while OpenAI takes product_category, so that field appears on one side only.
Price includes the currency
Meta accepts an amount with a separate currency, following the Google convention. OpenAI wants a decimal amount, a space and an uppercase ISO 4217 code in one string, so "79.99 USD". Shopify stores the two apart, which makes this a generation-time join rather than a mapping.
Variants are described rather than grouped
Meta groups variant rows with item_group_id and builds its picker from that alone. OpenAI wants group_id, a listing_has_variations flag and a variant_dict mapping option names to values, so the feed says what varies rather than only that something does. That is new structure, not a renamed column.
condition matters on Meta and barely registers on OpenAI
Meta requires condition on every item. OpenAI treats it as optional. Meanwhile OpenAI requires brand, which Meta only recommends, so the two channels are strict about entirely different things.
seller_name has no Shopify equivalent
OpenAI requires the selling merchant's name on every item. Nothing on a Shopify product carries it, and vendor is the wrong field because it describes the manufacturer. It has to be a static value set once for the store.
Reusing one feed for the other channel
What actually has to change, in the order it is worth doing.
-
Build the SFTP delivery before the mapping
Prove you can land a snapshot on the endpoint on a schedule. Everything else is familiar work; this is the part with no equivalent in a Meta setup.
-
Rename the five shared fields at publish time
Keep one internal representation of each value and render channel-specific names when the file is generated. Maintaining two parallel mappings is how the two feeds start disagreeing about the same product.
-
Join amount and currency into one price string
Format as decimal amount, space, uppercase ISO code, and apply the same rule to any sale price. Watch zero-decimal currencies and thousands separators, which are the two ways this quietly goes wrong.
-
Rebuild variants around group_id and variant_dict
Map group_id from the Shopify product id, set listing_has_variations where a product has more than one variant, and build variant_dict from the option names and values Shopify already stores. The Meta item_group_id mapping gives you the grouping but none of the description.
-
Add brand coverage and seller_name
Brand is only recommended on Meta, so a catalogue fed to Meta alone often has patchy brand data. OpenAI requires it. Audit coverage, then set seller_name as a static store-level value rather than deriving it from a product field.
Every attribute, side by side
All 16 attributes documented in this knowledge base, as Meta and OpenAI each treat them.
| Attribute | Meta | OpenAI |
|---|---|---|
| availability | Required availability | Required availability |
| brand | Recommended brand | Required brand |
| condition | Required condition | Optional condition |
| custom_label_0 | Optional custom_label_0 | Optional ads_metadata |
| description | Required description | Required description |
| google_product_category | Not supported — | Optional product_category |
| gtin | Recommended gtin | Optional gtin |
| id | Required id | Required item_id |
| identifier_exists | Not documented here — | Not supported — |
| image_link | Required image_link | Required image_url |
| item_group_id | Required in some cases item_group_id | Optional group_id |
| link | Required link | Required url |
| mpn | Optional mpn | Optional mpn |
| price | Required price | Required price |
| sale_price | Optional sale_price | Optional sale_price |
| title | Required title | Required title |
Frequently asked questions
Can I send my Meta catalogue feed to OpenAI?
No. Five core attributes are named differently, price has to carry its currency code inside the value, variants need group_id with listing_has_variations and variant_dict, seller_name is required, and the file is pushed over SFTP rather than fetched.
Does OpenAI require brand?
Yes, where Meta only recommends it. A catalogue that has only ever fed Meta often has incomplete brand data, so it is worth auditing coverage before building the feed rather than discovering it in the rejection report.
How are variants handled in an OpenAI product feed?
With group_id to tie the variants together, a listing_has_variations flag, and a variant_dict that maps each option name to its value. Meta's item_group_id provides the grouping but nothing that describes what actually varies.
How often should an OpenAI feed be pushed?
At least daily, on a predictable cadence. The most recently processed snapshot is retained for up to 14 days, so a pipeline that stops pushing ages out of the catalogue rather than simply going stale.
Both specifications in full
- Meta Meta's product catalogue is the data source behind Facebook and Instagram Shops, Advantage+ catalogue ads and dynamic retargeting, populated by a product feed uploaded to Commerce Manager. Its attribute names largely mirror Google's, but its accepted values and its handling of variants differ enough to break a feed copied straight across.
- OpenAI OpenAI ingests a merchant product feed so ChatGPT can surface products in shopping answers and complete purchases through Instant Checkout. It is the one major channel that does not fetch a feed URL you host: you push full catalogue snapshots to an OpenAI SFTP endpoint, and the most recently processed snapshot is retained for up to 14 days.
Errors on either channel
- Missing value: brand The "Missing value: brand" issue means a channel expects a brand name for a product and the feed did not supply one, or supplied a placeholder it treats as empty. On Shopify it usually means the vendor field is blank, or holds a supplier or internal category rather than the brand a shopper would recognise.
- Duplicate product id A duplicate id error means two or more rows in a feed claim the same identifier, so the channel cannot tell which one describes the item and keeps only the last it processed. On Shopify it usually means the feed was built per product rather than per variant, or that a SKU used as the id is blank or reused across variants.
Related concepts
- Variant-level feed A variant-level feed emits one row for each purchasable variant rather than one row per product, because sales channels treat every size, colour and material as a separately buyable item with its own price, stock and barcode. A Shopify product with four sizes in three colours is one product in the admin and twelve items to a channel.
- Feed scheduling Feed scheduling is the arrangement where a sales channel fetches a feed from a fixed URL on a repeating timetable instead of the merchant uploading a file. It matters because the interval between regenerations is the window in which a channel can be wrong about a price or a stock level, and most mismatch disapprovals are caused by that window being too wide rather than by a bad mapping.
- Product feed A product feed is a structured file listing every item a shop sells, with one row per purchasable item and one column per attribute the destination understands. Sales channels use it to build their own copy of a catalogue, which is why a feed is a translation of a shop's data into another system's schema rather than an export of it.
Primary sources
Channel specifications change. These are the official documents this page is based on.