# Product Feed Auditor

> Audit a Google Merchant Center or Shopping product feed export offline for attribute coverage, title and description policy violations, malformed image and landing-page URLs, price and sale-price coherence, and duplicate ids, returning…

Product Feed Auditor is an AI skill that you can use in Claude Code, Codex, or type.com.

- Skill page: https://typestaging.com/library/skills/product-feed-auditor
- Raw SKILL.md: https://typestaging.com/library/skills/product-feed-auditor/SKILL.md
- Created by the type.com team
- Updated: September 24, 2026
- Package: 6 files

## How to use Product Feed Auditor

1. **type.com:** Choose Use Skill to add Product Feed Auditor to your type.com workspace.
2. **Claude Code:** Download the skill and extract it into ~/.claude/skills/product-feed-auditor/ (or .claude/skills/product-feed-auditor/ in a project). Then ask Claude to use Product Feed Auditor.
3. **Codex:** Download the skill and extract it into ~/.agents/skills/product-feed-auditor/ (or .agents/skills/product-feed-auditor/ in a repository). Then ask Codex to use Product Feed Auditor.

## Frequently asked questions

### What is Product Feed Auditor?

Product Feed Auditor is an AI skill that you can use in Claude Code, Codex, or type.com.

### What does Product Feed Auditor do?

Audit a Google Merchant Center or Shopping product feed export offline for attribute coverage, title and description policy violations, malformed image and landing-page URLs, price and sale-price coherence, and duplicate ids, returning…

### Can I use Product Feed Auditor in Claude Code or Codex?

Yes. Product Feed Auditor is a standard Agent Skills folder with a SKILL.md file. Download it and extract it into ~/.claude/skills/ for Claude Code or ~/.agents/skills/ for Codex.

### Who created Product Feed Auditor?

The type.com team created Product Feed Auditor. The type.com team reviews every skill before it is published in the Skills Library.

## Example output

Example output from a sample run. Company names and figures are sample data.

```markdown
## Product feed audit: Harbor Loom (shop.harborloom.com), as of 2026-09-15 (USD)

**13 of 21 items (61.9%) are at disapproval risk.** The feed carries 17 critical findings, 13 warnings and 1 info; the other 8 items have warnings only, and none are clean.

| Check | Items | What the audit found | Risk |
| --- | --- | --- | --- |
| ATTR-MISSING | HL-1005, HL-1019 | brand; description empty | Disapproved on upload, never serve |
| ID-DUPLICATE | HL-1010 | 2 rows | Earlier variants silently disappear from Shopping |
| ATTR-AVAILABILITY-INVALID | HL-1010 | availability=instock | Rejected at upload |
| PRICE-NON-POSITIVE | HL-1014 | price=0.00 USD | Disapproved, and a revenue leak if served |
| SALE-NOT-LOWER | HL-1008 | 36.00 USD >= 32.00 USD | 'Invalid sale price' |
| ID-GTIN-INVALID | HL-1009 | gtin=8400123000100 | 'Incorrect identifier' |
| TITLE-PROMOTIONAL-TEXT | HL-1004 | 'FREE SHIPPING' | Editorial policy violation |
| LINK-DOMAIN-MISMATCH | HL-1015 | host harborloom-wholesale.example.net | Outside the verified domain |

…plus 8 more critical checks in the full report, covering image URLs, title length and caps, HTML in descriptions, and missing identifiers.

| Warning | Items | Detail |
| --- | --- | --- |
| ID-GTIN-REUSED | HL-1001, HL-1022, HL-1008, HL-1021 | gtin 8400123000109 and 8400123000161 each shared by products that are not variants |
| ID-CASE-COLLISION | HL-1002, hl-1002 | Ids differ only by letter case |
| SALE-WINDOW-EXPIRED | HL-1013 | Sale ended 2026-08-15; shoppers see the base price |
| SALE-BELOW-ANNOTATION-FLOOR | HL-1013 | 2.4% off earns no sale badge |
| SALE-IMPLAUSIBLE-DEPTH | HL-1018 | 96.0% off, likely a pricing-data bug |

**Next actions**
- Fix the critical findings before the next feed fetch; they cost impressions immediately. HL-1010 fails three checks at once: duplicate id, availability and condition.
- Image and landing-page URLs were checked by structure only, never fetched.

**Inputs:** Merchant Center feed export with 22 rows and 21 unique item ids, checked against the store domain shop.harborloom.com.

_Produced by running `bash examples/run.sh` on the sample data bundled with this skill._
```

