murattunalı.

hreflang errors.

The most frequent errors in hreflang setups are missing reciprocity, not declaring oneself, wrong code usage and conflict with the canonical address.

hreflang is a layer that works silently when set up right and fails silently when set up wrong. There is no error message, the page looks normal, and only in the search results does the wrong language version begin to appear — a symptom that takes weeks to notice.

A hreflang setup therefore cannot be done once and left; it needs auditing and, preferably, binding to a test. The errors below are the ones seen most often on real sites.

Missing reciprocity

The most common error. Page A declares B, but B does not declare A. The search engine treats the declaration as invalid in that case and behaves as if the set did not exist.

The cause is usually partial updating: while a new language is added, adding the new links to the main-language pages is forgotten. Or when a page is deleted, the links in the other languages are not cleaned up.

The durable solution is not writing the declarations by hand: when the links are generated from a single source, reciprocity is structurally guaranteed. On this site the generator provides that, and the suite additionally verifies it.

Not declaring oneself

The second most common error and the most surprising one. Every page must declare its OWN language along with the other versions in the set. On a trilingual site every page must carry three links — itself included.

It is often skipped because it runs against intuition: “this page is already Turkish, why should I additionally say it is Turkish?” The answer is that the set is defined as a list — an incomplete list is an invalid list.

Conflict with the canonical address

This error is more insidious because two separate markups talk to each other. If a page says “I am the German version” via hreflang but its canonical address points to the Turkish page, the two signals conflict.

The usual result is the German page never entering the index: because the canonical declaration says “the real page is that one”, the engine counts the German version as a copy and discards it. Everything hreflang said goes to waste.

The rule is clear: every language version must give the canonical to ITSELF. Translations are not copies of one another; they are separate pages. On this site every generated page gives the canonical to itself, and that was verified by measurement — not a single page deviates.

Every language version gives the canonical to itself; translations are not copies of one another.

Wrong and invented codes

Language and region codes are taken from standard lists and cannot be guessed. The frequent errors are well known.

  1. Using the region code alone — a language code is always required.
  2. Wrong country code — some countries’ codes are not intuitive; look them up in the list.
  3. An invented language code — a code not in the standard invalidates the whole set.
  4. Upper/lowercase confusion — for readability the language is written lowercase, the region uppercase.
  5. Using an underscore — the separator is a hyphen; the underscore is another standard’s format.

The silent-breakage problem

What these errors share is invisibility. The page opens, looks right, the user has no problem — and only the search engine shows the wrong language version. Noticing the symptom takes weeks, and once noticed, hunting the cause gets harder.

A second difficulty is that the error can be partial: part of the set can be correct while part is broken. Without a site-wide audit that distinction is invisible — looking at a single page and ruling “it works” is misleading.

  1. Scan site-wide — a single-page audit is not enough.
  2. Bind the links to a generator — a hand-written set breaks at the first addition.
  3. Check the canonicals separately — a canonical conflicting with hreflang is the most insidious error.
  4. Read the search console report regularly — the only real data coming from the live site.
  5. Bind it to a test — visible at deploy time, not weeks later.

The fifth item is applied on this site: the verification suite measures on every run that the set is complete and reciprocal, that every page gives the canonical to itself, and that the codes are standard. When a page is added and a link forgotten, the defect shows at deploy time.

And a frame: when this layer breaks, what is lost is not visibility but WRONG visibility. A user searching in German is shown the Turkish page — the page is in the index, in the rankings, but reaching the wrong person. That is a condition noticed less and harming more than not appearing at all.

One more error: missing pages

One more error belongs on the list, and on large sites it is the most common: a page declared in the set does not actually exist. The Turkish page declares its German counterpart, but that address returns a 404.

The cause is usually templated generation: the links are produced under the assumption “every page has a counterpart in every language”, and that assumption collapses when one page is untranslated. The set is counted invalid and the search engine ignores the entire declaration.

The correct behaviour is declaring only the versions that REALLY exist. If a page exists in two languages, two links are written, not three. The set must be complete, but every declared member must also be real.

On this site the rule is protected by code: when a language has no content, no page is generated for that language AND it does not enter the hreflang set. The two behaviours come from the same source, so they cannot drift apart.

A priority order to close: asked which of these errors to fix first, the answer is the canonical conflict. Because that error breaks not just the matching but the indexing — the page does not appear in search results at all. The others show the wrong version; this one shows no version.

An audit-habit suggestion: run the hreflang check EVERY time a new language or a new page is added. Those two events are the moments where nearly all the errors are born — because the existing pages’ links need updating, and that step is the most often forgotten.

And a record-keeping rule: which languages are in the set must be written down somewhere. When someone on the team adds a new language, they need to know which pages to update, and that knowledge must not live in anyone’s memory.

And a final frame: none of these errors requires intelligence — all are attention errors and all repeat. That is why the solution is not attention but automation: let the links be generated from a single source, let reciprocity be structural, and let a test verify on every deployment.

SOURCES