UXFixUXFix
Language
Audit my store free
Agent UX

Why AI Shopping Agents Misread Your Prices

Abdulhameid Grandoka·24 August 2026
Why AI Shopping Agents Misread Your Prices

AI shopping agents quote the wrong price when they read a number from your page's code that isn't what a human actually pays. Agents parse HTML and structured data literally, not visually, so a strikethrough original price, a JavaScript-rendered total, a missing currency code, or a split bundle price all read as valid to a script. The gap between what displays and what the markup says stays invisible until an agent repeats it to a shopper.

Why AI shopping agents show the wrong price

When a customer asks ChatGPT, Perplexity or a similar agent to find and price a product, the agent doesn't open your site in a browser and read it the way a person does. It fetches the page, looks for structured data first, then falls back to text nodes in the HTML. If none of that lines up with the number your checkout actually charges, the agent quotes whatever it found first, not whatever is correct.

We see the same five failure modes across almost every audit:

  1. Client-side rendered totals. The price is injected by JavaScript after the initial page load, so the agent's fetch returns a placeholder, a blank, or "$0.00".
  2. Ambiguous sale markup. A crossed-out original price sits next to the sale price with no labelling distinguishing the two, so the agent can't tell which number to quote.
  3. Missing or incomplete schema. No Offer.price, or a price with no priceCurrency, forces the agent to guess from visible text.

The other two are formatting issues that look fine to a human but mean something different to a script:

  1. Bundle and tiered pricing. A per-unit price, a pack price and a subscription price all sit in the DOM together, and the agent grabs the first number it encounters rather than the one that matches the product being asked about.
  2. Currency symbol collisions. A bare $ sign used for both USD and CAD, or £ for both GBP and older Egyptian pound listings, with no ISO code to disambiguate.

Currency collisions deserve a closer look, because they're the failure mode store owners notice last. A store selling in both USD and CAD, using a bare $ throughout, gives an agent no way to know which currency a given price belongs to.

The ambiguity only resolves if surrounding context, a locale in the URL, an hreflang tag, or the priceCurrency field itself, disambiguates it. We've seen agents default to USD by convention even when the page is clearly serving a Canadian shopper, simply because the symbol carries no code at all.

Any one of these is enough to make an agent misquote your price to a shopper who never lands on your page to check it themselves.

How do AI agents actually read a price?

Most shopping agents follow a strict order of preference. They check schema.org structured data first, because it's explicit and machine-readable by design. If that's missing or incomplete, they fall back to visible text in the rendered DOM, and only some agents execute JavaScript before reading that DOM.

Some agents don't fetch your page directly at all. They query a retailer feed, a shopping API, or a cached snapshot from a search index, and that cache can lag behind a live price change by hours or days. If your feed and your live schema disagree, an agent quoting from the feed will still be wrong even though your website is technically correct at the moment someone actually checks it.

This matters because a price that looks perfectly clear to a human, rendered in a bold font at the top of the page, may not exist yet in the markup the agent actually receives. Google's own guidance on structured data for products is explicit that price, currency and availability should be present as discrete, typed fields, not just visible text. The schema.org Offer type exists specifically so a price doesn't have to be inferred from formatting.

Human shoppers have a related problem, just with a different cause. Baymard's checkout research has repeatedly found that unclear or late-disclosed pricing is one of the largest drivers of cart abandonment, because people can't reconcile what they see on the product page with what they're charged at checkout. Confusing price markup doesn't only cost you with agents, it costs you with people, which we cover in more depth in our piece on why shoppers leave your product page without buying.

The five failure patterns we see most in audits

Across the storefronts we've run through the UXFix 115-rule audit, price-parsing failures cluster around a small number of root causes. The numbers below are from our own audit set, not a claim about any single retailer.

61%
of product pages we audit finalize price via a JavaScript call after initial page load · UXFix, n=200
1 in 3
sale prices we check have no machine-readable sale value in schema, only visual strikethrough · UXFix, n=200
48%
of checkout abandoners cite unexpected costs as a reason to leave · Baymard

The first two rows are the ones that most directly cause an agent to misquote a price. The third is included because it shows the same root problem, ambiguity between what's promised and what's charged, shows up for humans too, just later in the funnel. If your checkout also introduces new costs at the last step, that's a separate but related leak covered in why shoppers abandon checkout at payment.

None of these numbers describe a single retailer. They describe a pattern across the stores in our audit set, and the pattern repeats regardless of platform, whether the store runs on a hosted cart, a headless commerce stack, or a custom build. The common denominator is always the same: the number a script can extract on first fetch doesn't match the number a shopper eventually pays.

See the dollars leaking from your checkout.
Run a free audit →

How to format prices so agents get them right

The fix is almost always a markup change, not a redesign. Three things matter more than anything else: the price has to exist in the initial HTML response, it has to be typed correctly in schema, and sale versus original price has to be unambiguous to something reading code, not pixels.

Do
  • Put the exact payable price in Offer.price with an explicit priceCurrency (ISO 4217, e.g. USD, not just "$").
  • Render the price server-side so it's present in the first HTML response, before any JavaScript runs.
  • Mark the current price and the reference price as separate, labelled fields, not just visual strikethrough.
Don’t
  • Rely on a <s> or <del> tag alone to signal "was" versus "now" with no underlying data distinction.
  • Use a bare currency symbol on a multi-currency store without an ISO code somewhere in the markup.
Before

A crossed-out $89 sits next to a bold $61, no schema present, and the $61 is calculated by a discount script that runs after the page loads.

After

