SEO Guide · 2026
E-commerce checkout structured data: what AI agents see before and after purchase (2026)
The cart and checkout are the most misunderstood pages in e-commerce structured data. Merchants add Product schema to cart pages thinking it helps — it doesn't, it causes validation errors. The real post-purchase opportunity is Order schema on confirmation pages, where AI agents like ChatGPT can use it for order tracking answers. Here's the complete picture for Shopify merchants.
Order schema with nested OrderItem objects lets AI agents (and Google's receipt-parsing system) read order details for tracking intents. Shopify Plus merchants can inject this into checkout.liquid or the thank-you page extension; non-Plus merchants must add it to the /orders/{token} customer account template instead.
The structured data landscape around checkout
The checkout funnel for a Shopify store consists of four distinct page types, each with different structured data rules, different AI agent touchpoints, and different technical constraints for implementation. Understanding what's valid — and what's explicitly harmful — at each stage is essential before adding any JSON-LD.
| Page type | Shopify URL pattern | Valid schema types | Explicitly excluded | AI agent touches this? |
|---|---|---|---|---|
| Cart page | /cart |
None — no structured data | Product, ItemList, BreadcrumbList (technically valid HTML but provides no value; Google doesn't crawl session-specific carts) | No — session-locked, no public crawl |
| Checkout steps | /checkouts/{token} |
BreadcrumbList (Plus only via checkout.liquid) | Product, Order, FAQPage — these pages are session-gated and not publicly crawlable | No — requires authentication; not indexed |
| Order confirmation | /thank-you (Plus) or thank-you step in checkout |
Order, OrderItem, BreadcrumbList |
Product standalone, ItemList, FAQPage | Partial — Google reads receipts; ChatGPT with email access |
| Account order page | /account/orders/{order_id} |
Order, OrderItem, BreadcrumbList |
Product standalone (wrong context) | Yes — publicly crawlable if logged in with correct session; Google indexes order status pages |
Why you should NOT add Product schema to cart pages
This is the most common checkout structured data mistake. Merchants add Product JSON-LD to the cart page (/cart) intending to reinforce product data for Google. The result is the opposite of helpful — it causes three specific problems:
Problem 1: Duplicate conflicting signals. Your product page at /products/cloudstrike-pro already outputs Product schema with canonical: https://yourstore.com/products/cloudstrike-pro. If the cart page also outputs Product schema for the same product, Google sees two different URLs claiming to be the authoritative source for the same product's structured data. This creates a duplicate signal conflict that can suppress both pages' rich result eligibility.
Problem 2: Session-specific content on a crawlable URL. /cart is a publicly accessible URL. Googlebot crawls it. What it finds there depends entirely on which session's cart is cached or what an empty cart shows. If Googlebot visits /cart and finds Product schema for items from a previous crawl session, then visits again and finds an empty cart with no schema, the structured data becomes inconsistent and unreliable — Google's quality systems treat inconsistent structured data as a spam signal.
Problem 3: Rich Results Test validation errors. Product schema requires Offer with a current price, availability, and URL. On a cart page, the product URL in the schema correctly points to /products/cloudstrike-pro, but the page URL is /cart. The Rich Results Test flags this as a mismatch — the schema URL doesn't match the page URL, which is a validation error for Product rich results.
Product or ItemList JSON-LD block. The cart page's structured data should be empty. If your theme or an app is injecting Product schema on the cart page, remove it.
Pre/post-purchase AI agent touchpoints
| Journey stage | AI agent | What it reads | Merchant action |
|---|---|---|---|
| Pre-purchase research | ChatGPT Shopping, Google AI Mode, Perplexity | Product page JSON-LD (Product, Offer, AggregateRating, shippingDetails, returnPolicy) | Ensure complete Product schema on all product pages |
| Cart / checkout | None publicly | Session-gated; no AI agent crawls these pages | No action — leave without structured data |
| Order confirmation email | ChatGPT (Gmail integration), Google Assistant | Email body order details; Schema.org email markup (ConfirmationOrder); tracking links | Structure confirmation email with clear order #, item list, estimated delivery, and tracking link |
| Order confirmation page | Google (receipt page indexing) | Order JSON-LD with OrderItem details, order number, total, merchant identity | Add Order schema to confirmation page via checkout.liquid (Plus) or post-purchase extension |
| Order status / account page | Google AI Mode (order tracking queries) | Order JSON-LD with current orderStatus, tracking URL, estimated delivery | Add Order schema with dynamic orderStatus to customer account order pages |
| Delivery / receipt | ChatGPT (email access), Google (Gmail actions) | Shipping confirmation email; tracking number; delivery confirmation | Structure shipping emails with machine-readable tracking numbers and carrier names |
Order schema JSON-LD for confirmation pages
The Order schema type represents a purchase order. For an e-commerce order confirmation page, include the order number, order date, order status, the merchant as seller, the customer as customer (with care about PII), and each ordered item as an OrderItem. The orderStatus field should reflect the current status using the https://schema.org/OrderStatus value set.
<!-- Order confirmation page: Order JSON-LD (Shopify Plus: checkout.liquid or post-purchase extension) -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Order",
"orderNumber": "1058273",
"orderDate": "2026-06-02T14:37:00Z",
"orderStatus": "https://schema.org/OrderProcessing",
"confirmationNumber": "1058273",
"merchant": {
"@type": "Organization",
"name": "TrailForce Store",
"url": "https://trailforce.com",
"logo": "https://trailforce.com/assets/logo.svg"
},
"seller": {
"@type": "Organization",
"name": "TrailForce Store",
"url": "https://trailforce.com"
},
"url": "https://trailforce.com/account/orders/1058273",
"priceCurrency": "USD",
"price": "167.98",
"discount": "0.00",
"acceptedOffer": [
{
"@type": "Offer",
"itemOffered": {
"@type": "Product",
"name": "Cloudstrike Pro Women's Trail Running Shoe — Midnight Blue / US 8",
"sku": "TF-CLOUDSTRIKE-W-US8-MIDBLUE",
"url": "https://trailforce.com/products/cloudstrike-pro-women",
"image": "https://trailforce.com/cdn/shop/products/cloudstrike-pro-w-midnight-blue-front.jpg"
},
"price": "139.99",
"priceCurrency": "USD"
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Product",
"name": "TrailForce Performance Running Socks — 3-Pack",
"sku": "TF-SOCKS-3PK-M",
"url": "https://trailforce.com/products/performance-socks-3pack",
"image": "https://trailforce.com/cdn/shop/products/performance-socks-3pack.jpg"
},
"price": "27.99",
"priceCurrency": "USD"
}
],
"orderedItem": [
{
"@type": "OrderItem",
"orderItemNumber": "1",
"orderQuantity": 1,
"orderDelivery": {
"@type": "ParcelDelivery",
"expectedArrivalFrom": "2026-06-05",
"expectedArrivalUntil": "2026-06-07",
"hasDeliveryMethod": {
"@type": "DeliveryMethod",
"name": "Standard Shipping"
}
},
"orderedItem": {
"@type": "Product",
"name": "Cloudstrike Pro Women's Trail Running Shoe — Midnight Blue / US 8",
"sku": "TF-CLOUDSTRIKE-W-US8-MIDBLUE",
"url": "https://trailforce.com/products/cloudstrike-pro-women"
}
},
{
"@type": "OrderItem",
"orderItemNumber": "2",
"orderQuantity": 1,
"orderedItem": {
"@type": "Product",
"name": "TrailForce Performance Running Socks — 3-Pack",
"sku": "TF-SOCKS-3PK-M",
"url": "https://trailforce.com/products/performance-socks-3pack"
}
}
],
"paymentMethod": "https://schema.org/CreditCard",
"paymentMethodId": "Visa ending 4242",
"billingAddress": {
"@type": "PostalAddress",
"addressCountry": "US"
}
}
</script>
customer and billingAddress fields, but these should contain only the minimum necessary for machine-readable context (e.g. addressCountry) — not full PII that would be visible in the page source. Order status pages protected by customer account authentication can include more detail; public confirmation pages cannot.
Shopify Plus vs. non-Plus structured data options
| Capability | Shopify Plus | Shopify (non-Plus) |
|---|---|---|
| Customize checkout step pages | Yes — via checkout.liquid (being deprecated) or checkout extensibility | No — checkout is locked by Shopify |
| Add BreadcrumbList to checkout steps | Yes — via checkout.liquid or checkout UI extension script tag | No |
| Add Order schema to thank-you page | Yes — via checkout.liquid additional_checkout_scripts or Post-Purchase extension | Limited — via "Additional scripts" in Settings › Checkout (being removed) |
| Add Order schema to customer account order page | Yes — edit customers/order.liquid | Yes — edit customers/order.liquid |
| Checkout UI Extensions (post-purchase page) | Yes | No |
| Order status schema on account pages | Yes | Yes |
| Add script tags to checkout | Yes | No |
| Transactional email customization | Full HTML email editor | Full HTML email editor |
Implementing Order schema on the Shopify customer account order page
The customer account order page (/account/orders/{order_id}) is available on all Shopify plans. Unlike the checkout confirmation page, the account order page remains accessible to the customer after their session ends — and importantly, it's where customers return to check order status. Adding Order schema to this template benefits both non-Plus merchants and Plus merchants as a stable, non-session-gated location for order structured data.
Edit customers/order.liquid in your Shopify theme and add this Liquid-generated JSON-LD block:
{% comment %}
Order schema for customer account order page
File: customers/order.liquid
Works on: All Shopify plans
{% endcomment %}
{% assign order_url = shop.url | append: '/account/orders/' | append: order.id %}
{% comment %} Map Shopify order financial_status to schema.org OrderStatus {% endcomment %}
{% case order.financial_status %}
{% when 'pending' %}
{% assign schema_order_status = 'https://schema.org/OrderPaymentDue' %}
{% when 'authorized', 'partially_paid' %}
{% assign schema_order_status = 'https://schema.org/OrderProcessing' %}
{% when 'paid' %}
{% assign schema_order_status = 'https://schema.org/OrderProcessing' %}
{% when 'refunded', 'voided' %}
{% assign schema_order_status = 'https://schema.org/OrderCancelled' %}
{% else %}
{% assign schema_order_status = 'https://schema.org/OrderProcessing' %}
{% endcase %}
{% comment %} Override with fulfillment status if shipped {% endcomment %}
{% if order.fulfillment_status == 'fulfilled' %}
{% assign schema_order_status = 'https://schema.org/OrderDelivered' %}
{% elsif order.fulfillment_status == 'partial' %}
{% assign schema_order_status = 'https://schema.org/OrderInTransit' %}
{% endif %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Order",
"orderNumber": {{ order.name | json }},
"orderDate": {{ order.created_at | date: '%Y-%m-%dT%H:%M:%SZ' | json }},
"orderStatus": {{ schema_order_status | json }},
"confirmationNumber": {{ order.name | json }},
"url": {{ order_url | json }},
"priceCurrency": {{ order.currency | json }},
"price": "{{ order.total_price | money_without_currency }}",
"merchant": {
"@type": "Organization",
"name": {{ shop.name | json }},
"url": {{ shop.url | json }}
},
"seller": {
"@type": "Organization",
"name": {{ shop.name | json }},
"url": {{ shop.url | json }}
},
"orderedItem": [
{% for line_item in order.line_items %}
{
"@type": "OrderItem",
"orderItemNumber": "{{ forloop.index }}",
"orderQuantity": {{ line_item.quantity }},
"orderedItem": {
"@type": "Product",
"name": {{ line_item.title | json }},
"sku": {{ line_item.sku | json }},
"url": {{ shop.url | append: line_item.product.url | json }},
"image": "https:{{ line_item.product.featured_image | img_url: '400x' }}"
},
"orderItemStatus": {% if order.fulfillment_status == 'fulfilled' %}"https://schema.org/OrderDelivered"{% else %}"https://schema.org/OrderInTransit"{% endif %}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
{% if order.fulfillments.size > 0 %}
{% assign first_fulfillment = order.fulfillments | first %}
{% if first_fulfillment.tracking_number != blank %}
,"trackingUrl": "{{ first_fulfillment.tracking_url }}"
{% endif %}
{% endif %}
}
</script>
OrderStatus values and their meanings
| Schema.org OrderStatus | Shopify equivalent | When to use |
|---|---|---|
OrderPaymentDue |
financial_status: pending | Order placed but payment not yet captured (e.g. bank transfer, net-30) |
OrderProcessing |
financial_status: paid; fulfillment: unfulfilled | Payment received; order being picked, packed, and prepared for shipment |
OrderInTransit |
fulfillment_status: partial or in transit | At least one shipment dispatched; tracking available |
OrderDelivered |
fulfillment_status: fulfilled + delivery confirmed | All items delivered to customer |
OrderCancelled |
financial_status: refunded or voided; cancelled_at set | Order cancelled before or after shipment |
OrderProblem |
No direct Shopify equivalent; use for dispute/issue states | Delivery exception, damaged goods, or fulfillment failure |
OrderReturned |
financial_status: partially_refunded after fulfillment | Items returned and refund issued |
How AI agents use purchase confirmation data
ChatGPT with Gmail integration
ChatGPT Plus users can grant ChatGPT access to their Gmail inbox. When a customer asks "what did I order from TrailForce last week?", ChatGPT can search the Gmail inbox for order confirmation emails from TrailForce and parse the order details from the email body. Google's email platform also supports Schema.org markup in emails — if your transactional email includes OrderAction or ConfirmationOrder structured data, Gmail renders rich UI actions (view order, track shipment) directly in the email client. This is separate from web page structured data but uses the same schema.org vocabulary.
Google AI Mode for order tracking queries
Google's AI Mode can answer questions like "when will my order from [store] arrive?" by parsing order status pages indexed in Search Console or accessed via Google's receipt page indexing. When a user is signed into their Google account and performs this query, Google can match it to order confirmation emails in Gmail or to indexed order status pages on your website. Order schema on your customer account order page — with current orderStatus and trackingUrl — makes this matching more reliable and the AI Mode answer more accurate.
Post-purchase opportunity: OrderStatus on account pages
The customer account page is the highest-value post-purchase structured data location because it's persistent (unlike the one-time confirmation page) and publicly accessible to signed-in users (unlike the transient checkout). Updating the orderStatus field dynamically as the Shopify order fulfillment status changes means AI agents that index this page get current order status information — not just the initial "OrderProcessing" state from the confirmation email.
For Shopify stores, this dynamic update happens automatically if your customers/order.liquid template uses the Liquid order.fulfillment_status and order.financial_status variables to drive the schema orderStatus value, as shown in the Liquid snippet above. The page re-renders with the current status on every load — no additional webhook or job is needed.
BreadcrumbList on checkout pages (Shopify Plus)
Shopify Plus merchants can add BreadcrumbList to checkout step pages via checkout.liquid. While checkout pages are not indexed by Google (they require session cookies), BreadcrumbList on these pages benefits AI agents that access them via authenticated sessions — such as ChatGPT browsing a customer's checkout session with explicit permission, or automated order-tracking tools that use a customer's OAuth-connected Shopify account.
{% comment %}
checkout.liquid: BreadcrumbList for checkout steps (Shopify Plus only)
Output in the <head> of checkout.liquid
{% endcomment %}
{% assign step_position = 2 %}
{% case checkout.step %}
{% when 'contact_information' %}
{% assign step_name = 'Contact Information' %}
{% assign step_position = 2 %}
{% when 'shipping_method' %}
{% assign step_name = 'Shipping Method' %}
{% assign step_position = 3 %}
{% when 'payment_method' %}
{% assign step_name = 'Payment' %}
{% assign step_position = 4 %}
{% endcase %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": {{ shop.name | json }}, "item": {{ shop.url | json }} },
{ "@type": "ListItem", "position": {{ step_position }}, "name": {{ step_name | json }} }
]
}
</script>
Frequently asked questions
Should I add Product schema to my Shopify cart page?
No. Product schema on cart pages causes duplicate structured data conflicts (the product page is the canonical source), generates validation errors (schema URL doesn't match page URL), and serves inconsistent content to Googlebot (which sees different products or an empty cart on different crawls). Cart pages should have no JSON-LD structured data.
What structured data is valid on an order confirmation page?
Order schema with nested OrderItem objects is the appropriate type for order confirmation pages. Include the order number, order date, orderStatus, merchant identity, and each ordered item. BreadcrumbList is also valid on confirmation pages. Do not add standalone Product, FAQPage, or ItemList schema to confirmation pages.
Can ChatGPT access customers' order confirmation emails?
Yes, with explicit user permission. ChatGPT Plus users with Gmail integration can allow ChatGPT to search their inbox for order confirmations. Merchants who structure confirmation emails with clear, machine-readable order details (order number, items, estimated delivery, tracking link) provide a better ChatGPT order-tracking experience for their customers.
What structured data can Shopify Plus merchants add to checkout that non-Plus merchants cannot?
Shopify Plus merchants can add BreadcrumbList to checkout step pages and Order schema to the thank-you page via checkout.liquid or checkout UI extensions. Non-Plus merchants cannot modify checkout pages — their best option is adding Order schema to the customer account order page (/account/orders/{id}), which is available on all Shopify plans via the customers/order.liquid template.
Audit your checkout structured data
CatalogScan detects Product schema incorrectly placed on cart pages, missing Order schema on confirmation pages, and other post-purchase structured data gaps that affect your AI agent order-tracking visibility.
Scan your store free Read the blog