SEO-Safe Pagination and Tag Pages

Nobody writes a blog's archive pages, and that is the problem. A static generator happily creates /page/2/ through /page/62/, a page per tag, per author, per year and per month — hundreds of URLs whose content is a list of other pages' summaries. Some are genuinely useful for readers and crawlers. Many are thin, near-duplicate pages that dilute crawl attention and show up in Search Console as "Crawled – currently not indexed" by the hundred.

This guide sets up archives on Eleventy and Hugo that help discovery without generating thin pages: crawlable pagination with self-referencing canonicals, a minimum size for tag pages, no automatic date archives, and a report that watches the count. It is part of Technical SEO for Static Sites. The numbers are from an Eleventy blog with 1,240 posts and 380 tags.

Prerequisites

  • A blog or changelog with a paginated index and tag or category archives.
  • Search Console access, to count thin and excluded pages before and after.
  • A crawl tool, or a script over the built output, to count archive URLs.

Where Thin Pages Come From

On the blog, the built output contained 1,240 posts and 1,183 archive pages:

Archive typePagesTypical content
Main pagination (/page/N/)12410 posts each
Tag pages380 tags → 612 pages with pagination211 tags had 1–2 posts
Year archives12useful
Month archives1391–15 posts
Author pages316283 authors with one post

Search Console listed 418 of the archive URLs as indexed-but-low-value or excluded as "Crawled – currently not indexed". The single-post tags and single-post authors were the bulk of them: each was a page containing one post summary that already existed on the post itself and on the main index.

Number of generated archive pages per type Vertical bars of archive page counts. Tag pages including their pagination 612. Author pages 316. Month archives 139. Main index pagination 124. Year archives 12. Archive pages by type before changes 612 Tag pages 316 Author pages 139 Month archives 124 Main pagination 12 Year archives
Tags and authors produced three quarters of the archive pages and nearly all of the thin ones.

Each paginated page must link to the next with an ordinary <a href>. A "Load more" button that fetches JSON is fine as an enhancement, but only on top of real links. Each page canonicalizes to itself — page 7 is not a duplicate of page 1. Titles should include the page number so they are unique.

