Index of every page on this site: llms.txt

Duplicate Content SEO in Nuxt

Identify equivalent Nuxt URLs, suggest a preferred canonical, and redirect URLs that have permanently moved.
Harlan Wilton15 mins read Published Updated
What you'll learn
  • Duplicate content lives at more than one URL. Equivalent variants can require unnecessary crawling; Google can consolidate signals automatically
  • Google does not penalize duplicate content on its own. Its selected canonical can differ from your preference
  • Use 301 redirects for permanent moves and canonical tags for duplicates you need to keep live

Duplicate content is the same content living at more than one URL. Google can consolidate it automatically. Consistent canonical signals help express your preference and manage unnecessary crawling.

Google doesn't penalize duplicate content unless you're deliberately scraping other sites.

Common Causes

URL Variations

www vs non-www

www.mysite.com and mysite.com are treated as separate sites. Choose one, redirect the other.

HTTP vs HTTPS

http://mysite.com and https://mysite.com create duplicates. Always redirect HTTP to HTTPS.

Trailing slashes

/products and /products/ are different URLs. Pick one format site-wide.

This option changes prerendered file layout. It does not configure a redirect:

nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      autoSubfolderIndex: false
    }
  }
})

For HTTPS and www vs non-www redirects, configure at the server level (Netlify, Vercel, Cloudflare) for best performance and SEO.

Query Parameters

URL parameters can create many variations. Three binary filters generate 8 combinations. Compare their content before calling them duplicates.

/products
/products?color=red
/products?color=red&size=large
/products?color=red&size=large&sort=price
/products?color=red&size=large&sort=price&page=2

Fix: compare the actual content. Use canonical tags for equivalent variations. Keep distinct indexable filter and pagination pages self-canonical. Use noindex when the goal is exclusion, not consolidation.

If your app treats parameter order as irrelevant, ?sort=price&filter=red and ?filter=red&sort=price identify equivalent content with different URLs. Enforce consistent parameter order in canonical URLs; see the Query Parameters guide for the implementation.

Tracking Parameters and Pagination

Analytics params (utm_source, fbclid, gclid) do not change content but create duplicate URLs. Paginated pages can show distinct content and need their own canonical URLs.

Fix: strip tracking parameters. Strip tracking parameters (utm_source, fbclid, gclid) from canonical URLs. See the Query Parameters guide for configuration. A canonical can omit tracking parameters while preserving the visitor's URL.

Fix: self-reference paginated pages. Each paginated page has unique content. Use self-referencing canonicals; don't point page 2 to page 1. See the Pagination SEO guide for the implementation.

Print and Mobile Versions

Printer-friendly URLs (/article?print=true) and mobile subdomains (m.mysite.com) create duplicates.

Fix: Canonical to desktop version

pages/article.vue
<script setup lang="ts">
const siteUrl = useSiteConfig().url

useHead({
  link: [{
    rel: 'canonical',
    // Always point to main URL
    href: `${siteUrl}/article`
  }]
})
</script>

For print, use CSS @media print instead of separate URLs.

Session IDs and Click Tracking

Session IDs in URLs create infinite variations.

/products?sessionid=abc123
/products?sessionid=xyz789
/products?sessionid=def456

Fix: Don't put session IDs in URLs. Use cookies. If session parameters create a crawl trap, robots.txt can express a crawl restriction. It does not consolidate or deindex blocked URLs:

