Canonicals & hreflang

Canonical tag issues: how to find and fix them

The canonical tag problems that matter: conflicts, canonicals to redirects, 404s or noindex pages, chains, header vs HTML mismatches, and what is intentional.

rel="canonical" tells search engines which URL you prefer when several URLs show the same or very similar content. Google treats it as a strong hint, not a directive: it weighs the canonical together with redirects, internal links, sitemaps and HTTPS when choosing a canonical URL (Google: consolidate duplicate URLs). Most canonical “issues” are either harmless notices or contradictions between those signals. The skill is telling them apart.

Where canonicals can be declared

  • In the HTML <head>: <link rel="canonical" href="https://www.example.com/page/">. A canonical in the <body> is ignored.
  • In an HTTP response header: Link: <https://www.example.com/page/>; rel="canonical". This also works for non-HTML files such as PDFs.

Audit both. A CMS may write one in the HTML while a CDN or plugin adds another in the header. If they disagree, you have a conflict that a tool only reading the HTML will never see.

Use absolute URLs. Relative canonicals are allowed but easy to get wrong on staging hosts and protocol variants.

Notices that are usually fine

Situation Why it’s often intentional
Canonical points to a different URL Parameter or tracking variants, print versions and syndicated copies are supposed to point elsewhere.
No canonical at all Google will still choose a canonical. A self-referencing canonical is good practice, not a requirement.

Report these as notices. Check them only where the pattern looks wrong, for example a whole section of unique pages canonicalising to its category page.

Problems worth fixing

1. Conflicting canonicals

Two or more different canonical targets on one URL (two <link> tags, or HTML vs header). With conflicting signals, Google may disregard the hints and choose for itself. Fix it by emitting exactly one canonical from one place.

2. Canonical to a URL that returns 4xx or 5xx

You are asking search engines to prefer a page that doesn’t exist. Point the canonical at the live equivalent, or self-reference.

3. Canonical to a redirect

/page-a/ canonicalises to /page-b/, which 301s to /page-c/. The signals disagree about which URL is preferred. Update the canonical to the final URL.

4. Canonical to a noindex page

“Index that URL instead, but that URL says don’t index me.” Search engines receive contradictory instructions. Either remove noindex from the target or choose a different canonical.

5. Canonical to a URL blocked by robots.txt

Search engines can’t fetch the target to confirm it. Allow crawling of canonical targets.

6. Canonical chains

A → B, and B → C. Each page should point straight to the final preferred URL. Chains usually appear after a URL restructure where old canonicals were never updated.

7. noindex combined with a canonical to another URL

A page that is both noindex and canonicalised elsewhere sends mixed messages: “drop me” and “merge me into that page”. Google has advised against using noindex to choose a canonical within a site. Pick one intent: a canonical (or redirect) to consolidate, or noindex to exclude.

8. Canonicals that undermine hreflang

Each language or region version should be its own canonical. If /fr/ canonicalises to /en/, its hreflang annotations point to a page that has asked to be replaced, and the French version may never be shown.

How to check a canonical target properly

A finding is only confirmed if you actually fetched the target. For every canonical target:

  1. Request it and record its own status code without following redirects.
  2. Check its meta robots and X-Robots-Tag.
  3. Read its canonical: it should point to itself.
  4. Check whether robots.txt allows it.

If the target is on another domain or wasn’t crawled (for example, the audit hit its page limit), mark the finding not verified rather than guessing. Cross-domain canonicals are legitimate for syndicated content.

Fixing at scale

Canonical problems are almost always template-level:

  • Group findings by the pattern of affected URLs (all product variants, all paginated pages, all ?sort= URLs).
  • Fix the template or the CMS/SEO-plugin setting once.
  • Make sure internal links, sitemaps and redirects agree with the canonical. Canonical is one signal among several, and contradicting it elsewhere weakens it.

Confirm with search-engine data

A crawler can tell you what you declared. Only Google can tell you what it chose. Use URL Inspection in Search Console to compare the user-declared canonical with the Google-selected canonical for representative URLs. Where they differ, look for the conflicting signal: internal links, sitemaps, redirects or near-identical content.

Checklist

  • Read canonicals from HTML and HTTP headers; flag conflicts
  • Fetch every in-scope target: status, redirects, noindex, robots.txt, its own canonical
  • Mark out-of-scope or uncrawled targets “not verified”
  • Remove chains; point straight to the final URL
  • Never combine noindex with a canonical to another URL
  • Keep each hreflang alternate self-canonical
  • Align internal links, sitemaps and redirects with your canonicals
  • Spot-check Google-selected canonicals in Search Console