Canonical URLs
When to Use
Configure canonical URLs whenever a page is accessible at more than one URL — this is the norm in Drupal, not the exception. Drupal generates clean aliases via Pathauto but the same node is also reachable at
/node/123. Without canonicals, search engines may split ranking signals across duplicate URLs.
Decision
| Situation | Choice | Why |
|---|---|---|
| Standard page canonicalization | Metatag module canonical tag | Signals preferred URL without redirecting users |
| www vs non-www domain mismatch | Redirect module + server redirect | 301 redirect consolidates ranking signals |
| Trailing slash inconsistency | Server-level redirect (nginx/Apache) | Drupal alone does not enforce this consistently |
| Alias change (old URL still valid) | Redirect module auto-redirect | Pathauto integration creates 301 automatically |
| Multilingual content | hreflang + canonical per language | Each translation gets its own canonical, linked by hreflang |
| Pagination (/page=2, /page=3) | canonical to page 1 or rel=next/prev |
Prevents paginated pages from competing |
| Faceted navigation (views filters) | Disallow in robots.txt + canonical to base | Query string URLs should not be indexed |
Pattern
Metatag Canonical Configuration
Enable the Metatag module and navigate to:
/admin/config/search/metatag
Under Global defaults, set the canonical URL token:
Canonical URL: [current-page:url]
This uses Drupal's current page URL, which resolves to the alias (e.g., /blog/my-article) rather than the node path (/node/123).
For per-content-type overrides, add a Content metatag group and set:
Canonical URL: [node:url]
[node:url] resolves to the node's canonical alias including the base URL.
Drupal's Default Canonical Handling
Drupal core outputs a <link rel="canonical"> tag automatically for nodes via html.html.twig. The Metatag module overrides this with configurable tokens. Install Metatag to take control — do not rely on core's default.
Core canonical behavior:
- Node pages: resolves to alias if Pathauto alias exists
- Views pages: canonical = current URL (may include query strings)
- User pages: canonical = /user/[uid]
www vs Non-www Canonicalization
This must be handled at the server or DNS level — Drupal alone cannot reliably redirect all requests.
Nginx — redirect non-www to www:
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
Redirect module can supplement this for Drupal-handled requests:
/admin/config/search/redirect → add redirect from http://example.com to https://www.example.com
Also set in settings.php to lock the trusted host pattern:
$settings['trusted_host_patterns'] = [
'^www\.example\.com$',
];
Redirect Module — Alias Change Auto-Redirect
When Pathauto regenerates an alias, the Redirect module automatically creates a 301 from the old alias to the new one. Verify this is enabled at:
/admin/config/search/redirect/settings → "Automatically create redirects when URL aliases are changed"
Manual redirects: /admin/config/search/redirect/add
Status code decision: - 301 — permanent redirect; passes ranking signals; use for all production URL changes - 302 — temporary redirect; search engines do not pass signals; use for A/B testing or maintenance pages only
Multilingual Canonical + hreflang
Each language version of a page should have: 1. A canonical pointing to its own language URL 2. hreflang annotations pointing to all other language versions
The metatag_hreflang submodule handles this automatically when content is translated. See Metatag for Multilingual for configuration.
Pagination
For paginated content (Views pager, node body pagination):
Page 1: <link rel="canonical" href="https://example.com/blog">
Page 2: <link rel="canonical" href="https://example.com/blog"> (points to page 1)
Or use rel="prev" / rel="next" (still useful for Bing even though Google deprecated it):
<link rel="prev" href="https://example.com/blog">
<link rel="next" href="https://example.com/blog?page=2">
In Drupal, add these via hook_page_attachments() or a custom Metatag plugin. For most sites, canonical to page 1 is sufficient.
Common Mistakes
- Wrong: Relying on Drupal core canonical without Metatag → Right: Install Metatag for configurable, token-driven canonicals
- Wrong: Canonical URL token that includes query strings (
[current-page:url:absolute]on filtered views) → Right: Point to the base view URL, not the filtered URL - Wrong: No 301 redirect for www/non-www — letting both versions be indexed → Right: Pick one, redirect the other at the server level before launch
- Wrong: Internal links using
/node/123paths → Right: Always link using aliases; broken aliases expose node paths to crawlers - Wrong: Not enabling auto-redirect on alias change → Right: Enable Redirect module integration with Pathauto immediately after install
See Also
- Metatag Architecture — cascading inheritance for canonical defaults
- Redirect Management — 301/302 decision and bulk redirect management
- Metatag for Multilingual — hreflang configuration
- Robots.txt — disallowing faceted navigation query strings
- Reference: Google canonical URL guide
- Reference: Redirect module