TidyURLs
Go to Tools
BLOG
The TidyURLsJournal

Practical guides, tutorials, and insights about URLs, SEO, web development, and online marketing. Learn, troubleshoot, and get the most of the web.

Back to the Journal
TidyURLs Journal

How to Fix Duplicate Canonical URLs in Next.js

Practical insights, clear explanations, and useful ideas for understanding the web.

October 26, 20267 min read5 topics
How to Fix Duplicate Canonical URLs in Next.js
Explore the details
#Next.js#technical SEO#canonical URLs#metadata#URL redirects
October 26, 20267 min read

A Next.js page can be reachable through multiple URLs—for example, with and without www, with and without a trailing slash, or through more than one route. If those URLs serve equivalent content but declare inconsistent canonicals, search engines may have a harder time identifying the preferred URL. This tutorial shows how to choose one URL format, set route-appropriate canonical metadata, and verify the result without assuming Google will always follow your preference.

Key Takeaways

  • Choose one HTTPS hostname and one trailing-slash policy, then redirect alternate forms to it.
  • In the App Router, use metadataBase with a route-specific alternates.canonical; a canonical in a shared layout can accidentally apply to every page.
  • Canonical tags are signals, not guarantees. Align redirects, internal links, and sitemap URLs with the preferred version.
  • Check both the HTML your site serves and Google’s reported canonical for important pages.

1. Decide what the preferred URL should be

Before changing metadata, decide the canonical format for each page. For example, a site might choose:

https://www.example.com/products/widget

Then identify the alternatives that might serve the same content:

http://example.com/products/widget/
https://example.com/products/widget
https://www.example.com/products/widget/

These variations can arise from hostname configuration, trailing-slash settings, redirects, rewrites, or links created by other systems. They are not automatically separate pages in Google’s index, but inconsistent signals can make URL consolidation less clear.

Pick either www or non-www

Choose one public hostname, such as www.example.com or example.com. Configure the other hostname to redirect to it, preferably in your hosting platform, CDN, or web server. Use HTTPS consistently and avoid redirect chains where practical.

Setting metadataBase to the preferred hostname helps generate absolute metadata URLs. It does not redirect visitors or crawlers from another hostname. The redirect must be configured separately, and the preferred hostname should also be used in internal links and sitemap entries.

Pick a trailing-slash policy

Next.js uses trailingSlash: false by default. Setting it to true changes the URL format so routes end in a slash. Whichever policy you choose, make redirects and canonical metadata agree with it. Do not have one URL redirect to a slash version while the page declares the non-slash version as canonical.

The setting belongs in next.config.js or next.config.ts:

/** @type {import('next').NextConfig} */
const nextConfig = {
  trailingSlash: false,
};

module.exports = nextConfig;

This example keeps routes without trailing slashes. If your project uses a different configuration format, preserve that format and set the same option. Review the hosting layer too: an edge platform or proxy may apply its own redirects.

2. Set canonical metadata in the App Router

In the App Router, Next.js supports canonical links through the Metadata API. Set the production origin with metadataBase, then provide a canonical path for the page:

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

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

export default function RootLayout({
  children,
}: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
// app/products/widget/page.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  alternates: {
    canonical: '/products/widget',
  },
};

export default function WidgetPage() {
  return <main><h1>Widget</h1></main>;
}

With this base and path, Next.js can emit a canonical URL for https://www.example.com/products/widget. Put a page’s canonical on that page, or generate it for that route. Avoid setting a single page-specific canonical in the root layout: metadata inherited by child routes can make unrelated pages point to the same URL.

For dynamic routes, construct the canonical from the route’s validated, normalized identifier—not from an arbitrary incoming Host header or the full request URL. For example, a product with the slug widget should have a stable canonical such as /products/widget. If your route supports aliases or case variations, decide which slug is preferred and redirect the others where appropriate.

metadataBase provides the base for resolving URL metadata; it is not a substitute for choosing the correct canonical path. Check the generated HTML after changing metadata, especially when metadata is composed across layouts and pages.

