How AI assistants read pricing and affiliate pages
Why numbers rendered by JavaScript are often invisible to AI crawlers, which schema.org types help, and how to write a terms block an agent can quote.
AI assistants read pricing and affiliate pages by fetching the HTML and extracting the numbers they find in it, and many of them do not run JavaScript. Vercel's December 2024 analysis of its network found that none of the major AI crawlers it studied rendered JavaScript, naming OpenAI's crawlers, Anthropic's ClaudeBot and PerplexityBot, while Gemini and AppleBot did [2]. So a price or commission rate that only appears after a script runs may be invisible to the assistant a buyer or a creator is asking. The fix is plain: put every number in the initial HTML, state each one once in a consistent form across pages, and add schema.org markup that repeats what the visible text already says. This post shows what fetchers see, which markup helps, and a before-and-after terms block.
How do AI assistants fetch a pricing page?
There are two kinds of visits, and they behave differently. The first is a crawler that visits pages ahead of time and builds an index the assistant searches later. The second is a fetch triggered by a user's question: someone asks "what does this tool cost?" and the assistant retrieves the page right then. OpenAI documents both. OAI-SearchBot surfaces sites in ChatGPT search, GPTBot collects content that may be used to train models, and ChatGPT-User visits a page when a user asks a question or uses an external action; OpenAI notes that ChatGPT-User does not crawl automatically and that robots.txt rules may not apply to it [1].
Both kinds have the same practical limit: they read what the server sends. A browser downloads the HTML, runs the scripts, calls your pricing API, and paints the result. A fetcher that does not execute scripts stops after the first step. If your pricing table is a React component that loads plan data from an endpoint after the page mounts, the fetcher sees the empty container and whatever placeholder text you left in it.
Vercel's analysis is the clearest public evidence on this. It reported that ChatGPT and Claude crawlers fetch JavaScript files but do not execute them, that Gemini renders JavaScript because it uses Google's infrastructure, and that AppleBot renders with a browser-based crawler [2]. It also noted that content present in the initial HTML response, including JSON data, may still be indexed. Crawlers change, and a 2024 measurement is not a guarantee for 2026, but it is a strong reason to design for the fetcher that does the least.
| Fetcher | Purpose | Runs JavaScript? | Source |
|---|---|---|---|
| GPTBot | Collects content that may train OpenAI models | No (Vercel, Dec 2024) | [1] [2] |
| OAI-SearchBot | Surfaces sites in ChatGPT search | No for OpenAI crawlers (Vercel, Dec 2024) | [1] [2] |
| ChatGPT-User | Fetches a page when a user asks | Not stated in OpenAI docs | [1] |
| ClaudeBot | Anthropic crawler | No (Vercel, Dec 2024) | [2] |
| PerplexityBot | Perplexity crawler | No (Vercel, Dec 2024) | [2] |
| Gemini (Google infrastructure) | Google AI features | Yes | [2] |
| AppleBot | Apple crawler | Yes, browser-based | [2] |
HTML vs JavaScript-rendered pricing: what the fetcher sees
You can test this yourself in a minute. Request your pricing page without a browser, for example with curl, and search the response for a dollar sign. If you see your plan prices and your commission rate in the raw HTML, a non-rendering fetcher sees them too. If you see a loading spinner, an empty div with an id, or a script tag that will "hydrate" the table later, it does not.
Three common setups behave differently. A static or server-rendered page sends the full table in the first response; every fetcher reads it. A framework page that renders on the server and then hydrates in the browser also sends the full table, as long as the data is fetched on the server; this is the default in most modern frameworks when you load data in a server component or at build time. A single-page app that requests pricing from an API after load sends nothing useful; the numbers exist only in the browser.
Watch for the partial cases too. Toggles between monthly and annual pricing often render one set of prices and swap in the other with JavaScript, so the fetcher sees only the default. FAQ accordions sometimes load answers only when clicked. Currency switchers based on the visitor's location may show a fetcher, which comes from a data center, a currency you did not expect. For each of these, make sure the default HTML contains the version you most want quoted, and state the other version in plain text nearby: "$49 a month, or $490 a year billed annually".
Why consistent numbers across pages matter more than markup
An assistant rarely reads one page. Asked to compare affiliate programs, it may read your affiliate landing page, your terms page, a help article and a third-party review, then reconcile them. When your own pages disagree, the assistant either picks one, averages them into a range, or says the terms are unclear. None of those outcomes helps you.
Disagreement is common because different people write different pages at different times. Marketing writes "partners earn up to 30%" on the homepage after a promotion. The affiliate page still says "20% recurring for 12 months". The legal terms say "20% of net revenue", which is a different base. And the cookie window is 60 days on one page and 30 days in an old help article nobody updated.
| Page | Commission as written | Cookie window | What an assistant may conclude |
|---|---|---|---|
| Homepage footer | Up to 30% | — | Rate is 30% |
| Affiliate landing page | 20% recurring for 12 months | 60 days | Rate is 20% |
| Terms page | 20% of net revenue, 12 months | 60 days | Base is net, not invoice |
| Old help article | 20% recurring | 30 days | Cookie may be 30 days |
| FAQ answer loaded by script | — | 60 days | Not seen by non-rendering fetchers |
The audit is the most useful hour you can spend on this topic. List every page that mentions a price, a commission rate, a duration, a cookie window, a hold period or a minimum payout. Put each number in a spreadsheet next to the page it appears on. Every row that disagrees with the others is a wrong answer some assistant is giving right now. Fix the pages, and where an old page cannot be changed, add a line that points to the current terms.
Which schema.org types help pricing pages?
Structured data is a second copy of your facts in a format with named fields. It does not replace the visible text; it confirms it. The schema.org vocabulary has the types you need for prices and for question-and-answer content, and it is embedded as JSON-LD in a script tag. Because the JSON-LD is part of the initial HTML, a non-rendering fetcher can read it, which is consistent with Vercel's note that JSON in the initial response may be indexed [2].
For a price, the type is Offer. Its price property holds the amount and priceCurrency holds the currency as an ISO 4217 code such as USD; priceSpecification links to a more detailed price description; eligibleDuration states how long the offer is valid; and offeredBy points to the organization making it [3]. For subscriptions, UnitPriceSpecification adds billingDuration, the length of time a price is billed for, which accepts a duration; billingStart, for prices that change after a period; and priceType, for list or sale prices [4].
{"@context":"https://schema.org","@type":"Offer","name":"Pro plan","price":"49","priceCurrency":"USD","priceSpecification":{"@type":"UnitPriceSpecification","price":"49","priceCurrency":"USD","billingDuration":"P1M"},"url":"https://example.com/pricing"}
For questions and answers, the type is FAQPage, a web page that presents one or more frequently asked questions, with each question as the page's mainEntity [5]. One change matters here: Google's Search Central changelog recorded the deprecation of the FAQ rich result in May 2026, saying it would stop appearing in Google Search from May 7, 2026, and recorded the removal of its documentation in June 2026 [6]. So FAQPage markup no longer earns a special search snippet in Google. It is still a clear, named structure that any parser can read, and it costs little if your FAQ answers are already in the visible HTML.
There is a gap worth stating plainly. We did not find a schema.org type designed for affiliate commission terms. You can describe a program as an Offer with a description, but rate, duration, cookie window and hold period have no dedicated fields. For those, the visible text is the machine-readable format, which is why the next section matters more than any markup.
| Fact on the page | schema.org type and property | Example value | Source |
|---|---|---|---|
| Monthly plan price | Offer.price + priceCurrency | "49", "USD" | [3] |
| Billing period | UnitPriceSpecification.billingDuration | "P1M" | [4] |
| Intro price that changes later | UnitPriceSpecification.billingStart | Number of periods | [4] |
| How long an offer is valid | Offer.eligibleDuration | QuantitativeValue | [3] |
| Questions and answers | FAQPage with mainEntity | Question items | [5] |
| Commission rate, cookie window, hold | No dedicated property found | State in visible text | — |
What makes affiliate terms machine-readable?
Machine-readable does not need a special format. It means that each fact is a short sentence with one number, a unit and a scope, written the same way everywhere. An assistant extracting terms is doing pattern matching on text. "20% of each paid invoice for the first 12 months" can be extracted reliably. "Earn generous recurring commissions on every customer you send our way" cannot, because there is no number in it.
Five rules cover most of it. Use one sentence per term. Put the number first or early in the sentence. Name the base of the percentage: invoice amount, net revenue, or first payment. Name the unit of time: days, months, invoices. And add a visible "last updated" date, so an assistant reading two versions of a page can tell which one is current.
Before: a terms block written for skimming
Join our partner program and earn industry-leading recurring commissions! Our generous cookie gives you plenty of time to convert, and we pay out fast. Top partners unlock even higher rates. Terms apply.
That block has no numbers at all. An assistant asked "what does this program pay?" has to say it does not know, or guess from a third-party review that may be years old. "Industry-leading" and "generous" are claims a model will either ignore or repeat without support, and neither helps a creator decide.
After: a terms block written for extraction
- Commission: 20% of each paid invoice for the first 12 months after the customer's first payment.
- Tiers: 25% on new customers after your 10th paying customer.
- Cookie window: 60 days from the last click. Last-click attribution.
- Coupon: your personal code attributes the sale with no click.
- Hold: commission becomes payable 30 days after the invoice is paid. Refunds and disputes are deducted.
- Payout: monthly, by PayPal or Wise, once your balance reaches $50.
- Not eligible: purchases by you or your company, and bidding on our brand name in search ads.
- Last updated: October 1, 2026.
Every line has one number and one scope, the base of the percentage is explicit, and the exclusions are named. An assistant can quote any line on its own and be correct. A creator comparing three programs can line these up in a table in seconds. Keep this block in the server-rendered HTML of your affiliate page, use exactly the same sentences on the terms page, and link the two.
How to test what an assistant sees on your page
- Fetch the page without a browser and save the response. Search it for every price and every commission number you expect. Anything missing is invisible to non-rendering fetchers.
- Check the default state of every toggle: monthly or annual, currency, region. The default is what gets quoted.
- Open the JSON-LD in the response and compare each value with the visible text next to it. Markup that disagrees with the page is worse than no markup.
- Run the cross-page audit: list every page that mentions a term and confirm that each states the same number in the same words.
- Ask two or three assistants a direct question, such as "what commission does this program pay and for how long?", and compare the answer with your terms block. Note which page each one cites.
- Repeat after every pricing or program change, and update the "last updated" date when you do.
This is also why RelayWonder renders program pages on the server with the terms as plain sentences, publishes an llms.txt file that points language models at the pages worth reading, and offers an MCP endpoint and API keys so that agents can read program terms as typed data rather than scraping them. Whatever tool you use, the test above tells you whether the facts reach the reader.
What to change on your pages this week
- Move pricing and commission numbers into the server-rendered HTML if they are fetched by script today.
- Rewrite the affiliate terms block as one sentence per term, number first, with the base and the unit named.
- Add a "last updated" date to the pricing page and the terms page.
- Fix or redirect every old page that states a different rate, duration or cookie window.
- Add Offer and UnitPriceSpecification markup for plan prices, and FAQPage markup for an FAQ that is already visible in the HTML.
- Write down which assistants you tested and what they answered, so you can see whether the changes reached them next month.
FAQ
Do AI crawlers run JavaScript?
Many do not. Vercel's December 2024 analysis found that none of the major AI crawlers it studied rendered JavaScript, including OpenAI's crawlers, ClaudeBot and PerplexityBot, while Gemini and AppleBot did. Put prices and terms in the initial HTML so every fetcher can read them.
What is the difference between GPTBot, OAI-SearchBot and ChatGPT-User?
According to OpenAI, GPTBot collects content that may be used to train models, OAI-SearchBot surfaces sites in ChatGPT search, and ChatGPT-User fetches a page when a user asks a question. OpenAI notes that ChatGPT-User does not crawl automatically and that robots.txt rules may not apply to it.
Which schema.org type should I use for subscription prices?
Use Offer with price and priceCurrency, and link a UnitPriceSpecification whose billingDuration states the billing period, for example P1M for a month. The markup should repeat the numbers that are already visible on the page.
Is FAQPage markup still useful after Google removed FAQ rich results?
Google's changelog says the FAQ rich result stopped appearing in Search from May 7, 2026. The markup no longer earns a Google snippet, but it remains a named structure that parsers can read, and it costs little when the answers are already in the visible HTML.
Is there a schema.org type for affiliate commission terms?
We did not find one designed for commission rate, cookie window or hold period. State those terms as short visible sentences with one number each, such as "20% of each paid invoice for the first 12 months", and use the same wording on every page.
How do I check what an AI assistant can see on my pricing page?
Fetch the page without a browser, for example with curl, and search the raw response for every price and rate. Anything that appears only after scripts run is likely invisible to non-rendering fetchers. Then ask an assistant directly and compare its answer with your terms.
Sources
- OpenAI: Overview of OpenAI crawlers · Purpose of OAI-SearchBot, GPTBot and ChatGPT-User, and robots.txt behavior. Checked October 2026.
- Vercel: The rise of the AI crawler · December 2024 analysis: major AI crawlers did not render JavaScript; Gemini and AppleBot did; JSON in initial HTML may be indexed. Checked October 2026.
- schema.org: Offer · Definitions of price, priceCurrency, priceSpecification, eligibleDuration and offeredBy. Checked October 2026.
- schema.org: UnitPriceSpecification · Definitions of billingDuration, billingStart, billingIncrement, priceType and referenceQuantity. Checked October 2026.
- schema.org: FAQPage · Definition of a page of frequently asked questions and the mainEntity property. Checked October 2026.
- Google Search Central: Latest documentation updates · May 2026 deprecation of the FAQ rich result (no longer shown from May 7, 2026) and June 2026 removal of its documentation. Checked October 2026.