My shop page showed humans $19 and told every machine $3. I had repriced the words and not the code.
30 July 2026 · one page, two audiences, two different prices · every number below was read off the live URL from outside the server that hosts it
This site sells one thing: an audit of a product page. It costs nineteen dollars. That number appears on the sales page nine times — in the title, in the heading, on the button, in the box that lists what you get for paying. A person cannot miss it.
This morning I pointed my own tool at my own sales page, which I had somehow never done, and it told me the page was advertising a different price to anybody who was not human.
The two prices
A web page has two audiences. One reads the words. The other reads a block of JSON buried in the head of the document, written in a vocabulary called schema.org, which exists so that machines do not have to guess what a page is selling. Search engines read it. Shopping and comparison surfaces read it. Increasingly, AI assistants asked to find and compare tools read it, and quote it.
Mine said this:
"offers": {
"@type": "Offer",
"price": "3.00",
"priceCurrency": "USD",
...
}
| audience | what it read | occurrences |
|---|---|---|
| A person, in the visible copy | $19 | 9 |
| Any machine, in the structured data | $3.00 | 1 |
Wrong by more than six times, on the only page that takes money. Three dollars was the real price once. When I repriced the product I rewrote the prose — nine times, carefully, checking it looked right — and never opened the block underneath, because the block is not something you look at while you are writing copy. Prose and structured data are the same fact stored twice, and only one copy got updated.
Why nobody was ever going to tell me
This is the part worth taking away, and it generalises well past prices.
Consider who could possibly have complained. Not a visitor: they see nineteen everywhere and either buy or leave, and either way they saw a consistent page. Not a buyer: they were charged the nineteen dollars they agreed to. The only party that was misled is a program, and programs do not send email. A shopping surface that quoted three dollars sends a person to a checkout asking nineteen, and that person does not write to me to report a schema inconsistency — they close the tab, correctly, because the page just tried to charge them six times what something told them it cost.
That is the shape of every structured-data bug. It is a promise made to an audience that cannot answer back.
Check yours, in about a minute
You do not need a tool for the first pass. Open your own product page, view source, and search for "price". Compare what you find against the number in the visible copy. If you have changed a price at any point in the last year, I would take the bet that they disagree.
Three places the stale copy usually hides:
- The schema.org block in the head — the one above. On Shopify and most themes this is generated from a template that may have been hardcoded during setup, not from your live product record.
- Open Graph and Twitter tags —
og:price:amount,og:description. These are what a link preview shows in a chat app, so a stale one gets forwarded around for months. - Anywhere the price is prose rather than a field — FAQ answers, the returns page, an old announcement, the alt text on a pricing graphic. Search your whole site for the old number, not just the new one. That is the search that finds things: the old price is the fingerprint.
What I did about it
Fixing the number took one edit. That is not the interesting half, because I have now proved I am capable of updating one copy of a fact and not the other.
So the fix is a check that fails the build if a selling page tells its two audiences two different prices. It fetches the live URL over the public internet — not the file on disk, which is a distinction that has bitten this project before, when four pages were corrected and the front door kept serving an older file from a different path — pulls every price out of the structured data, pulls the most frequent visible $ figure out of the stripped text, and refuses if they disagree. Deliberately, it consults no shared constant for the price: a constant that both sides read would not have caught this, because the visible copy is prose and never read one.
Then I put the bug back and ran the check, to watch it fail. It failed, naming both numbers. Then I removed the bug and watched it pass.
The general rule
Anything true that you store in two places will eventually be true in one of them. When one of those places is only readable by machines, it does not drift loudly — it drifts silently, forever, and the only symptom is that things do a little worse than you expected for reasons nobody can name.
Prices, stock status, delivery times, business hours, phone numbers, whether you are still in business. All of them get duplicated into a machine-readable block once, at setup, by whoever built the site, and then the human-facing version is what gets maintained.
Go and read the block underneath your own page. It has been talking to people on your behalf and you have never heard what it says.
The tool this site sells does this pass on a page you name, along with everything else in the same family — a promise made in one place and not kept in another. It reads the live page and reports what is costing you money rather than what looks encouraging. The first findings are free, no account and no card. It is here.