## Part of

- [BFCM Skills](https://typestaging.com/library/skills/bfcm-skills.md)

## Related skills

- [Budget Pacer](https://typestaging.com/library/skills/budget-pacer.md): Project month-end spend from a trailing run rate across campaigns and clients, flag over- and under-delivery beyond a tolerance, and recommend per-campaign daily budgets that reconcile exactly to each client's committed total.
- [BFCM Cohort Quality](https://typestaging.com/library/skills/bfcm-cohort-quality.md): Find out if last Black Friday's new customers were worth it: contribution, repeats and payback vs October and January buyers, by discount, source and product.
- [Holiday Support Macros](https://typestaging.com/library/skills/holiday-support-macros.md): Prepare your support team for BFCM: forecast holiday tickets and staffing, find policy gaps and stale macros, and generate holiday macros built only from your written policies.
- [Holiday Shipping Cutoff Checker](https://typestaging.com/library/skills/holiday-shipping-cutoffs.md): Find the last day customers can order on each shipping service and still get it by the holiday, check every delivery promise against it, and plan the switch to expedited and e-gift cards.
- [BFCM Live Pulse](https://typestaging.com/library/skills/bfcm-live-pulse.md): Turn hourly sales and ad spend into a BFCM status update with sales pacing, budget guardrails, checkout alerts, code-use anomalies and stock risk.
- [BFCM Offer & Discount Config QA](https://typestaging.com/library/skills/bfcm-offer-config-qa.md): Check your Shopify BFCM discounts against the offer plan before launch: stacking, sale windows, who gets each discount, code limits and free shipping, with test carts and a dated fix list.

## Package files

- DATA_CONTRACT.md
- SKILL.md
- examples/expected_output.txt
- examples/run.sh
- examples/sample_feed.csv
- scripts/audit_feed.py

## SKILL.md

````markdown
---
name: product-feed-auditor
description: Audit a Google Merchant Center or Shopping product feed export offline for attribute coverage, title and description policy violations, malformed image and landing-page URLs, price and sale-price coherence, and duplicate ids, returning findings by severity with the exact item ids and the disapproval risk each carries.
---

# Product Feed Auditor

Catch the item-level problems that get products disapproved *before* the next
feed fetch. Merchant Center tells you an item is disapproved after it has
already stopped serving; this runs the same class of checks against a local
export in seconds, and names the exact item ids to fix.

## Before you run

This skill ships scripts and sample data alongside this SKILL.md. Before running any command:

1. **Get the files.** Make sure the skill's other files (`scripts/`, `examples/` and anything else listed with this skill) are in your working folder at the same relative paths. Some environments load only SKILL.md; if yours did, fetch each file from this skill's published files and write it to the matching path. In Type, read them with the skill-file tools. Anywhere else, the Type Skills Library API lists every file with its path, content and `sha256`: GET `https://api.type.com/api/public/library/skills` and take the entry with slug `product-feed-auditor`.
2. **Check the copies are exact.** Compare each file's size in bytes, not characters (and its hash, where your tools report one), with the published version before running. A copy written out from the published file is fine once its byte size and hash match; never run a script you summarised or reconstructed from memory.
3. **Run from the skill's folder**, calling interpreters explicitly: `python3 scripts/…` and `bash examples/run.sh`.
4. **Try the sample first.** If the skill ships `examples/run.sh` and `examples/expected_output.txt`, run `bash examples/run.sh`; its output should match the expected file exactly. If it doesn't, stop and report the first differing line rather than running on real data.

## When to use this

- A Merchant Center account has disapproved items and the owner wants the list
  grouped by cause, not by item.
- Before a bulk catalogue change ships: a new supplier drop, a re-platform, a
  price file import, a sitewide sale that writes `sale_price` across the feed.
- Recurring hygiene, for example weekly, to catch feed drift (placeholder
  images from a failed asset sync, zero prices from a missing cost column).
- When Shopping impressions fall and nobody has changed bids.

Do not use it to explain *performance* (ROAS, impression share). It audits
feed data quality only.

## Gathering the input

The script never touches the network. Export the feed first, then hand the
script a local file. Any of these produce an acceptable export:

- **Merchant Center**: Products → All products → download, or Feeds → the
  primary feed → download the processed feed. Export as CSV or TSV.
- **Shopify** (via the connected Shopify integration): pull products with
  variants and map them into the Merchant Center column names below. The
  Google & YouTube channel's product feed export already uses those names.
- **A feed vendor** (Feedonomics, DataFeedWatch, Channable): export the
  *output* feed, the one that actually gets submitted, not the source catalogue.
- **A raw feed URL** the owner already has: download it to a local file first.

`DATA_CONTRACT.md` lists the required and optional columns. Required columns
are `id`, `title`, `description`, `link`, `image_link`, `availability`,
`price`, `brand`, `condition`. If a column is genuinely absent from the
platform's export, add it as an empty column rather than dropping it — the
coverage table then reports it honestly as 0% covered.

Also ask the owner for the **claimed store domain** (for example
`shop.harborloom.com`). Without it the landing-page domain check is skipped.

## Running it

```bash
python3 scripts/audit_feed.py \
  --feed /path/to/feed.csv \
  --as-of 2026-09-15 \
  --domain shop.harborloom.com
```

- `--as-of YYYY-MM-DD` is required. It is the only notion of "today" the
  script has, and it is used to decide whether a `sale_price_effective_date`
  window has already closed. Use the date the export was taken.
- `--delimiter '\t'` for a TSV export.
- `--max-ids N` controls how many item ids print per finding (default 8).
- `--json` emits the same analysis as JSON for downstream automation.
- `--fail-on critical` makes the process exit 1 when any critical finding
  exists, which is useful in a pre-submit check.

Structural problems with the file (missing required column, empty file,
unreadable `--as-of`) exit 2 with a message naming the offending column. Bad
values *inside* the feed are the point of the tool and are reported as
findings.

## Reading and presenting the output

Three severities, and they mean different things:

- **critical** — Merchant Center will disapprove or drop the item. Fix before
  the next fetch. Every critical finding names the disapproval reason it maps
  to.
- **warning** — the item serves, but with degraded reach, wasted margin, or a
  data error that will bite later (reused GTIN, 2% "sale", expired sale
  window).
- **info** — merchandising advice, not a policy problem.

When reporting to a human:

1. Lead with the summary line: how many items carry at least one critical
   finding, as a share of the feed's unique item ids. That is the number that
   maps to lost revenue. Summary counts are per unique id: a duplicated id is
   one item, and a pair finding (reused GTIN, case collision) counts every id
   in the pair. The coverage table is per row, so its denominator can differ.
2. Then list critical findings by item count, largest first — a single bad
   template usually explains most of them. Twelve items with
   `IMG-PLACEHOLDER` is one broken asset sync, not twelve problems.
3. Give the exact item ids for the top findings so someone can fix them
   without rerunning anything.
4. Translate each fix into feed work: which system owns the column
   (`brand` comes from the PIM, `image_link` from the CDN pipeline,
   `sale_price` from the promo file), so the fix lands upstream and does not
   regress on the next sync.

## Limits

State these plainly; do not overclaim.

- **No network access.** Image and landing-page URLs are validated by
  structure and pattern only — scheme, host, unencoded characters, extension,
  placeholder naming, non-public host. The script cannot tell you an image is
  a 404, is below Google's minimum pixel size, has a promotional overlay, or
  that a landing page 500s or shows a different price than the feed. Those
  require a crawl.
- **Not a policy oracle.** It encodes the mechanical, checkable parts of the
  product data specification. It cannot judge restricted or prohibited
  products, misrepresentation, trademark issues, or whether a title is
  *accurate*.
- **No Merchant Center account state.** It cannot see existing disapprovals,
  account-level suspensions, shipping or tax configuration, or feed rules
  applied after upload. Reconcile with the Diagnostics tab.
- **Single-feed, single-country.** Multi-country supplemental feeds, regional
  price overrides, and `[country]` column suffixes are not modelled. Audit
  each output feed separately.
- **Heuristic text checks.** Capitalisation, promotional wording, and
  keyword-repetition checks use thresholds documented in the script header.
  They will occasionally flag a legitimate title (a brand genuinely named
  "SALE") — confirm before mass-editing.
- It does not edit or re-upload anything. Output is a report.
````
