sfw/fix
Multiple canonicals high

Multiple / conflicting canonical URLs on one page

One page declares two or more canonicals that disagree, so Google distrusts the signal and may pick its own URL.

What you see

URL Inspection > Page indexing
User-declared canonical: https://example.com/page?ref=nav
Google-selected canonical: https://example.com/page
Multiple rel=canonical detected (2)

What’s actually happening

The page ships more than one canonical hint and they point at different URLs. Classic combo: a hardcoded <link rel="canonical"> in the theme head plus a second one injected by an SEO plugin, or a <link> tag that says one thing while the HTTP Link: header says another. Google's rule here is blunt — when it sees conflicting canonicals it discards all of them and falls back to its own choice. In Search Console you'll see "Duplicate, Google chose different canonical than user," and the version that ranks is often the one with tracking params still attached.

Common causes

  • A theme/template hardcodes a canonical and an SEO plugin (Yoast, Rank Math, All in One SEO) injects a second one into the same <head>.
  • The HTML <link rel="canonical"> and the HTTP Link: rel="canonical" response header name different URLs.
  • A page builder or AMP plugin adds its own canonical that disagrees with the main one.
  • Server-side caching served a stale head with an old canonical while the CMS now emits a new one, so both end up in the response.
  • JavaScript rewrites or appends a canonical after the server already sent one, leaving two in the rendered DOM.

How to fix it

  1. Count the canonicals in the raw responsecurl -s https://example.com/page | grep -i 'rel="canonical"' shows every <link> tag in the source. Then curl -sI https://example.com/page | grep -i '^link:' checks the HTTP header. If you get more than one URL across both, that's the conflict — note each value.
  2. Pick one owner for the canonicalDecide whether the theme or the SEO plugin emits it — never both. In Yoast/Rank Math leave canonical management on and strip the hardcoded <link> from header.php; or disable the plugin's canonical output and keep the template one. One source, one tag.
  3. Make the header and the tag agreeIf you set a Link: rel="canonical" header (common on PDFs or via Nginx/Apache add_header), make it match the HTML tag exactly — same scheme, host, trailing slash, no tracking params. Easiest is to drop the header for HTML pages and keep only the <link>.
  4. Purge the cache, then recheck rendered HTMLClear full-page cache (Varnish, WP Rocket, Cloudflare) so a stale head can't reintroduce the old tag. Then use URL Inspection > View crawled page (or Rendering) to confirm exactly one canonical survives in the DOM Google actually sees.
  5. Confirm the survivor is a 200, indexable URLThe single remaining canonical must return 200, carry no noindex, and not redirect. A lone-but-broken canonical fails the same way two good ones do.

Stop it recurring

Let exactly one system own canonical output and assert it in code review — grep the rendered HTML for a second rel=canonical on every release.

Related errors