Hreflang overview
Multi-store / multi-language stores need hreflang tags to tell Google which version of a page belongs to which audience. The SEO Suite emits them automatically from your store-view configuration — and validates the result.
What it emits
For each storefront page on a multi-store install:
<link rel="alternate" hreflang="en-gb" href="https://uk.example.com/product.html">
<link rel="alternate" hreflang="en-us" href="https://us.example.com/product.html">
<link rel="alternate" hreflang="de-de" href="https://de.example.com/product.html">
<link rel="alternate" hreflang="x-default" href="https://uk.example.com/product.html">
The x-default is configurable to be either:
- The "default store" of the website, or
- A specific store ID you choose
Configuration
Stores → Configuration → SEO Suite → Hreflang Configuration (per-website scope)
| Field | Default |
|---|---|
| Enable hreflang | No |
| Include region variations | No (just en instead of en-gb) |
| Enable x-default | No |
| X-default store | (default store of the website) |
Region variations (en-gb vs en) are recommended when you operate stores in the same language but different markets (en-gb vs en-us vs en-au). Without them, Google has no signal to differentiate.
How URLs are matched across stores
The default behaviour is "same URL on every store" — the current request path is used unchanged. This works for catalog pages where Magento generates the same URL key per store (or where you've configured byte8_seosuite/hreflang to match by SKU/url_key).
For CMS pages, manual pairing via the hreflang_identifier field on the CMS page edit form: pages sharing the same hreflang_identifier are linked together regardless of their identifier.
For product/category pages with diverging URL paths across stores, use the URL Relationship manager (Marketing → SEO Suite → Manage URL Relationship) to set canonical/alternate mappings explicitly.
Locale code rules
Magento's store locale (e.g. en_GB) is normalised:
- With "Include region variations" = Yes →
en-gb(lowercase,_→-) - With "Include region variations" = No →
en(first two chars only)
A store with locale de_AT becomes de-at or de depending on the toggle.
What about CMS pages?
CMS pages have a hreflang_identifier text field on the edit form. Pages across stores sharing the same identifier get linked.
Workflow:
- Create a "Returns Policy" CMS page in the UK store with
identifier = returns-policyandhreflang_identifier = returns-policy-global - Create a German equivalent in the DE store with
identifier = ruckgaberechtandhreflang_identifier = returns-policy-global - Visit the UK page → see
<link rel="alternate" hreflang="de-de" href=".../ruckgaberecht">and vice versa
If you share the same identifier across stores (no hreflang_identifier), the suite still picks them up — hreflang_identifier is only needed when the URL keys differ.
Validation
Two paths to verify your setup is correct:
- CLI —
bin/magento seosuite:hreflang:validate— full report, JSON output for CI - Admin grid —
Marketing → SEO Suite → Hreflang Health— same data persisted, plus per-row Auto-Match action
See Validator for the validator deep-dive and Auto-matcher for the auto-pairing tool.
Common issues
- Two stores emit the same hreflang locale → Google picks one arbitrarily. Enable "Include region variations" so they're distinguishable.
- x-default on a localised page → only the home page should typically be flagged x-default. Set
x_default_storeto your default-locale store and only enable x-default on home-page-equivalent CMS pages if needed. - Self-referencing tag missing → Google's spec requires every page to also tag itself as a hreflang variant. The suite emits this automatically — if it's missing, your locale config is invalid (run the validator).
Headless / GraphQL
Hreflang tags are NOT yet exposed via GraphQL. Roadmapped for v2.9. For now, headless storefronts that need them must either:
- Render the storefront HTML server-side and scrape the
<head>, or - Re-implement the locale loop client-side using the
seo.canonicalfrom each store's GraphQL query
Next
- Validator — what gets checked, how to read the output
- Auto-matcher — bulk-discover cross-store product/category pairs