If you've ever exported a product feed, uploaded it to Google Merchant Center, and gotten back a pile of "Disapproved" or "Limited performance" items, you know the feedback loop is slow. Processing can take hours, and the error messages don't always point at the exact row.

Most disapprovals I've seen come from a small set of data problems you can catch locally before uploading. Here's a checklist and a quick way to check each one.

1. Missing required attributes

For most products, Google requires id, title, description, link, image_link, availability, and price. Depending on the product and country you may also need brand, gtin/mpn, condition, and google_product_category.

Quick check in Python:

import csv REQUIRED = ["id","title","description","link","image_link","availability","price"] with open("feed.tsv", newline="", encoding="utf-8") as f: for i, row in enumerate(csv.DictReader(f, delimiter="\t"), start=2): missing = [k for k in REQUIRED if not (row.get(k) or "").strip()] if missing: print(f"row {i}: missing {missing}") 

Also check the header row itself. A typo like image link instead of image_link makes the column invisible to Google.

2. Price format

Google expects a number plus an ISO 4217 currency code, e.g. 12.99 USD. Common breakages: currency symbols ($12.99), comma decimals from European locale exports (12,99), or an empty currency.

import re PRICE = re.compile(r"^\d+(\.\d{1,2})? [A-Z]{3}$") 

3. Availability values

Use only the allowed values: in_stock, out_of_stock, preorder, backorder. In Stock, instock, or available from a CMS export will be rejected.

4. Title length

Titles max out at 150 characters. Long titles get truncated, and keyword-stuffed ones can get flagged. Front-load the important part (brand + product type + key attribute).

5. GTIN check digits

GTINs (UPC/EAN/ISBN) have a mod-10 check digit, so a typo is detectable:

def valid_gtin(g): g = g.strip() if not g.isdigit() or len(g) not in (8, 12, 13, 14): return False digits = [int(c) for c in g] check = digits.pop() total = sum(d * (3 if i % 2 == 0 else 1) for i, d in enumerate(reversed(digits))) return (10 - total % 10) % 10 == check 

Don't invent GTINs to fill the column. If a product really has none (custom or handmade items), set identifier_exists to no instead.

6. Excel mangling your IDs and GTINs

This one causes a lot of trouble. Open a CSV in Excel, save it, and 0012345678905 becomes 12345678905, or a long ID becomes 1.23457E+12. The leading zeros are gone and the GTIN no longer validates. Look for scientific notation and GTINs that are suddenly 11 digits long. Import the columns as Text, or edit in a plain-text-safe tool.

7. Broken links and image URLs

link and image_link need to be absolute https:// URLs that resolve. Relative paths (/products/foo) and placeholder images are common failure points. A quick HEAD request per URL catches dead ones.

Putting it together

You can wire the snippets above into a small pre-upload script and run it in CI or before every manual upload. That shortens the feedback loop from hours to seconds.

If you'd rather not write it yourself, I packaged these checks into a free browser tool: Merchant Center Feed Checker. You don't need an account.

Disclosure: I built this tool. There's also an optional US$19 fix-template kit here if you want it. The checks in this post work fine without either.

What feed errors have bitten you? Let me know in the comments and I'll add them to the list.