Technical SEO · E-commerce

Anatomy of a Perfectly Optimised PDP

Every element of a high-performing product page — what Google reads, what LLMs parse, and where most sites break.

Product detail pages are the primary battleground in ecommerce SEO. Google treats them as standalone ranking opportunities. LLM agents prefer them to category pages. Users need them to answer "should I buy this?"

Most PDPs fail to do all three simultaneously. They optimise for human visitors, miss critical schema signals for Google, and leave product data too thin or inconsistent for LLMs to parse reliably.

This page breaks down every element — front-end to technical layer — and explains what each one does, what breaks when it's missing, and how it reads differently to Google versus an AI agent.

↓ Click any element to jump to that section

example-store.com/clothing/jackets/mens-merino-wool-jacket
HomeClothingJackets › Men's Merino Wool Jacket
9
🧥
🧥
🟩
🟫
3
Men's Merino Wool Jacket — Premium Weight Winter Outerwear
1
★★★★★ 4.8 342 reviews
7
$189 $249 24% off
✓ In stock — ships in 1–2 days
4
Short description
A mid-weight merino wool jacket for cold-weather commutes and weekend wear. Slim fit. Machine washable. Made in Portugal.
5
Size
XS
S
M
L
XL
Colour
Navy
Charcoal
Olive
8
Product Description
Full description
100% ZQ-certified merino wool at 280gsm — warm enough for winter commutes, light enough to layer under a shell. Moisture-wicking and temperature-regulating, so it handles both heated offices and cold platforms. Slim cut through the torso and shoulders, designed to sit cleanly over a shirt or light knit. Machine washable at 30°C. Does not pill with regular use.

Best paired with the Merino Rollneck as a mid-layer, or worn under the Waterproof Overshell on wet days. For a warmer option, see the Premium Cashmere Jacket.
5
Specifications
Material100% Merino Wool
Weight280gsm
FitSlim
CareMachine wash 30°C
OriginMade in Portugal
GTIN5012345678901
6
Customer Reviews
4.8
5★
4★
3★
7
Complete the look
10
Structured Data (JSON-LD)
@type: Product · ProductGroup · MerchantListing
offers.price: 189.00 · availability: InStock
aggregateRating.ratingValue: 4.8 · reviewCount: 342
11
GMC Feed Sync
price: 189.00 ✓ · availability: in_stock ✓ · gtin: 5012345678901 ✓ · description: ↻ pending
12
SERP — Page Title Tag
Men's Merino Wool Jacket | Winter Outerwear | Brand
2
Title tag + Meta
<title>Men's Merino Wool Jacket | Winter Outerwear | Brand</title>
<meta name="description" content="Premium 280gsm merino wool jacket for cold-weather commuting
and layering. Slim fit, machine washable, made in Portugal. Free shipping."/>
<link rel="canonical" href="https://example-store.com/clothing/jackets/mens-merino-wool-jacket"/>
2
Breadcrumb HTML
<nav aria-label="breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/clothing/">Clothing</a></li>
    <li><a href="/clothing/jackets/">Jackets</a></li>
    <li aria-current="page">Men's Merino Wool Jacket</li>
  </ol>
</nav>
9
H1 + Price (must be real HTML — not JS-rendered)
<h1>Men's Merino Wool Jacket — Premium Weight Winter Outerwear</h1>

<span class="price">$189.00</span>
<span class="availability">In stock — ships in 1–2 days</span>

// ⚠ Price MUST be in server-rendered HTML — not JS-injected.
1
Short description + Full description
<!-- Short description: above the fold, 1–2 sentences, scannable -->
<p class="product-short-desc">
  A mid-weight merino wool jacket for cold-weather commutes and weekend wear.
  Slim fit. Machine washable. Made in Portugal.
</p>

