# Pricing page schema: 120 of 195 pricing pages showed a price and declared none in their markup

> Lantad asked all 1,419 hostnames in this repository's two committed corpus seed files for robots.txt on 10 October 2026, read every permitted home page with no JavaScript executed, then followed each page's own link to a pricing page and read that too. 205 home pages linked one, 196 answered HTTP 200 with HTML, and 195 answered again on a second pass the same day. 146 of the 195 showed a currency amount in the text the extractor read, and 28 declared a price in JSON-LD.

- Canonical page: https://lantad.co/blog/pricing-page-schema-120-of-195-declared-none
- This file: https://lantad.co/blog/pricing-page-schema-120-of-195-declared-none.md
- Last substantive update: 2026-10-10

## Key facts

- **Published:** 2026-10-10
- **Category:** Findings
- **Author:** Lantad
- **Length:** 3034 words
- **Takeaway 1:** Pricing page schema is the markup that states a plan price in a form a machine can lift, and of the 195 corpus pricing pages Lantad read twice on 10 October 2026, 146 showed a currency amount in the page text while 28 declared a price or lowPrice property in JSON-LD.
- **Takeaway 2:** 120 of those 195 pricing pages showed a reader a price and declared none in their markup on 10 October 2026, and 59 of the 120 carried at least one JSON-LD block on the pricing page while leaving the price out of it.
- **Takeaway 3:** Of the 28 pages that did declare a price, 8 declared no value above zero, and on 2 of those 8, atlasgo.io and dropbox.com, the first currency amount in the page text was already above zero.
- **Takeaway 4:** UnitPriceSpecification, the schema.org type built to say what a recurring plan costs per unit of time or seat, appeared on 8 of the 195 pricing pages Lantad read on 10 October 2026.
- **Takeaway 5:** 49 of the 195 pricing pages showed no currency amount at all, and 35 of those 49 carried language asking the reader to contact sales or request a quote.

## Summary

