Canonical bugs rarely throw errors. The site renders, the sitemap parses, search results appear. The damage shows up later as split signals — two versions of the same page competing for the same query, AI assistants citing the wrong URL, or Search Console reporting "Google chose different canonical than user." Google's own canonicalization docs are explicit that rel=canonical is a hint, not a directive. Get the hint wrong and Google picks for you.

This is an inventory. Find the bug you have. Fix it. Move on.

Trailing slash mismatch

The bug: your sitemap lists https://example.com/pricing/ and the canonical tag on that page says https://example.com/pricing. Google treats these as two separate URLs. The 2010 Search Central post on slashes still applies — each URL is evaluated independently.

The cause is usually a templating system that strips slashes for "pretty URLs" while a CMS export keeps them in the sitemap. Or a CDN rewrite rule that adds a slash on edge but the canonical tag is rendered server-side from the un-rewritten path.

Symptom: Search Console shows duplicate URLs flagged as "Alternate page with proper canonical tag" or, worse, "Google chose different canonical than user." The URL you wanted ranking does not rank.

Fix it at the edge. Pick one form. Issue 301 redirects from the other form to the canonical one. Then make every layer agree — sitemap, internal links, canonical tag, og:url, structured data url field. A correct setup looks like this:

<!-- WRONG: tag and sitemap disagree -->
<link rel="canonical" href="https://example.com/pricing">
<!-- sitemap.xml: <loc>https://example.com/pricing/</loc> -->

<!-- RIGHT: every reference uses the same form -->
<link rel="canonical" href="https://example.com/pricing/">
<!-- sitemap.xml: <loc>https://example.com/pricing/</loc> -->

Query parameters bleeding into canonical

The bug: a visitor lands on https://example.com/post?utm_source=newsletter and your CMS renders the canonical tag as the same URL — parameters and all. Now every UTM variant is its own indexable page. Click counts split. Backlink equity splits. The clean URL competes with itself.

John Mueller's guidance is direct: the canonical should point to the clean URL stripped of tracking parameters. UTM, gclid, fbclid, ref, session IDs — none of them belong in the canonical tag.

Symptom: Search Console's coverage report fills with parameter variants of the same page. AI assistants cite the UTM-tagged URL because that's what got shared on social. Internal analytics inflate session counts because a self- link with a UTM creates a phantom new visitor.

Fix: render the canonical from the route, not the request URL. Strip the search component before output.

<!-- WRONG: parameters survive into the canonical -->
<link rel="canonical" href="https://example.com/post?utm_source=newsletter&fbclid=IwAR123">

<!-- RIGHT: clean route only -->
<link rel="canonical" href="https://example.com/post">

Never UTM-tag your own internal links. That alone causes most parameter bleed.

www vs non-www, and the redirect-without-canonical trap

The bug: www.example.com 301-redirects to example.com, but the canonical tag on the apex page reads https://www.example.com/.... The redirect tells Google one thing, the tag tells it another. Google has to guess.

Worse pattern: both hosts serve content with HTTP 200 and identical canonical tags pointing at themselves. That is a true split. Backlink equity divides between the two hosts and neither version wins.

Pick one host. Apex or www, it does not matter — the Search Central blog is neutral on which. What matters is that the other host returns a 301 to the chosen one, and that every canonical, every sitemap entry, every og:url, and every internal link uses the chosen host.

Verify by curling both hosts. If curl -I https://www.example.com/ returns 200 instead of 301, you have a split. If it returns 301 but the canonical tag at the destination still references www., your tag is lying.

Mixed http and https in canonical or sitemap

The bug: HTTPS rolled out years ago, but a sitemap generator still emits http:// URLs, or a hard-coded canonical tag in a legacy template points to the insecure scheme. Google prefers HTTPS as canonical and will usually override the wrong scheme — usually is not always.

The HSTS interaction makes this worse. If your origin sends Strict-Transport-Security: max-age=31536000, browsers refuse to load http:// for a year. A canonical tag pointing to http://example.com/page is a tag pointing at a URL no real browser will ever fetch. AI crawlers without HSTS state may follow it and get a 301 you did not anticipate.

Symptom: GSC reports the canonical as the HTTPS URL, but inspection shows the page tag says HTTP. Mixed-content warnings on subresources. Some AI agents cite an http:// version that immediately redirects.

Fix: grep your codebase for http://yourdomain and replace every match. Regenerate the sitemap. Add a build-time check that fails CI if any canonical or sitemap entry uses http://.

Self-referencing canonicals on paginated pages

The bug: /blog?page=2 carries <link rel="canonical" href="https://example.com/blog?page=2">. That is correct. The mistake is the opposite — pointing page 2's canonical to /blog (page 1). John Mueller has warned against this for years. "Page 2 isn't equivalent to page 1," he said in a Search Central hangout — "the rel=canonical like that would be incorrect."

Google's October 2021 e-commerce documentation made the recommendation explicit: paginated URLs should be indexable, each with a self-referencing canonical. The 2019 deprecation of rel=next/rel=prev for indexing did not change this guidance — it strengthened it.

Why it matters: canonicalizing page 2 to page 1 either gets ignored (because Google sees the pages differ) or gets honored, in which case page 2's unique posts vanish from the index. Either outcome wastes crawl budget.

<!-- WRONG: page 2 claims to be page 1 -->
<!-- on /blog?page=2 -->
<link rel="canonical" href="https://example.com/blog">

<!-- RIGHT: page 2 is its own canonical -->
<!-- on /blog?page=2 -->
<link rel="canonical" href="https://example.com/blog?page=2">

The same rule applies to filter URLs that produce genuinely different content. If the filter changes the result set, the filtered URL is its own page and should self-canonicalize.

Cross-domain canonical without a return signal

The bug: you syndicated a post to Medium, used their canonical-import feature to point back to your domain, and then forgot to verify it. Or worse, your CMS canonical-tagged your own post to the syndicated copy. Cross-domain canonicals work — but only when one side points to the other and the target is a real, indexable page.

Symptom: the syndicated copy outranks your original because the canonical chain is broken or reversed. AI assistants cite the third-party domain.

Fix: the original always carries a self-referencing canonical. The syndicated copy carries <link rel="canonical" href="https://yourdomain.com/post">. Test by fetching both URLs and reading the head. If the chain is wrong, the platform either honored a stale tag or the syndication tool never wrote one.

Verify before shipping

Run isitready.dev on your canonical origin. The audit fetches every page in your sitemap, parses the canonical tag, and flags every mismatch — slash inconsistency, scheme drift, parameter bleed, www splits, paginated misdirection. Each finding includes the raw HTML evidence so you can fix the exact template that emitted it, not guess at which CMS field is wrong.