next js canonical url

How to Set a Canonical URL in Next.js (App Router)

Set canonical URLs in the Next.js App Router with alternates.canonical and metadataBase, including dynamic routes, query parameters, and common mistakes to avoid.

Open Next Metadata Generator

Quick answer: how do I set a canonical URL in Next.js?

In the App Router, set the canonical URL with the `alternates.canonical` field of the Metadata object, then set `metadataBase` in the root layout so relative canonical paths resolve to your production host. Use a static `metadata` export for fixed pages and `generateMetadata` for dynamic routes.

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "Pricing",
  alternates: {
    canonical: "/pricing",
  },
};

Why canonical URLs matter

A canonical URL tells search engines which URL is the preferred version of a page when the same or similar content is reachable from multiple URLs. Without it, duplicate URLs from query parameters, trailing slashes, or www and apex hosts can split ranking signals or let Google pick the wrong canonical.

  • Consolidate duplicate or near-duplicate URLs to one preferred URL.
  • Avoid query-parameter and trailing-slash duplicates competing in search.
  • Keep the canonical aligned with the URL you actually want indexed.

Set metadataBase so relative canonicals resolve

When canonical and Open Graph URLs use relative paths, set `metadataBase` in the root layout to your canonical production host. Next.js then resolves relative `alternates.canonical` and `openGraph.url` values into absolute URLs.

// app/layout.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  metadataBase: new URL("https://example.com"),
  alternates: {
    canonical: "/",
  },
};

Canonical URLs for dynamic routes

For dynamic segments such as app/blog/[slug]/page.tsx, build the canonical inside `generateMetadata` from the route params so every page gets its own canonical URL instead of a shared one.

import type { Metadata } from "next";

type PageProps = {
  params: Promise<{ slug: string }>;
};

export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
  const { slug } = await params;

  return {
    alternates: {
      canonical: "/blog/" + slug,
    },
  };
}

Canonical URLs for pagination and query parameters

Filters, sorting, and tracking parameters create many URLs for one logical page. Point the canonical at the clean URL so search engines consolidate them, unless a paginated page is genuinely a distinct indexable page.

  • Drop tracking parameters such as utm_source from the canonical.
  • For filtered lists, canonicalize to the unfiltered page when the content is essentially the same.
  • Keep page 2 and beyond self-canonical only when each page should be indexed independently.

Common Next.js canonical URL mistakes

Most canonical issues come from drift between the canonical, the Open Graph URL, and the real indexable route, or from host and slash inconsistencies.

  • Canonical drift: `alternates.canonical` and `openGraph.url` pointing at different URLs.
  • Mixing www and apex, or http and https, in the canonical host.
  • Trailing-slash mismatch between the canonical and the route Next.js actually serves.
  • Reusing one canonical across every dynamic route instead of per-page values.
  • Setting a canonical to a noindex or redirected URL.

Verify the canonical URL

After deploying, confirm the rendered canonical link tag matches the URL you want indexed, then validate it in Google Search Console.

  • View source and check the canonical link tag in the document head.
  • Use the URL Inspection tool to see the Google-selected canonical.
  • Confirm the canonical returns HTTP 200 and is not blocked by robots.

Generate canonical metadata quickly

Use the Next Metadata Generator to produce a typed App Router starter with the canonical URL, Open Graph URL, and Twitter fields aligned, then paste it into the route and adjust per-page values.

Next.js canonical URL scenarios

ScenarioWhereCanonical approach
Static page`metadata` exportSet `alternates.canonical` to the page path such as `/pricing`.
Dynamic route`generateMetadata`Build the canonical from route params, for example `/blog/` + slug.
Paginated or filtered list`generateMetadata`Point the canonical at the clean page URL without tracking or filter query params.

Use FrameworkKit to generate the starter code, then review the output before shipping it in production.

Generate with Next Metadata Generator

Next Metadata resources

FAQ

How do I set a canonical URL in the Next.js App Router?

Set `alternates.canonical` in the Metadata object, using a static `metadata` export for fixed pages or `generateMetadata` for dynamic routes, and set `metadataBase` in the root layout so relative canonical paths resolve to absolute URLs.

Should the canonical URL be absolute or relative in Next.js?

You can use a relative path in `alternates.canonical` as long as `metadataBase` is set. Next.js resolves it into an absolute URL using that base.

How do I set canonical URLs for dynamic routes?

Use `generateMetadata`, read the route params, and build the canonical from them, for example `/blog/` + slug, so each dynamic page has its own canonical URL.

Why is Google choosing a different canonical than mine?

Google treats your canonical as a signal, not a directive. If your canonical points at a duplicate, a noindex page, a redirect, or drifts from the Open Graph URL and internal links, Google may pick a different URL. Keep all signals consistent.

Do canonical and Open Graph URLs need to match?

For normal content pages they should identify the same public page. Build both from the same canonical URL input so social previews and the indexable page stay aligned.

Related tools