Evidence — fetched pages 1, 2, 3 and 13 and diffed them
/collections/vibrators 386 products · 32 per page · 13 paginated URLs
page 1 page 2 page 3 page 13
intro lede ✓ ✓ ✓ ✓
intro paragraph ✓ ✓ ✓ ✓
shop-by-type chips ✓ ✓ ✓ ✓
Coyscore explainer ✓ ✓ ✓ ✓
FAQ (visible, ×2) ✓ ✓ ✓ ✓
FAQPage schema ✓ ✓ ✓ ✓
buying guide (3+3 img) ✓ ✓ ✓ ✓
keep-exploring ✓ ✓ ✓ ✓
meta description ✓ ✓ ✓ ✓ byte-identical
Only the 32-product grid and the "– Page N" title suffix differ.
Across the catalogue: 29 of 109 collections paginate
93 paginated URLs beyond page 1
deepest: vibrators 13 · anal-toys 11 · bondage 10 · lubricants 10
The diagnosis is right: thirteen near-identical URLs where only the grid changes is a genuine thin/duplicate signal, and it dilutes the one page that should be ranking for the category term.
"So shouldn't page 2 canonical to page 1?" — four reasons not to
1. It doesn't remove the duplicate content — which is the actual complaint. rel=canonical is an index-selection hint. It doesn't delete a block, stop a crawl, or change a byte of what renders. Even honoured perfectly, the intro, FAQ and buying guide still ship on all 93 URLs and still get crawled. You'd have added a directive and changed nothing about the thing that bothered you.
2. It probably won't be honoured. Canonical is a hint, and Google's own content comparison overrides it when the pages genuinely differ — and page 2 has 32 different products. The likely outcome is a no-op.
3. If it is honoured, here is the measured cost. Across 104 collections and 1,788 distinct products, 279 products (15.6%) appear only on page 2 or deeper in every collection they belong to. Those lose their only collection-level internal link. They stay in the XML sitemap so they don't vanish — but sitemap-only discovery is a slower, weaker refresh signal, and it lands on the products already sitting deepest in the catalogue.
4. The alternative is cheaper and strictly better. One Liquid conditional in two sections removes the duplication at source, keeps all 93 URLs crawlable, keeps every signal agreeing, and requires no bet on how Google reads a hint. There is no scenario where the canonical wins and the gate loses.
The competitor precedent — checked, and it argues the other way
peachesandcream.co.nz/collections/anal-toys?page=2
canonical → /collections/anal-toys (canonicalised to page 1)
intro copy → still present on page 2
meta desc → identical to page 1
visible words → page 1: 7,561 page 2: 7,596
Coy for comparison page 1: 2,835 page 2: 2,741
Peaches and Cream have the same duplication Coy has, and the canonical did not fix it — their page 2 still carries the repeated intro and a byte-identical meta description. They didn't solve the problem; they asked Google to look away from the URL hosting it. That's the clearest available demonstration of reason 1.
They're also a far larger, older domain, which absorbs technical debt Coy can't. Copying the tactic without the authority copies the cost and not the cushion.
The fix — gate the repeated blocks on page 1
{%- unless current_page == 1 -%}
{%- comment -%} page 2+: grid only {%- endcomment -%}
{%- else -%}
… intro lede · intro paragraph · shop-by-type chips
… Coyscore explainer · FAQ + FAQPage schema
… buying guide · keep-exploring
{%- endunless -%}
Keep on every page: breadcrumb, H1, the product grid, pagination nav, global header and footer. That's exactly what a paginated listing page should be — a grid with a grid's worth of content is not "thin".
current_page is a global Liquid object (value 1 for non-paginated resources), so this works inside the existing coy-collection-header and coy-collection-footer sections without threading paginate through. Verified against Shopify's Liquid reference.
Pagination stays crawlable, indexable and self-canonicalising. Title already appends "– Page N"; add the same suffix to the meta description while you're in there.
Found while checking this — unbounded soft-404 pagination
?page=11 → 200 · 32 products
?page=12 → 200 · 32 products
?page=13 → 200 · 2 products ← real last page
?page=50 → 200 · 0 products · self-canonical
?page=999 → 200 · 0 products · self-canonical
Every page number past the end returns a 200 with an empty grid and a self-referencing canonical — an unlimited crawlable surface of near-empty pages, on every one of the 109 collections.
Fix: emit noindex when a paginated page has an empty grid.
{%- if collection.products.size == 0 and current_page > 1 -%}
<meta name="robots" content="noindex">
{%- endif -%}
Safe here: the canonical on those URLs is self-referencing, so this is the harmless noindex-plus-canonical combination, not the contradictory one that forwards a noindex to a different target.