<!-- Full description: use case, material, pairing, differentiation -->
<div class="product-description">
  <p>100% ZQ-certified merino wool at 280gsm — warm enough for winter commutes,
  light enough to layer under a shell...</p>
  <ul>
    <li>Moisture-wicking, temperature-regulating</li>
    <li>Machine wash 30°C, does not pill</li>
    <li>Slim cut, designed to layer over a shirt</li>
  </ul>
  <!-- Named internal links — product relationship signal for LLMs -->
  <p>Pairs well with the <a href="/products/merino-rollneck">Merino Rollneck</a>
  or under the <a href="/products/waterproof-overshell">Waterproof Overshell</a>.</p>
</div>

// ⚠ On Shopify: avoid H2/H3 tags inside the description field —
// they can cause duplicate heading structure depending on your theme.
5
Image markup + alt text
<img
  src="mens-merino-wool-jacket-navy-front.jpg"
  alt="Men's navy merino wool jacket, slim fit, front view, white background"
  width="800"
  height="1000"
  loading="eager"
/>

// Hero image: white background, straight-on, no props
// Required for Google Shopping + virtual try-on eligibility
// File name: attribute-colour-angle.jpg — not IMG_4823.jpg
3
Rating HTML (must match schema)
<div class="aggregate-rating">
  <span class="rating-value">4.8</span>
  <span class="rating-count">342 reviews</span>
</div>

