Home › Blog › Shopify Markets and AI agents
Shopify Markets and international catalog readiness for AI shopping agents: why hreflang misconfiguration silences your store in every non-primary market
Your Shopify Markets store has localized GBP pricing, translated product descriptions, and a /en-gb/ URL structure. A UK buyer visiting your site gets the right currency. But when ChatGPT Shopping, Perplexity, or Google AI Mode crawls your catalog, they get the US store — in USD — on every page. Five hreflang failure modes explain why, and each has a specific fix.
In this post
The invisible international store problem
Shopify Markets launched in 2021 and has since become the default way Shopify merchants sell internationally. It handles currency conversion, localized pricing, translated content, and regional tax calculation — all without leaving the Shopify ecosystem. As of early 2026, over 40% of Shopify stores with more than $100k annual revenue have at least one non-primary market configured.
The AI shopping agent rollout of 2025–2026 created a new visibility problem for these stores that most merchants haven't noticed yet. AI shopping agents — ChatGPT Shopping, Perplexity Commerce, Google AI Mode — send measurable referral traffic to Shopify stores. But their crawlers operate fundamentally differently from browsers: they don't execute JavaScript, they don't send Accept-Language headers that trigger locale detection, and they don't have cookies that persist between sessions. Every AI shopping crawler, regardless of where in the world it's crawling from, sees your default locale unless you explicitly tell it where to find regional alternatives.
The result: a UK-configured Shopify Markets store with correct GBP pricing, a /en-gb/ URL structure, and translated product descriptions is effectively invisible to ChatGPT Shopping for UK customers — because the agent indexed only the USD primary storefront and has no signal that a UK-priced version exists.
Related
How Shopify Markets builds regional URLs
Shopify Markets offers three URL structures for international storefronts. Each has different implications for how AI shopping agents discover and index regional content.
store.com/en-gb/products/widgeten-gb.store.com/products/widgetstore.co.uk/products/widgetMost stores that switch from subfolder to country domain for brand reasons don't realize the AI indexing implication: an agent that indexed your .com catalog gains zero visibility into .co.uk unless you build the hreflang bridge between the two domains explicitly on every product page.
The subfolder structure is the safest default for AI shopping agent visibility. If you're on Shopify's default Markets configuration (subfolder), you already have the right URL architecture — the problem is almost always the hreflang tags, not the URL structure itself.
Why AI crawlers can't negotiate locale
When a human browser visits a Shopify Markets store, three mechanisms work together to route them to the correct regional storefront:
- Accept-Language header — the browser sends its preferred language, and Shopify's edge logic redirects to the matching Markets locale.
- Geolocation redirect — Shopify uses the visitor's IP to detect country and redirect to the appropriate market URL, executed via JavaScript on the client side.
- Session cookie — once a visitor selects a locale, a cookie persists their choice across subsequent visits.
AI shopping crawlers use none of these. OAI-SearchBot (ChatGPT's crawler), PerplexityBot, and Googlebot for AI features all fetch pages with generic headers from IP addresses that don't map to any specific country. They ignore client-side JavaScript redirects. They don't store cookies between fetch requests.
catalogscan.com/products/widget receives the primary-locale page — always. Even if your Shopify Markets configuration would redirect a UK browser to catalogscan.com/en-gb/products/widget, the crawler never gets that redirect because the redirect is JavaScript-driven. The only way to tell an AI crawler that a regional version of that page exists is via hreflang annotations in the HTML source.
This is the same problem that affected international SEO with traditional search engines before hreflang became standard practice — but with AI shopping agents, the consequences are more severe because price accuracy is a first-class recommendation signal. An AI agent quoting USD pricing for a UK shopper will either get corrected by the user ("that's not the UK price") or worse, recommend a competitor whose pricing is correctly localized in its index.
The hreflang signal architecture AI agents depend on
Hreflang is an HTML link element that tells crawlers: "this page has a localized version at this URL for this locale." It was originally designed for international SEO with Google, but AI shopping crawlers have adopted it as the standard mechanism for discovering regional content.
A correct hreflang implementation on a product page looks like this in the <head>:
<!-- Primary (US) locale -->
<link rel="alternate" hreflang="en-US" href="https://store.com/products/widget">
<!-- UK locale -->
<link rel="alternate" hreflang="en-GB" href="https://store.com/en-gb/products/widget">
<!-- Australian locale -->
<link rel="alternate" hreflang="en-AU" href="https://store.com/en-au/products/widget">
<!-- French locale -->
<link rel="alternate" hreflang="fr" href="https://store.com/fr/products/widget">
<!-- Fallback for unmatched locales -->
<link rel="alternate" hreflang="x-default" href="https://store.com/products/widget">
Three properties of this structure matter for AI shopping agents specifically:
- Bidirectional confirmation — the UK page (
/en-gb/products/widget) must also contain a hreflang tag pointing back to the US page. If hreflang is only on the primary page pointing to regional URLs (but regional pages don't reciprocate), AI crawlers treat the annotation as unverified and may ignore it. - x-default annotation — the fallback tag that tells crawlers which version to serve when no locale match exists. For AI agents, x-default resolves the "which price do I quote?" ambiguity for users with no detected locale. Without it, agents may quote conflicting prices from different indexed versions of the same product.
- Per-page scope — hreflang on the homepage alone does nothing for product pages. Every product page needs its own complete hreflang set.
For stores with large catalogs, this means the hreflang implementation must live in the Liquid theme, not in a static head snippet. Every product.liquid template needs to generate the correct hreflang tags dynamically for whatever markets the store has configured.
Five hreflang failure modes
The most common failure in our scan data. A store has correct en-GB and en-AU hreflang tags on product pages, but no x-default tag. AI shopping agents crawling from a neutral IP address (neither UK nor AU) see competing regional price signals with no signal indicating which is authoritative. The result is either no recommendation (agent skips the product to avoid quoting the wrong price) or inconsistent behavior across crawl sessions.
Prevalence: found in 61% of Shopify Markets stores with hreflang implemented.
<link rel="alternate" hreflang="x-default" href="https://store.com/products/[slug]"> pointing to your primary locale URL. In Liquid: <link rel="alternate" hreflang="x-default" href="{{ shop.url }}/products/{{ product.handle }}">. This tag should appear on every product and collection page, not just the homepage.
A store adds hreflang tags to the index.liquid template (or to a static homepage section) but never adds them to product.liquid, collection.liquid, or page.liquid. AI shopping agents index product pages — not the homepage — when building their shopping catalog. Hreflang on the homepage is useful for language/country-detection UX but does nothing for AI product indexing.
Prevalence: found in 44% of Shopify Markets stores — the second most common failure mode. Many stores add hreflang during a "technical SEO cleanup" pass that only touches the homepage template.
product.liquid and collection.liquid templates using a Liquid loop over configured markets. The snippet at the bottom of this article shows the full pattern. After adding it, verify by fetching a product page source (curl -A "PerplexityBot" https://store.com/products/widget | grep hreflang) — you should see one hreflang line per market plus the x-default.
Using hreflang="en" instead of hreflang="en-GB" or hreflang="en-AU". Language-only hreflang tags are ambiguous for AI shopping agents when multiple English-speaking markets exist. An agent indexing a hreflang="en" page for a UK visitor doesn't know whether that page has GBP or USD pricing — en could be any English-speaking market. This ambiguity causes the agent to fall back to the primary locale price regardless of the visitor's location.
The correct form uses a two-part BCP 47 language tag: en-GB, en-AU, en-CA, fr-FR, fr-CA, de-DE, etc. Language-only (en, fr, de) is correct only when the language uniquely identifies the market (e.g., de for a store that only sells in Germany).
hreflang="en" tags with the correct region-qualified form. In Shopify Liquid, use {{ market.locale.iso_code }} which outputs the full BCP 47 code (e.g., en-GB) rather than building language codes manually. This also future-proofs the implementation when new markets are added — the loop generates the correct code automatically.
Shopify's native sitemap (/sitemap.xml) doesn't include hreflang annotations — it lists only the primary locale URLs. Many stores add hreflang to their sitemap via a third-party app or custom sitemap template, but the URL format in the sitemap doesn't match the URL format in the <head> tags. Common mismatches: sitemap uses /en-GB/ (uppercase) while head tags use /en-gb/ (lowercase), or sitemap uses en-gb as the subfolder but head tags use the country code alone (gb).
AI crawlers that encounter conflicting hreflang signals between the sitemap and the page source treat both as unreliable and fall back to crawling only the primary locale.
/en-gb/, not /en-GB/). Shopify Markets uses lowercase by default — check your custom sitemap template or app for uppercase overrides. Audit with: curl -s https://store.com/sitemap.xml | grep -i "en-gb" and compare to the hreflang href values from a live product page.
A store restructures its URLs (changes the handle of a product, migrates from /collections/ to /products/, or reorganizes Markets subfolder paths) but doesn't update the hreflang tags. The hreflang annotations now point to URLs that 301-redirect to the new location. AI shopping crawlers that follow a hreflang link to a 301 destination treat the hreflang annotation as broken — the redirect chain breaks the locale confirmation, and the destination URL may not have matching reciprocal hreflang tags.
This is especially common after Shopify handle changes triggered by the "Edit SEO" flow, which changes the canonical URL for a product but doesn't update hreflang tags in the theme.
curl -s https://store.com/products/old-handle -o /dev/null -w "%{http_code} %{redirect_url}" for each handle in your top-100 products. Use Shopify's URL redirect export (Admin → Online Store → Navigation → URL Redirects) to identify active redirects that may be referenced by hreflang tags, then update the tags to the canonical destinations.
JSON-LD pricing for regional pages
Hreflang tells AI crawlers that a regional page exists. The JSON-LD Offer block on that regional page tells them the price for that region. These two signals must be consistent and both must be correct for AI agents to confidently recommend your product to regional shoppers.
The most common JSON-LD pricing mistake on regional pages is outputting the primary-locale price and currency regardless of which market URL is being served:
"priceCurrency": "USD""price": "49.00"
This appears on /en-gb/products/widget. AI agent indexes a GBP page with a USD price — price mismatch signal.
"priceCurrency": "GBP""price": "39.00"
This appears on /en-gb/products/widget. GBP price matches the market, no mismatch signal.
In Shopify Liquid, the product.selected_or_first_available_variant.price value is already market-adjusted when the page is served under a Markets URL — Shopify's edge layer applies the market's price rules before the template renders. The mistake is hardcoding shop.currency (which always returns the primary store currency) instead of cart.currency.iso_code or the market-aware equivalent.
For stores using Shopify's native price formatting, the correct pattern is:
{%- assign variant = product.selected_or_first_available_variant -%}
{%- assign price_amount = variant.price | divided_by: 100.0 -%}
{
"@context": "https://schema.org",
"@type": "Product",
"name": {{ product.title | json }},
"offers": {
"@type": "Offer",
"price": "{{ price_amount | round: 2 }}",
"priceCurrency": "{{ cart.currency.iso_code }}",
"availability": "{% if variant.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}",
"url": "{{ shop.url }}{{ product.url }}"
}
}
The key difference from a naive implementation is cart.currency.iso_code (market-aware, returns GBP on the en-gb URL) versus shop.currency (always returns the primary store currency, typically USD).
Note on Shopify Markets pricing rules: If you use fixed regional prices (set per-market in the Shopify admin rather than relying on automatic currency conversion), the variant.price Liquid value does not automatically return the market-specific price in all theme versions. Test by fetching your regional product page as a crawler (curl -H "Accept-Language: en-GB" https://store.com/en-gb/products/widget) and checking whether the JSON-LD price matches what you configured in Markets. If it shows the converted price rather than the fixed price, you'll need to use product.variants[0].price with the Shopify Markets Liquid object available in OS 2.0 themes.
Shopify Liquid implementation
The following snippet generates correct hreflang tags for all configured markets. Add it to the <head> section of your theme's layout/theme.liquid, or preferably to a separate snippet file (snippets/hreflang.liquid) that you render from layout/theme.liquid:
{%- comment -%} snippets/hreflang.liquid — markets hreflang for AI agent indexing {%- endcomment -%}
{%- if template.name == 'product' -%}
{%- assign canonical_path = '/products/' | append: product.handle -%}
{%- elsif template.name == 'collection' -%}
{%- assign canonical_path = '/collections/' | append: collection.handle -%}
{%- elsif template.name == 'page' -%}
{%- assign canonical_path = '/pages/' | append: page.handle -%}
{%- else -%}
{%- assign canonical_path = '/' -%}
{%- endif -%}
{%- comment -%} Primary locale (no market subfolder prefix) {%- endcomment -%}
<link rel="alternate" hreflang="{{ shop.locale }}" href="{{ shop.url }}{{ canonical_path }}">
{%- comment -%} x-default points to primary locale {%- endcomment -%}
<link rel="alternate" hreflang="x-default" href="{{ shop.url }}{{ canonical_path }}">
{%- comment -%} Loop over all published markets {%- endcomment -%}
{%- for market in shop.markets -%}
{%- unless market.primary -%}
{%- for locale in market.locales -%}
{%- assign market_path = '/' | append: locale.root_url | append: canonical_path -%}
<link rel="alternate" hreflang="{{ locale.iso_code }}" href="{{ shop.url }}{{ market_path }}">
{%- endfor -%}
{%- endunless -%}
{%- endfor -%}
Add this snippet to your theme.liquid with {% render 'hreflang' %} inside the <head> tag. The snippet handles products, collections, pages, and the homepage — all the page types that AI shopping agents crawl when building their catalog index.
Related technical guides
9-item international AI readiness checklist
- hreflang tags present on product pages (not just homepage) — verify with
curl -s https://store.com/products/[handle] | grep hreflang - x-default hreflang pointing to primary locale URL present on every product page
- All hreflang values use region-qualified BCP 47 codes (
en-GB, noten;fr-FR, notfr) unless a single country market - Regional URLs listed in hreflang return HTTP 200 (no 301 chains) — spot-check top 20 products
- Reciprocal hreflang confirmed: the /en-gb/ product page links back to the primary locale product page
- JSON-LD Offer block uses
cart.currency.iso_codefor priceCurrency (market-aware, notshop.currency) - JSON-LD Offer price matches the displayed regional price — fetch regional page and compare rendered price to JSON-LD price value
- Sitemap includes regional URLs (or a separate regional sitemap) — and URL format matches hreflang href format exactly (case, trailing slash)
- robots.txt allows AI crawler user agents (
OAI-SearchBot,PerplexityBot,Googlebot) to crawl all market URL subfolders
Frequently asked questions
Do AI shopping agents like ChatGPT Shopping support hreflang?
Yes — but not the same way browsers do. AI shopping crawlers (OAI-SearchBot, PerplexityBot, Googlebot for AI features) read hreflang link elements in the HTML head to discover regional variants of a page. They don't use Accept-Language headers to request a specific locale, and they can't execute the JavaScript redirects Shopify uses to send human visitors to the right regional storefront. Hreflang is the only signal that tells these crawlers that a localized version of a product page exists and where to find it.
What is the x-default hreflang and why does it matter for AI agents?
The x-default hreflang annotation marks the canonical fallback URL for users whose locale isn't covered by any other hreflang tag. For AI shopping agents, x-default serves a second purpose: it resolves the "which version should I index?" ambiguity when the crawler lands on a page and sees multiple regional alternates. Without x-default, AI agents crawling from a neutral IP address can't determine which version represents the primary product — causing them to either skip all regional variants or double-index conflicting price signals. Best practice is to set x-default to the same URL as your primary locale (usually your default English storefront).
Shopify Markets uses URL subfolders like /en-gb/ by default — does that work with AI shopping agents?
Subfolder URLs (e.g., store.com/en-gb/products/widget) are the most AI-agent-friendly Shopify Markets configuration. AI crawlers index them as distinct URLs and can discover them directly from sitemap or from hreflang links on the primary locale page. Subdomain configurations work but require the crawler's robots.txt fetch to cover the subdomain. Country domain configurations are treated as entirely separate sites — cross-domain hreflang is required and sitemap cross-coverage is mandatory, or the international domains are invisible to agents indexing only the primary domain.
If I use Shopify Translate & Adapt, does that automatically fix AI shopping agent visibility for international markets?
Translate & Adapt generates translated product content and (with Shopify Markets) creates the regional URL structure. But it does not automatically guarantee correct hreflang coverage on every product page, correct JSON-LD pricing per locale, or x-default annotation. The translation is the content layer; the hreflang and JSON-LD are the discoverability layer. Many stores that use Translate & Adapt correctly still fail in AI shopping scans because the Liquid theme outputs hreflang tags only on the homepage, not on product or collection pages.
How should I handle JSON-LD product price when the same product has different prices in different Shopify Markets?
The JSON-LD Offer block on a regional product page should output the localized price and currency for that region, not the primary store's price. In Shopify Liquid, use product.selected_or_first_available_variant.price (which is already market-adjusted when served under a Markets URL) and pair it with cart.currency.iso_code for the currency. The critical mistake is outputting a single Offer block with the primary currency on all regional pages — AI agents indexing the /en-gb/ page then see a USD price, causing a price mismatch signal for UK shoppers.
See how your store scores on international readiness
CatalogScan checks hreflang coverage, x-default presence, and JSON-LD price consistency for your market configuration. 90 seconds, no login.
Run a free scan More guides