← Merchant Feed Check

Merchant Feed Check vs. eyeballing the feed in a spreadsheet

Opening the feed in a spreadsheet and scanning it row by row is the normal first check before a sync, and it works well for the obvious case — a screaming promotional title, a repeated SKU. Two of the most common documented disapproval reasons are specifically the kind that look like ordinary data on a visual scan, because the value that fails is the same length and shape as every valid value around it.

A four-row feed, checked both ways

Take a feed with one clean row and three rows each carrying a different problem. This is the exact feed this page's own test runs through checkFeed() — nothing below is invented.

RowWhat a spreadsheet scan seesWhat checkFeed() reports
sku-1A normal-looking row: real title, real description, a 13-digit GTIN, a priced-and-in-stock item.0 errors, 0 warnings — correctly passes.
sku-2Looks wrong immediately: GREAT DEAL Red Hoodie 50% off Free Shipping, a 5-character description, not-a-url for the link, maybe for availability, cheap for a price.5 errors, 4 warnings — the checker catches the same row a careful reviewer already flags on sight.
sku-3Looks identical to sku-1. Same title shape, same description length, a 13-digit all-numeric GTIN sitting in the same column as every other valid one.Exactly 1 error: invalid-gtin-checksum. The GTIN is 4006381339931 against sku-1's 4006381333931 — two digits transposed, same length, same shape, fails the GS1 check-digit calculation.
sku-4Looks identical to sku-1. Price column reads 19.99, which is what every price in the sheet looks like once the spreadsheet software applies its own currency formatting.Exactly 1 error: invalid-price-format. The underlying value is 19.99 with no currency code, and the required shape is NUMBER CURRENCY, e.g. 19.99 USD.

Feed-level total, from the same test: 4 items, 3 with at least one error, 7 errors and 4 warnings overall. Two of those three flagged rows (sku-3 and sku-4) would not draw a second look in a spreadsheet — nothing about them differs visually from the row directly above.

Why the checksum and the format rule are the quiet ones

A GTIN is 8, 12, 13, or 14 digits. A single mistyped or transposed digit produces another number of the exact same length, made entirely of digits — it does not look different from a valid one in the next cell. Telling them apart means running the GS1 check-digit calculation on every row: weight each digit of the payload 3 and 1 alternating from the digit immediately left of the check digit, sum the weighted digits, and the check digit must equal (10 - sum mod 10) mod 10. That is not a check anyone runs by hand across a feed of any real size.

The price format rule is quieter still, because the failure is an absence rather than a wrong value. Google's and Meta's shared spec requires NUMBER CURRENCY — 19.99 USD, not 19.99 or $19.99. A spreadsheet applying its own currency number format renders 19.99, $19.99, and 19.99 USD as visually similar cells; nothing on screen signals that the underlying string never carried the required three-letter code.

Common questions

Why doesn't scanning the feed by eye catch a bad GTIN?

A GTIN is a 13-digit (or 8/12/14-digit) number, and a transposed or mistyped digit produces another number of the exact same length made entirely of digits -- it looks identical to a valid one sitting in the next cell. Telling the two apart means running the GS1 check-digit calculation (weight each digit 3/1 alternating from the right, sum, and the check digit must equal (10 - sum mod 10) mod 10), which nobody does by eye on a 2,000-row feed. Google and Meta both run this calculation and reject the mismatch as a bad or missing product identifier.

Why doesn't scanning the feed by eye catch a missing currency code?

The published price format is "NUMBER CURRENCY", e.g. "19.99 USD" -- but a bare "19.99" reads as a completely ordinary price to anyone scanning the column, especially in a spreadsheet where every other price cell is formatted as currency by the spreadsheet software itself, hiding that the underlying feed value never carries the required currency code. The rejection only shows up once the feed is parsed against the spec's exact regular-expression shape, not from looking at the rendered column.

What does a spreadsheet scan catch that this checker doesn't add much to?

A title in all caps with "50% OFF" and "FREE SHIPPING" in it, or the same SKU appearing on two rows, both look wrong on sight -- this checker flags the same two rows for the same reasons, so a careful reviewer scanning for those specific shapes was already going to catch them. The value here is narrow: two specific, well-documented rejection reasons that are constructed to look like ordinary data on a visual scan, checked mechanically on every row instead of on however many rows get a close look.

Does this replace reviewing the feed before it syncs?

No. It is a deterministic, row-by-row check against Google's and Meta's own published product-data specification, not a review of whether the products, pricing, or category placement make business sense. A reviewer scanning the feed still catches the obviously wrong-looking rows and anything domain-specific this tool has no rule for; this checker adds the two specific, quiet failure modes a visual scan is structurally unlikely to catch.

Nothing here says a spreadsheet review is a bad first check — it is exactly right for the case it is good at. This page describes two specific, narrow failure modes that are constructed to look like ordinary data, not a fault in reviewers.

Check your own feed

Paste or load your feed — CSV, TSV, or JSON — and get the same per-row report, including the GTIN checksum and price-format checks a visual scan cannot run.

Open Merchant Feed Check

Also worth a pass if you route the same feed to many channels: this checker vs. DataFeedWatch.