[object Object]

The HubSpot blog listing page is a quietly catastrophic SEO surface on most portals. Default templates generate ?page=2, ?page=3 URLs that compete with the canonical listing, all sharing the same title tag and meta description, all internally linked, all crawled, all indexed. Google sees seventeen near-duplicate pages of your blog and decides none of them deserves to rank. Then you wonder why your blog index lost half its traffic last quarter.

The fix is HubL plus canonical discipline plus internal linking that does not waste authority. Here is the working pattern.

What is actually wrong with the default

Three problems compound.

  1. Paginated URLs share title and meta with page one, creating duplicate metadata at scale.
  2. Pagination links appear in every blog post, sending link equity to thin paginated pages instead of to the canonical listing.
  3. No rel="prev" or rel="next" is rendered, and even those are deprecated as Google signals in 2026, so there is no native way to tell crawlers these are sequential.

The cumulative effect is dilution of the listing’s authority and confusion about which URL deserves the rank.

The fix at a glance

Three rules.

  • Canonical: every paginated page canonicalizes to page one. Yes, even page two.
  • Title and meta: pages two and above get a Page N suffix, but the canonical still points to page one. The suffix is for the rare user landing there.
  • Internal linking: blog post related-posts and main nav links go to page one, never to paginated URLs.

This is conservative. Some SEOs argue paginated pages should self-canonicalize. They are not wrong in pure theory. In practice, on a HubSpot blog with under 5,000 posts, the simpler “canonicalize to page one” rule recovers traffic faster and is easier to maintain.

The HubL template change

Open your blog listing template. Find the head block. Add this.

{% if current_page_num and current_page_num > 1 %}
  <link rel="canonical" href="{{ group.absolute_url }}" />
  <title>{{ group.public_title }} — Page {{ current_page_num }}</title>
  <meta name="robots" content="noindex,follow" />
{% else %}
  <link rel="canonical" href="{{ group.absolute_url }}" />
  <title>{{ group.public_title }}</title>
{% endif %}

The noindex,follow on pages two and up is the lever. Google does not index them but still follows links from them so individual blog posts remain discoverable. The canonical reinforces the signal.

If you have a deep archive that you want indexed, replace noindex,follow with index,follow and accept the duplicate-content risk. Most blogs do not have a deep enough archive to justify it.

The pagination component

Default pagination shows Previous 1 2 3 4 5 Next. Replace with a numbered pagination that uses HubL to render proper URLs and rel="nofollow" is not added, since these are internal links.

<nav class="blog-pagination" aria-label="Blog pagination">
  {% if last_page_num > 1 %}
    {% if current_page_num > 1 %}
      <a href="{{ blog_page_link(current_page_num - 1) }}">Previous</a>
    {% endif %}

    {% for page in range(1, last_page_num + 1) %}
      {% if page == current_page_num %}
        <span aria-current="page">{{ page }}</span>
      {% else %}
        <a href="{{ blog_page_link(page) }}">{{ page }}</a>
      {% endif %}
    {% endfor %}

    {% if current_page_num < last_page_num %}
      <a href="{{ blog_page_link(current_page_num + 1) }}">Next</a>
    {% endif %}
  {% endif %}
</nav>

blog_page_link(n) is HubSpot’s HubL function that produces clean pagination URLs. Do not hand-construct query strings; they break with the next theme update.

Stop linking to paginated URLs from posts

The default blog post template’s “recent posts” or “related posts” sidebar often links to /blog?page=2. Audit your post template. Every such link should point to the blog index root, a specific tag, or a topic cluster page, never to a paginated URL.

<!-- Before, in post template -->
<a href="{{ group.absolute_url }}?page=2">More articles</a>

<!-- After -->
<a href="{{ group.absolute_url }}">More articles</a>

That single change concentrates link equity where it belongs.

Topic and tag listings need the same fix

Every blog tag and topic listing in HubSpot is also paginated and suffers identically. The same head-block conditional applies. Wrap it in a partial and include from each listing template.

{% include "../partials/pagination-canonical.html" %}

One file to update when the pattern evolves. Better than three templates drifting.

Sitemap discipline

HubSpot’s auto-generated sitemap includes paginated URLs by default. If you noindex them, Google will eventually drop them from the index, but the sitemap signal is loud.

If you have access to a custom sitemap module or you generate one server-side, exclude paginated URLs. If you only have HubSpot’s default, accept the slow cleanup and noindex correctly.

Measuring the recovery

In Search Console, before deploying:

  • Note impressions and clicks on the blog index URL
  • Note number of indexed pages on the property

After deployment, monitor weekly for 8-12 weeks:

  • Paginated URLs should drop out of the index
  • Page one impressions should rise as duplicate competition shrinks
  • Overall blog category traffic should recover within a quarter

If you see no movement after 12 weeks, the issue is elsewhere — most likely content quality or internal link structure, not pagination.

Related: HubSpot CMS Hub overview and topic clusters and pillar pages.

Bottom line

  • Canonical every paginated page to page one; the simpler rule wins on HubSpot scale.
  • Noindex, follow on pages two and up; preserve crawl paths to individual posts.
  • Audit blog post templates for paginated internal links; redirect that equity to the index.
  • Apply the same pattern to tag and topic listings via a shared partial.
  • Measure recovery in Search Console over 8-12 weeks; pagination is rarely the only problem if you see no lift.
[object Object]
Share