How to Correctly Implement Hreflang with Shopify Markets (with Code Examples)
Shopify Markets automatically generates hreflang tags for active markets when you use the built-in localization features - but only if your theme is correctly structured. Misconfigured or missing hreflang tags are one of the most common reasons international Shopify stores fail to rank in their target regions. This guide gives you the exact Liquid code and troubleshooting steps you need to get it right.
What Shopify Markets Does (and Doesn't) Handle Automatically
Since Shopify Markets launched with deeper hreflang support, many store owners assume the tags appear automatically regardless of setup. That assumption causes silent SEO failures. Here is exactly what Shopify handles on its own versus what you must configure manually:
- Automatic: Hreflang tags for markets using subfolders (e.g.,
/fr-fr/,/de/) when the theme uses thelocalizationLiquid object correctly. - Automatic: The
x-defaulttag pointing to your primary market URL. - Not automatic: Hreflang for country-specific domains or subdomains- those require manual implementation or a third-party app.
- Not automatic: Correct tags on themes that have overridden or stripped the
content_for_headerLiquid block. - Not automatic: Tags when a market is set up but no published translations exist for that locale.
The Core Liquid Code: Adding Hreflang to Your Theme
Open your theme's layout/theme.liquid file. Inside the <head> block, verify that {{ content_for_header }} is present and unmodified. Shopify injects hreflang tags through this tag. If it is missing or wrapped in a conditional that suppresses it, hreflang tags will not render.
If you need explicit control - for example, to support country-targeted domains - add this Liquid snippet directly to your <head> block:
{% comment %} Hreflang for Shopify Markets {% endcomment %}
{% for market in shop.markets %}
{% if market.enabled %}
{% for locale in market.published_locales %}
<link
rel="alternate"
hreflang="{{ locale.iso_code | downcase }}-{{ market.primary_domain.country | upcase }}"
href="{{ market.primary_domain.url }}{{ canonical_url | remove: shop.primary_domain.url }}"
/>
{% endfor %}
{% endif %}
{% endfor %}
<link rel="alternate" hreflang="x-default" href="{{ canonical_url }}" />
Important note: The shop.markets object and market.primary_domain properties require Shopify's Online Store 2.0 theme architecture. If you are running a Legacy theme (pre-2.0), upgrade the theme before relying on this approach.
Subfolder vs. Domain: Implementation Differences
Setup Type Hreflang Source Manual Code Required? Notes Subfolders (/fr/, /de-de/)
Injected via content_for_header
No, if theme is OS 2.0
Most reliable; recommended default
Country-specific domains (example.fr)
Not automatic
Yes
Requires manual Liquid or a Shopify app
Subdomains (fr.example.com)
Not automatic
Yes
Less common; same manual requirement as domains
Single domain, multiple currencies only
N/A - no locale difference
No
Currency-only markets do not need hreflang
Step-by-Step Implementation for Subfolder Markets
- Enable the market in Shopify Admin: Go to Settings → Markets, create or activate the target market, and assign a primary language.
- Add at least one published translation: Use Shopify Translate & Adapt or a compatible translation app. A market with zero published translations will not trigger hreflang injection.
- Verify
content_for_headerin theme.liquid: Search the file for the string. It must appear exactly once, unconditionally, inside<head>. - Check the rendered source: Visit a product page in your market's subfolder URL (e.g.,
yourstore.com/fr/products/example), right-click → View Page Source, and search forhreflang. You should see one tag per active locale plusx-default. - Submit an updated sitemap: Shopify's auto-generated sitemap at
/sitemap.xmlincludes alternate URLs for active markets. Resubmit to Google Search Console after enabling new markets.
Troubleshooting Hreflang on Shopify: 6 Common Errors
1. Tags Missing Entirely
content_for_header is absent or inside a conditional block. Restore it unconditionally inside <head> in theme.liquid.
2. Only the Primary Locale Tag Appears
The market is active but has no published translations. Publish at least one translated resource (even partial) to trigger the alternate tag for that market.
3. Wrong Locale Code Format
Google requires the BCP 47 format: en-US, fr-FR, de-DE. Shopify's Liquid locale.iso_code returns lowercase codes like en or fr. If you are building tags manually, append the country code using | upcase on the country segment as shown in the code example above.
4. Reciprocal Tags Not Present on All Pages
Every page referenced by an hreflang tag must itself include the full set of hreflang tags pointing back to all other variants. Shopify's injected tags handle this automatically for subfolder setups. For manual implementations on custom domains, use a loop that outputs all markets on every page - not just the current page's locale.
5. x-default Pointing to a Localized URL
x-default must point to your primary domain root (e.g., https://yourstore.com/products/example), not a localized path. In the Liquid example above, canonical_url on the primary domain handles this correctly.
6. Hreflang Present in Sitemap but Not in Page <head>
Google accepts hreflang in sitemaps or in page headers - not a mixture where they conflict. If Shopify's sitemap includes alternate URLs but your custom code in <head> outputs different ones, Google treats them as conflicting signals. Choose one method and apply it consistently.
Validating Your Implementation
Use these tools to confirm correct hreflang output before and after deployment:
- Google Search Console → International Targeting report: Shows detected hreflang errors across your indexed pages.
- Ahrefs Site Audit or Screaming Frog SEO Spider: Both crawl hreflang tags and flag missing reciprocal links, incorrect formats, and non-200 alternate URLs.
- hreflang.org Tag Testing Tool: Paste a URL to validate the hreflang tags on that specific page instantly.
- View Page Source + Ctrl+F "hreflang": Fast manual check during development - always do this on at least one page per market after changes.
Key Takeaways
- Shopify Markets injects hreflang automatically for subfolder setups on OS 2.0 themes - but only when translations are published and
content_for_headeris intact. - Country-targeted domains require manual Liquid code or a third-party app.
- Always validate with Google Search Console and a dedicated hreflang auditing tool after enabling new markets.
- Use BCP 47 format (
en-US, not justen) and always include a reciprocalx-defaulttag.
Does Shopify automatically add hreflang tags when I enable a new market?
Yes, for subfolder-based markets on Online Store 2.0 themes, Shopify injects hreflang tags via content_for_header- but only after you publish at least one translation for that market. Markets with no published translations will not generate alternate tags.
Do I need an app to implement hreflang on Shopify?
No, for subfolder markets on OS 2.0 themes, no app is required. You do need an app or custom Liquid code for country-specific domain setups (e.g., yourstore.fr), where Shopify does not inject hreflang automatically.
What is the correct hreflang format for Shopify Markets?
Use BCP 47 format: a lowercase language code combined with an uppercase country code, separated by a hyphen - for example, en-US, fr-FR, or de-DE. Shopify's Liquid locale.iso_code returns only the language portion, so append the country code manually if you are building tags outside of content_for_header.
How do I check if my Shopify hreflang tags are working?
View the page source of a localized URL (e.g., /fr/products/your-product) and search for "hreflang." You should see one tag per active market locale plus one x-default tag. Then verify in Google Search Console under the International Targeting report for any crawl-level errors.
Can I use hreflang in my Shopify sitemap instead of the page head?
Yes, Google accepts hreflang in XML sitemaps as an alternative to <head> tags. Shopify's auto-generated sitemap at /sitemap.xml includes alternate URLs for active markets. Avoid using both methods simultaneously if they produce different values, as conflicting signals will cause Google to ignore both.
