# Anatomy of a Citable, Comparable Product Detail Page
> An AI agent can cite and compare a product page only when the whole offer is readable from the page itself: a descriptive title, the all-in price, availability, key specs, and review depth, in server-rendered text and structured data.
## Key takeaways
- An AI agent does not browse your product page, it extracts it: title, all-in price, availability, specs, and reviews become one structured row it lines up against every competitor.
- A page that reads fine to a person can be un-comparable to an agent. If an element is missing from the text or markup, the agent guesses or drops you on that axis.
- The individual parts are taught on their own pages; this is the whole-page view: which elements matter and how an agent assembles them into a comparable offer.
- Under all of it sits server-rendered HTML plus structured data. Get the substrate wrong and every element above is invisible, however complete it looks to a human.
## The whole-page view: your PDP becomes one comparable row
When an AI shopping agent reads a product detail page, it is not browsing it the way a person does. It is extracting it: pulling the title, the price, what shipping adds, whether the item is in stock, the specs, and the reviews into a single structured record it can line up next to every competing offer. A product detail page an agent can cite and compare is one where that whole record is readable from the page itself, with nothing left for the agent to infer.
The strongest public evidence, the academic ACES framework, found that what moved an agent's choice were structured attributes (grid position, price, star rating, platform endorsement, and description text) in a controlled simulation of Claude, GPT-4.1, and Gemini agents rather than a record of real sales. The practical reading of that is a whole-page one. We expect an agent can only compare you on the axes you make legible, so a page that reads fine to a person but leaves the all-in price, a key spec, or the review count out of its text and markup is a page the agent cannot fully place against its rivals.
This page is the connective view over the catalog cluster. The individual elements each have their own page, linked in place below; here we walk the whole product detail page and how its parts combine into a comparable offer. For why these signals decide the pick at all, start at the hub, [how AI shopping agents choose products](/how-ai-agents-choose-products/), and the definition of [agent selection](/glossary/#agent-selection).
## The identity layer: title and product identifiers
Before an agent can compare your offer, it has to match your product to the shopper's query and resolve it to a known item. Two elements do that work. The **title** is the text matched most directly against what the shopper typed, so it has to lead with the category and defining attributes a query can land on. That formula, and the literal-match failure mode behind it, is the whole subject of [product titles that AI agents match](/product-titles-for-ai-agents/), which this page does not restate.
The **identifiers** (GTIN, brand, MPN) are what let an agent tie your listing to the same product sold elsewhere and de-duplicate it across sources. The open Agentic Commerce Protocol, the checkout standard behind ChatGPT Instant Checkout, standardizes the core product attributes an agent reads, including product identifiers such as GTIN, price, and availability. Where those identifiers belong in your markup is the job of [product schema for AI shopping](/product-schema-for-ai-shopping/), and keeping them filled and correct across every listing is the job of [your product feed](/make-product-feed-ai-readable/). The whole-page point is smaller and it is this: a title that matches but no identifier to anchor it, or an anchor with a brand-only title, leaves the agent with half of what it needs to place you.
## The offer layer: the all-in price, availability, and delivery
An agent does not compare list prices, it compares offers, and the offer is the price a shopper actually pays plus whether and when the item can arrive. The single most common way a PDP becomes un-comparable is hiding the parts of that number until checkout.
The **all-in price** (item price plus shipping, fees, and tax treatment) is the figure an agent lines up against competitors, so it has to be computable from the page before checkout starts, not revealed at the payment step. Surfacing it early is a selection lever the [agent selection checklist](/tools/agent-selection-checklist/) treats as its first offer-legibility item, and the field-level how-to sits in [make your product feed AI-readable](/make-product-feed-ai-readable/); this page only insists the page carry it. **Availability and delivery** answer the two questions an agent will not recommend around: can you fulfil this, and by when. A blank or stale availability field is an easy reason to skip you rather than risk recommending something out of stock.
There is a hard constraint on all of it: the offer an agent reads must be the offer a shopper is charged. Google's structured-data policies require your markup to be a true representation of the content visible on the page. Its merchant-listing documentation defines the offer, shipping, and return fields an agent parses. Showing an agent one price and a shopper another is not a targeting tactic, it is a parity violation that can get products disapproved and erodes trust. Serving the same data in a machine format is fine; serving different data is cloaking, a boundary drawn in full on [raising information density](/handbook/information-density/).
## The comparison layer: the specs and reviews that break a tie
Identity and offer get you into the comparison. What wins it, once several products are eligible, is the content an agent can actually rank on. Two elements carry most of that weight.
**Specs and attributes** are the columns of the comparison table. An agent can only compare products on the attributes every candidate exposes, so the fields your category's leaders fill and you leave blank are silent losses, a completeness-versus-peers judgment no validator makes for you. That judgment, and the evidence that agents rank on structured attributes, live on the hub, [how AI shopping agents choose products](/how-ai-agents-choose-products/). **Review depth** is the trust column. In the ACES simulation, ratings were a strong selection lever and review count mattered as a signal distinct from the average score, so genuine depth (a truthful count, recent reviews, and a real distribution) plausibly gives a rating-sensitive agent more to weigh. Depth is the lever; fabricated ratings are both a rule violation and, on this evidence, a weak play.
These are the fields worth auditing against your competitors first, because they are the ones tied to a decision rather than to a checkbox. And how completely they are filled is itself measurable. On Adobe's AI Content Visibility Checker, retail product pages score an average of 66 out of 100 for machine readability, meaning roughly a third of a typical product page is not cleanly machine-readable to an agent. The [machine-readability score](/glossary/#machine-readability-score) is where that gap becomes a number you can move.
## The substrate: server-rendered HTML and structured data
Every element above is only as legible as the layer that carries it. Two things make up that substrate, and both are load-bearing for the whole page.
**Structured data** (the Product and Offer JSON-LD) is the block an agent can lift field by field without interpreting your layout or your marketing copy. It is the tie-breaker an agent trusts when your page and feed disagree, and its fields and syntax are the subject of [product schema for AI shopping](/product-schema-for-ai-shopping/). **Server-rendered HTML** is the precondition under that: we expect a crawler or agent that does not execute JavaScript to miss any price, spec, or availability injected client-side, so a fact locked in a script-rendered widget, a PDF, or a product image reads as absent even when a human plainly sees it. A price baked into a hero graphic, a spec table fetched only on click, a policy trapped in a PDF: to the agent, each is a blank cell. Whether agents can reach and afford to read that HTML at all is its own layer, covered in [manage AI crawlers, robots.txt and llms.txt](/ai-crawlers-robots-llms-txt/) and [serving agent traffic](/handbook/serving-agent-traffic/).
The rule that ties the substrate together: state each decision fact as text or markup, not only as a picture, and keep image `alt` describing the product honestly rather than repeating keywords. What an agent cannot read, it cannot use, however good the page looks.
## How an agent assembles the offer
Put the layers together and the mechanism is simple. The agent reads the page top to bottom, extracts each element it recognises, and assembles one comparable record. Every element you leave out of the text and markup is a cell it fills with a guess or leaves empty, and an empty cell is a reason to prefer a competitor whose row is complete.
> Illustrative example, not measured data.
Two sleep masks answer the same query. The agent tries to build one comparison row per store from each page:
| Axis | Store A (complete PDP) | Store B (gaps) |
| --- | --- | --- |
| Identity | "Weighted sleep mask" + GTIN | "The Luna", no identifier |
| All-in price | $24.99 + $4.99 ship, shown | $19.99, shipping hidden until checkout |
| Availability | In stock, ships in 1-2 days | Blank |
| Key specs | Weight, material, strap type | Marketing copy only |
| Review depth | 4.6 from 1,842, recent | "4.6 stars", no count |
Store B is cheaper on the list price, but the agent cannot fill three of its five cells from the page, so it cannot confirm the total cost, that the item ships, or how deep the reviews run. The completed row is the one it can recommend with confidence.
We read the whole-page evidence to mean the least-legible element caps how well you place: the offer is only as comparable as its weakest-filled axis, because the agent has to reason about the row as a whole and one blank cell is enough to move it to a safer pick. That is why a complete PDP beats a marginally cheaper incomplete one, and why the elements above are worth treating as a set rather than a punch list.
## What to measure
Do not eyeball this; build the row the agent builds. Take one product page and, with JavaScript disabled or from view-source, try to fill a five-column comparison table by hand: identity (title plus a GTIN), the all-in price to a real destination, availability and a delivery estimate, the top five specs your category's leaders expose, and the review count with a recency signal. Every cell you cannot fill from the raw HTML and structured data alone is an axis an agent cannot compare you on either. Count the blanks, close them, and re-run the check after any template change.
Then confirm it moves the outcome that matters. Run the manual [agent win-rate protocol](/research/methodology/) across ChatGPT, Gemini, and Perplexity before and after you complete the row, log a win or no-win per engine, and keep the definition fixed so results stay comparable over time. Real measured numbers stay in a "data collection in progress" state on this site until the experiments produce them; your own win rate is the honest test of whether a more complete page earned more selections.
## Frequently asked questions
### Does an AI agent read my product page, or only my feed?
Both, and they can disagree. An agent reads the structured data and text on your live page as well as any feed you submit. When the two conflict, we expect the agent to trust the on-page machine-readable layer, which is why the page has to carry the whole offer, not lean on the feed to fill gaps.
### What is the difference between an eligible product page and a comparable one?
Eligible means the page passes validation and can appear at all. Comparable means an agent can extract every axis it lines competitors up on (identity, all-in price, availability, key specs, review depth) from the page itself. A page can be fully eligible and still lose because one of those axes is blank.