Canonical URLs in Nuxt

Canonical URLs tell search engines which version of a page to index when duplicate content exists. Here's how to set them up in Nuxt.
Harlan WiltonHarlan Wilton10 mins read Published Updated
What you'll learn
  • Canonical tags are hints, not directives. Google may choose differently
  • Always use absolute URLs (https://mysite.com/page, not /page)
  • Self-referencing canonicals recommended even for unique pages

Canonical URLs tell search engines which version of a page is the primary copy when duplicate content exists at multiple URLs. 67.6% of websites have duplicate content issues due to poor canonicalization.

Use canonicals for URLs with query parameters (filters, sorting), same content on multiple paths, paginated sequences, and cross-domain syndication. For redirecting users, use HTTP redirects instead. For blocking pages from search, use meta robots with noindex.

Quick Setup

Add canonical URLs to your Nuxt pages using useHead():

Basic Usage
useHead({
  link: [
    {
      rel: 'canonical',
      href: 'https://mysite.com/products/phone'
    }
  ]
})
With Query Params
// Keep sort parameter in canonical
useHead({
  link: [
    {
      rel: 'canonical',
      href: `https://mysite.com/products?sort=${sort}`
    }
  ]
})
Cross Domain
useHead({
  link: [
    {
      rel: 'canonical',
      href: 'https://otherdomain.com/original-article'
    }
  ]
})
SEO Utils v7.0.19
1.6M
120
SEO utilities to improve your Nuxt sites discoverability and shareability.

Understanding Canonical URLs

A canonical URL is implemented as a link tag in your page's head:

<link rel="canonical" href="https://mysite.com/page">

Canonical Tags Are Hints, Not Directives

Google treats canonicals as strong signals, not mandatory rules. Google's Joachim Kupke: "It's a hint that we honor strongly. We'll take your preference into account, in conjunction with other signals, when calculating the most relevant page to display in search results."

Google may choose a different canonical than you specify when:

  • Content differs significantly between URLs
  • Multiple conflicting canonical declarations exist
  • Google believes a different page is more authoritative

Google uses the canonical page as the main source to evaluate content and quality. Non-canonical URLs may still be crawled but usually won't appear in search results.

Self-Referencing Canonicals

Self-referencing canonicals are recommended even for unique pages. They establish a clear preferred URL and prevent search engines from guessing when tracking parameters or alternate URL formats appear.

Google's John Mueller: "I recommend using a self-referential canonical because it really makes it clear to us which page you want to have indexed, or what the URL should be when it is indexed."

Important Notes

  • Must use absolute URLs (Google documentation)
  • Only one canonical per page (multiple declarations cause Google to ignore all hints)
  • Must be server-side rendered (crawlers don't run JavaScript)
  • Include canonical pages in sitemaps, exclude non-canonical pages
  • Don't combine canonical with noindex meta robots. Sends conflicting signals

Common Patterns

Filter and Sort Parameters

pages/products/[category].vue
const route = useRoute()
const { sort, filter, page } = route.query
const category = route.params.category

useHead({
  link: [{
    rel: 'canonical',
    // Only include sort in canonical, remove filter and pagination
    href: sort
      ? `https://mysite.com/products/${category}?sort=${sort}`
      : `https://mysite.com/products/${category}`
  }]
})

Pagination

Use self-referencing canonicals on paginated pages. Don't point them all to page 1. Each page in the sequence has unique content and should be indexed separately.

pages/blog/[page].vue
const route = useRoute()
const page = route.params.page || '1'

useHead({
  link: [{
    rel: 'canonical',
    // Each page references itself
    href: `https://mysite.com/blog${page === '1' ? '' : `?page=${page}`}`
  }]
})

Google deprecated rel=prev/next in 2019 and now automatically recognizes pagination patterns.

Mobile/Desktop Versions

If you have separate mobile URLs (m.domain.com), keep the desktop URL as canonical even with mobile-first indexing. Google uses canonicals to understand which pages belong together, then internally selects the mobile version for indexing.

pages/products/[id].vue
const route = useRoute()
const id = route.params.id

useHead({
  link: [{
    rel: 'canonical',
    // Mobile site (m.mysite.com) points to desktop
    href: `https://mysite.com/products/${id}`
  }]
})

Don't switch canonicals from desktop to mobile URLs. Google advises against this. Use responsive design with a single URL instead.

Cross-Domain Syndication

Google no longer recommends cross-domain canonicals for syndicated content. Instead, syndication partners should use noindex meta robots to block indexing.

pages/article/[slug].vue
// If syndicating TO other sites, have them use noindex
useSeoMeta({
  robots: 'noindex, follow'
})
pages/original-article.vue
// If this IS the original, use self-referencing canonical
useHead({
  link: [{
    rel: 'canonical',
    href: 'https://mysite.com/articles/original-slug'
  }]
})

Exception: News publishers syndicating to Google News should still use cross-domain canonicals per Google's news publisher guidance.

Testing

Using Google Search Console

Use the URL Inspection tool to verify canonical implementation:

  1. Enter the URL you want to inspect
  2. Check the "Page indexing" section
  3. Compare "User-declared canonical" vs "Google-selected canonical"
  4. If they don't match, Google found conflicting signals

Note: Live tests won't show Google-selected canonical. You'll only see this for already indexed pages.

When Google Selects a Different Canonical

Common reasons Google ignores your canonical preference:

  • Content differs significantly between URLs
  • Canonical URL returns non-200 status code
  • Canonical URL uses HTTP instead of HTTPS
  • Multiple conflicting canonical declarations on page
  • Canonical chain detected (A → B → C)

Fix canonicalization issues by checking internal links, sitemap inclusion, and removing conflicting signals.

Important Checks

  • Validate absolute URL format
  • Check for canonical chains (A → B → C)
  • Verify SSR implementation (view page source, not inspected HTML)
  • Test with and without parameters
  • Don't combine canonical with noindex meta robots

Handling Edge Cases

Multiple Language Versions

For multilingual sites, combine canonicals with hreflang:

useHead({
  link: [
    {
      rel: 'canonical',
      href: 'https://mysite.com/en/page'
    },
    {
      rel: 'alternate',
      hreflang: 'fr',
      href: 'https://mysite.com/fr/page'
    }
  ]
})

Protocol/WWW Variations

Handle through server redirects in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Redirect non-www to www
    'http://mysite.com/**': { redirect: 'https://www.mysite.com/**' }
  }
})

Or handle with Nitro middleware:

server/middleware/canonicalize.ts
export default defineEventHandler((event) => {
  const host = getRequestHost(event)
  if (!host.startsWith('www.')) {
    return sendRedirect(event, `https://www.${host}${event.path}`, 301)
  }
})

Dynamic Canonicals

For dynamic routes, create a composable for consistent canonical URLs:

composables/useCanonical.ts
export function useCanonical(path: string) {
  const config = useRuntimeConfig()
  return {
    link: [{
      rel: 'canonical',
      href: `${config.public.siteUrl}${path}`
    }]
  }
}
nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://mysite.com'
    }
  }
})

Quick Check

Quick Check

You're permanently moving /old-page to /new-page. What should you use?

  • A canonical tag pointing to /new-page: Canonicals are hints, not redirects. Users would still see the old URL and Google might ignore the hint
  • A 301 redirect in routeRules: Correct! Redirects move users and pass PageRank. Use canonicals for duplicate content, redirects for moved pages
  • Both a canonical and a redirect: Using both creates confusion. Pick one: redirect for moved content, canonical for duplicates