Skip to content
feedlab Request early access

Channel comparison

Google Shopping vs OpenAI: feed requirements compared

OpenAI is the least Google-like channel documented here. Half the core attributes carry a different name, price is one string with the currency inside it, variants use a different grouping shape, and the feed is pushed over SFTP rather than fetched from a URL you host.

Where the two specifications diverge

The 11 attributes one channel treats differently from the other. Everything else is identical and is listed further down.

Attributes treated differently by Google Shopping and OpenAI
Attribute Google Shopping OpenAI What that means
brand Required in some cases Required Stricter on OpenAI.
condition Required in some cases Optional Stricter on Google Shopping.
custom_label_0 Optional custom_label_0 Optional ads_metadata The field is named differently on each channel.
google_product_category Recommended google_product_category Optional product_category Stricter on Google Shopping. The field is named differently on each channel.
gtin Required in some cases Optional Stricter on Google Shopping.
id Required id Required item_id The field is named differently on each channel.
identifier_exists Optional Not supported Only Google Shopping accepts it.
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 Google Shopping. The field is named differently on each channel.
link Required link Required url The field is named differently on each channel.
mpn Required in some cases Optional Stricter on Google Shopping.

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.

You push the feed, OpenAI does not fetch it

Google takes a feed URL and re-fetches it on a schedule you choose. OpenAI issues an SFTP endpoint and expects full catalogue snapshots pushed to it on a predictable cadence of at least daily. Every other channel here needs a URL; this one needs a delivery step, which is the single biggest difference between the two.

Six of the core fields are named differently

id becomes item_id, link becomes url, image_link becomes image_url, item_group_id becomes group_id, google_product_category becomes product_category and custom labels move into ads_metadata. None of this changes what you send, but all of it changes the file, and a Google feed pointed at OpenAI unchanged carries almost no recognisable columns.

Price is a single string with the currency in it

The price attribute is a decimal amount, a space, then an uppercase ISO 4217 code, so "79.99 USD" rather than an amount in one column and a currency somewhere else. Shopify holds the amount and the currency apart, so this is a formatting rule rather than a field you can map straight across, and it applies to sale prices too.

Variants use a different shape entirely

Google groups variants with item_group_id and leaves it there. OpenAI groups them with group_id, flags the parent relationship with listing_has_variations, and describes the variation with a variant_dict mapping option names to values. A feed already mapped for Google needs this rebuilt rather than renamed.

seller_name is required and no Shopify field holds it

Alongside the expected identity, price and availability fields, the specification requires seller_name. Nothing on a Shopify product carries it, so it has to come from a static value set once for the store. It is the clearest example of a required attribute that is a property of the merchant rather than the product.

Snapshots age out rather than going stale

Google expires product data after 30 days. OpenAI retains its most recently processed record for up to 14 days, so a catalogue that stops being pushed disappears sooner. Because the cadence is push rather than pull, a failed job is also silent unless you monitor it yourself.

Reusing one feed for the other channel

What actually has to change, in the order it is worth doing.

  1. Build the delivery step first

    Get a snapshot landing on the SFTP endpoint on a schedule before worrying about field-level polish. Delivery is the part with no analogue in your existing setup, so it is the part most likely to hold the launch up.

  2. Rename the six fields as a mapping, not a find and replace

    item_id, url, image_url, group_id, product_category and ads_metadata all carry values you already produce. Keep one internal mapping and render the channel names at publish time, so the Google feed does not drift away from the OpenAI one as either specification changes.

  3. Reformat every price into amount plus currency code

    Concatenate the decimal amount, a space and the uppercase ISO code, and apply the same rule to sale prices. Check what happens to a zero-decimal currency and to a price with a thousands separator, because both are easy to get wrong once and never notice.

  4. Rebuild the variant relationship

    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. This is real work rather than renaming, and it is what makes variants usable in a shopping answer.

  5. Set seller_name once, at the store level

    It is a static value for the whole catalogue. Set it deliberately rather than deriving it from vendor, which is a product field and will be wrong the moment you stock someone else's brand.

  6. Monitor the push, because nothing else will

    A fetched feed fails visibly: the channel tells you it could not read your URL. A pushed snapshot that never leaves your side fails silently until the 14-day retention runs out. Alert on the job, not on the channel.

Every attribute, side by side

All 16 attributes documented in this knowledge base, as Google Shopping and OpenAI each treat them.

Full attribute comparison between Google Shopping and OpenAI
Attribute Google Shopping OpenAI
availability Required availability Required availability
brand Required in some cases brand Required brand
condition Required in some cases condition Optional condition
custom_label_0 Optional custom_label_0 Optional ads_metadata
description Required description Required description
google_product_category Recommended google_product_category Optional product_category
gtin Required in some cases gtin Optional gtin
id Required id Required item_id
identifier_exists Optional identifier_exists 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 Required in some cases 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 Google Shopping feed to OpenAI?

Not as it stands. Six of the core attributes are named differently, price has to be a single string with the currency code inside it, variants use group_id with listing_has_variations and variant_dict, and the file is pushed over SFTP rather than fetched from a URL.

How does the OpenAI product feed get delivered?

You push full catalogue snapshots to an SFTP endpoint OpenAI issues you, on a predictable cadence of at least daily. It is the only channel documented here that does not fetch a feed URL you host.

What price format does the OpenAI feed use?

A decimal amount, a space, then an uppercase ISO 4217 currency code, for example "79.99 USD". Shopify stores the amount and the currency separately, so the two have to be joined at generation time.

Why does the OpenAI feed need seller_name?

Because a shopping answer needs to say who is selling the item, and that is a property of your store rather than of the product. No Shopify product field holds it, so set it as a static value for the whole catalogue.

Both specifications in full

Errors on either channel

Related concepts

Primary sources

Channel specifications change. These are the official documents this page is based on.

Last reviewed View as markdown