All rules

Sheath rule

seo-canonical-tag

HTML documents should have a canonical URL.
Package
Core
Category
SEO
Default severity
info by default
Auto-fix
Manual fix

#Why

The same page is usually reachable at several URLs: with and without a trailing slash, with ?ref= or ?utm_source= appended, on both www and the bare domain. A search engine treats those as candidates for the same content and picks one to index.

A canonical tag makes that choice explicit rather than leaving it to be inferred, and points the signals gathered by every variant at one URL.

#Examples

#Bad

<!-- Missing canonical tag -->
<head>
<meta charset="utf-8">
<title>My Page</title>
</head>
<!-- Empty canonical href -->
<head>
<link rel="canonical" href="">
</head>

#Good

<!-- With canonical URL -->
<head>
<meta charset="utf-8">
<title>My Page</title>
<link rel="canonical" href="https://example.com/page">
</head>
<!-- Self-referencing canonical -->
<head>
<link rel="canonical" href="{{ url()->current() }}">
</head>
<!-- Canonical to primary version -->
<head>
<!-- On https://example.com/page?ref=twitter -->
<link rel="canonical" href="https://example.com/page">
</head>

#Common Canonical Use Cases

Point each duplicate or alternate URL to the preferred version of the content.

Scenario Canonical Should Point To
HTTP and HTTPS versions HTTPS version
www and non-www versions Preferred version
URL with query params Clean URL without params
Mobile (m.) subdomain Desktop version (or vice versa)
Paginated content A self-referencing canonical for each page; use a view-all URL only when it is genuinely equivalent
Syndicated content Original source

#Best Practices

  1. Use absolute URLs: Always include the full URL with protocol
  2. One per page: Only include one canonical tag
  3. Self-referencing is OK: A page can be its own canonical
  4. Match content: Canonical should point to same/similar content
  5. Stay within domain: Don't canonical to different domains (usually)

#Laravel Example

<head>
<link rel="canonical" href="{{ url()->current() }}">
<!-- Or for specific routes -->
<link rel="canonical" href="{{ route('posts.show', $post) }}">
</head>

#Notes

  • A dynamic rel value is left for runtime and suppresses the missing-link diagnostic.
  • A canonical link inside Blade control flow must exist on every render path.
  • Only documents with a <head> element are checked
  • A missing canonical link is not reported when <head> contains dynamic content such as <x-seo>, <s:se_meta>, @include, @stack, @yield, or {!! ... !!}
  • The canonical tag should be in the <head>, not <body>
  • rel is a space-separated keyword list, so combinations such as rel="alternate canonical" are recognized
  • When several canonical links are present, each empty static href is reported at its own location. See best-practices-no-duplicate-in-head for duplicate declarations
  • Search engines treat canonical as a hint, not a directive

#Related Rules