Ask an assistant what a product costs and it has to get the number from somewhere. The page a buyer would read is the obvious place, and on most sites the number is there, set in large type next to a plan name. Whether it is there in a form a machine can lift without guessing is a separate question, and pricing page schema is the part of [structured data](https://lantad.co/glossary/structured-data) that answers it: an Offer node with a price on it, rather than a figure that exists only as styled text in a column.

So this run counted both halves on the same pages. Every hostname in the corpus committed to this repository was asked for its robots.txt, every permitted home page was read with no JavaScript executed, and where that home page linked to its own pricing page, that page was read as well. 205 sites linked one. On the 195 that returned a readable page twice, 146 showed a currency amount in the text and 28 declared a price in their markup. The gap between those two numbers is 120 pages that tell a reader exactly what they charge and tell [a crawler](https://lantad.co/glossary/ai-crawler) nothing.

## An engine asked what you charge has to find a number

The pricing page is not a page a scanner can assume exists. Most of the corpus is government, education, healthcare and news, and a great many of those sites sell nothing at all. So the population here is defined by the sites themselves: a page counted as a pricing page only if the home page linked to it on the same host, and the link either sat on a path naming prices, plans, subscriptions, membership, rates or tariffs, or carried anchor text that was one of those words and nothing else. That rule is deliberately narrow. It finds the page a visitor would reach by clicking the word Pricing, which is the page an engine following the same link would reach too.

205 of the 1,077 readable home pages offered such a link. Not one of the 205 paths was disallowed to Lantad by the site's own robots.txt, which is worth stating because it is the opposite of the pattern [a run that found robots.txt closing declared search endpoints](https://lantad.co/blog/searchaction-schema-57-of-224-endpoints-robots-closed) turned up: nobody hides their prices from crawlers on purpose. 196 answered HTTP 200 with HTML. Nine did not, and the nine are a reminder that the fetch itself is a measurement: box.com, gitlab.com and pipedrive.com each returned 403 to [a plainly identified crawler](https://lantad.co/bot), cloudsmith.com returned 429, and bangkokpost.com returned 451.

Every figure below is counted over the 195 pages that answered 200 with HTML on a first read and again on a second read the same day, because a price is exactly the sort of thing a template renders inconsistently and a single fetch should not be trusted to settle. The two passes agreed on every page. The median page carried 790 words. Five carried none at all, among them hubspot.com's marketing pricing page and jetbrains.com's store, both of which served a crawler a document with no readable text in it. The [method notes](https://lantad.co/methodology) describe how the extractor decides what counts as text.

## 120 of 195 pricing pages showed a price and declared none

Two independent tests ran over each page. The first asked whether a currency amount appears anywhere in the text the shipped extractor reads: a symbol or an ISO code sitting against digits, so a dollar sign followed by a figure counts and the bare word free does not. The second asked whether any JSON-LD node on the page carries a price or lowPrice property with a value in it, using the same JSON-LD walk the scanner uses for its schema sub-score rather than a parser written for the occasion.

146 pages passed the first test. 28 passed the second. 26 passed both. 120 passed the first and failed the second, which is the headline, and 2 passed the second and failed the first. 47 passed neither.

The 120 is not a story about sites that do not do markup. 59 of the 120 carried at least one JSON-LD block on the pricing page itself, so three sites in every five already had the machinery on the page and did not put the price through it. fly.io served seven blocks on a page whose first visible figure was a per-hour rate. nbcnews.com served three. pressmodernmassage.com served four, and gonosotros.com four, both on a hosted builder that emits its own markup whether the author asks for it or not. The other 61 carried no JSON-LD on the page at all, which is a different problem with the same result and one this blog has counted before, when [141 of 382 home pages carried no structured data in the raw HTML](https://lantad.co/blog/structured-data-141-of-382-home-pages-carried-none).

The named cases run across every stratum rather than clustering in one. costco.com and nike.com showed amounts and declared none, which is its own kind of surprise given that [42 of 50 product pages declared Product schema](https://lantad.co/blog/product-schema-42-of-50-declared-it) when this blog counted them. monzo.com and brex.com did. So did clickhouse.com, grafana.com, cnn.com, usps.com and nursingworld.org. This is not a small-site problem or a builder problem. It is the default, and the 28 are the exception.

## What does pricing page schema actually declare?

The vocabulary for this is old and settled. [The schema.org Offer type](https://schema.org/Offer) is defined as "An offer to transfer some rights to an item or to provide a service", and it carries price, described there as the offer price of a product. For anything billed per seat or per month there is a more exact instrument: [UnitPriceSpecification](https://schema.org/UnitPriceSpecification), a subtype of PriceSpecification that adds the unit the price is charged against, so a figure can say twelve dollars per seat per month rather than just twelve.

[Google's product snippet documentation](https://developers.google.com/search/docs/appearance/structured-data/product-snippet), last updated 8 September 2026, treats this as settled too. It lists offers among the recommended properties on a Product, and inside an Offer it puts price under required properties, with the heading written as price or priceSpecification.price so either shape satisfies it. priceCurrency it marks as recommended for product snippets and required for merchant listings, advising that it always be included.

Measured against that, the 195 pages divide sharply. 33 declared an Offer or an AggregateOffer node: 30 the former, 7 the latter, 4 both. 32 declared a priceCurrency. 28 declared a price or lowPrice with a value. And 8 declared a priceSpecification of any kind, every one of them a UnitPriceSpecification, which is the only type in the set that can express a subscription correctly and is therefore the number worth looking at twice. sentry.io, intercom.com, monday.com, metalbear.com, countrystatecity.in, chiro.london, carecycle.ai and eightdigitmedia.com are the eight.

The ones that did it did it properly. monday.com emitted a UnitPriceSpecification with a unitCode of MON and a billingIncrement, so the markup says per month rather than leaving a reader of the data to infer it. carecycle.ai declared a referenceQuantity against an active policy, which is a unit nothing in the vocabulary supplies by default. This is the same pattern a run on [Organization and WebSite nodes](https://lantad.co/blog/website-schema-markup-158-of-338-connected-neither) found: the sites that reach for a property at all tend to use it correctly, and the finding is almost never a misuse. It is an absence.

## Eight of the 28 declared no price above zero

Declaring a price is not the same as declaring the price. Of the 28 pages carrying a numeric price or lowPrice value, 8 carried no value anywhere above zero. netlify.com, auth0.com, zapier.com, novavoice.app and uplisting.io each declared a single zero. opper.ai declared two. atlasgo.io and dropbox.com declared one zero each on pages whose first visible currency amount was already above zero: nine dollars on one, nine dollars and ninety nine cents on the other.

For the five whose own page also opened on a zero, the markup is at least consistent with the free tier the page leads with, and nothing here says those sites are wrong about themselves. The point is narrower and it is about what the data says on its own. A node that declares price zero and stops has described a free product. An engine reading only the markup, which is the entire reason to write markup, is told the product costs nothing. The paid plans next to it on the page are not in the data at any price.

The 20 that declared something above zero mostly declared a range rather than a point, which is the honest shape for a page with four plans on it. busy.in declared values from zero to twenty two thousand rupees. sentry.io ran from zero to nine hundred and sixty dollars. umbraco.com emitted twenty two values across five currencies. chiro.london, a single clinic on a hosted builder, emitted thirty two price values, more than monday.com's twenty three.

None of this is a validator finding, which is what makes it persistent. A price of zero is a valid price, a single Offer on a page with five plans is valid markup, and nothing in a testing tool reports either. It is the same class of defect as [markup values that are not on the page](https://lantad.co/blog/structured-data-for-ai-70-of-146-values-off-page) and as [a node too incomplete to identify an organisation](https://lantad.co/blog/ai-structured-data-103-of-385-named-no-organization): structurally sound, and describing something other than the page it sits on.

## 49 showed no price, and 35 asked the reader to get in touch

The other end of the distribution is the 49 pages carrying no currency amount in their text at all, and most of them are not a failure of any kind. 35 of the 49 carried language asking the reader to contact sales, request a quote, book a demo or talk to the team, and 11 carried free tier language, with 10 pages doing both. A page that genuinely does not publish a price cannot mark one up, and an enterprise sales motion is a business decision rather than a markup defect. This blog has published what that looks like from the buyer's side, when [three of six AEO tools published no price a crawler could read](https://lantad.co/blog/best-aeo-tools-three-of-six-published-no-price).

13 of the 49 carried neither cue, and those are worth separating because they are mostly not pricing pages by the time a crawler arrives. walmart.com served a bot challenge reading Robot or human, which is the condition [a run on crawler access](https://lantad.co/blog/is-my-site-blocking-ai-crawlers-79-of-115) measured directly. nzherald.co.nz and yogaoffeast.com served zero words. jalan.net returned text the extractor read as mojibake, a character encoding failure of the kind [15 home pages declaring no encoding](https://lantad.co/blog/character-encoding-for-ai-search-15-of-1088-declared-none) turned out to be. 1password.com, grist.org, news24.com and meininger-hotels.com served real pages where the plan figures arrive with JavaScript, so the crawler read the surrounding copy and none of the numbers.

That last group is the one a site owner can act on, and it is the oldest finding on this site restated on a new page: a figure that exists only after a script runs does not exist for a client that does not run scripts. Lantad measures that gap as [prose parity](https://lantad.co/glossary/prose-parity), and the [crawler view of any page](https://lantad.co/tools/what-gptbot-sees) shows which side of it a price falls on. For a pricing page the stakes are unusually concrete, because the number is the whole reason the page exists.

## What this run did not measure

The population is sites that link a pricing page from their home page using a word this run recognised. A site whose plans live behind a link reading Get started, or inside a navigation menu built by a script, was not counted, and the 205 is therefore a floor on how many corpus sites publish prices rather than a census. The corpus itself is a sampling frame of 1,419 hostnames chosen to spread across industries and site builders, not a random sample of the web, so the proportions here describe this corpus on this date and are not a population estimate. The seed files are committed, which is what makes the number checkable rather than authoritative.

Nothing here was rendered in a browser. That is the point of reading a page as a crawler reads it, and it is also a limit: a price that arrives with JavaScript is absent from these counts by design, and a run that compared both views would find more visible prices and exactly the same amount of markup. Nothing here checked whether a declared price is correct, either. The comparison in the zero section is between a declared value and the first currency amount in the page text, which is a weaker test than reading the plan table and matching it row by row, and on a page with several plans the first visible figure need not be the cheapest.

Nor does any of this measure whether markup changes what an assistant says about your prices. That would need a controlled test against the engines, which is a different instrument from the one used here, and this blog has already published that [structured data came third in a citation audit](https://lantad.co/blog/structured-data-came-third-in-a-citation-audit) rather than first. What is measured is narrower and still worth knowing: on 120 of 195 pages, the number a buyer came for is present for a person and absent for a machine, and closing that gap is a property on a node rather than a project. The [glossary entry on generative engine optimization](https://lantad.co/glossary/geo) sets out where this sits among the rest, and [what AI says about a site](https://lantad.co/what-ai-says) is where the downstream question gets asked, while [the guide to being cited by ChatGPT](https://lantad.co/how-to-get-cited/chatgpt) covers the retrieval side of it.

## Questions and answers

**What is pricing page schema?**

It is structured data on a pricing page that states the price as data rather than as styled text, normally an Offer node carrying a price property, or a priceSpecification for anything billed per seat or per month. schema.org defines the Offer type as an offer to transfer some rights to an item or to provide a service, and Google's product snippet documentation, last updated 8 September 2026, lists price or priceSpecification.price as a required property inside an Offer.

**How many sites put their price in their markup?**

Of the 195 corpus pricing pages Lantad read twice on 10 October 2026, 28 declared a price or lowPrice property with a value in it, against 146 that showed a currency amount in the page text. 120 pages showed a price to a reader and declared none in their markup.

**Does a price of zero in markup matter?**

It matters when it is the only price declared. 8 of the 28 pages carrying a numeric price value declared nothing above zero on 10 October 2026, and on 2 of those, atlasgo.io and dropbox.com, the first currency amount in the page text was already above zero. No validator reports this, because zero is a valid price and one Offer on a page of five plans is valid markup.

**Is it a problem that a pricing page says contact sales instead of a price?**

Not for this measurement. 35 of the 49 pages showing no currency amount asked the reader to contact sales, request a quote or book a demo, and a page that does not publish a price cannot mark one up. The separable group is the 13 that carried neither a figure nor that language, where the cause was a bot challenge, a zero-word response, a character encoding failure or plan figures that only arrive once JavaScript runs.

---

Lantad measures whether AI crawlers can actually read a page: it fetches as a non-rendering
crawler, renders as a browser, and reports the gap. Free scan, one URL, no signup.

Method and weights: https://lantad.co/methodology | All pages as markdown: https://lantad.co/md | Crawler policy: https://lantad.co/bot