3. Fix duplicates caused by routes and URL variants

A canonical tag works best when the alternate URLs genuinely represent the same or substantially equivalent content. Audit the routes and URL forms your application exposes:

  • Aliases or rewrites: If two public paths show the same page, choose one preferred path. Redirect the other when it is a permanent alias; otherwise, have the alternate page point to the preferred URL.
  • Query parameters: Tracking parameters such as utm_source often do not change the page’s main content, so the clean page URL may be the appropriate canonical. Do not strip parameters indiscriminately: parameters that create meaningfully different pages, such as distinct product configurations, may need distinct URLs.
  • Locale routes: Keep genuinely localized pages distinct and provide suitable language and regional metadata. Do not canonicalize every language version to one language merely because the templates are similar.
  • Generated links: Make navigation, breadcrumbs, structured data, and sitemap entries use the preferred hostname and slash format. Conflicting internal links weaken the consistency of your URL signals.

For the Pages Router, add a canonical link with next/head in the relevant page component and build its href from the same fixed production origin and normalized route. Avoid generating it from an untrusted request host. Do not add both a hand-written canonical and a Metadata API canonical to the same page.

4. Verify the canonical URL

Check the response and rendered page, not just the metadata source code:

  1. Test URL redirects. Request each known alternate hostname and slash form. Confirm that it reaches the chosen URL and does not loop or pass through unnecessary intermediate redirects.
  2. Inspect the final HTML. View the page source or request the final URL and find the <link rel="canonical"> element. Confirm there is one intended canonical and that its scheme, hostname, path, and trailing slash are correct.
  3. Check representative routes. Test a static page, a dynamic route, a route with query parameters, and any locale or alias routes. Ensure one page’s canonical has not leaked into another through shared metadata.
  4. Use Google Search Console for indexed URLs. URL Inspection can show Google’s selected canonical alongside the user-declared canonical when that information is available. If they differ, review redirects, internal links, sitemap URLs, duplicate content, and the page Google actually crawled. Search Console results may not update immediately after a change.

A URL parser can help inspect a URL’s components while diagnosing hostname and path differences: inspect URL components. It cannot verify your server’s redirects or determine which canonical Google selected.

Common Mistakes

  • Treating a canonical tag as a redirect. A canonical link expresses a preference; it does not make the alternate URL redirect or prevent it from being accessed.
  • Changing metadataBase but not the hosting configuration. Metadata and redirects solve different problems. Configure both where needed.
  • Putting one canonical in a shared layout. A static canonical can be wrong for every child route except one. Generate or declare canonicals at the page or route level.
  • Using inconsistent URL formats. A slash policy, hostname preference, sitemap, internal links, redirects, and canonical URLs should agree.
  • Canonicalizing distinct content together. A canonical is not a way to make unrelated pages disappear from search results. Keep separate pages self-canonical when their content or purpose is meaningfully different.
  • Assuming Google must honor the declared canonical. Search engines use canonical annotations as signals and may select a different URL based on their own evaluation.

Best Practices

  • Use one HTTPS hostname and a deliberate trailing-slash policy across the site.
  • Redirect permanent URL aliases to the preferred URL, and keep redirects and canonical links consistent.
  • Use a stable production metadataBase; do not derive the canonical origin from user-controlled request data.
  • Give each indexable page an appropriate canonical, usually a self-referencing URL unless an equivalent preferred page exists.
  • Keep canonical URLs absolute in the rendered output, and check them after deployment as well as locally.
  • Keep internal links and sitemap entries pointed at preferred URLs. Treat Search Console’s selected canonical as a diagnostic signal, not a promise that a specific change will be reflected immediately.

Conclusion

Fixing duplicate canonical URLs in Next.js means aligning the preferred hostname, slash policy, redirects, route metadata, internal links, and sitemap. Verify the canonical emitted for representative routes, then use Search Console to see how Google interprets the signals. A consistent setup helps clarify your preference, but it cannot guarantee Google’s choice.

References