
Documentation
TYPO3 Extension “Hreflang Multisite”
Version 2.3.1 (2026-09-30)
A page set is a group of pages, spread across different root pages, that represent the same content for different regions or languages. Every page in the set renders hreflang tags pointing at all the others—including each page’s own translations, which TYPO3 already handles.
For hreflang to be valid, all the tags of a set need to be present on every page within the set. That reciprocity is why a page belongs to at most one set.
Background on hreflang itself: Localized versions of your pages, Google Search Central.
When This Applies
Only when you run more than one root page.
If all your languages live in a single page tree as translations of one page, TYPO3 renders correct hreflang tags out of the box and this extension has nothing to add.
The case it is built for looks like this:
- One page tree for Europe, one for North America, one for Asia
- Each of them possibly with its own translations
- The same page exists in all three trees, and none of them knows about the other two

What Your Setup Needs
| Requirement | Why |
|---|---|
| More than one root page | Otherwise TYPO3 covers it already |
| Unique language and region codes within a set | Two URLs in one set claiming en-US is not valid hreflang |
| At most one page per root page in a set | Enforced when saving, see below |
One page flagged as x-default per set | Enforced when saving, see below |
Each root page may carry one or several languages. Not every root page has to be part of a set—you can have three root pages forming one set, two more forming another, and a handful that belong to none.
What Is Checked When a Set Is Saved
Three rules are validated, and the errors are shown against the root page they belong to:
- An
x-defaultis set. An empty value is rejected. - The
x-defaultpoints at a page inside the set. A page outside the group is rejected. - Only one page per root page. A set cannot contain two pages from the same root page.
Not validated: that a page belongs to only one set. In practice this is kept by the selection wizard, which filters out pages already referenced elsewhere—but nothing checks it on save.
A Set With Fewer Than Two Pages Is Deleted
Saving a set that ends up with fewer than two referenced pages deletes the set, and the validation errors above are skipped in that case.
That is consistent—a set of one page has nothing to link to—but it is surprising if you did not expect it: removing the second-to-last page from a set does not leave you with a one-page set to fix, it leaves you with no set.
x-default
x-default is the page a search engine falls back to when none of the language and region combinations match the visitor. The backend requires one per set and validates it as described above.
In the frontend the tag is appended as the last entry of the set, mirroring what TYPO3’s own generator does for a single tree. Its URL is copied from the finished map, which has two consequences worth knowing:
- A listener that rewrites the flagged page’s URL is followed. The
x-defaultpoints at whatever that language ended up with, not at the original value. See Events. - A listener that removes the flagged language drops the
x-defaultwith it. No fallback is emitted pointing at a tag that is no longer there.
A page flagged as x-default that is hidden, carries no_index, or sits outside its start and end time is skipped like any other translation and does not become the fallback.

The Flag Always Lands on a Root Page’s Default Language
You flag a page, and the page you flag is a default-language page. A set stores default-language pages, so the flag can only ever resolve to the default language of the root page you picked—never to one of its translations.
This matters when the fallback is meant to be a different market. A company based in Germany that also runs a US site may want the German content as the fallback for the US set. Flagging the German page does that, and the x-default then points at the default language of the German root page. If that root’s default language is German, the fallback is German. There is no way to say "use the English translation of the German root as the x-default for the US set", even when that translation exists.
Usually the page you are editing is also its own x-default, and none of this comes up.
Where it does come up is the setup where the international version is not a site of its own but a translation inside a regional tree—an English version under the German root, serving every visitor no market matches. That English page cannot be made the x-default. The way to have it is to give it its own root page, which makes it a normal member of the set.
The event is not a way around this. The fallback is appended after every listener has run, from the flagged language’s entry in the finished map, so a listener that sets x-default itself is overwritten. What a listener can do is change where the flagged language points—and that moves the alternate tag for that language with it. There is no way today to point the fallback somewhere the set does not otherwise point.
What Gets Rendered
For each page in the set the extension resolves the site, its languages, and the corresponding URLs, and emits one <link rel="alternate" hreflang="…"> per language and region combination.
Translations that are hidden, carry no_index, sit outside their start or end time, or whose language is not available in the frontend are skipped.
The resulting set of tags replaces the tags TYPO3 generated itself. If you need to change that output, use the event rather than a template override.
For the set shown throughout Editing—one page per market, with Germany carrying an English version and the United States a Spanish one—the head of every page in the set carries:
<link rel="alternate" hreflang="de-DE" href="https://example.com/produkte">
<link rel="alternate" hreflang="en-GB" href="https://example.com/en/products">
<link rel="alternate" hreflang="en-US" href="https://example.com/usa/products">
<link rel="alternate" hreflang="es-MX" href="https://example.com/usa/mx/productos">
<link rel="alternate" hreflang="en-AU" href="https://example.com/australia/products">
<link rel="alternate" hreflang="x-default" href="https://example.com/usa/products">
Every page of the set emits the same six tags, pointing at each other and at itself—that reciprocity is what makes the markup valid. The hosts and paths come from each site’s own configuration, so separate domains per market produce the same tags with different hosts. x-default is last, and repeats the URL of the version it was set on—here the English one, which is the sensible fallback when none of the language and region combinations match.
Page Sets