Setting Canonical URLs for SPA Pagination

Pagination and faceted filtering are where SPA canonical strategy gets subtle: page two of a listing is not a duplicate of page one — it contains different items — yet a sort parameter usually is a duplicate. Treating them the same is how sites either lose deep pages from the index or bloat it with near-identical filter URLs. This page gives the rules for paginated and filtered routes, extending canonical URL management.

Canonical target for each listing variant Paginated pages self-canonicalize because they list different items, while sort and filter variants canonicalize to the clean listing URL. Which URL should each listing variant declare canonical? /products?page=2 different items rel=canonical /products?page=2 self — index it /products?sort=price same items, reordered rel=canonical /products fold into clean URL /products?color=blue filter, not unique rel=canonical /products fold into clean URL
Deeper pages point at themselves so their items stay indexed; sort and filter states fold back into the clean listing URL.

Step-by-step fix

  1. Self-canonicalize each paginated page. Page two points at page two, because it lists different content.

    <!-- ✅ On /products?page=2 -->
    <link rel="canonical" href="https://example.com/products?page=2">
    <!-- ❌ Do NOT canonicalize page 2 to page 1 — its items would never be indexed -->
  2. Canonicalize non-unique filter/sort states to the clean URL. A re-sorted list is the same content in a different order.

    <!-- ✅ On /products?sort=price (same items, reordered) -->
    <link rel="canonical" href="https://example.com/products">
  3. Keep pagination crawlable with real links. Crawlers must be able to reach deeper pages without executing click handlers.

    <!-- ✅ Crawlable pagination -->
    <a href="/products?page=2" rel="next">Next</a>
  4. Set these in the rendered head per route, mutating a single canonical tag as the user paginates — reuse the manager from fixing duplicate canonical tags.

What the index holds under each pagination canonical choice Canonicalizing every page to page one leaves only page-one items in the index and drops the items unique to deeper pages, whereas self-canonicalizing each page keeps every page's items indexed. Canonicalize to page 1 and the deeper items vanish Every page → page-1 canonical Google index for /products page-1 items ✓ indexed page-2 items ✗ dropped page-3 items ✗ dropped Each page self-canonical Google index for /products page-1 items ✓ indexed page-2 items ✓ indexed page-3 items ✓ indexed
Self-canonicalizing each paginated page keeps items that appear only on deeper pages in the index; folding them all onto page one loses them.

Validation

  • Each paginated page reports itself as the user-declared canonical in URL Inspection.
  • Sort/filter variants report the clean listing URL as canonical.
  • site:example.com/products returns distinct paginated pages, not just page one.
  • Coverage report shows deep pages indexed, not marked as duplicates.
onClick pagination versus real anchor links Pagination bound to onClick handlers leaves the crawler stranded on page one, while real anchor links let it hop from page one to two to three. A crawler follows hrefs, not click handlers Pagination via onClick page 1 page 2 page 3 deeper pages never discovered Pagination via <a href> page 1 page 2 page 3 crawler hops through every page
Real anchor links let the crawler walk page to page; onClick handlers strand it on page one so deeper pages stay undiscovered.

Reference

// Decide the canonical for a listing route
function canonicalForListing({ path, page, sort, filter }) {
  const base = `https://example.com${path}`;
  if (page && page > 1) return `${base}?page=${page}`; // self-canonical: unique items
  // sort/filter that don't create unique content → clean URL
  return base;
}
How canonicalForListing picks a canonical URL The helper checks whether the page number is greater than one; if so it returns a self-canonical paged URL, otherwise it returns the clean base URL, folding sort and filter states into it. One check decides the canonical for a listing route Listing route path, page, sort, filter page > 1 ? yes no Self-canonical — index it base + "?page=" + page Clean base URL sort and filter states fold in here
The helper is one branch: pages beyond page one self-canonicalize, everything else folds into the clean base URL.

Frequently Asked Questions

Should paginated pages canonicalize to page one? No. Each paginated page should self-canonicalize, because page two contains different items than page one. Canonicalizing every page to page one tells Google the deeper pages are duplicates, and the items only listed there may never be indexed.

How should I handle filter and sort parameters? Filter and sort states that do not create meaningfully unique content should canonicalize to the clean listing URL. States that do produce unique, search-worthy content can self-canonicalize, but be conservative to avoid index bloat.

← Back to Canonical URL Management in SPAs