Canonical URL resolves through a redirect: how to spot it
A canonical that redirects sends search engines on an extra hop before the real URL. squirrel checks the tag against the page's own redirect chain.
What a canonical chain is
A <link rel="canonical"> names the URL you want a page indexed under. It should be the address that serves the content directly, with no redirect in between.
When the canonical points at a URL that redirects, the crawler has to follow a hop before it reaches the page, and the signal is weaker than a direct one. The common causes are a canonical built from a stored URL that has since moved, a canonical using the wrong scheme or host variant, and a canonical that points at the requested URL on a page that redirected on the way in.
What squirrel checks
The rule runs on every crawled page. It reads the first link[rel="canonical"] in the document and resolves it against the page URL. It can emit several checks:
page-redirect-chainwarns when the page itself redirected before serving content. Message:Page redirects before content is served, with the hops listed.canonical-chainis skipped when there is no canonical tag. Message:No canonical tag found.canonical-chainwarns when the canonical href cannot be parsed. Message:Invalid canonical URL.canonical-protocolwarns when the page is HTTPS and the canonical is HTTP. Message:Canonical points to HTTP instead of HTTPS.canonical-chainwarns when the canonical URL matches one of the redirect-looking patterns/?...redirect,/go/,/out/,/link/or/r/. Message:Canonical URL may be a redirect. It passes otherwise withCanonical URL appears direct.canonical-targetreports info when the canonical names a different URL from the page, ignoring a trailing slash difference. Message:Page canonicalizes to different URL.canonical-redirectswarns when the canonical names the exact URL that was requested and that request redirected. Message:Canonical URL resolves through a redirect chain, with the hops listed.
The last check compares request targets, not normalised forms, so /page, /page/ and /page?x=1 are treated as distinct. Only the one that was actually fetched carries the chain. Severity warning, weight 5.
How to fix it
<link rel="canonical" href="https://example.com/pricing" />Point the canonical at the final URL: the scheme, host and path that answer 200 directly. Generate it from the resolved route rather than from a stored string, so it moves when the route does.
A cross-page canonical, where one page deliberately points at another, is reported as info rather than a defect. That is a normal deduplication choice.
| Rule ID | crawl/canonical-chain |
| Category | Crawlability |
| Scope | Per-page |
| Severity | warning |
| Weight | 5/10 |
Enable / disable
Disable this rule
[rules]
disable = ["crawl/canonical-chain"]Disable all Crawlability rules
[rules]
disable = ["crawl/*"]Enable only this rule
[rules]
enable = ["crawl/canonical-chain"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- crawl/redirect-chain: multi-hop chains anywhere on the site.
- crawl/pagination: paginated pages canonicalizing to page 1.
- crawl/indexability-conflicts: directives that disagree about the same URL.
- url/trailing-slash: the slash difference this check normalises away.
Crawlability findings ship in every audit next to the SEO, performance and agent experience rules. See The Screaming Frog alternative for agents for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the Crawlability section of the report. Each canonical is reported with its target and any redirect hops behind it. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.