{# Eleventy: posts index with pagination #}
---
pagination:
  data: collections.posts
  size: 20
  reverse: true
permalink: "/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber + 1 }}/{% endif %}"
eleventyComputed:
  title: "Articles{% if pagination.pageNumber > 0 %} – page {{ pagination.pageNumber + 1 }}{% endif %}"
---
<nav aria-label="Pagination">
  {% if pagination.href.previous %}<a href="{{ pagination.href.previous }}" rel="prev">Newer</a>{% endif %}
  {% if pagination.href.next %}<a href="{{ pagination.href.next }}" rel="next">Older</a>{% endif %}
</nav>

Raising the page size from 10 to 20 halved the main pagination from 124 pages to 62, and each page became more useful. Also link to a few pages ahead (1 2 3 … 62) rather than only "next", so deep pages are a few hops from the index instead of sixty.

Hops from the index to the oldest page with different pagination links With next-only links and 10 posts per page, the oldest posts were 124 hops from the index. With 20 per page they were 62 hops. With numbered links to first, last and nearby pages plus year archives, every post was at most 3 hops from the index. Click depth to the oldest posts Next only, 10/page 124 hops deep Next only, 20/page 62 hops deep Numbered links first and last linked Plus year archives at most 3 hops
Crawlers and readers both give up long before hop 62; numbered links and year archives are what make old posts reachable.

Rule 2: Tag Pages Need a Minimum Size

Generate a tag page only when a tag has enough posts to be a useful collection. Five worked well. Smaller tags stay visible on posts but link somewhere useful rather than to a thin page — the site search filtered by tag, or a combined "all topics" page.

// eleventy.config.js
eleventyConfig.addCollection('tagPages', (api) => {
  const counts = new Map();
  for (const post of api.getFilteredByTag('posts')) {
    for (const tag of post.data.tags.filter((t) => t !== 'posts')) {
      counts.set(tag, (counts.get(tag) ?? 0) + 1);
    }
  }
  return [...counts].filter(([, n]) => n >= 5).map(([tag]) => tag).sort();
});
eleventyConfig.addFilter('tagUrl', (tag, tagPages) =>
  tagPages.includes(tag) ? `/tags/${slugify(tag)}/` : `/search/?tag=${encodeURIComponent(tag)}`);

In Hugo, taxonomy term pages are always generated, but a term template can set noindex and omit itself from the sitemap when len .Pages is below the threshold. That keeps the URL alive for existing links while stopping it from counting as a thin indexed page:

{{ if lt (len .Pages) 5 }}<meta name="robots" content="noindex, follow">{{ end }}

noindex, follow lets crawlers still follow links from the page to the posts.

Rule 3: Give Tag Pages Something of Their Own

A tag page that clears the threshold is more valuable with a short introduction: two or three sentences written for the tag, plus links to the best posts first rather than strictly by date. On the blog, the 40 largest tags got hand-written introductions stored in a data file; those 40 pages went from "Crawled – currently not indexed" to indexed and began receiving search traffic for topic queries such as "css container queries articles". The rest remained plain lists, which is fine.

Rule 4: Drop Month Archives, Keep Years

Month archives were the least visited pages on the blog — 0.02% of page views — and the most numerous after tags. Year archives were visited, linked from the footer, and short enough to list every post of the year with titles, which made them ideal crawl paths. Removing month archives and redirecting their URLs to the year page (/2023/04/ → /2023/#april) removed 139 pages with no measurable loss. Author pages got the same treatment as tags: only authors with five or more posts have a page.

Archive and thin page counts before and after the rules Paired bars. Archive pages generated fell from 1,183 to 214. Thin or crawled-not-indexed archive URLs in Search Console fell from 418 to 37. Tag pages with an introduction receiving search clicks went from 0 to 40. Archive pages generated and thin pages indexed Before After Archive pages generated 1,183 214 Thin archive URLs indexed or excluded 418 37 Tag pages receiving search clicks 0 40
Search Console counts measured eight weeks after deployment; redirects preserved every removed URL.

Documentation Sites Have Archives Too

Pagination and tag pages sound like blog problems, but documentation generators produce the same pattern under different names. Docusaurus and many Hugo docs themes generate tag pages for every frontmatter tag; changelogs paginate; API references generate an index page per namespace, some containing a single type; versioned docs multiply every archive by the number of versions kept online.

The same rules apply. A namespace index with one entry should link to that entry rather than exist as its own page, or be noindex, follow. Changelog pagination should use large pages — fifty entries — and be complemented by per-version or per-year pages that are genuinely useful to readers looking for "what changed in 4.2". Versioned documentation should keep archive and tag pages only for the current and previous major versions; older versions can keep their content pages indexable while their generated archives are dropped. On the 3,900-page documentation site, applying the tag threshold and trimming generated index pages for versions older than two majors removed 540 URLs from the build, and the section sitemaps showed no change in indexed content pages — the removed pages had never been doing any work.

Keeping It That Way

Add the archive count to the build summary and fail the build if it grows faster than the post count — a new plugin or template change that suddenly generates hundreds of pages is caught on the pull request. The sitemap check from Generating Sitemaps for Large Static Sites should exclude noindex tag pages automatically, since it compares the sitemap with indexable pages only.

Measured Impact

MeasureBeforeAfter (8 weeks)
Archive pages generated1,183214
Thin archive URLs in Search Console41837
Maximum click depth to any post1243
Posts not indexed9622
Build time (Eleventy, hyperfine, 5 runs)18.4 s14.1 s

The drop in unindexed posts is the result that matters: with archives pointing crawlers at posts more efficiently, 74 posts that had never been indexed were picked up.

Pitfalls & Rollback

  • Canonicalizing pagination to page one. Hides posts listed on later pages.
  • Removing archive URLs without redirects. They may have external links; redirect to the nearest useful page.
  • noindex, nofollow on tag pages. nofollow stops link discovery; use noindex, follow.
  • JavaScript-only "load more". Keep real paginated URLs underneath.
  • Rollback: all rules are template and config changes. Restoring the templates regenerates the archives; the redirects can stay, since they point at pages that still exist.

Conclusion

Archive pages should earn their URLs. Keep pagination crawlable with plain links, numbered navigation and self canonicals; generate tag and author pages only above a minimum size and give the largest an introduction; prefer year archives over month archives. On the blog that cut archive pages by 82%, brought every post within three clicks of the home page, and got 74 previously ignored posts indexed.

FAQ

Should paginated pages canonicalize to page one?

No. Page two of an archive lists different posts from page one, so it is not a duplicate. Each paginated page should carry a self-referencing canonical. Pointing all of them at page one can stop search engines from discovering the posts listed on later pages.

Are rel next and rel prev still needed?

Google stopped using them as an indexing signal in 2019, though they are harmless and some other consumers read them. What matters is that each paginated page links to the next with a plain anchor element that crawlers can follow.

How many posts should a tag have before it gets its own page?

A threshold of around five posts worked well on the blog measured here. Below that, a tag page mostly repeats the summaries of one or two posts. Keep showing small tags on posts, but link them to search results or a combined page instead of generating a thin archive.

Does infinite scroll hurt SEO on static sites?

Only if it replaces links. Infinite scroll that progressively enhances a normal paginated archive, where each page also exists at its own URL with plain next links, is fine. Scroll-only loading with no URLs hides everything beyond the first batch from crawlers.

Filed underHow-tosEleventyHugo