Shopify International SEO
Shopify hreflang and structured data
for international AI agent visibility
How to set up language and region signals so ChatGPT, Google AI Mode, and Perplexity recommend your products to shoppers in the right country — at the right price.
inLanguage. Fix priceCurrency with Liquid variables, add inLanguage to your WebPage wrapper, and verify each regional URL is independently indexed before expecting AI agents to surface regional results.
Why international stores break AI agent discovery
AI shopping agents like ChatGPT and Perplexity answer product queries by crawling indexed pages and reading structured data. If your UK store at /en-gb/products/running-shoes is not indexed — or if it is indexed but its JSON-LD still says priceCurrency: "USD" — AI agents either skip it or present the wrong price to UK shoppers.
Three failure modes are responsible for most international AI agent blind spots:
- Missing or broken hreflang — search engines cannot identify the canonical regional URL, so only one locale gets indexed deeply.
- Hard-coded currency in JSON-LD — the Shopify default theme outputs
"priceCurrency":"USD"even on UK or EU market pages. - Missing
inLanguage— AI agents that rank pages by language relevance cannot confirm a German page is German without this signal.
How Shopify Markets handles hreflang
Shopify Markets (released 2022) supports three URL structures for international stores. Each has different hreflang behavior:
| Structure | Example | Hreflang auto-injected? | Notes |
|---|---|---|---|
| Subfolders | example.com/en-gb/ | Yes | Shopify injects full hreflang set in <head> |
| Subdomains | uk.example.com | Partial | Requires Translate & Adapt app; validate manually |
| Separate domains | example.co.uk | No | Must add hreflang manually in theme or via app |
| Third-party translation app | Langify, Weglot | Varies | Check rendered HTML — many inject incorrectly |
What correct hreflang looks like
Each regional URL needs a complete set of <link rel="alternate"> tags in the <head>, including a self-referential tag and an x-default fallback:
<!-- In Shopify theme: layout/theme.liquid --> <link rel="alternate" hreflang="en" href="https://example.com/products/running-shoes"> <link rel="alternate" hreflang="en-gb" href="https://example.com/en-gb/products/running-shoes"> <link rel="alternate" hreflang="de" href="https://example.com/de/products/running-shoes"> <link rel="alternate" hreflang="fr" href="https://example.com/fr/products/running-shoes"> <link rel="alternate" hreflang="x-default" href="https://example.com/products/running-shoes">
With Shopify Markets + subfolders, this is generated automatically. Verify by viewing source on a non-default locale URL.
Fixing priceCurrency in Product JSON-LD
The default Dawn theme and most Shopify themes output a static "priceCurrency":"USD" in Product schema, even when the page is rendered for a UK or EU market. AI agents read this as a US product and may filter it from GBP or EUR queries.
The broken default
<!-- Common theme bug: currency is hard-coded -->
{
"@type": "Offer",
"price": "{{ product.price | money_without_currency }}",
"priceCurrency": "USD" <!-- Wrong for non-US markets -->
}
The fix: Liquid currency variable
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "{{ product.title | escape }}",
"offers": {
"@type": "Offer",
"price": "{{ product.price | money_without_currency | remove: ',' }}",
"priceCurrency": "{{ cart.currency.iso_code }}",
"availability": "{% if product.available %}https://schema.org/InStock{% else %}https://schema.org/OutOfStock{% endif %}",
"url": "{{ shop.url }}{{ product.url }}"
},
"inLanguage": "{{ request.locale.iso_code }}"
}
</script>
cart.currency.iso_code returns GBP, EUR, AUD, etc. based on the market the shopper is browsing. request.locale.iso_code returns the BCP 47 language tag (en-GB, de, fr) matching the active locale.
Adding inLanguage to WebPage context
The inLanguage property should appear on the WebPage or ItemPage entity wrapping your product page. AI agents that process multilingual indexes use it to filter by language before scoring products.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ItemPage",
"url": "{{ shop.url }}{{ product.url }}",
"name": "{{ product.title | escape }}",
"inLanguage": "{{ request.locale.iso_code }}",
"about": {
"@type": "Product",
"name": "{{ product.title | escape }}"
}
}
</script>
AI agent behavior by international signal quality
| Agent | Hreflang indexed? | priceCurrency correct? | inLanguage set? | Result |
|---|---|---|---|---|
| ChatGPT Shopping | Yes | Yes | Yes | Surfaces regional URL with correct local price |
| ChatGPT Shopping | Yes | No | No | May surface regional URL but shows USD price — confuses user |
| Google AI Mode | Yes | Yes | Yes | Correct regional result in Shopping Graph |
| Google AI Mode | No | — | — | Only US URL indexed; UK/EU shoppers see US result or none |
| Perplexity Shopping | Partial | Yes | No | Inconsistent — sometimes surfaces, sometimes shows US fallback |
| Bing Shopping | Yes | Yes | Yes | Regional result surfaces in Copilot with correct currency |
Common hreflang mistakes on Shopify
| Mistake | Impact | Fix |
|---|---|---|
| Missing x-default tag | Google cannot determine primary fallback URL | Add hreflang="x-default" pointing to default market URL |
| Hreflang on collection pages only | Product pages not alternated — split indexing signals | Include hreflang on product, collection, and blog pages |
| Wrong language code format | en_GB (underscore) fails; must be en-GB (hyphen) | Use BCP 47 format: en-GB, de, zh-TW |
| Weglot URL not canonical | Weglot creates /fr/ pages that aren't in sitemap | Enable Weglot sitemap + submit to GSC manually |
| Currency not switching in JSON-LD | Geo-priced products still show USD in structured data | Use cart.currency.iso_code Liquid variable |
| Translate & Adapt not publishing all locales | Translated pages exist but are not published — 404 for crawlers | Publish each locale in Markets dashboard before adding hreflang |
Verifying international structured data
Check three things before assuming your international setup is AI-agent ready:
- Hreflang validation: Run your product URL through the structured data testing tools that support hreflang (Merkle's hreflang checker, Aleyda's hreflang tag generator for expected output). Confirm all locales are listed and self-referential.
- JSON-LD currency check: Use
curl -H "Accept-Language: en-GB" https://yourstore.com/en-gb/products/slugand grep forpriceCurrency. Should returnGBP, notUSD. - Google Search Console International Targeting: Under Legacy Tools, confirm no hreflang errors for your configured locales.
CatalogScan checks for international stores
When you scan a Shopify store with CatalogScan, the international signal check confirms:
- Whether
priceCurrencyin JSON-LD matches the page's apparent locale - Whether
inLanguageis present on the Product or WebPage entity - Whether hreflang tags exist in the page
<head>(presence check — not full cross-validation)
Stores missing any of these signals score lower on the AI-agent readiness dimension. Run a free scan to see where your international pages stand.
Frequently asked questions
Does Shopify automatically add hreflang tags for international stores?
Shopify Markets automatically injects hreflang tags when you enable multiple markets with subfolders. Subdomain stores and third-party translation apps vary — always verify the rendered HTML head element on a live product page.
Do AI shopping agents use hreflang to show regional products?
AI agents primarily follow structured data signals (inLanguage, priceCurrency) rather than hreflang directly. But hreflang determines which regional URLs get indexed — if a regional URL isn't indexed, AI agents can't surface it regardless of structured data quality.
What is the inLanguage property and why does it matter?
The inLanguage property tells AI crawlers the primary language of the page. Language-aware agents filter results by language — a German page without inLanguage: "de" may be returned for English queries or skipped for German ones.
Should hreflang and priceCurrency always match the URL locale?
Yes. A UK page at /en-gb/ should have hreflang: en-GB, priceCurrency: GBP, and prices in pounds. Any mismatch confuses both search engines and AI agents and can suppress the product from regional queries.
Related: Shopify international SEO and AI agents · Shopify schema markup guide · Structured data testing tools