Blog

How Should Pricing Pages Expose Plans, Limits, and Add-Ons to AI Systems?

AI systems can only summarize SaaS pricing reliably when the page states plans, limits, currencies, and exclusions in clear, crawlable text—not just in visual cards or JavaScript widgets.

Why pricing pages are unusually difficult for AI systems to parse

Pricing pages often look simple to a person and remain surprisingly ambiguous to a parser. A human can connect a plan name in one card with a price badge, a tooltip, a footnote, and a toggle for monthly versus annual billing. An AI system may receive those elements in a different order, miss a client-rendered value, or combine a limit from one plan with a price from another.

The practical goal is not to create a special “AI pricing format.” It is to make the page unambiguous for any consumer of web content: search engines, accessibility tools, procurement researchers, browser agents, and language models. Treat the page as a small, documented data set with a readable interface.

This is also why structured data should be considered a supporting layer, not a replacement for visible content. A useful machine-readable content approach starts with crawlable HTML, clear labels, stable URLs, and then uses metadata or JSON-LD to reinforce facts.

Start with a complete, crawlable HTML representation

Every plan should have a distinct heading and a nearby block of text that states its commercial terms. Do not make the plan name, price, or limits available only after a click, inside an image, or through a JavaScript calculator. Interactive controls can improve the user experience, but the underlying facts should still exist in the initial document or in accessible HTML.

  • Give each plan a unique heading, such as “Growth plan” or “Enterprise plan,” rather than relying on position alone.
  • State whether the price is monthly, annual, per user, per workspace, per event, or another unit.
  • Expose the currency using both a symbol and an ISO code where useful, such as “$49 USD per month.”
  • Separate included limits from overage charges and from hard product restrictions.
  • Label annual-discount displays clearly; do not present an annual total beside a monthly price without explaining the billing period.
  • Use ordinary text for “not included,” “available as an add-on,” “contact sales,” and “requires Enterprise.”
  • Keep plan URLs stable and link to detailed documentation for limits, billing rules, and eligibility.

A semantic table can help when the page compares the same features across plans. The table should have real header cells, a meaningful caption, and text values rather than checkmark icons with no accessible name. A card layout is acceptable too, provided each card contains a complete, self-contained description.

Use a consistent data model for each plan

Before writing markup, define the fields that every plan should expose. Consistency is more valuable than adding a large amount of schema. If one plan says “10 seats,” another says “unlimited users,” and a third says “contact us,” make the differences explicit instead of forcing readers to infer that the units are comparable.

FieldWhat to stateExample
Plan identityName, short description, and stable plan URLGrowth — for teams up to 25 users
PriceAmount, currency, billing period, and pricing unit$49 USD per workspace per month
AvailabilityWho can buy it and any geographic or account restrictionsAvailable to new customers in supported countries
Included usageQuantity and unit, with reset period where relevant100,000 API calls per month
OveragesExtra cost or hard stop after the included amount$0.001 per additional API call
ExclusionsImportant features, seats, support levels, or integrations not includedSSO and audit logs not included
Add-onsName, price, unit, and compatibility with plansExtra 10 seats: $20 USD per month; Growth and Enterprise
Billing conditionsAnnual commitment, minimum spend, taxes, refunds, and cancellation rulesBilled annually; taxes calculated at checkout

Use the same vocabulary everywhere. If the product calls a unit a “workspace” on the pricing page, do not call it an “account” in the FAQ unless they are genuinely different. Ambiguous nouns are a common source of incorrect summaries.

Make price, currency, and billing period explicit

A bare “$29” is not machine-readable enough for a reliable answer. It leaves open whether the amount is monthly or annual, whether it applies per seat, and whether it is an introductory price. Put the full commercial statement near the plan name: “$29 USD per user per month, billed monthly,” or “$290 USD per user per year, billed annually.”

  1. Name the billing unit: per user, per organization, per project, per thousand events, or another unit.
  2. Name the period: monthly, annually, one-time, per transaction, or usage-based with a defined measurement period.
  3. Identify the currency. Use ISO 4217 codes such as USD, EUR, or GBP when symbols could be ambiguous.
  4. Distinguish list price, promotional price, and renewal price.
  5. Explain whether the displayed amount excludes taxes, implementation fees, or required minimums.
  6. State whether customers can switch billing periods and whether the displayed discount requires an annual commitment.

