Avoiding the most common mistakes
A broken hreflang implementation makes Google show users the wrong language version of a page and can flag multilingual content as duplicate content. This article explains hreflang syntax, the reciprocal linking rule, the correct use of x-default, and the most common sources of error, then shows how a clean implementation looks in practice using the mironsoft.de blog itself.
Table of Contents
- 1. What hreflang is and what problem it solves
- 2. hreflang syntax: language codes, region codes, and placement
- 3. The reciprocal linking rule: why hreflang must always be mutual
- 4. x-default: purpose and correct usage
- 5. Common mistake 1: missing or broken return tags
- 6. Common mistake 2: wrong or inconsistent language/region codes
- 7. Common mistake 3: canonical conflicts and non-indexable target URLs
- 8. Testing and validating your hreflang implementation
- 9. Real example: hreflang in the mironsoft.de DE/EN blog
- 10. Summary
- 11. FAQ
1. What hreflang is and what problem it solves
hreflang is an attribute that lets site owners tell Google and other search engines which language and region variants of a page exist and how those variants relate to each other. Without hreflang, Google treats every language version as a separate, potentially competing page: for a bilingual blog like mironsoft.de, that would mean the German and English articles compete for the same ranking positions even though they serve the same content to different audiences. The result is a duplicate content signal that unnecessarily weakens the visibility of both language versions.
The real value of hreflang, though, is not just avoiding duplicate content, it is serving the correct language: ideally, Google automatically shows a user in Germany the German version while a user in the US sees the English version in the search result, even when both search for the exact same term. For international Magento stores with multiple store views, this is not a nice-to-have, it is a baseline requirement to stay visible in every target market with the right language and currency, instead of losing traffic to mismatched language versions.
2. hreflang syntax: language codes, region codes, and placement
The basic hreflang syntax is a <link> element with rel="alternate" and an hreflang attribute, whose value combines an ISO 639-1 language code (two letters, e.g. de or en) with an optional ISO 3166-1 region code (also two letters, e.g. DE or US), separated by a hyphen. de targets all German-speaking users worldwide, de-DE targets only users in Germany, and de-AT targets only users in Austria. The region code is optional and should only be set when genuinely different content exists for different regions of the same language.
hreflang can be delivered in three places: in the <head> of the HTML page as a <link> element, as a Link HTTP header (relevant for non-HTML resources such as PDFs), or as an entry in the XML sitemap. All three methods are equally valid to Google, but they must not be mixed without staying consistent: maintaining hreflang in both the head and the sitemap in parallel risks conflicting values on every update. For Magento stores with few store views, the head variant is the easiest to maintain; for very large catalogs with many language variants, the sitemap variant noticeably reduces HTML file size.
<!-- HTML head: reciprocal hreflang for DE, EN and x-default -->
<link rel="canonical" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen">
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/seo-implementing-hreflang-correctly">
<link rel="alternate" hreflang="x-default" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen">
<!-- The English page must confirm the exact same set, pointing back -->
<link rel="canonical" href="https://mironsoft.de/blog/seo-implementing-hreflang-correctly">
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/seo-implementing-hreflang-correctly">
<link rel="alternate" hreflang="x-default" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen">
<!-- XML sitemap: hreflang entries as an alternative to head markup -->
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen</loc>
<xhtml:link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen"/>
<xhtml:link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/seo-implementing-hreflang-correctly"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen"/>
</url>
<url>
<loc>https://mironsoft.de/blog/seo-implementing-hreflang-correctly</loc>
<xhtml:link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen"/>
<xhtml:link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/seo-implementing-hreflang-correctly"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen"/>
</url>
</urlset>
3. The reciprocal linking rule: why hreflang must always be mutual
Google's documentation explicitly requires every hreflang annotation to be reciprocally confirmed: if page A links to page B via hreflang, page B must link back to page A via hreflang in return. This return link is not an optional detail, it is the actual trust basis of the entire system. Without it, Google cannot verify the language relationship and ignores the hreflang annotation of the one-sided linking page entirely, not just partially.
In practice, this means at least two mutually confirming entries per language pair, and with three or more language variants the number of required links grows quadratically: with five language versions of a page, every variant needs four outgoing hreflang links, all of which must be confirmed back. This complexity is the main reason manual hreflang maintenance becomes error-prone once more than two languages are involved, and why a dynamic, code-generated solution, such as a Magento ViewModel that automatically lists every store view URL, is the only robust approach for growing stores.
4. x-default: purpose and correct usage
hreflang="x-default" is a special value that does not address a specific language, but instead marks the page Google should show to users whose language or region does not match any of the explicitly defined variants, for example a visitor from France on a store that only offers German and English. Typically, x-default points to a language selector page or to the globally most neutral version of the content, often the English variant.
A common mistake is omitting x-default entirely or treating it incorrectly as an additional language variant instead of a fallback. Without x-default, Google decides on its own which variant to show for uncovered languages and regions, usually based on popularity or relevance signals, which rarely matches the intended user experience. For mironsoft.de, x-default sensibly points to the German version, since German is the agency's primary target language and English serves as the international secondary language. This decision should always be based on the actual audience distribution, never made arbitrarily.
5. Common mistake 1: missing or broken return tags
By far the most common hreflang mistake in practice is asymmetric linking: page A links correctly to page B, but page B was never given the return link back to page A after a redesign, a URL change, or simply by oversight. Google reports this issue in Search Console under notices about missing return tags. If ignored, the affected hreflang relationship loses its entire effect, and both pages are again at risk of being treated as competing duplicate content.
This mistake is especially treacherous during URL migrations: if a German blog page is renamed without updating the corresponding hreflang reference on the English sister page, the English page keeps linking to a dead or outdated URL. Automated tests that check every hreflang pair for reciprocity on each deployment prevent this problem far more reliably than manual review, particularly for blogs or category pages that get updated regularly.
<!-- BROKEN: asymmetric hreflang, page A links to B, but B never links back -->
<!-- Page A (DE) head: -->
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/alte-seite-de">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/neue-seite-en">
<!-- Page B (EN) head after a URL rename, still using the outdated slug: -->
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/alte-seite-de">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/alte-seite-en">
<!-- Mismatch: page A expects "neue-seite-en", page B still self-references the old EN slug -->
<!-- FIXED: both pages reference the exact same, current URLs -->
<!-- Page A (DE) head: -->
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/alte-seite-de">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/neue-seite-en">
<!-- Page B (EN) head: -->
<link rel="alternate" hreflang="de" href="https://mironsoft.de/blog/alte-seite-de">
<link rel="alternate" hreflang="en" href="https://mironsoft.de/blog/neue-seite-en">
6. Common mistake 2: wrong or inconsistent language/region codes
A second widespread mistake is confusing language and region codes: hreflang="de-DE" is correct, hreflang="DE-de" or hreflang="deu" are not, because Google only accepts validated ISO 639-1 language codes in lowercase and ISO 3166-1 region codes in uppercase. Another classic mistake is using a country code in place of a language code, for example hreflang="uk" for British English: uk is not a valid language code, the correct value is en-GB, since UK is not the ISO 3166-1 country code for the United Kingdom. The correct country code is GB.
Inconsistency between the codes of the same language version is also a frequent problem: if a page self-references as en in its sitemap entry but as en-US in the HTML head, this creates two technically different hreflang targets for the same content that Google cannot reliably merge. The rule is therefore: use one code per language version consistently across every output channel, never swap language and region codes, and never handle casing inconsistently.
7. Common mistake 3: canonical conflicts and non-indexable target URLs
hreflang and canonical serve different purposes and must not be mixed up: a page's canonical tag must always point to itself, a so-called self-referencing canonical, never to the other language version. If the German page's canonical points to the English page, that signals to Google that the German version should not be indexed on its own, which undermines the entire hreflang structure, since a page marked as non-canonical is not eligible as an hreflang target in the first place.
Equally critical: hreflang links must never point to URLs that are excluded via noindex, trigger a 3xx redirect, or return a 404. Google ignores such target URLs completely and reports corresponding warnings in Search Console. A common real-world case in Magento stores: after a store view is disabled, old hreflang references to its URLs remain in place even though they now redirect to the homepage. These dead references should be cleaned up systematically with every store view change.
8. Testing and validating your hreflang implementation
Google Search Console no longer offers a dedicated hreflang report like the old "International Targeting" section, but it still surfaces broken hreflang relationships through the page indexing report and through individual URL checks in the URL Inspection tool, which shows the hreflang targets Google actually detected for a page. For a complete overview of every hreflang pair in a store, third-party tools such as Screaming Frog, with hreflang auditing enabled, or Sitebulb are far more practical, since they automatically list all missing return links and inconsistent codes in a single crawl overview.
For quick, manual spot checks, a simple curl command against the HTML head of both pages is often enough to verify that the return link is actually live and not just tested locally. It is important to repeat every hreflang check after each deployment, since even small layout or template changes can accidentally strip hreflang tags from the head without any visible sign. An automated check as part of the CI/CD pipeline prevents such regressions from going live unnoticed.
#!/usr/bin/env bash
# Verify that DE and EN pages reciprocally reference each other via hreflang
DE_URL="https://mironsoft.de/blog/seo-hreflang-korrekt-einsetzen"
EN_URL="https://mironsoft.de/blog/seo-implementing-hreflang-correctly"
echo "Checking hreflang tags on DE page..."
curl -s "$DE_URL" | grep -o '<link rel="alternate" hreflang="[^"]*" href="[^"]*"'
echo "Checking hreflang tags on EN page..."
curl -s "$EN_URL" | grep -o '<link rel="alternate" hreflang="[^"]*" href="[^"]*"'
# Confirm the DE page's hreflang="en" value matches EN_URL exactly
curl -s "$DE_URL" | grep -q "hreflang=\"en\" href=\"$EN_URL\"" \
&& echo "OK: DE page correctly links to EN_URL" \
|| echo "FAIL: DE page is missing or has a wrong hreflang=en link"
# Confirm the EN page's hreflang="de" value matches DE_URL exactly
curl -s "$EN_URL" | grep -q "hreflang=\"de\" href=\"$DE_URL\"" \
&& echo "OK: EN page correctly links back to DE_URL" \
|| echo "FAIL: EN page is missing or has a wrong hreflang=de link"
9. Real example: hreflang in the mironsoft.de DE/EN blog
This very article is a practical example of a correctly implemented hreflang setup: the German version at /blog/seo-hreflang-korrekt-einsetzen and the English version at /blog/seo-implementing-hreflang-correctly reference each other reciprocally in the HTML head. Each page carries both an hreflang="de" and an hreflang="en" link, whose href values point exactly to the other URL. Both pages also carry a self-referencing canonical that points exclusively to their own URL, never to the translation.
Structurally, both language versions are deliberately built identically: the same number of sections, the same code examples, the same FAQ count, only the text is translated. This consistency is not accidental, it is a deliberate SEO decision: Google can identify language pairs more reliably as genuine translations of the same content when structure and scope match, rather than when the English version is just a shortened summary of the German one. For a growing blog archive with dozens of article pairs, a dynamic, ViewModel-based generation of hreflang tags per store view is the only practical way to keep this reciprocity intact without manual maintenance.
<?php
declare(strict_types=1);
namespace Mironsoft\SeoSuite\ViewModel;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface;
/**
* ViewModel that generates reciprocal hreflang link tags for every active store view.
*/
class HreflangViewModel implements ArgumentInterface
{
/**
* @param StoreManagerInterface $storeManager Store manager used to resolve all active store views.
*/
public function __construct(
private readonly StoreManagerInterface $storeManager
) {
}
/**
* Builds a map of hreflang code to absolute URL for the current page across all store views.
*
* @param string $currentPath Relative request path shared by all language variants, e.g. "blog/example".
* @return array<string, string> Map of hreflang code (e.g. "de", "en", "x-default") to absolute URL.
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getHreflangLinks(string $currentPath): array
{
$links = [];
/** @var StoreInterface[] $stores */
$stores = $this->storeManager->getStores();
foreach ($stores as $store) {
$hreflangCode = (string) $store->getConfig('general/locale/hreflang_code');
if ($hreflangCode === '') {
continue;
}
// @phpstan-ignore-next-line StoreInterface::getBaseUrl() exists on the Store model
$links[$hreflangCode] = rtrim($store->getBaseUrl(), '/') . '/' . ltrim($currentPath, '/');
}
if (isset($links['de'])) {
$links['x-default'] = $links['de'];
}
return $links;
}
}
The table below summarizes the hreflang mistakes covered in this article, along with the symptom, the root cause, and the correct fix for each.
| Mistake | Symptom | Why it happens | Correct fix |
|---|---|---|---|
| Missing return tag | hreflang relationship is ignored by Google | URL change without updating the sister page | Both pages confirm each other via hreflang |
| Wrong language/region code | hreflang tag is not recognized or misassigned | Country code instead of language code, wrong casing | ISO 639-1 lowercase + ISO 3166-1 uppercase, e.g. en-GB |
| hreflang/canonical conflict | Target page is not indexed, hreflang has no effect | Canonical points to the other language instead of itself | Self-referencing canonical on every language version |
| Missing x-default | Wrong language version for uncovered regions | x-default forgotten or treated as a normal language | Point x-default to a language selector or neutral version |
| hreflang points to redirect/404 | Google ignores the hreflang target entirely | Store view disabled, URL not cleaned up | Update hreflang references on every store view change |
In practice, these mistakes often reinforce each other: a missing return link is frequently noticed only once a language code has also been set incorrectly in parallel, since both issues look similar in the Search Console report. Generating hreflang dynamically per store view from the start, combined with automated testing, prevents most of these error sources upfront instead of fixing them manually after the fact.
Mironsoft
International SEO, hreflang audits, and multi store view setup for Magento stores
Ready to get hreflang implemented properly?
We analyze your Magento store's hreflang structure, identify missing return links and code errors, and implement a dynamic, maintenance-free solution across all store views.
hreflang audit
Full review of every language pair for reciprocity and correct codes
International SEO consulting
Strategy for x-default, target audiences, and store view structure
Multi store view setup
Dynamic hreflang generation directly in the Magento ViewModel
10. Summary
Implementing hreflang correctly solves a core problem of multilingual websites: Google needs to reliably identify which language version to show to which user, without treating the variants as competing duplicate content. The syntax itself is simple, an ISO 639-1 language code plus an optional ISO 3166-1 region code, but the real challenge lies in consistent reciprocal linking: every hreflang annotation must be confirmed back by the target page, or Google ignores it entirely.
The most common mistakes, missing return links, wrong language codes, and conflicts with the canonical tag, can be reliably prevented with automated tests and regular crawls. For Magento stores with multiple store views, a dynamic, code-generated solution such as a ViewModel is the only robust approach, since manual maintenance quickly becomes error-prone as the number of languages grows. This article itself demonstrates the correct implementation through its own German and English versions.
Implementing hreflang correctly, the essentials at a glance
Correct syntax
ISO 639-1 language code plus optional ISO 3166-1 region code. Placed in the head, HTTP header, or sitemap.
Reciprocal linking
Every hreflang annotation must be confirmed back by the target page, or Google ignores it.
x-default
Fallback for uncovered languages and regions, pointing to a language selector or the neutral version.
Testing & validation
Search Console URL Inspection, Screaming Frog, and curl checks after every deployment.