Guide

How to Build and Validate a Shopify Product Feed for ChatGPT Ads

A product feed is the structured list of your catalog — titles, prices, availability, images, and identifiers — that OpenAI Ads product campaigns use to know what you sell and match it to relevant shopper queries. Shopify's product data model gives you most of the raw material for a feed, but it's rarely clean or complete out of the box, and product campaigns depend on that data being accurate: OpenAI Ads supports product feeds (see the product feeds section of the developer docs), and the exact field requirements should always be verified against that official spec before you build or submit one.

If your Shopify store is running (or planning to run) OpenAI Ads product campaigns, the feed is doing work your pixel and Conversions API setup can't do on its own. Event tracking tells OpenAI Ads what happened after someone clicked an ad. The feed tells it what you're selling in the first place — the product-level data that lets a campaign surface the right item for a relevant shopper query. Bad feed data doesn't cause an error message; it causes wasted impressions on stale prices, out-of-stock items, or listings too vague to match anything.

What Shopify already gives you, and what's usually missing or dirty

Shopify's admin already stores most of the fields a product feed needs: title, description, price, images, variants, and inventory status all exist natively on every product and variant. That's a real head start compared to building a feed from scratch. But "the data exists" and "the data is feed-ready" are different things, and the gap between them is where most feed problems come from.

Titles are usually written for browsing humans, not for matching against ad queries — short, brand-first, missing the attributes (size, color, material, model) that make a title specific enough to match a search intent. "Classic Tee" tells a shopper less than "Classic Tee — Men's, Navy, Cotton, Size M," and it tells an ad system even less.

Variants are where Shopify's data model and a feed's expectations diverge most. A single Shopify product can have a dozen variants (size and color combinations), but a feed generally needs each sellable variant represented with its own price, availability, and image — not one blended entry for the parent product. Skipping this collapses your whole size/color range into one feed entry that doesn't reflect what's actually purchasable.

Identifiers — the kind of unique, standardized product identifier a feed spec typically asks for — are inconsistently populated on most Shopify catalogs. Some products have a barcode field filled in accurately, some have it blank, some have it filled with an internal SKU that isn't actually a standardized identifier. Don't guess at what to put here: check the official product feed field requirements for what counts as a valid identifier before deciding how to populate it.

Category mapping is the last common gap. Shopify's own product organization (collections, product types, tags) doesn't automatically translate into whatever category taxonomy a feed spec expects. Left unmapped, products either get miscategorized or omitted from the categorization dimension of a campaign entirely.

Step-by-step: mapping Shopify product data to a feed