For a monthly/annual toggle, include both values in the HTML if both are important to the buying decision. A toggle that swaps text only after a user action can be missed by a crawler or an extraction process. If showing one default value, label the alternate price in nearby text or a linked billing explanation.

Represent limits, exclusions, and add-ons without visual shorthand

Limits are often more important than the headline price. “Unlimited projects” may still mean a limit on members, storage, API requests, retention, or support. Write each material limit as a sentence or a labelled value. For example: “Growth includes up to 25 users, 100,000 API calls per month, and 50 GB of storage.”

Avoid using a blank cell, dash, or greyed-out icon to represent an exclusion. Say what the state means. These statements are much safer to extract: “SSO is not included in Starter,” “Audit logs are available only on Enterprise,” and “Extra storage is available as a paid add-on.”

  • Define whether “unlimited” is a contractual entitlement, a fair-use allowance, or simply an absence of a published numeric cap.
  • State reset dates or rolling windows for usage limits.
  • Describe whether unused units roll over.
  • Give overage rates and explain whether overages are billed automatically or blocked.
  • List add-on compatibility: which plans can buy it, whether a minimum quantity applies, and whether it renews with the base plan.
  • Link to terms or documentation for exceptions, but keep the main commercial fact on the pricing page.

If a table uses checkmarks, provide text alternatives such as “Included,” “Not included,” or “Available with add-on.” This helps both assistive technology and extraction systems interpret the value without depending on icon semantics.

Add JSON-LD carefully, and do not invent precision

JSON-LD can provide a structured representation of a product or offer, but it should mirror what users can see. For a fixed-price plan, an Offer may include a price, priceCurrency, availability, and a URL. A Product can identify the plan and connect it to the offer. Use the vocabulary supported by the relevant schema documentation, and validate the syntax.

A simplified conceptual pattern might look like this in the page source:

  • A Product or Service identifies the plan, its name, description, and URL.
  • An Offer identifies the public price, currency, availability, and the page or checkout URL.
  • Properties such as priceValidUntil should be used only when the date is real and maintained.
  • A unit of measure or billing explanation should remain visible in HTML because not every consumer will interpret custom pricing fields consistently.
  • Add-ons can be represented as separate offers or products when they have their own stable names, prices, and eligibility rules.

Do not encode “$0” for a free trial if the trial automatically converts to a paid subscription, and do not encode a placeholder number for “contact sales.” Likewise, do not mark every plan as InStock merely because the page exists if a plan is limited by region, invitation, or sales approval. Structured data that is technically valid but commercially misleading is worse than no structured data.

Handle custom, usage-based, and regional pricing honestly

Not all pricing fits a single numeric Offer. For custom pricing, use visible text such as “Custom pricing based on users and data volume” and link to the qualification process. For usage-based pricing, define the meter: “$0.01 per API call after the included allowance,” not merely “usage-based.” Include minimums, rounding, free tiers, and overage behavior.

Regional pricing needs similar care. If prices vary by country, state the region beside the price and explain how location is determined. Do not let an IP-based currency switch create a page where the same URL exposes contradictory values without a clear locale signal. Consider stable locale URLs, hreflang where appropriate, and visible currency labels.

Pricing situationClear page wordingCommon extraction risk
Fixed subscription$49 USD per workspace per month, billed monthlyThe parser sees $49 but misses the unit or period
Annual commitment$490 USD per workspace per year; annual commitment requiredA discounted annual total is mistaken for a monthly price
Usage-based$0.01 USD per API call after 100,000 calls per month“Starts at” or a unitless number is treated as the full price
CustomContact sales for a quote based on users and data volumeA fake numeric value is added to structured data
Regional€45 EUR per user per month for customers billed in the EUA currency symbol is shown without a region or currency code