public/robots.txt
User-agent: *
Disallow: /*?sessionid=
Disallow: /*&sessionid=
Disallow: /*?sid=
Disallow: /*&sid=

Or use the Robots module:

Robots 
   
Tame the robots crawling and indexing your site with ease.

Finding Duplicate Content

Google Search Console

Use the Page indexing report to identify duplicates:

  1. Open Search Console
  2. Go to "Indexing" → "Pages"
  3. Look for:

    • "Duplicate, Google chose different canonical than user"
    • "Duplicate without user-selected canonical"
    • "Alternate page with proper canonical tag"

Click each category to see affected URLs. If Google chose a different canonical than you specified, conflicting signals exist.

Using URL Inspection:

  1. Enter any URL
  2. Check "User-declared canonical" vs "Google-selected canonical"
  3. If they differ, Google found stronger signals pointing to a different URL

View page source (not DevTools) to verify canonical tags are server-rendered:

curl https://mysite.com/products?sort=price | grep canonical

Check for canonicalization conflicts:

  • Multiple rel="canonical" tags on same page
  • Canonical in <head> vs HTTP header
  • Canonical points to redirect or noindexed page
  • Canonical URL returns 4xx/5xx status

Test redirect chains:

curl -I https://mysite.com/old-url

Check the intended permanent 301 or 308 and confirm the destination terminates without a chain.

Screaming Frog

Screaming Frog detects exact and near-duplicate content:

Exact duplicates: Pages with identical HTML (MD5 hash match)

Near duplicates: Pages with 90%+ similarity (minhash algorithm)

Setup:

  1. Enable near duplicates: Config > Content > Duplicates
  2. Crawl your site
  3. Go to "Content" tab
  4. Filter by "Exact Duplicates" or "Near Duplicates"

Check these columns:

  • Closest Similarity Match: Percentage match to most similar page
  • No. Near Duplicates: Count of similar pages
  • Hash: MD5 hash for exact duplicate detection

Screaming Frog auto-excludes nav and footer elements to focus on main content. Adjust threshold if needed (default 90%).

Manual and Third-Party Tools

Use Google site search to find duplicates manually:

site:mysite.com "exact title text"

If multiple URLs share a title, compare their content. A shared title alone does not establish duplication.

Siteliner is a free tool that crawls up to 250 pages and shows a duplicate content percentage. Copyscape detects external duplicate content, i.e. other sites copying you. Both are useful for content audits but don't replace Search Console or Screaming Frog for technical SEO.

Canonical vs 301 Redirect

When to UseCanonical Tag301 Redirect
Need both URLs live✅ Yes❌ No
User should see one URL❌ No✅ Yes
Products in multiple categories✅ Yes❌ No
Old page no longer needed❌ No✅ Yes
UTM tracking parameters✅ Yes❌ No
www vs non-www❌ No✅ Yes
HTTP vs HTTPS❌ No✅ Yes
Moved/renamed pages❌ No✅ Yes

Canonical tags are hints, not directives. Google may choose another canonical. Both versions remain accessible. Use for duplicates you need (tracking params, multiple category paths).

301 and 308 redirects are permanent. Users see the redirect target. They provide a canonicalization signal; indexing and ranking changes are not guaranteed. Use for outdated or unnecessary URLs.

Keep signals consistent. If an old URL redirects to a replacement, the replacement page should declare the intended canonical URL.

Decision Tree

Examples:

  • http://mysite.com → https://mysite.com: 301 redirect
  • www.mysite.com → mysite.com: 301 redirect
  • /products?utm_source=twitter → /products: Canonical tag
  • /products/shoes and /sale/shoes (same product): Canonical tag (one canonical, one alternate)
  • /products?filter=red: Self-canonical if distinct and indexable; consolidate only if equivalent, or use noindex for exclusion
  • /old-page → /new-page: 301 redirect

Common Mistakes

Mistake 1: Canonicalizing all paginated pages to page 1

<!-- ❌ Wrong - suggests one canonical for distinct pages -->
<script setup lang="ts">
useHead({
  link: [{ rel: 'canonical', href: 'https://mysite.com/blog' }]
})
</script>

Each paginated page should reference itself.

Mistake 2: Using relative canonical URLs

<!-- Supported relative URL, but Google recommends absolute URLs -->
<link rel="canonical" href="/products/phone">

<!-- Recommended absolute URL -->
<link rel="canonical" href="https://mysite.com/products/phone">

Google recommends absolute canonical URLs.

Mistake 3: Combining canonical with noindex

<!-- ❌ Conflicting signals -->
<script setup lang="ts">
useHead({
  link: [{ rel: 'canonical', href: 'https://mysite.com/page' }]
})
useSeoMeta({
  robots: 'noindex, follow'
})
</script>

Canonical says "this is a duplicate of X." Noindex says "don't index this." Pick one.

Mistake 4: Canonical chains

Page A → canonical → Page B → canonical → Page C

A chain dilutes the signal and search engines may not follow it all the way through. Canonical directly to the final target instead.

Mistake 5: Client-side canonicals in SPAs

Google can process JavaScript canonicals. Server-rendered canonicals are available earlier and reduce dependence on rendering.

Preventing Duplicate Content

Configure Trailing Slashes

This setting controls the prerendered file layout. Your static host determines slash redirects:

nuxt.config.ts
export default defineNuxtConfig({
  // Emit prerendered routes as nested index.html files
  nitro: {
    prerender: {
      autoSubfolderIndex: true
    }
  }
})

For dynamic redirects, use server middleware.

Validate Parameter Values

Prevent infinite URL variations by whitelisting allowed parameter values:

const allowedSortValues = ['price', 'name', 'date', 'rating']
const route = useRoute()
const sort = route.query.sort

if (sort && !allowedSortValues.includes(sort as string)) {
  // Redirect to base URL or default sort
  await navigateTo({ query: { ...route.query, sort: undefined } })
}

Block Low-Value Pages

Choose crawl-control rules from your application's content policy. The example below assumes these variants should not be crawled. A blocked URL can still be indexed, and Google cannot read its canonical or noindex metadata. Authenticate private admin pages. Do not block useful filter or pagination pages merely because they have parameters:

public/robots.txt
User-agent: *

# Block search results
Disallow: /search?
Disallow: /*?q=
Disallow: /*?query=

# Block filters
Disallow: /*?filter=
Disallow: /*&filter=

# Block tracking params
Disallow: /*?utm_source=
Disallow: /*?fbclid=
Disallow: /*?gclid=

# Block session IDs
Disallow: /*?sessionid=
Disallow: /*?sid=

Or configure via the Robots module:

Robots 
   
Tame the robots crawling and indexing your site with ease.

Automatic Handling with Nuxt SEO Utils

Nuxt SEO Utils handles canonical URLs, trailing slashes, and parameter normalization automatically through site config:

SEO Utils 
   
SEO utilities to improve your Nuxt sites discoverability and shareability.

Configure once in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  site: {
    url: 'https://mysite.com',
    trailingSlash: false
  }
})

The module automatically:

  • Generates canonical URLs with correct trailing slash handling
  • Strips tracking parameters from canonicals
  • Normalizes URL formats across your site

Checklist

Checklist
  • Choose one canonical domain (www or non-www, HTTP or HTTPS) and redirect the rest
  • Pick one trailing slash format and enforce it site-wide
  • Canonicalize equivalent variants; keep distinct pagination pages self-canonical
  • Strip tracking parameters (utm_source, fbclid, gclid) from canonical URLs
  • Prefer absolute canonical URLs to avoid resolving relative paths against an unexpected base
  • Never combine noindex with a canonical tag on the same page
Was this page helpful?