> ## Documentation Index
> Fetch the complete documentation index at: https://docs.37audits.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pricing

> Crawls the site for a pricing or plans page, through Offer structured data or a pricing heading, so buyers and AI assistants can find what you charge.

<Info>
  **SEO Auditor** — crawls the audited site, breadth first and on the same host, until it finds a page that looks like a pricing or plans page: Offer structured data (JSON-LD or Microdata) or a heading, link or button that reads like a pricing label.
</Info>

<CardGroup cols={2}>
  <Card title="Buyers" icon="users">
    A visitor who cannot find what you charge compares a competitor instead of asking.
  </Card>

  <Card title="AI assistants" icon="robot">
    Answer engines quote prices from structured data and clearly labelled pricing pages; sites without one are left out of the comparison.
  </Card>
</CardGroup>

A pricing page is one of the most visited pages of any product site, and the first one a buyer, a procurement team or an AI assistant looks for. This auditor starts at the monitored URL, follows links on the same host and stops at the first page that carries Offer structured data or a pricing heading, or after 500 pages.

## How it works

1. **Validate** — normalizes the monitored URL (adds `https://` when the scheme is missing). A URL that does not parse or has no host ends the audit with `501`.
2. **Fetch the start page** — sends a `GET` request to the monitored URL as 37AuditsBot. A blocked request ends the audit with `590`; a timeout, DNS or TLS failure, an HTTP status of 400 or more, or a body that is not `text/html` ends it with `500`.
3. **Detect** — on every page read, three detectors run in order: Offer structured data in JSON-LD (`Offer`, `AggregateOffer`, `PriceSpecification`, or a `Product`, `Service`, `SoftwareApplication`, `Organization` or `LocalBusiness` with `offers`, `price`, `priceCurrency` or `priceRange`), Offer structured data in Microdata (`itemtype` of `Offer`, `AggregateOffer` or `PriceSpecification`, or an `itemprop` of `offers`, `price`, `priceCurrency` or `priceRange`), and a pricing heading (an `h1`–`h4`, link or button whose text matches labels such as `Pricing`, `Plans`, `Subscription`, `Billing`, `Packages`, `Preços`, `Planos`, `Assinatura` or `Valores`).
4. **Crawl** — when no detector matches, every `http(s)` link to the same host is queued and the crawl continues breadth first, at most 500 pages. A page that cannot be fetched, answers HTTP 400 or more (including 403) or is not HTML is skipped silently; only the start page can block or fail the audit.
5. **Rules** — a crawl that ran out of pages or reached the 500-page limit without a match fails (`400`); the first match succeeds (`200`) and names the page, the detector and the number of pages crawled.

## What it audits

Every row maps to one `checkRule*` method and one `CheckCode`, in the order the auditor runs them. CheckCode suffixes use status ranges: `200` success, `400–499` fail, `500–599` error.

| CheckCode | Status | When it fires | Recommendation | Why it matters |
| - | - | - | - | - |
| <a id="37A-PricingAuditor-400" />`37A-PricingAuditor-400` | `FAIL` | The crawl ran out of same-host pages, or reached the 500-page limit, without any detector matching a page. | Publish a pricing or plans page on `{host}`, link it from the main navigation of `{startUrl}` so it is reached within the first 500 pages, and mark it with Offer structured data or a heading such as "Pricing" or "Plans". | Buyers who cannot find what you charge leave to compare a competitor instead of asking, and AI assistants that answer pricing questions leave your product out of the comparison. |
| <a id="37A-PricingAuditor-200" />`37A-PricingAuditor-200` | `SUCCESS` | A detector matched a crawled page. Message names the page, the detector (JSON-LD, Microdata or a pricing heading) and the number of pages crawled. | — | — |
| <a id="37A-PricingAuditor-500" />`37A-PricingAuditor-500` | `ERROR` | The start page could not be fetched (timeout, DNS, TLS, HTTP 400 or more other than a block) or is not an HTML page. | Make sure `{startUrl}` answers with HTTP 2xx and an HTML body, then run the audit again. Last error: `{error}`. | — |
| <a id="37A-PricingAuditor-501" />`37A-PricingAuditor-501` | `ERROR` | The start URL does not parse or has no host, so there is nothing to crawl. | Monitor an absolute URL with a scheme and a host, such as [https://example.com/](https://example.com/), instead of "`{startUrl}`". | — |
| <a id="37A-PricingAuditor-590" />`37A-PricingAuditor-590` | `ERROR` | The audited page answered HTTP 403, HTTP 429 or a Cloudflare challenge, so 37AuditsBot was blocked before it could read the page. | Allow 37AuditsBot in your firewall or bot protection: allowlist its user agent, or verify its Web Bot Auth signature. See [https://www.37audits.com/bot](https://www.37audits.com/bot). | While 37AuditsBot is blocked this audit cannot look at the site, so problems on it go unreported. |

## Output documentation

| Status | Description | Test logic |
| - | - | - |
| **SUCCESS** | A pricing or plans page was found | A crawled page matched the JSON-LD, Microdata or heading detector (`200`). |
| **FAIL** | No pricing or plans page was found | The crawl exhausted the same-host pages or reached the 500-page limit without a match (`400`). |
| **ERROR** | The auditor could not crawl the site | Start page fetch failure, HTTP 400 or more, or non-HTML body (`500`); invalid start URL or no host (`501`); site blocked 37AuditsBot (`590`). |

Every check carries the same `data` fields: `startUrl`, `host`, `pagesCrawled`, `maxPages`, `pricingUrl`, `detector` (`json-ld`, `microdata` or `heading`), `schemaDetected` and `headingDetected`.

## Risks and considerations

### Why a findable pricing page matters

* Procurement teams, founders and AI assistants all look for a price before they contact sales; a site without a reachable pricing or plans page loses the comparison by default.
* Offer structured data (`Offer`, `AggregateOffer`, `priceSpecification`) lets search engines show prices in rich results and lets answer engines quote them accurately.

### How the crawl can miss or mislabel a page

* The crawl follows only `http(s)` links to the same host, breadth first, and stops after 500 pages. A pricing page reachable only through another host (a billing subdomain, an app store), through JavaScript navigation or deeper than 500 pages is reported as missing.
* The heading detector is a word match on `h1`–`h4`, links and buttons (English and Portuguese labels). A page that mentions "plans" in another sense, or a navigation link to a pricing page, counts as a match; the message names the page and the detector so you can confirm it.
* Only the first matching page is reported; the auditor does not judge whether the prices on it are complete or current.

### Changes from the previous version

* An invalid start URL, or one without a host, is now an `ERROR` (`501`) instead of a `FAIL`: the auditor could not run, so the result is not charged.
* A start page that cannot be fetched (timeout, DNS, TLS, HTTP 400 or more, non-HTML body) is now an `ERROR` (`500`) instead of the "no pricing page found" `FAIL`.
* The "no pricing page found" verdict now carries a check (`400`) with the pages crawled, the host and the limit, so it can be referenced and filtered like every other finding.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.