Test the page as a crawler and as a buyer

A pricing page is not finished when it looks correct in one browser. Test the raw response, rendered page, structured data, and alternate states. The checks should be repeatable so a redesign or pricing update does not quietly remove important facts.

  1. Fetch the URL without executing JavaScript and confirm that plan names, prices, periods, limits, and exclusions are present in the HTML.
  2. Render the page with a browser and compare the visible result with the raw response. Look for values that exist only after interaction.
  3. Inspect the accessibility tree for headings, table headers, labels, and text alternatives to icons.
  4. Validate JSON-LD syntax and compare every price, currency, availability state, and URL with the visible page.
  5. Test monthly, annual, locale, logged-out, and mobile states if they change commercial information.
  6. Check robots.txt, canonical tags, sitemap inclusion, and response status. Access is a prerequisite for any downstream discovery.
  7. Ask an independent reader to answer: What is the cheapest paid plan, what does it include, what does it exclude, and what happens after the limit?

This work addresses different layers that should not be conflated. Robots access for AI crawlers concerns whether a system can fetch content. Training presence concerns whether a source may have appeared in a dataset. Live answer citations concern whether a system retrieves and cites the page for a particular question. Better pricing markup improves interpretation, but it cannot guarantee any of those outcomes.

A practical implementation pattern

For most SaaS teams, a resilient implementation has four layers: complete server-rendered HTML, accessible comparison markup, carefully maintained JSON-LD, and linked documentation for details. Keep plan facts in one source of truth so the pricing cards, table, FAQ, checkout, and structured data do not drift apart.

  • Use a plan data object or CMS record containing name, URL, price, currency, period, unit, limits, exclusions, add-ons, and availability.
  • Generate readable HTML from that source, not only a client-side pricing widget.
  • Generate JSON-LD from the same source, with rules that omit fields when the value is unknown rather than inventing one.
  • Add automated tests that flag a mismatch between displayed prices and checkout prices.
  • Record pricing changes and update the page's last-modified signal when material terms change.
  • Keep a human-readable changelog or billing FAQ for changes that could affect existing customers.

You can compare this work with the broader JSON-LD and AI discovery guide, but the principle is simple: structured data should confirm a clear page, not compensate for a confusing one. A machine-readable pricing page is successful when a reader can extract the same answer from the HTML, the table, and the metadata.

How to measure whether the improvements help

Measure quality before and after changes with a fixed set of pricing questions. Examples include “What is the monthly price for the Growth plan?”, “How many API calls are included?”, “Is SSO included?”, and “Can Starter customers buy extra seats?” Record the expected answer, the page URL, the date, and whether the answer cites the correct source.

FAQ

Should every pricing plan have its own Product or Offer schema?

Not necessarily. Use visible HTML as the primary source of truth, then add JSON-LD where it accurately represents a plan and its price. Separate Offer objects can be useful when plans have distinct prices, currencies, URLs, or availability, but schema should not describe details that are missing or ambiguous on the page.

Can JSON-LD make an AI system cite my pricing page?

No. JSON-LD can make facts more structured, but it does not guarantee crawling, inclusion in a model's training data, retrieval, citation, or recommendation. Those outcomes depend on access, freshness, query context, and the system's own selection process.

Should pricing be rendered server-side?

For important pricing facts, yes. Put plan names, prices, billing periods, limits, and exclusions in the initial HTML when practical. Client-side rendering may work for some crawlers, but relying on JavaScript adds an avoidable extraction failure point.

How should I represent custom or usage-based pricing?

State the pricing model plainly in HTML, such as “Contact sales,” “$0.01 per API call,” or “Starts at $500 per month.” Do not use a misleading numeric price in structured data when no fixed public price exists. Explain the unit, minimum commitment, overage rules, and whether taxes are included.