WriteMySEO / Blog / How to Find the hreflang Clusters Google Silently Drops
SEO technology

How to Find the hreflang Clusters Google Silently Drops

hreflang fails without errors or warnings. Here's the mechanism behind cluster confirmation, the failure modes that kill annotations, and how to audit them from your own crawl.

hreflang has no failure mode you can see. A broken annotation does not throw an error, does not produce a warning in Search Console, and does not change anything on the page. It just stops being used, and German users keep landing on the English URL.

Since Google retired the International Targeting report in Search Console, there is no first-party surface that tells you which of your annotations were accepted. You have to build that check yourself, and to build it you need to understand what Google is actually assembling when it reads an hreflang attribute.

hreflang is a cluster, not a tag

The thing Google builds from your annotations is a set of alternates — a group of URLs each labeled with a language and optional region. The attribute on any single page is not self-contained; it is one vote toward the existence of a group.

Google has documented that annotations must be confirmed bidirectionally: if page A declares B as its de-DE alternate, B must declare A in return. Without that return link, the documentation says the annotations may be ignored or interpreted incorrectly. The mechanism is anti-spam — without reciprocity, any site could claim to be the French alternate of a competitor.

This is why hreflang behaves so unlike other on-page signals. A rel=canonical on one page does something on its own. An hreflang attribute on one page does nothing on its own. The unit of success is the cluster, and a cluster with one broken edge can lose more than that one edge.

Why reciprocity breaks in practice

Reciprocity almost never breaks because someone forgot to add the tag. It breaks because the two sides of the pair disagree about the exact URL string.

hreflang matching is on the URL as a string, not on "whatever this resolves to." Treat any difference in scheme, host, case, trailing slash, or query as a different URL, because that is how it will be treated upstream.

Canonical conflicts delete annotations quietly

The second large failure class is a conflict between hreflang and canonicalization. Google's documentation is explicit that hreflang annotations should point to canonical URLs, and that each page's self-reference should match its own canonical.

The common accident: a regional page carries rel=canonical pointing at the global page — someone added it to "avoid duplicate content" between en-us and en-gb — while also carrying hreflang annotations. You have now told Google two incompatible things: this URL is not the one to index and this URL is the one to serve British users. Google's documented guidance resolves this in favor of the canonical, which means the regional URL drops out of the index and the cluster edge pointing at it has nowhere to land.

A softer version of the same problem happens without any explicit canonical tag. If your en-us and en-gb pages are near-identical, Google may cluster them on its own and pick one as canonical. The reasonable inference — not something Google has documented in detail — is that annotations naming the non-selected duplicate become much less useful, because the selected canonical is what actually competes in results. If your regional variants differ only in currency symbol and a phone number, expect this.

The failure modes worth checking, in order

FailureWhat you see in a crawlEffect
Missing return linkA → B exists, B → A absentEdge unconfirmed; likely ignored
URL string mismatchTrailing slash, scheme, host differSame as missing return link
Target redirectshreflang target returns 301/302Annotation names a non-canonical URL
Target is 404/410/noindexNon-indexable alternateCluster member cannot be served
Canonical points elsewhereCanonical ≠ self-referencing hreflangAnnotations likely discarded
Invalid codeen-uk, en_US, hreflang="us"Entry ignored; region alone is invalid
Missing self-referencePage lists siblings but not itselfWeakens cluster membership
Conflicting sourcesSitemap and <head> disagreeUnpredictable resolution

On language codes: Google documents ISO 639-1 for language and optional ISO 3166-1 Alpha 2 for region. The United Kingdom is GB, not UK. A region without a language (hreflang="us") is not valid. Underscores are not valid separators.

Building the validation dataset

The check is a graph problem, and you already have the data if you crawl with hreflang extraction enabled. Export one row per annotation edge, then:

-- unconfirmed edges: A declares B, B never declares A
SELECT a.source_url, a.target_url, a.hreflang
FROM hreflang_edges a
LEFT JOIN hreflang_edges b
  ON b.source_url = a.target_url
 AND b.target_url = a.source_url
WHERE b.source_url IS NULL;

Then join target_url against your crawl's status and canonical columns to catch redirecting, non-indexable, and canonical-conflicting targets in the same pass. Count unconfirmed edges as a percentage of total edges and track it per release — it is a far better health metric than "do we have hreflang: yes/no."

If you implement in HTTP headers for non-HTML files, the syntax is:

Link: <https://example.com/en-gb/guide.pdf>; rel="alternate"; hreflang="en-GB",
      <https://example.com/en-us/guide.pdf>; rel="alternate"; hreflang="en-US"

For large sites, XML sitemaps are usually the more reliable implementation, because the entire cluster is generated from one data structure and reciprocity is a property of the generator rather than of thirty templates.

Measuring whether it is actually working

hreflang is a serving signal, not a ranking signal — Google's position is that it helps select which of your URLs to show, not how high it shows. So do not measure it with total clicks. Measure it with the country-by-page crosstab.

Pull country and page together from the Search Console API or the BigQuery export and ask one question per cluster: for users in Germany, what share of impressions went to the de-DE URL versus its siblings? Baseline that share before a fix and re-measure after. Correct swapping shows up as a shift in which URL receives a given country's impressions, with roughly stable cluster-level totals. If the share barely moves, the annotations were probably never the constraint — check for an unconfirmed edge or a canonical conflict before assuming Google ignored you.

What to do

  1. Crawl with hreflang extraction on, build the edge list, and run the reciprocity join. Fix unconfirmed edges first; they are the largest category.
  2. Normalize URL generation to one function. Trailing slash, scheme, and host should be impossible to get wrong per-template.
  3. Assert that every page's self-referencing hreflang equals its own rel=canonical. Fail the build if it does not.
  4. Delete cross-regional canonicals that point at a global page while hreflang claims regional variants exist.
  5. Validate codes against ISO 639-1 and ISO 3166-1 Alpha 2 lists rather than eyeballing them, and add an x-default for your language selector or fallback page.
  6. Store the country × page impression split per cluster monthly, so the next time someone asks whether hreflang is working, you have a before.
hreflanginternational seocrawlingSearch Console

WriteMySEO produces marketing content, not legal, medical, financial, or compliance advice. Figures cited reflect publicly reported industry data at time of writing and shift over time.

Get started

We write this well about your industry, every month.

AI-drafted, human-reviewed SEO content on a flat subscription. Blog posts, metadata, schema, and internal links, shipped on a monthly rhythm.

See plans

More from the blog