← Blog

Why product feeds break, and how to stop patching them

April 19, 2026

Ten years of Shopify and Google Merchant pipelines taught me that the bugs are always in the same three places.

If you run an e-commerce store with any channel presence beyond your own website, you’re running a product feed, whether you know it or not. Every morning somewhere, a CSV or JSON file moves from a source (Shopify, Magento, a warehouse ERP) to a destination (Google Merchant Center, Meta Commerce Catalog, TikTok, a marketplace). And every morning, some percentage of the rows in that file fail silently.

I’ve spent most of a decade watching product feeds fail and then fixing them. Here’s what I wish someone had told me in year one: the bugs are always in the same three places.

1. The identifier problem

Google and Meta both require a unique identifier per product variant: GTIN or MPN or a manufacturer-assigned SKU. Shopify stores’ source of truth for this is either the barcode field (which store owners sometimes use for internal bin numbers) or nothing at all. When the feed transformation maps barcode to gtin and half your variants have an empty barcode field, you get the infamous identifier_exists disapproval. Google will reject the entire variant group.

The fix is to check whether the barcode value actually looks like a GTIN (length 12/13/14, numeric, valid checksum) before mapping it. If it doesn’t, set identifier_exists to noexplicitly. This one change has saved more disapproved-product dashboards than any other tweak I’ve shipped. Trying to manually scrub every merchant’s barcode field sounds satisfying and scales terribly.

2. The image quality problem

Every channel has its own opinion about image dimensions, backgrounds, and watermarks. Google likes 800×800 minimum, white background preferred, no promotional text. Meta wants 500×500 minimum, is more tolerant of lifestyle shots, but will flag any text overlay. TikTok wants portrait aspect ratios.

The workable approach is to have the merchant upload channel-ready images once, to a dedicated image CDN or metafield, and let the feed pick the right URL based on the target channel. Resizing at export time sounds appealing and scales linearly with product count, which breaks as soon as you pass 10,000 variants.

3. The inventory and availability problem

Inventory lives in more places than any other piece of product data. In Shopify alone, a single variant can have inventory across multiple locations, each with its own commitment tracking. The feed needs to decide: which location counts as “available”? Usually it’s the sum, minus committed, minus buffer. But Google also wants an availabilitystring (in stock / out of stock / preorder), and the policy for what counts as “in stock” differs per merchant.

The fix here is unglamorous. Pick one explicit policy per merchant, write it down in the feed config, and stop making that decision in code at runtime. When the policy is implicit, every engineer who touches the transformation thinks their interpretation is obviously right, and the transformation keeps drifting.

The meta-fix: row-level error tracking

All three of these problems have the same failure mode: they fail silently at row level. The feed pipeline succeeds (it wrote 50,000 rows!), but only 47,000 of those rows make it to the destination without disapproval. The pipeline logs “success.” Only someone going into Merchant Center and scrolling through rejected items notices the problem, days or weeks later.

The single most high-leverage change you can make to any feed system is row-level error tracking: every row that fails validation or destination-side rejection gets captured in a dead-letter queue with the specific error reason, linked back to the source record. Once you have that, the feed stops being a black box. You know exactly what fraction of your catalog is losing money every day and why.

The plug

SnowPipe is the tool I wish I’d had in year one. It does the three fixes above by default: identifier validation, image URL routing, explicit availability policy, and row-level error tracking with a dashboard. If you’re running a Shopify store pushing to Google Merchant, Meta, or both, it’s at pipe.snowforge.dev. Free tier exists. If you try it and it’s bad, email me and tell me why.