Offer.price is set to 61.00 with priceCurrency USD, rendered in the initial HTML, with the $89 reference price stored as a separate, clearly labelled property.

Here's what correct markup looks like in practice, using the same $61 sale price from the example above:

json
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Example Product",
  "offers": {
    "@type": "Offer",
    "price": "61.00",
    "priceCurrency": "USD",
    "priceValidUntil": "2026-12-31",
    "availability": "https://schema.org/InStock"
  }
}

The reference price, the crossed-out $89, doesn't belong in Offer.price at all. If you want to expose it to agents and search engines, PriceSpecification allows you to record a comparison price separately, so the discount is explicit rather than implied by a strikethrough style. It's worth using if your platform supports it, rather than leaving the "was" price as unstructured text next to the "now" price.

One detail worth calling out: agents don't reliably wait for animations, countdown-timer discounts, or "price drops in your cart" scripts. If the true price only appears after a customer adds the item to cart, quote the cart price in your schema, not the pre-discount shelf price, or expect the agent to relay the wrong number.

Bundle pricing, subscriptions and multi-currency stores

Standard single-SKU pricing is the easy case. A handful of situations cause most of the remaining errors we see.

Situation What goes wrong What to do instead
Bundles ("buy 2 get 1 free") Agent quotes the single-unit price, not the bundle total Use a distinct Offer per bundle SKU with its own total price, not a shared price node
Subscriptions Agent quotes the first-period discount as the ongoing price Expose both the intro price and the recurring price as separate schema fields, not just in body text
Multi-currency / multi-region Agent quotes the wrong currency for the shopper's region Serve region-specific schema based on locale, and always include the ISO currency code, never a symbol alone
Quantity tiers Agent quotes the price for one unit when the shopper asked about a case or pack Structure tiered pricing as separate Offer entries with explicit eligibleQuantity
Variant-dependent pricing (size, color, material) Agent quotes the base variant's price for a request about a different variant Model variants as a ProductGroup with individual Offer entries via hasVariant
Tax-inclusive vs. tax-exclusive display Agent quotes a pre-tax figure in a market where tax is included at checkout, understating the true cost Set the relevant priceSpecification field explicitly rather than leaving tax treatment implied

The common thread across all six is that the agent has no way to infer intent from layout. A human reading "3 for $45" understands the deal instantly. A parser reading the same three words needs the $45 tied explicitly to the quantity of three in the underlying data, or it will report $45 as the price of one unit.

Variant pricing catches stores that otherwise have clean markup. A single Product node with one Offer and a $40 price looks correct until a shopper asks an agent about the size that actually costs $52.

If your variants are modelled as a ProductGroup with individual Offer entries per hasVariant, the agent can resolve the right SKU. If they're modelled as one product with a dropdown that changes the DOM price via JavaScript, the agent will quote whichever price loaded first, usually the cheapest variant, and that's the number it repeats to the shopper regardless of what they actually asked for.

Tax display causes a quieter version of the same problem. A store that shows tax-inclusive prices on the page but exposes a tax-exclusive figure in schema will have an agent confidently quote a number that's lower than what the shopper pays at checkout. This is the same root cause as the late-cost problem Baymard has documented in checkout research, just surfaced earlier, at the point an agent reads the page rather than the point a human reaches payment.

If you're not sure whether agents can even discover these pages before they get to the pricing problem, that's a separate and earlier failure point, covered in our crawlability checklist for AI shopping agents. Price formatting only matters once the page has been found and fetched.

Questions we get asked

Can ChatGPT read sale prices correctly?

Only when the sale price is explicit in the page's structured data or clearly separated from the original price in the rendered text. If the only signal is a strikethrough style on the original price with no accompanying label or schema field, ChatGPT and similar agents frequently quote the crossed-out number, the discounted number, or an average of the two, because none of those visual cues survive into plain text or markup the same way.

Does price have to be in schema markup?

It doesn't have to be, but it should be. Agents that check schema.org Offer data first will get a precise, typed price and currency without guessing. Without it, they fall back to whatever text is visible in the DOM, which is far more likely to include ambiguous formatting, multiple candidate numbers, or a price that hasn't finished loading yet.

Why does my price show blank to AI agents?

This almost always means the price is being injected by JavaScript after the page's initial HTML response, and the agent's fetch either doesn't run that script or times out before it finishes. The fix is to render the price server-side in the HTML that's returned on first request, so it's present regardless of whether a script executes afterward.

Does variant selection, like size or color, break price accuracy too?

Yes, and it's one of the more common edge cases we see. If your product page uses one Offer for all variants and updates the visible price with JavaScript based on a dropdown selection, an agent reading the initial schema will find whichever price was present at load, which is usually the base or cheapest variant. Structuring variants as a ProductGroup with a distinct Offer per SKU fixes this at the source.

Should schema show tax-inclusive or tax-exclusive prices?

Whichever number the shopper actually pays at checkout, stated explicitly rather than implied by regional convention. If your checkout adds tax on top of the displayed price, that's the same late-disclosure problem Baymard has linked to cart abandonment, just happening at the schema level instead of the payment step. Use priceSpecification fields to mark whether tax is included, rather than leaving an agent to guess based on your store's country.

Does this affect Google Shopping results too, not just conversational agents?

Yes. Google's structured data guidance for products applies to both its shopping and search surfaces, and the same Offer.price and priceCurrency fields that fix agent misquotes are what Google's Shopping Graph uses to validate listings. A price mismatch between your schema and your checkout can get a listing suppressed entirely, not just misquoted.

See what UXFix finds on your own store

115 rules, your product page, cart and checkout, a screenshot of every issue. About four minutes.

Audit my store free