What an agent gets from a Shopify product page today
Most writing about Shopify AI agents starts with protocols and ends in speculation. The practical starting point is smaller: one HTTP response. Our reference capture asks what a shopping agent receives when it requests a single product page — a $148 daypack, three colorways — from a Shopify-style storefront fixture with the familiar anatomy of a theme-built PDP: theme CSS, a mega-menu, product JSON blobs, tracking snippets, a review widget, upsells, a cookie banner, a newsletter modal, and cart JS.
| Response | Bytes | Approx tokens |
|---|---|---|
| Before — the full PDP HTML | 91,226 | ~22,789 |
| After — gateway markdown, same request | 1,315 | ~328 |
| Reduction | 98.6% | 98.6% |
Position is the deeper problem. In the before-HTML, the first machine-readable price appears at character offset 23,185 — "price":14800, in cents, inside a product JSON blob. The human-readable $148.00 waits until offset 44,139. Availability is an unlabeled <span>; the backordered colorway is a CSS class. Shipping and returns sit inside collapsed <details> accordions, after ~18 reviews of widget markup. In the markdown response, price is on line 4, availability on line 5, and shipping and returns follow in the first screenful. Roughly 69x less context, and the facts get better, not worse.
Shopify agentic commerce: the protocol layer and the serving layer
Two different things hide under the term Shopify agentic commerce, and conflating them is how merchants end up waiting for the wrong one. The first is the protocol layer — the checkout rails. UCP — the Universal Commerce Protocol — arrived in January 2026, co-launched by Google and Shopify and backed by Etsy, Wayfair, Target, and Walmart. ACP, from OpenAI and Stripe, has been live since September 2025. MCP settled in as the data connectivity layer, and all three major card networks support agent-initiated payments. Shopify co-launching UCP means the platform your store runs on is a first party to this future, not a bystander.
The second is the serving layer: whether an agent can read your product page at all. It is more mundane and more urgent, because of a shift in how assistants behave — OpenAI moved from in-chat checkout toward discover in chat, transact on site. The assistant shortlists; the human lands on your storefront to buy. That is the model OpenAI moved ChatGPT shopping to in mid-2026 — the shape a Shopify ChatGPT shopping journey takes under it — and it makes the reading step decisive: an assistant that cannot cleanly extract your price and return policy recommends the store where it can.
- Conversion lift, AI-referred visitors vs search
- ~38%
- Cyber Week 2025 retail data
- Cyber Week 2025 sales growth with agent integration
- ~7x
- Cyber Week 2025 retail data
- Content negotiation vs llms.txt, accurate retrieval
- ~4.2x
- 300k-domain study, mid-2026
The ~4.2x line names the mechanism. Content negotiation — answering the Accept: text/markdown request header with clean text — measured ~4.2x more effective than llms.txt for accurate retrieval in the mid-2026 300k-domain study, and llms.txt alone showed no citation lift. The serving layer is the part you control this week, and on Shopify it has a specific shape.
An app proxy puts clean markdown under your shop domain
Shopify lets an app claim a subpath on the merchant’s own storefront domain — here, /apps/rebilder/.... Requests to that subpath are forwarded server-side by Shopify to a URL the app hosts, and the response is returned to the requester from the shop’s domain. So an agent fetching https://your-shop.myshopify.com/apps/rebilder/products/trail-pack is answered by the gateway: the agent-facing URL lives on your store, the serving lives with the handler.
This is the Shopify app proxy markdown pattern, and it has three properties worth noticing. No theme edits and no Liquid — your storefront is untouched. No new dependencies — signature verification uses Web Crypto, which every modern runtime ships. And nothing is generated per request — the markdown is rendered from source-of-truth data you wire in (product, policies, catalog), so prices and availability are injected values, never model output. Your source resolvers and the emitted events see canonical storefront URLs, the same as every other adapter.
Setup: the adapter in three steps
- Configure the proxy in Shopify Partners. Your app → Configuration → App proxy: set Subpath prefix to
appsand Subpath torebilder— the storefront path becomes/apps/rebilder— and point Proxy URL at the endpoint where your handler will run. - Provide the client secret via env. Copy the app’s Client secret; it is the HMAC key Shopify uses to sign every proxy request. Set it as an environment variable — never hardcode it.
- Deploy the handler on any web-standard runtime. Wire the same
GatewayConfigevery adapter uses, then export the proxy handler:
import { createShopifyAppProxyHandler } from '@rebilder/gateway/shopify'
import { gatewayConfig } from '@/lib/gateway-config'
export const GET = createShopifyAppProxyHandler(gatewayConfig, {
sharedSecret: process.env.SHOPIFY_APP_SECRET!,
pathPrefix: '/apps/rebilder',
})The full walkthrough, including the gatewayConfig wiring, is in the Shopify adapter reference; the config itself is the two-file setup from the quickstart. The gateway is free, and the same config also generates your llms.txt.
Signed requests or nothing: the security model
Shopify appends query parameters to every forwarded proxy request — the shop, the path prefix, a timestamp — plus a signature: a hex HMAC-SHA256 over the canonicalized parameters, keyed with your app’s shared secret. The handler treats that signature as the price of admission:
- The signature is verified with Web Crypto and a constant-time comparison. Failure means
401— no content. - A signed timestamp older than 90 seconds (with ±5s clock-skew tolerance) is also rejected with
401, bounding the replay window of a captured signed URL. - Only then is the canonical storefront URL reconstructed — proxy prefix and Shopify’s injected parameters stripped — and handed to the core gateway.
- Because the proxy is the endpoint, with no downstream HTML to fall through to, every pass-through becomes
404JSON ({"error":"no_source"}): unmatched URLs, sources that returned nothing, and non-agent requesters. A human or crawler hitting the subpath gets a 404, not markdown — your real pages live at their canonical URLs.
Verify it: one preview, two fetches
The Console’s side-by-side preview fetches a URL twice, sequentially — first as an agent, with Accept: text/markdown and an honest rebilder-preview user agent, then as a regular browser — and shows each side’s status, content type, size, and an approximate token count (characters ÷ 4, labeled approx). A green verdict means your store serves agents markdown, with the savings quantified; amber means agents currently get your full HTML. It works against any public https:// page, before you install anything.
From a terminal, the same check is two requests against the proxy subpath — Shopify signs the forwarded request server-side, so plain curl works:
# Agent view — expect text/markdown and x-rebilder-path: markdown
curl -si -H 'Accept: text/markdown' \
https://your-shop.myshopify.com/apps/rebilder/products/trail-pack
# Non-agent view of the same subpath — expect 404 {"error":"no_source"}
curl -si https://your-shop.myshopify.com/apps/rebilder/products/trail-packBoth requests also land in the Console visit log — one row each, with the classification (agent, human, crawler, or protocol), the platform where identifiable, what was served, and the render time in milliseconds. Agent traffic on your store stops being invisible.
Honest scope: what ships today, and what doesn’t
Precision matters more than enthusiasm here, so this is the exact state of the Shopify path:
| Capability | Status today |
|---|---|
| Agent detection + markdown serving via app proxy | Live — the free gateway’s Shopify adapter |
| Console: visit log, side-by-side preview, install page | Live |
| llms.txt generated from the same config | Live — or build one by hand with the free generator |
| Adapters beyond Shopify: Next.js, Express, Fastify, Cloudflare Workers | Live |
| Full Shopify app: OAuth install flow, billing, embedded admin | Not yet — the proxy config and shared secret are set up manually in Partners |
| UCP / ACP / MCP protocol endpoints | Live — spec-pinned v0 adapters, wired in through the gateway; a store that hasn’t wired them yet still records the protocol visits |
| Web Bot Auth signature verification | Live in the gateway — it enforces once trusted platform keys are pinned into the (deliberately empty) registry, so the Verified column still reads “no” today, which is normal |
None of the manual setup is throwaway. The source-of-truth wiring that renders markdown today is the exact same wiring object the protocol endpoints read — getting legible now is the prerequisite, not a detour.