There's no single required tool here — what matters is that the output matches the current official field spec, not which method produced it. Three general approaches:

  1. Native export. Shopify's admin can export product data (typically as a CSV) covering the core fields — title, description, price, inventory, images, and variant details. This is a reasonable starting point for a small catalog, but it's a manual, one-time snapshot: you'll need to re-export and re-map every time products, prices, or stock levels change, and you'll still need to transform Shopify's native field names and structure into whatever the feed spec expects.
  2. A feed-building app. Several Shopify apps exist specifically to generate and maintain product feeds, handling the field mapping and keeping the output in sync with your live catalog automatically. This removes the manual re-export step and is usually the most sustainable option for catalogs with regular price or inventory changes.
  3. A custom export. For stores with non-standard data (a large variant matrix, a category structure that needs custom logic to map correctly, or a headless storefront where Shopify isn't the only source of product truth), a custom script pulling from Shopify's product data and writing out a feed in the required format gives the most control.

Whichever method you choose, the fields you're mapping toward — generically: title, description, price, currency, availability, image, a unique identifier, and category/type — should always be checked against the current official product feeds documentation before you finalize field names, exact formatting, or file structure. Feed specs change, and guessing at field names or formats you haven't verified is how a feed silently gets rejected or partially ignored.

Validation checklist

Before submitting or resubmitting a feed, work through this list. Most feed rejections and wasted spend trace back to one of these:

  • Required fields present on every row. A feed with a handful of products missing a required field (a blank price, a missing identifier) doesn't just skip those products cleanly — depending on how strict the ingestion is, a malformed row can cause more disruption than a missing one. Spot-check a sample of rows, not just the header.
  • Price and currency formatting is consistent — and matches how you report amounts elsewhere. This is worth being precise about: OpenAI Ads pixel and Conversions API events represent monetary amounts as integers in ISO 4217 minor units (12999 for $129.99 USD). Product feed price fields are a separate spec from event data and are typically represented as a currency-formatted value with an explicit currency code, not necessarily the same minor-unit integer format as events — check the current feed field spec for the exact expected format rather than assuming it mirrors event amount formatting. What should match across both is the currency code and the actual price — a feed showing $89.98 for a product that fires an order_created event at a different amount is a sign something in your pricing pipeline is out of sync.
  • Availability is accurate, not stale. A feed field showing "in stock" for a product that's actually sold out wastes ad spend driving clicks to something the shopper can't buy, and a feed showing "out of stock" for something available loses sales you're otherwise paying to generate.
  • Images are real product photos, not placeholders. A feed row pointing at a generic "coming soon" or placeholder image, or a broken image URL, undermines the listing even if every other field is correct.
  • No placeholder text left in title or description fields. "Lorem ipsum," "TODO," or draft copy that made it into a live feed is an easy, embarrassing miss that a final read-through catches.

Keeping the feed fresh

A feed is only as good as its last sync. Two things break silently if you're not watching them:

  • Inventory sync. If your feed doesn't reflect Shopify's live stock levels, you'll keep advertising products that sold out hours or days ago. This is one of the strongest arguments for an automated feed-sync method (app or scheduled export) over a manual one-time export for any catalog with meaningful sales velocity.
  • Price changes. A sale price, a permanent price change, or a currency adjustment that updates in Shopify but not in the feed creates a mismatch between what an ad shows and what a shopper actually sees at checkout — which is exactly the kind of discrepancy that damages trust and can trigger feed rejections.

Stale feeds don't fail loudly. They just quietly waste spend on inaccurate listings until someone notices the gap between what's advertised and what's true. Whatever cadence you choose — real-time sync via an app, a daily scheduled export, or a manual weekly refresh for a small, slow-moving catalog — pick one you'll actually maintain, and revisit it whenever your catalog size or update frequency changes materially.

Connecting feed clicks to purchase events

A feed gets someone to click. What happens after that click is a tracking problem, not a feed problem — and it's the other half of making product campaigns measurable. Once a shopper clicks through from a feed-driven ad, the events that matter are the same standard ones covered elsewhere: contents_viewed on the product page, items_added at cart, checkout_started, and order_created on purchase, fired via the pixel and backed by server-side Conversions API events for reliability on Shopify's restricted checkout.

If you haven't set that up yet, OpenAI Ads pixel and CAPI setup for Shopify covers the manual build and the free-app shortcut for getting those events firing correctly. A clean feed without reliable event tracking tells you what you're advertising but not whether it's converting; reliable events without a clean feed give you accurate purchase data on top of a shaky, error-prone campaign. Both need to be right for the full picture — feed data attracting the right shopper, event data confirming what they did next — to add up to something you can actually optimize against.

When to exclude products from feed campaigns

Not every product belongs in a feed-driven campaign. Consider excluding:

  • Out-of-stock or discontinued items that haven't been fully removed from Shopify yet — better to exclude proactively than rely on inventory sync catching it after spend has already gone out.
  • Low-margin or clearance items where the cost of a click doesn't make sense against the product's price or margin.
  • Products with incomplete or unreliable data — missing images, no identifier, a vague or auto-generated title — until that data is fixed. Advertising a product with bad feed data doesn't just underperform; it can drag down how the campaign values similar-quality entries.
  • Items under a minimum price threshold where ad spend per click could exceed what's economically sensible for that specific product.
  • Test, sample, or internal-use products that exist in your Shopify catalog for operational reasons but were never meant to be customer-facing.

Excluding a product from a feed campaign isn't a permanent decision — it's a way to keep campaign data clean while a product's listing, pricing, or availability catches up to a state worth advertising.

Want this done for you?

Fixed-scope setup, tested end-to-end and documented.

Explore the serviceTake the free audit