// ⚠ If schema says ratingValue: 4.8 but this number doesn't
// appear in rendered HTML, Google treats it as hidden markup.
// Rich results will be suppressed.
7
JSON-LD — Product + ProductGroup + MerchantListing
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "ProductGroup",
  "name": "Men's Merino Wool Jacket",
  "description": "Mid-weight merino wool jacket for cold-weather commutes...",
  "brand": { "@type": "Brand", "name": "Brand" },
  "variesBy": ["https://schema.org/color", "https://schema.org/size"],
  "hasVariant": [{
    "@type": ["Product", "MerchantListing"],
    "name": "Men's Merino Wool Jacket — Navy, M",
    "sku": "MWJ-NAV-M",
    "gtin13": "5012345678901",
    "color": "Navy",
    "size": "M",
    "image": "https://example-store.com/img/mens-merino-wool-jacket-navy-front.jpg",
    "offers": {
      "@type": "Offer",
      "price": "189.00",
      "priceCurrency": "USD",
      "priceValidUntil": "2026-06-30",
      "availability": "https://schema.org/InStock",
      "hasMerchantReturnPolicy": { "@type": "MerchantReturnPolicy", "applicableCountry": "US", "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow", "merchantReturnDays": 30 },
      "shippingDetails": { "@type": "OfferShippingDetails", "shippingRate": { "@type": "MonetaryAmount", "value": "0", "currency": "USD" }, "deliveryTime": { "@type": "ShippingDeliveryTime", "businessDays": { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"] }, "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" }, "transitTime": { "@type": "QuantitativeValue", "minValue": 1, "maxValue": 2, "unitCode": "DAY" } } }
    },
    "aggregateRating": {
      "@type": "AggregateRating",
      "ratingValue": "4.8",
      "reviewCount": "342"
    }
  }]
}
</script>
11
GMC Feed (key fields — must match page exactly)
id:                   MWJ-NAV-M
title:                 Men's Merino Wool Jacket Navy - Size M
description:          Mid-weight merino wool jacket for cold-weather commuting...
link:                  https://example-store.com/clothing/jackets/mens-merino-wool-jacket
image_link:           https://example-store.com/img/mens-merino-wool-jacket-navy-front.jpg
price:                 189.00 USD          ← must match page price exactly
sale_price:           189.00 USD
availability:         in_stock             ← must match schema availability
brand:                 Brand
gtin:                  5012345678901        ← prefer GTIN over SKU-only
item_group_id:        MWJ                  ← links all variants to parent product
color:                 Navy
size:                  M
google_product_category: Apparel & Accessories > Clothing > Outerwear
12
The breakdown

Each element explained — what it signals, what breaks when it's missing, and how Google and LLMs read it differently.

01
Product Title / H1
The most important on-page signal
What it does

The H1 is the first thing Google and LLMs evaluate when deciding what a page is about. It sets the primary topic, anchors semantic relevance across the whole page, and determines whether your product is a candidate for a given query before any other element is considered.

Best practice

Structure: primary attribute + product type + key differentiator. Lead with what users search for, not what the brand calls it internally.

  • Include material, audience, or use case where it's a search signal: "Men's Merino Wool Jacket" beats "The Ridgefield Jacket"
  • Don't repeat the exact same string as the title tag — they should complement each other, not duplicate
  • One H1 per page, in server-rendered HTML — never injected via JS after load
  • Keep it under ~70 characters so it renders cleanly in most SERP formats when Google uses it as the title
Google vs. LLMs

Google uses the H1 as a primary topical signal and cross-references it against the title tag. Significant mismatch between H1 and title tag can cause Google to rewrite your SERP title.

LLMs treat the H1 as the most authoritative label for the product. A query like "warm jacket for layering under a shell" will match "Men's Merino Wool Jacket — Premium Weight Winter Outerwear" far more reliably than "The Ridgefield" or "Style #MW-0042".

Common failure
Using the manufacturer's internal model code or a branded product name with no descriptive context. "The Ridgefield" or "Style 2042-B" is invisible to both Google and LLMs for any non-branded query.
02
Page Title Tag
What Google shows in search results
What it does

The <title> tag is the clickable blue link in SERPs. It's a direct ranking signal, a primary driver of click-through rate, and the text Google uses when it can't determine a better label from your H1 or page content. Google may rewrite it — but giving it a clean, well-structured title reduces rewrites significantly.

Best practice
  • Keep under 60 characters — beyond that, mobile SERPs truncate with an ellipsis
  • Front-load the primary keyword: product type and key attribute first, brand last
  • Format: Primary keyword | Secondary descriptor | Brand
  • Don't use your brand as the first word unless users are specifically searching for you by name
  • Avoid filler words: "Shop", "Buy", "Best", "Amazing" add nothing and waste characters

Example: Men's Merino Wool Jacket | Winter Outerwear | Brand outperforms Brand | Shop Premium Men's Jackets Online for every non-branded query.

Google vs. LLMs

Google uses the title tag as a direct ranking signal and displays it in SERPs. It also cross-checks it against H1 and body content — if they conflict significantly, Google rewrites the title using its own judgment.

LLMs don't parse title tags the way Google does, but pages with well-structured, keyword-relevant titles tend to rank better and therefore appear more often in training data and retrieval contexts.

On Shopify: By default, Shopify constructs title tags as "Product Name — Store Name". This puts the brand first and often leaves little room for descriptive keywords. You can override this in theme Liquid (product.title | append: ' | ' | append: shop.name) or via a third-party SEO app. The default template is rarely optimal for non-branded product searches.

Common failure
Brand-first title tags across an entire catalogue — a single theme setting that costs every product page its best keyword position. On Shopify this is the default and most stores never change it.
03
Product Images & Alt Text
File names, backgrounds, angles, virtual try-on
What it does

Product images are crawlable content with multiple ranking surfaces: Google Image Search, Google Shopping panels, and Google's virtual try-on feature. The file name, alt text, and image format all carry signals. LLMs use alt text as the primary mechanism for "reading" a product's visual characteristics.

Best practice

Background and format:

  • Hero image: white or light-grey background — required for Google Shopping eligibility and Google's virtual try-on feature
  • Virtual try-on additionally requires: straight-on front-facing shot, model or no-model (both accepted), no busy backgrounds, no text overlays
  • WebP format preferred for page speed; provide width/height attributes to prevent layout shift

Multiple angles:

  • Front view (hero — white bg)
  • Back view
  • Close-up of material/detail
  • Lifestyle shot (worn in context)
  • Scale reference where relevant (furniture, accessories)

File naming: mens-merino-wool-jacket-navy-front.jpg — not IMG_4823.jpg. Attribute first, colour second, angle third.

Alt text: Describe what's literally in the image. "Men's navy merino wool jacket, slim fit, front view" — not keyword lists, not empty, not "product image".

On Shopify: Shopify generates image URLs with a CDN hash, so file names are preserved in the URL path — name files correctly before uploading. Alt text is set per-image in the media editor, or via the Storefront API / bulk CSV. It does not inherit from the product title automatically.

Google vs. LLMs

Google uses images for Image Search ranking, Shopping product carousels, and virtual try-on. Image quality and background compliance directly affects Shopping feed approval.

LLMs cannot "see" images but read alt text and file names as proxies for visual content. Material type, colour, and fit language in alt text feeds directly into AI shopping agent recommendations when a user asks "what's a good warm navy jacket?"

Common failure
Empty alt text ("") or generic alt text ("product image") on all images, combined with auto-generated file names from the camera roll. Google's image crawler gets nothing. LLMs have no visual context to work with.
04
Price & Availability
Page, schema, and feed must be identical
What it does

Price and availability are the most time-sensitive signals on any PDP and the most common source of Shopping disapprovals. They feed Shopping ads, free listings, and LLM agent recommendations — all of which depend on exact, real-time accuracy across three sources simultaneously: the visible page, the schema markup, and the GMC feed.

Best practice

On-page:

  • Price must be in server-rendered HTML — not injected by JavaScript after load. Google's crawler may not execute JS that renders pricing.
  • Display price prominently above the fold, in plain text with the currency symbol
  • Stock status must also be human-readable HTML: "In stock", "Only 3 left", "Out of stock"

In schema:

  • Use offers.price, offers.priceCurrency, offers.availability
  • For sale pricing, set offers.priceValidUntil — without it, when the sale ends, Google may flag a price mismatch
  • Availability values: use full schema.org URIs — https://schema.org/InStock, not just "InStock"

In GMC feed:

  • Price must match the page exactly, including currency format: 189.00 USD
  • Use sale_price alongside price for promotional pricing — don't just lower the price field
  • Availability values: in_stock, out_of_stock, preorder — match what's on the page

On Shopify: Shopify's default theme and product JSON includes price in the page HTML, but uses JavaScript to update prices when variants are selected. The base price renders server-side; variant-specific prices may be JS-driven. If you're using a headless or heavily customised theme, verify with Google's Mobile-Friendly Test or a server-side render check that prices appear in the raw HTML.

Google vs. LLMs

Google cross-checks page price, schema price, and feed price. Any conflict — even a currency formatting difference — can trigger a Shopping disapproval. It also checks price against competitor pages to detect unrealistic pricing claims.

LLMs (ChatGPT Shopping, Perplexity, Google's AI Mode) draw product data from feeds and indexed pages. A stale feed means AI agents surface the wrong price to users in an active buying moment — potentially sending them to a competitor when they see the correct price on your page.

Common failure
Running a flash sale by lowering the page price and schema without updating the GMC feed. Google sees the discrepancy within hours and disapproves the listing. The sale runs, but Shopping visibility drops to zero for its entire duration.
05
Product Description
Who it's for, what it does, why it's different
What it does

The product description is the primary body content Google indexes for long-tail query matching and the main signal LLMs use to understand use case, fit, and audience. Most descriptions fail because they're either copied from manufacturers (duplicate content) or written as keyword lists (unreadable to humans and machines alike).

Best practice

Write to answer five questions a buyer actually has:

  • What is it made of? Material, construction, origin — specific, not vague ("100% ZQ-certified merino wool, 280gsm", not "premium fabric")
  • Who is it for? Use case and audience — "for cold-weather commuting and weekend wear", not "for everyone"
  • What does it do? Functional benefits — "moisture-wicking, temperature-regulating, machine washable"
  • What does it pair with? Named product links — "pairs well with the Merino Rollneck or the Waterproof Overshell" — this is both useful UX and a product-relationship signal for LLMs
  • What makes it different? The one thing your competitors' descriptions don't say

Format matters: a short opening paragraph (2–3 sentences) followed by a bulleted feature list performs better for both readability and LLM parsing than a wall of prose.

On Shopify: The description field accepts rich HTML. Use the native editor or Liquid to structure it properly — opening paragraph, then a <ul> for features. Avoid using heading tags (H2/H3) inside the description field; they can create duplicate heading structure issues depending on your theme.

Google vs. LLMs

Google uses description content for topical relevance and long-tail query matching. Unique, specific descriptions improve the chance of ranking for queries like "merino wool jacket machine washable slim fit" — queries that generic descriptions can't match.

LLMs use the description as the primary source for intent matching. A query like "warm jacket I can layer under a shell and also machine wash" will match a rich description and fail to match a generic one. The more specific the language about use cases, the better LLM agents can recommend your product for real-world queries.

Common failure
Manufacturer descriptions used verbatim across all retailer sites. Google identifies duplicate content across domains and doesn't reward it. More importantly, identical descriptions give LLMs no reason to prefer your product page over a competitor's — you're just one of many copies.
06
Product Specifications
Structured attributes machines can parse reliably
What it does

Structured specifications are the machine-readable layer of product data. Where the description answers "what is it for", specs answer "exactly what is it". They map directly to schema.org Product properties, GMC feed attributes, and LLM comparison queries — and they only work when they're consistent across a catalogue.

Best practice

Format:

  • Use a table or definition list (<dl>/<dt>/<dd>) — not specs buried in prose
  • Label names must be consistent across the entire catalogue — "Material" everywhere, not "Fabric" on some, "Composition" on others, "Made from" on a third
  • Values should be precise and unambiguous: "280gsm" not "medium weight", "machine wash 30°C" not "easy care"

Key fields to include (where applicable):

  • Material / composition
  • Weight / dimensions
  • Fit / sizing notes (e.g. "runs true to size", "slim through torso")
  • Care instructions
  • Country of manufacture
  • GTIN / barcode — include this visibly on the page where possible; it strengthens feed and schema alignment

On Shopify: Product metafields are the correct place for structured specs. Use Shopify's native metafield definitions (available in the admin since 2022) to create typed metafields (e.g. single_line_text_field, number_decimal) and surface them in your theme via product.metafields. This keeps spec data structured and reusable across feeds, apps, and schema generation — far better than putting everything in the description body.

Google vs. LLMs

Google extracts structured product attributes from spec tables and maps them to schema.org properties. Consistent structured data across a catalogue improves eligibility for product-specific rich results.

LLMs use spec data to answer comparative queries: "which jacket is warmest?", "is this machine washable?", "what's the weight of this fabric?" — queries that require structured, numeric, or categorical data. A prose description cannot answer these reliably. A spec table can.

Common failure
Inconsistent attribute naming across a product catalogue — a natural consequence of content being added by multiple people over years without a controlled vocabulary. LLMs cannot reliably compare "Fabric: merino wool" against "Material: 100% wool" to determine they're the same thing.
07
Reviews & Ratings
Star snippets, trust signals, LLM sentiment data
What it does

Ratings and reviews serve three jobs simultaneously: social proof for users deciding whether to buy, structured quality signals for Google's Shopping and SERP ranking systems, and real-world sentiment data for LLMs building product recommendations. The aggregate rating drives star snippets in SERPs. Individual review text teaches LLMs what this product is actually like to own.

Best practice
  • Display the aggregate rating in server-rendered HTML above the fold — the number must be visible in the raw page source, not injected by JavaScript
  • Mark up with AggregateRating schema: ratingValue and reviewCount are required. The value in schema must match the value on the page — not a rounded version, not a different scale
  • Include at least a few individual review bodies in server-rendered HTML. Review apps that load entirely via JavaScript (AJAX after DOM ready) may not be crawled by Google
  • Individual reviews should use Review schema with author, reviewRating, and reviewBody

On Shopify: Shopify's native Product Reviews app (now deprecated in favour of native review metafields in some themes) and most third-party review apps (Judge.me, Yotpo, Okendo, Stamped) render reviews via JavaScript by default. Check whether your reviews are in the server-rendered HTML using "View Page Source" — not Inspect, which shows the rendered DOM. If reviews only appear in the rendered DOM, Google may not consistently crawl them.

Google vs. LLMs

Google shows star ratings in SERPs when AggregateRating schema is present and valid, the rating value appears on the page, and the page isn't on a blocked category (Google restricts star snippets on certain product types). Stars in SERPs typically improve CTR by 15–20% on product pages.

LLMs use review text to understand product nuance that specs and descriptions don't capture: "runs small — size up", "warm but not bulky, good for layering", "the zip sticks after six months". This context feeds directly into LLM shopping recommendations for users asking "what do people say about this jacket?"

Common failure
Marking up a rating in schema that isn't visible on the rendered page. If your schema says 4.8, the number 4.8 must appear in the HTML. Google treats hidden markup as manipulative and will suppress rich results for that page — and potentially others on the same domain.
08
Variants (Size, Colour)
ProductGroup schema + canonical strategy
What it does

Product variants — size, colour, material — multiply your URL count and create one of the most common crawl budget problems in ecommerce. Without a clear strategy, you're asking Google to crawl thousands of near-duplicate pages that dilute crawl budget, split authority, and generate thin-content signals across the catalogue.

Best practice

Schema strategy:

  • Use ProductGroup schema at the parent level to declare that all size/colour variants belong to the same product
  • Set variesBy to declare what changes: https://schema.org/color, https://schema.org/size
  • Each variant inside hasVariant should be a Product (or Product + MerchantListing) with its own GTIN, image, and offer

URL + canonical strategy:

  • Canonical all variant URLs (?colour=navy&size=M) to the base product URL
  • If colour variants have meaningfully different content (different images, different descriptions), consider separate indexed pages — but still link them via ProductGroup schema
  • Never let faceted navigation or filter parameters generate thousands of indexable variant URLs without canonicals

GMC feed: Each variant is a separate row with a unique GTIN or SKU, its own image URL, and the correct colour/size values. Link all variants to the parent product with item_group_id.

On Shopify: Shopify generates variant URLs as /products/jacket?variant=12345. By default, Shopify sets a self-referencing canonical on each variant URL — meaning each variant page is treated as indexable. This is a known crawl budget concern for large catalogues. You can override canonicals in your theme Liquid to point all variants to the base product URL (product.url), but test carefully as it may affect Shopping feed performance.

Google vs. LLMs

Google crawls every variant URL it discovers. A catalogue of 500 products in 8 colours and 6 sizes = 24,000 crawlable pages, most of them near-duplicate. This consumes crawl budget that could be spent on new or updated pages.

LLMs need ProductGroup schema to understand that "navy, size M" and "charcoal, size L" are the same jacket — not two different products. Without it, they may treat them independently and fail to answer queries like "does this come in olive?"

Common failure
Indexing colour variant pages without ProductGroup schema and without canonicals. Each colour ranks for slightly different queries but splits link equity. LLMs see fragmented product data instead of a coherent product with options.
09
Breadcrumb Navigation
Hierarchy signal + BreadcrumbList schema
What it does

Breadcrumbs tell Google and LLMs where a product sits in the site hierarchy. Google shows the breadcrumb path below your SERP title in search results — a clean, logical path signals good site architecture and makes your result look more trustworthy. A truncated or broken breadcrumb path in SERPs is often the first sign of structural problems.

Best practice
  • Include breadcrumbs in both visible HTML and BreadcrumbList schema — both matter
  • Logical depth: Home › Category › Subcategory › Product — don't flatten to Home › Product
  • Each item in the breadcrumb should be an anchor link to that category level — not just text
  • BreadcrumbList schema: use ListItem with position, name, and item (URL) for each level
  • The final breadcrumb item (current page) doesn't need a URL in schema, but must have a name

On Shopify: Shopify themes typically generate breadcrumbs automatically via the collections object — but the path shown depends on how the user navigated to the page, not a canonical category assignment. A product in multiple collections may show different breadcrumbs to different users, which can cause inconsistent BreadcrumbList schema. To fix this, either assign a primary collection and generate breadcrumbs from that, or hardcode the canonical category path in your schema.

Google vs. LLMs

Google displays the BreadcrumbList in SERPs directly below the title and uses it as a structural signal for site architecture. It prefers the schema-defined path over the navigation-rendered path when they conflict.

LLMs use the breadcrumb path to understand category hierarchy — classifying "this is a jacket, in men's outerwear, under clothing" without relying on the product title alone. This is particularly useful for ambiguous product names.

Common failure
BreadcrumbList schema that doesn't match the visible breadcrumb HTML. Google resolves the conflict in its own favour — usually suppressing the SERP breadcrumb entirely. On Shopify, this happens frequently when a product is in multiple collections and schema is generated dynamically from the referrer.
10
Internal Linking
Basket value, crawlability, product relationship graph
What it does

Internal links on a PDP serve three simultaneous purposes: keeping products in Google's crawl graph and distributing PageRank, increasing average order value through deliberate upgrade and pairing paths, and teaching LLMs which products are related, complementary, or interchangeable across your catalogue.

Best practice

Think in three link types — each has a different purpose:

  • Pair it with — complementary products that sell well together and share semantic context. "Pairs well with the Merino Rollneck" creates a product relationship signal for LLMs.
  • Upgrade — a higher-margin or premium version of this product. "Upgrade to the Premium Cashmere Jacket" is an explicit AOV signal and a product hierarchy signal.
  • Category link — a link back up to the parent category ("All Men's Jackets"). Keeps the product in the crawl graph and reinforces hierarchy.

Anchor text matters: "Waterproof Overshell" tells Google and LLMs what the linked product is. "See similar" tells them nothing. Descriptive anchors are the mechanism by which LLMs build your product relationship map.

On Shopify: The "Related products" and "You might also like" sections in most Shopify themes are generated algorithmically based on tags or collection membership. They often have generic anchor text and no editorial logic. Replace or supplement these with manually curated link sections — especially for high-value products — even if it means a metafield-driven template override.

Google vs. LLMs

Google uses internal links to determine crawl priority and PageRank flow within a catalogue. PDPs with no internal links pointing to them — orphaned pages — lose PageRank and may be crawled infrequently. Internal links from PDPs to related PDPs also create topical clusters.

LLMs use anchor text and link patterns to understand which products are related, which are substitutes, and which are upgrades — directly informing multi-product recommendations. A catalogue where every PDP links meaningfully to 2–3 related products creates a far richer product graph than one relying on generic "you might also like" carousels.

Common failure
Algorithmic "related products" with no editorial intent, generic anchor text, and no upgrade path. The section exists but does nothing for SEO, nothing for LLM product graph, and only weakly contributes to AOV. It's a placeholder that looks complete but isn't.
11
Product Schema (JSON-LD)
Three types, distinct purposes — pick the right one
What it does

Schema markup is the machine-readable layer that makes your product data legible to Google and LLMs. Without it, Google treats a product page as a generic webpage — no rich results, no Shopping eligibility. LLMs see unstructured HTML instead of typed product properties. Schema is not optional for competitive ecommerce SEO in 2026.

Best practice

The three Product schema types:

  • Product — base type. Use for simple, single-variant products. Minimum required fields for Google Rich Results: name, image, description, offers (price, priceCurrency, availability), aggregateRating.
  • MerchantListing — an extension of Product that adds seller-specific signals. Required fields for Google's free Shopping listings: shippingDetails (rate + delivery time) and hasMerchantReturnPolicy. Without these, your product may not qualify for free Shopping surfaces.
  • ProductGroup — parent type for variant products. Declares that multiple Product nodes (colours, sizes) are variants of the same item. Required properties: variesBy (what changes), hasVariant (array of Product nodes). Each child variant should have its own GTIN, image, and offer.

Key rules:

  • All schema values must match the visible page content — price in schema must equal price on the page
  • Use full schema.org URIs for enum values: https://schema.org/InStock, not just "InStock"
  • Place JSON-LD in <script type="application/ld+json"> in the <head> or body — both are valid, head is preferred
  • Use Google's Rich Results Test to validate structure, then manually verify data accuracy

On Shopify: Shopify themes generate Product schema automatically from product data, but the default output is usually incomplete — it often omits shippingDetails and hasMerchantReturnPolicy (required for MerchantListing), and doesn't output ProductGroup for variants. To get complete schema, you need to either modify the theme Liquid directly or use a dedicated schema app. Always check what your theme actually outputs with Rich Results Test before assuming it's correct.

Google vs. LLMs

Google uses schema to power Rich Results (star snippets, price in SERPs, availability badges) and Shopping eligibility. The Rich Results Test validates structure, but semantic correctness — correct prices, valid GTINs, matching availability — is what Google checks at crawl time. Structural validity is the floor, not the ceiling.

LLMs treat structured data as the highest-confidence source for product attributes — more reliable than prose descriptions. When schema and body copy conflict, LLMs typically defer to schema. This makes schema accuracy critical: stale or wrong schema directly corrupts LLM product recommendations.

Common failure
Passing the Rich Results Test and assuming schema is correct. The test validates JSON structure only — it doesn't check whether your price matches the page, whether your GTIN is real, or whether your availability value is current. Those are the checks that matter for Shopping and LLM accuracy.
12
Feed Alignment (GMC)
Page ↔ schema ↔ feed — all three must be consistent
What it does

Your product page doesn't exist in isolation. Google cross-references your PDP, its structured data, and your GMC feed against each other as part of Shopping eligibility checks. A clean page and valid schema can still trigger a disapproval if the feed data conflicts with either. The feed is also what LLM shopping agents query directly — it's your product data as seen by AI.

Best practice

Fields that must match exactly (page = schema = feed):

  • Price — including currency format: 189.00 USD, not $189 or 189
  • Availability — feed value in_stock must match schema https://schema.org/InStock and the text on the page
  • Main image URL — the feed image must be the same URL as the primary product image (or a direct equivalent)
  • GTIN — if present on the page or in schema, include it in the feed

Fields that should be consistent (can differ in format, not substance):

  • Title — feed title can be shorter, but must describe the same product
  • Description — feed allows up to 5,000 characters; keep it aligned with page copy, not a different version

GTINs vs. SKUs: Google strongly prefers GTINs (UPC, EAN, ISBN, JAN) over retailer-assigned SKUs. Products without GTINs may have reduced visibility in free Shopping listings and Shopping ads. If your manufacturer provides GTINs, use them — don't replace them with internal SKUs.

On Shopify: The Google & YouTube Shopify app (formerly Google channel) syncs your product catalogue to Google Merchant Centre automatically, pulling data from product fields and metafields. By default it maps product title, description, price, and images. GTINs must be stored in the Barcode field (found in the variant editor) or a dedicated metafield — they don't sync automatically from custom product fields. Set up feed rules in GMC to transform or supplement data where Shopify's default output isn't sufficient.

Google vs. LLMs

Google checks page, schema, and feed for consistency on every crawl cycle. Mismatches trigger disapprovals. Common triggers: price changed on the website without a feed update, out-of-stock status not reflected in the feed, or a promotional price that expired but the feed still shows the sale price.

LLMs — ChatGPT Shopping, Perplexity, and Google's AI Mode — query product data primarily from feeds and indexed pages, not from real-time page scraping. A stale feed means users asking "what's the price of this jacket?" get the wrong answer from an AI that's confidently wrong. Keeping the feed in sync is how you stay accurately represented in AI-powered shopping surfaces.

Common failure
Using retailer-assigned SKUs as the only product identifier in the feed, with no GTINs. Google accepts this but treats these products as lower-confidence matches for Shopping queries. Compounding this with a feed sync frequency of 24+ hours means any price or stock change leaves a window where the feed is wrong — and that window is when Google is most likely to check.