Set canonical URLs for all pages
A canonical URL tag is present to prevent duplicate content issues.
- Canonical URLs tell search engines which version of a page to index
- Prevents duplicate content penalties from URL variations
- Use absolute URLs including protocol and domain
- Self-referencing canonicals are a best practice
Rule Details
Canonical URLs prevent duplicate content issues by specifying the preferred page version. Google's canonicalization guidance (opens in new tab) works best when URL normalization rules such as lowercase paths and trailing-slash policy already point to the same preferred URL.
Code Example
<head>
<link rel="canonical" href="https://example.com/products/widget" />
</head>Why It Matters
Duplicate content from URL parameters, www vs non-www, or pagination dilutes ranking signals. Canonical tags consolidate those signals to the preferred URL, but they also need to stay consistent with broader canonical-chain cleanup.
When to Use Canonical Tags
| Scenario | Example | Canonical To |
|---|---|---|
| URL parameters | ?sort=price&page=1 | Base URL |
| HTTP vs HTTPS | http:// and https:// | HTTPS version |
| www vs non-www | Both exist | Preferred version |
| Trailing slash | /page and /page/ | Consistent version |
| Syndicated content | Same content on multiple sites | Original source |
Next.js Implementation
// app/products/[slug]/page.tsx
import { Metadata } from 'next'
interface Props {
params: { slug: string }
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
return {
alternates: {
canonical: `https://example.com/products/${params.slug}`,
},
}
}// pages/products/[slug].tsx (Pages Router)
import Head from 'next/head'
import { useRouter } from 'next/router'
export default function ProductPage() {
const router = useRouter()
const canonicalUrl = `https://example.com${router.asPath.split('?')[0]}`
return (
<Head>
<link rel="canonical" href={canonicalUrl} />
</Head>
)
}Dynamic Canonical URLs
// Handle pagination and filters
function getCanonicalUrl(path: string, page?: number): string {
const baseUrl = 'https://example.com'
// Remove query parameters for canonical-url
const cleanPath = path.split('?')[0]
// Include page number for paginated content
if (page && page > 1) {
return `${baseUrl}${cleanPath}?page=${page}`
}
return `${baseUrl}${cleanPath}`
}Common Mistakes
<!-- ❌ Bad: Relative URL -->
<link rel="canonical" href="/products/widget" />
<!-- ✅ Good: Absolute URL -->
<link rel="canonical" href="https://example.com/products/widget" />
<!-- ❌ Bad: Wrong protocol -->
<link rel="canonical" href="http://example.com/products/widget" />
<!-- ✅ Good: HTTPS protocol -->
<link rel="canonical" href="https://example.com/products/widget" />
<!-- ❌ Bad: Includes tracking parameters -->
<link rel="canonical" href="https://example.com/products/widget?utm_source=google" />
<!-- ✅ Good: Clean URL -->
<link rel="canonical" href="https://example.com/products/widget" />Self-Referencing Canonicals
// Every page should have a canonical-url, even if self-referencing
function PageHead({ path }: { path: string }) {
const canonicalUrl = `https://example.com${path}`
return (
<head>
<link rel="canonical" href={canonicalUrl} />
</head>
)
}Cross-Domain Canonicals
<!-- When content is syndicated to partner sites -->
<!-- On partner site: -->
<link rel="canonical" href="https://original-site.com/article" />
<!-- Original site should NOT link to partner -->Canonical vs Redirects
| Use Canonical When | Use 301 Redirect When |
|---|---|
| Same content, different parameters | Permanent page move |
| Content syndication | Domain migration |
| Print versions of pages | URL structure change |
| Session IDs in URLs | HTTP to HTTPS migration |
Exceptions
- Staging, utility, login, account, or internal search pages may intentionally use different crawl or index signals if they are not meant to rank.
- Temporary migration states can produce noisy intermediate signals; flag the live production URL pattern, not one-off transition artifacts.
- When redirects, canonicals, robots directives, or indexability signals conflict, fix the strongest final signal first instead of reporting every downstream symptom as a separate blocker.
Verification
Automated Checks
- View page source—verify canonical tag is present
- Check that canonical URL is absolute with HTTPS
- Use Google Search Console (opens in new tab) URL Inspection
- Test with Screaming Frog (opens in new tab) or a similar crawler
Manual Checks
- Verify canonical-url matches preferred URL version
Use with AI
Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.
Check
Verify implementation
Verify that this page has a canonical URL tag and that it points to the correct preferred version.
Fix
Auto-fix issues
Add or correct the canonical URL tag in the head section to prevent duplicate content issues.
Explain
Learn more
Explain how canonical URLs help search engines understand the preferred version of duplicate or similar pages.
Review
Code review
Review metadata generation, rendered HTML, structured data, and response headers related to Set canonical URLs for all pages. Flag exact routes or templates where search-facing output violates the rule, and describe how to verify the final page output.