# Canonical URL is set on each page

- **Pattern:** `ab-002517` (`seo-fundamentals.meta-tags.canonical-url`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002517
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002517)

## Why it matters

The same page reached via `/about`, `/about/`, `/about?ref=twitter`, and `https://www.yoursite.com/about` is four separate URLs to Google, and PageRank splits across all of them. Duplicate indexing dilutes ranking signals, triggers canonical-selection on Google's side (often picking a URL you did not intend), and on e-commerce sites causes faceted URLs to consume crawl budget that should go to product pages. A canonical tag consolidates all signals to the version you choose.

## Severity rationale

Medium because duplicate-URL dilution compounds silently — no error surfaces, but ranking authority leaks on every crawl.

## Remediation

Set `alternates.canonical` per page in Next.js metadata, pointing to the absolute URL you want indexed. For dynamic routes, use `generateMetadata` so each slug gets its own canonical.

```ts
// app/[slug]/page.tsx
export async function generateMetadata({ params }) {
  return {
    alternates: { canonical: `https://yoursite.com/${params.slug}` },
  }
}
```

For the Pages Router, emit a `<link rel="canonical" href="...">` inside `next/head`. Always use the HTTPS, www-or-not variant that matches your production hostname.

## Detection

- **ID:** `canonical-url`
- **Severity:** `medium`
- **What to look for:** Check for `<link rel="canonical" href="...">` tags or `metadata.alternates.canonical` in Next.js App Router. The canonical URL should point to the preferred version of each page.
- **Pass criteria:** Count all page routes. Pages have canonical URLs set, either explicitly per page or via a consistent pattern (e.g., a layout that generates canonical URLs from the current route). At least 1 canonical URL mechanism must exist. For each page route, classify as "has canonical" or "missing canonical."
- **Fail criteria:** No canonical URL mechanism found across the project. Report: `"0 of Y page routes have canonical URLs configured."`
- **Skip (N/A) when:** The project is purely an API with no HTML pages (project type detected as `api` in stack detection). Single-page marketing sites and SPAs still benefit from canonical URLs and should not be skipped.
- **Detail on fail:** `"No canonical URL configuration found. Pages may be indexed under multiple URLs (with/without trailing slashes, query parameters, etc.)"`
- **Remediation:** Canonical URLs tell search engines which version of a page is the "official" one, preventing duplicate content issues. In Next.js App Router:

  ```ts
  export const metadata = {
    alternates: {
      canonical: 'https://yoursite.com/about',
    },
  }
  ```

  Or generate them dynamically:

  ```ts
  export async function generateMetadata({ params }) {
    return {
      alternates: { canonical: `https://yoursite.com/${params.slug}` },
    }
  }
  ```

Taxons: findability

HTML version: https://auditbuffet.com/patterns/ab-002517
