Somebody loaded a supplier feed straight into their store and never merchandised it. Every product has a shouting title, no description, and no alt text. The owner knows something is wrong and cannot name it.
Most people would open the file and start fixing. That is the mistake. First you count, because a number you can defend is what turns "your catalog is messy" into a scope, a price, and a finish line. Then you repair what a script can honestly repair, and you say out loud which columns a script must never touch.
SYNTHETIC SAMPLE DATA, INVENTED FOR THIS DEMO. NO REAL COMPANY, NO CLIENT DATA.
Every product is opened and checked. The residual is counted, not implied: defective products plus clean products reconcile to the row count, and the buckets sum to the defect total.
| Defect | Count | Share of catalog | Repairable |
|---|
Six of the nine checks are scriptable and get fixed here in front of you. Three are not. Two of those three need content that does not exist yet, and inventing it would be the single worst thing a tool like this could do. The third needs somebody to decide which duplicate row wins, which is a business call and not a parsing problem.
Never repaired, by design: descriptions, meta descriptions, and any ingredient, nutrition, allergen, or certification content. A generator can produce a fluent paragraph about a food product it has never seen, and that paragraph can be wrong in a way that hurts somebody. Those cells stay empty, they are counted as an open defect, and they are quoted as human work with an hour count against them.
Also never invented: the vendor. A row with the platform default in that column is rewritten to UNMAPPED:ARB, using a token that was already in the row, rather than to a brand name that sounds plausible. An unmapped cell is a five minute conversation with the client. A wrong brand name on a live product page is a different kind of problem entirely, and it is one nobody notices for months.
That distinction is also the commercial one. The scripted repair costs the same for 60 products as for 6, so it is priced per catalog. Descriptions are genuine human work that does not script away, so they are priced per product. Getting that backwards caps the upside on the part that scales and undercharges the part that does not.
Reconciliation is not optional. Rows in equals rows out plus named drops, each drop with a reason. A cleanup tool that quietly loses four rows is worse than no tool, because the loss shows up a month later in somebody else's report.
The audit pattern here is the one I ran on a real 68 product catalog for a live bid. The checks, the bucketing, the worst case quote, and the reconciliation line are the same. The catalog on this page is invented, because a prospective client's product data is theirs and does not belong in my portfolio.
Honest about the checks: they are heuristics over the columns a store actually exposes, and they are tuned to catch the supplier-feed failure mode. A title of PREMIUM ORGANIC ARBORIO RICE 6X1KG is flagged because it is raw feed text, not because caps are always wrong. Run it on a well merchandised catalog and it should come back nearly empty. If it does not, the checks are wrong and I would rather find that out on your data than defend a number I cannot support.