The 30-second answer: when AI quotes wrong pricing, there is an old copy somewhere, and your job is to outrank it with a current one
Assistants do not invent prices often. They read one: from training data, from a third-party page that mentions your pricing, from an old page on your own site, or from a current page they could only partly parse. The fix has four parts, in order of effect. Make the pricing page itself quotable: plain HTML text, every plan and both billing periods as text, a visible date. Make the other copies agree: structured data on the page, a dated one-line summary in llms.txt. Find and neutralize stale copies on your own domain. Then ask the assistants again and see which source they cite.
llms.txt is one part of that, not the whole. Not every assistant reads it, and the ones that do still fetch the page. What it gives you is a short, dated statement at a fixed URL that an agent reads before anything else on your site.
Where the old number comes from
| Source | How to recognize it | Fix |
|---|---|---|
| Training data | The answer cites no URL, or says it may be out of date; the number matches a price from a year or more ago | Nothing on your site changes this directly. Make the fetched answer correct, and ask with browsing on |
| Third-party pages | The citation is a review site, a directory, or a comparison post with an old table | Update the listings you control; for the rest, publish a dated page they will cite next time |
| Your own stale pages | The citation is your blog, changelog, docs, or a PDF price list | Add a dated note linking to the current page, redirect retired pricing URLs, update docs |
| Unreadable current page | The citation is your pricing page but the number is wrong or partial (monthly vs annual, one region) | Render every plan and period as text in the HTML; put the date on the page |
The citation is the diagnostic. When an assistant with browsing quotes a price, it usually names the page; open it and you will find the number. When it quotes a price with no source, it is answering from memory, and the only lever you have is to make sure a fetched answer, when one happens, is right.
Make the pricing page the copy every reader prefers
The pricing page has to be readable by a plain HTTP fetch. OpenAI’s documented user-agent fetches the page a user is asking about at answer time, as an ordinary request; Google processes JavaScript in three phases, crawling, rendering, and indexing, with rendering queued separately. Anything that only exists after a click or a script run is at risk in both cases. The checklist:
- Every price as text in the HTML. If the page has a monthly/annual toggle, render both numbers in the markup and let the toggle show or hide them. A price drawn in an image or injected by a script after load is a price some readers never see.
- A visible date. “Prices as of October 2026” near the top. A reader comparing two copies of your pricing picks the dated one, and a model can say “as of October 2026” instead of guessing.
- Currency and tax basis stated once. USD or EUR, per seat or per workspace, tax included or not. These are the words an assistant drops when they are missing.
- Plan names that match everywhere. If the page says Team and the docs say Business, an assistant reading both reports two plans. Rename the docs.
- One URL. Keep /pricing as the canonical page. Retired pricing pages redirect to it; regional variants link to it and say which region they cover.
- No PDF price lists. A PDF is the hardest copy to update and the easiest to leave behind. If sales needs one, generate it from the page, with the same date.
Structured data: a second copy, not a different one
Google’s guidance for AI features in Search, last updated in December 2025, says there is no special schema.org markup to add for AI Overviews or AI Mode, and that structured data should match the visible text on the page. That is the right frame for pricing markup: it restates the visible price in a form that is easy to parse, and it must never say something the page does not.
For software, Google documents the SoftwareApplication type. Its required properties are name, offers.price (zero for a free app), and either aggregateRating or review; it recommends applicationCategory and operatingSystem and asks for priceCurrency next to a paid price. A minimal block for a product whose cheapest paid plan is 19 dollars a month:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Acme Analytics",
"applicationCategory": "BusinessApplication",
"operatingSystem": "Web",
"offers": {
"@type": "Offer",
"price": "19",
"priceCurrency": "USD",
"url": "https://acme.example/pricing"
},
"aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.6", "ratingCount": "212" }
}
</script>Generate it from the same data that renders the page, so a price change cannot update one and not the other. If you have no ratings, leave the type out rather than inventing them; the visible text is what matters for an assistant, and the markup is a bonus for search features.
The llms.txt part
The spec describes llms.txt as information used on demand, when an agent needs to know about a site. For pricing that means one section, one dated sentence, one link. The sentence should stay true for months, so it carries the starting price and the model, not the full table:
## Pricing As of October 2026: a free plan for one project, paid plans from 19 USD per month per workspace, billed monthly or annually (two months free on annual). Prices exclude tax. - [Pricing](https://acme.example/pricing): All plans, limits, and the annual discount, with the current date. - [Enterprise](https://acme.example/enterprise): Custom contracts, SSO, and procurement details; quote on request.
Three rules. The date is mandatory; without it the sentence is one more undated copy. The sentence and the page change in the same deploy; put llms.txt on the pricing-change checklist, or generate the sentence from the same data as the page. And do not list promotions or regional prices here; they expire, and the file does not.
A note on expectations: Google has said it does not use llms.txt, and OpenAI’s documented crawlers fetch pages rather than the file. The readers are agents, developer tools, and crawlers that look for it by name. For them, this is the first thing read about your site, which is why the sentence is worth getting right.
Sweep the stale copies
- Find them. Search your own site for the old numbers and plan names: a site search, a grep of the content repository, and a web search for your product name with “pricing” restricted to your domain. Check the changelog, launch posts, help articles, comparison pages, and any PDF.
- Date and redirect. For posts that are still useful, add a dated note at the top: this post is from 2024; current pricing is on the pricing page, with a link. For retired pricing URLs, redirect to /pricing. Do not delete a page without a redirect; the old URL is what the third-party pages link to.
- Fix the docs. Help articles mention plan limits more often than prices. Replace hard-coded numbers with a link to the pricing page where you can.
- Update listings you control. Review-site profiles, app marketplaces, and partner directories often have a pricing field you edit yourself. Those pages rank for “your name pricing” and get cited.
- Keep sitemap dates honest. Google uses a sitemap’s lastmod value when it is consistently and verifiably accurate, and says it should reflect the last significant update to the page. A real lastmod on /pricing is one more signal that the current copy is the current copy.
Check what the assistants say now
Ask the question a prospect would ask, in two or three assistants, with browsing on where that is a setting. Record the price quoted and the URL cited. Fix the cited copy, wait a few days, ask again. The citations article covers the log-based side: which bots fetch your pricing page and how often.
See what an AI crawler gets from your pricing page
Enter your URL and the checker fetches your pages the way a bot does, reports what is reachable as text, and drafts an llms.txt from what it found. Free, no account.
Run the check →FAQ
Why does an AI assistant quote pricing we changed a year ago?
Usually one of four reasons: the model is answering from training data without fetching anything; a third-party page (a review site, a directory, a comparison post) ranks for your name plus pricing and still shows the old table; your own site still has the old number somewhere, in a blog post, a changelog, a help article, or a PDF; or your current pricing page is not readable as plain text, so the assistant falls back to whatever it can read. Each has a different fix, which is why the article walks through finding the source first.
Will llms.txt alone fix wrong pricing answers?
No. Not every assistant reads llms.txt; Google has said it does not, and OpenAI's documented crawlers fetch ordinary pages. llms.txt helps the agents and tools that do read it, and the dated one-line summary it carries is a useful anchor. The fix that reaches every assistant is the pricing page itself: plain HTML text, dated, consistent with every other copy of the number.
Should we put exact prices in llms.txt?
Put the starting price, the plan names, the billing model, and the date, in one sentence, then link to the pricing page. Keep the sentence true for months: a starting price and whether a free tier exists change less often than the full table. If pricing changes, updating that sentence is part of the change, in the same deploy as the page.
What structured data applies to SaaS pricing?
Google's SoftwareApplication type requires name, offers.price (zero for a free app), and a rating or review; it recommends applicationCategory and operatingSystem and asks for priceCurrency alongside a paid price. Whichever type you use, Google's guidance for AI features in Search is that no special markup is needed and the markup must match the visible text. Treat structured data as a second copy of the visible price, not as a way to say something the page does not.
Our pricing is custom. What do we write?
Write what is true and stable: the pricing model (per seat, per usage, annual contract), the smallest engagement, whether a free trial or free tier exists, and how to get a quote. An assistant asked for your price will say something; a sentence saying the model is usage-based from a stated minimum is better than a number scraped from a 2023 blog post.
How do we find out what assistants currently say?
Ask them, with browsing turned on where that is an option, and record the answer and the sources they cite. The cited URL tells you which copy of the number they read. Repeat after each fix; fetched answers change within days, while answers from training data change only when the model does.
Next steps
- → How to check whether AI search has picked up your site (the four checks, from reachability to referrals)
- → Does ChatGPT use llms.txt? (what OpenAI’s crawlers actually fetch)
- → How to write llms.txt by hand
- → All Learn articles