What is the safest way to implement pagination or infinite scroll for SEO?
Give every results component a persistent URL, expose the sequence through crawlable HTML links, and use a self-referencing canonical on each useful component page. Infinite scroll or a load-more button can improve the interface, but they should enhance that URL-and-link foundation rather than replace it.
Key takeaways
- Every component page needs a stable, unique URL that works when opened directly; fragment identifiers such as #page=2 are not suitable for this job.
- Googlebot discovers links in HTML <a> elements with an href. It does not click a load-more button to reveal the rest of a listing.
- Use a self-referencing canonical on each useful paginated component. Do not canonicalise every page in the series to page one.
- Infinite scroll is an interface choice, not a separate indexing strategy. Keep crawlable pagination underneath it and update real URLs as the visible component changes.
- Accessibility needs deliberate focus order, status announcements and keyboard behaviour; a visually smooth feed can still be difficult to navigate.
A product grid can feel effortless to a shopper and remain almost invisible to a crawler. The first 24 products render, a button fetches the next batch, and the browser keeps the visitor on the same URL. Nothing looks broken. Yet the remaining products may have no crawlable path, page two may not exist as a durable address, and sharing the URL halfway down the list returns someone to the top.
The safest model is straightforward: give every results component a persistent URL, connect the sequence with ordinary HTML links, and put a self-referencing canonical on every useful component page. Pagination can expose that model directly. A load-more button or infinite scroll can sit on top as an interface enhancement. It should not be the only route to the content.
That distinction matters because Google says it generally crawls URLs found in the href attributes of <a> elements and does not click buttons to load more content (Google, crawlable links). The interface may be dynamic; discovery still needs links.
Pagination, load more and infinite scroll solve different problems
All three patterns divide a large set of results into smaller components, but they give users different controls.
Pagination displays one component at a time and provides explicit links to other components. It makes location visible: a visitor can recognise page four, copy its URL and return later. That works well for comparison-heavy tasks, search results and catalogues where users want a sense of progress.
Load more keeps the visitor in one visual list. They choose when to append another component. It removes page transitions without taking away control over when more results appear. The common technical mistake is to implement the button as the sole access mechanism.
Infinite scroll loads a component when the viewport approaches the end of the current content. It can suit exploratory browsing where the exact position matters less than continuity. It can also make the footer hard to reach, expand the document indefinitely and leave keyboard or assistive-technology users unsure that new items have appeared.
For SEO, these are presentation patterns rather than three separate indexing systems. Google’s pagination guidance treats sequential loading and infinite scroll as interfaces that should be supported by distinct component URLs (Google, pagination and incremental loading). The crawler-facing foundation remains a linked series.
A decision matrix for the interface
| Requirement | Pagination | Load more | Infinite scroll |
|---|---|---|---|
| Return to an exact results position | Strong by default when each page has a URL | Requires URL and scroll-state work | Requires careful URL and restoration work |
| Compare a bounded group of items | Clear page boundaries | Possible, but the list grows | Weak once the list becomes long |
| Casual, continuous discovery | More interruptions | Good compromise | Often the smoothest visual flow |
| Reach the footer predictably | Easy | Usually manageable | Needs a deliberate stop or alternate footer access |
| Keyboard and assistive technology | Familiar controls when labelled well | Needs focus and status handling | Highest implementation burden |
| Crawlable discovery | Natural with anchor links | Needs a linked fallback | Needs a linked fallback |
| Engineering and QA complexity | Lowest | Moderate | Highest |
Choose pagination when the user benefits from boundaries, direct navigation and an obvious location. Choose load more when continuity helps but the user should decide when the list expands. Choose infinite scroll only when uninterrupted exploration is central enough to justify its state-management and accessibility cost.
None of the patterns creates a ranking benefit by itself. The decision should follow the browsing task, while the technical implementation preserves discovery, stable addresses and indexation signals.
Build the URL model before the interaction
Start by splitting the complete result set into deterministic components. Each item should appear in a predictable component for a stable sort order. Then assign a URL that the server or rendering layer can open without depending on earlier interaction.
Query parameters are a conventional option:
/en/shop/?page=1
/en/shop/?page=2
/en/shop/?page=3
Path segments can work too:
/en/shop/page/1/
/en/shop/page/2/
/en/shop/page/3/
The choice is less important than consistency. A direct request for page three should return page-three results, the correct metadata and the links needed to move through the sequence. It should not first render page one and wait for client-side history to reconstruct the requested state.
Google explicitly recommends unique URLs for each component and advises against using fragment identifiers such as #page=2, because fragments are generally not used to determine what content should be loaded (Google, pagination and incremental loading). Use a query parameter or path that reaches the server.
Stable sorting belongs in this model. If products move randomly between components on every request, crawlers and users can encounter duplicates while other items disappear from the traversed series. Define the primary sort and a deterministic tie-breaker. Inventory changes will still alter a live catalogue, but the system should not add avoidable volatility.
Filters need a separate indexation policy. A paginated category and thousands of faceted combinations are not the same problem. Decide which filtered states deserve crawlable landing pages and which should remain user-only combinations. The faceted navigation SEO guide covers that URL-space decision in detail.
On retail sites, this URL contract also needs to fit category templates, product discovery and inventory behaviour. The technical SEO for ecommerce guide places pagination inside that wider architecture.
Expose links that work without a click handler
A crawler should be able to reach the next component from the HTML it receives. A plain navigation control is enough:
<nav aria-label="Results pages">
<a href="/en/shop/?page=1">1</a>
<a href="/en/shop/?page=2" aria-current="page">2</a>
<a href="/en/shop/?page=3">3</a>
<a href="/en/shop/?page=3">Next</a>
</nav>
Google considers an anchor crawlable when it is an <a> element with an href that resolves to a URL. A JavaScript function on a span, a div with button styling or an anchor without href is not an equivalent discovery path (Google, crawlable links).
You do not need to show hundreds of numbered links at once. Link the current component to the next and previous components, and add useful nearby or boundary links where the interface warrants them. What matters is that following links can traverse the sequence and that deeper components do not exist only in a JavaScript response.
Keep those links in the rendered document even when JavaScript upgrades them into a load-more or infinite-scroll experience. They may be visually presented as a compact pagination control or an accessible fallback, but do not remove the only crawl path after hydration.
Google’s JavaScript SEO guidance notes that server-side or pre-rendering remains useful because it makes content available to users and crawlers sooner, while not every bot can run JavaScript (Google, JavaScript SEO basics). In practice, rendering the component items and navigation in the initial HTML also makes testing much less ambiguous.
Canonicalise each useful component to itself
Page two is not merely a duplicate of page one when it lists different items. Give each useful component a self-referencing canonical:
<!-- /en/shop/?page=2 -->
<link rel="canonical" href="https://example.com/en/shop/?page=2">
Google’s pagination documentation says not to use the first page of a sequence as the canonical for every component. Each component should have its own canonical URL (Google, pagination and incremental loading). This avoids telling the search system that distinct result sets are all substitutes for page one.
A view-all page is different. If it genuinely contains the same items, performs well and is the preferred search version, it may be a canonical target. Do not invent a view-all endpoint purely to simplify tags; a page that times out, overwhelms the browser or omits items is not an honest substitute.
Canonical is a signal, not a guaranteed command. Google evaluates canonical declarations alongside redirects, sitemap inclusion and other signals, and recommends using consistent absolute URLs (Google, canonical URL guidance). Keep internal links, sitemap policy and canonical tags aligned instead of asking one tag to resolve a contradictory architecture.
rel="next" and rel="prev" do not fix this. Google no longer uses them as pagination signals, according to its pagination guidance. You may retain those relationships for another consumer or an internal convention, but Google still needs crawlable links and coherent component URLs.
Add load more without hiding the sequence
The robust load-more pattern begins with working pagination. JavaScript intercepts the user’s request, fetches the next component and appends its items. The underlying link remains a real URL.
A simplified control might look like this:
<a class="load-more" href="/en/shop/?page=3">Load more products</a>
With JavaScript available, the handler requests page three, appends only the intended results, changes the control’s next destination and announces the update. Without JavaScript, the anchor navigates normally. Googlebot can also follow it without needing to activate a button.
Prevent repeated requests while a load is in progress. Handle network failure without deleting the link, and let the user retry. When the sequence ends, remove or disable the control with an accurate explanation. A silent button that does nothing is bad UX and difficult to diagnose in automated tests.
Decide what the Back button should do. If loading several components changes the meaningful browsing state, record that state in the URL. If it does not, returning from a product detail page should at least restore the expanded list and a useful position. There is no universal answer, but losing ten minutes of browsing is a clear failure.
Infinite scroll needs real history, not a cosmetic address
Infinite scroll can use the same component endpoints. Observe a sentinel near the end of the current list, fetch the next component, append it and retain the component boundary in the DOM. The Intersection Observer API can detect when that sentinel intersects the viewport without continuously polling layout on the main thread.
As a component becomes the primary visible section, update the browser to its real URL. The History API provides pushState() and replaceState() for adding or replacing session-history entries without a full navigation (MDN, Working with the History API). The URL supplied to these methods must be same-origin; use the same paths that direct requests already understand.
Do not call pushState() for every small scroll movement. That fills the Back-button history with noise. A practical policy is to replace the current entry while the user is still within one component and push a new entry only when crossing a meaningful component boundary. Test the policy on real browsers because restoration behaviour and application routers can interact.
Handle popstate so Back and Forward restore the component represented by the URL. If the required results are no longer in memory, fetch or render them. If they are present, restore focus or scroll position without replaying every network request. Directly opening that same URL in a new tab must still work; History API calls cannot substitute for server routing.
The loading trigger also needs restraint. Prefetching just before the end can reduce waiting, but loading many screens ahead wastes bandwidth and makes failures harder to recover from. Respect data-saving and reduced-motion preferences where the interface uses motion. Provide a route to the footer or stop automatic loading after a sensible boundary and offer an explicit continuation control.
Accessibility is part of the architecture
Appending content changes the reading and focus experience even when focus itself does not move. A sighted mouse user sees new cards. A screen-reader user may receive no indication that the result count changed.
Use a status message to announce an outcome such as “24 more products loaded” without forcing focus onto the message. WCAG 2.2 explains that status messages can be exposed to assistive technology through roles or properties without receiving focus (W3C, Status Messages). Keep announcements concise and avoid firing several messages for one load.
Do not move keyboard focus automatically when infinite scroll appends a component. For an explicit load-more action, a considered focus move to the first new item can help some users, but it can also disrupt context. Test the chosen behaviour with the control, result structure and screen readers you support. At minimum, preserve a logical focus order. WCAG requires focusable components to receive focus in an order that preserves meaning and operability (W3C, Focus Order).
For an article or card stream, the WAI-ARIA feed pattern defines a container with article children and describes keyboard interaction and loading expectations (W3C, feed role). Use it only when the implemented interaction follows the pattern; adding role="feed" alone does not repair an inaccessible list.
Also provide a discoverable way to bypass the growing list. A skip link to pagination or the footer can prevent keyboard users from tabbing through every loaded card. Preserve headings and landmarks after appending. Never duplicate element IDs across components.
Common failures and what they reveal
The rest of the catalogue exists only behind a button
The initial HTML has no link to page two, and the button calls an API with an opaque cursor. Users with JavaScript see everything; Googlebot has no documented reason to activate the control. Add durable component URLs and anchors, then let the button enhance them.
Every component canonicalises to page one
This usually comes from a template that ignores the page parameter when building metadata. Generate the canonical from the resolved component URL and test pages one, two and the final page. Do not assume a tag is correct because it exists.
#page=3 appears to solve routing
Fragments can update the browser without a server request, which makes them tempting. Google advises against fragments for pagination component URLs. Use a query parameter or path and make direct requests return the matching component.
A changing sort order repeats and loses items
Offset pagination on a rapidly changing dataset can shift entries between requests. Use a stable sort with a tie-breaker, or choose cursor-based retrieval while still exposing durable, crawlable component URLs where indexation is required. A private personalised feed may not need indexable pagination at all; do not force SEO controls onto content that should not be in search.
Filters multiply the sequence indefinitely
Every colour, size, sort and page combination becomes crawlable. That can create a much larger URL space than the catalogue justifies. Define which facets have search value, constrain internal linking and keep the paginated architecture consistent with the site’s faceted-navigation policy. Review crawl budget optimisation when the concern is discovery at scale rather than a single component.
JavaScript changes the URL but direct requests fail
The interface looks correct during one session. Refreshing page four returns a 404 or page one. This is client-side theatre, not durable state. Add server or static routing for every address placed in history.
New results arrive silently
Visual loading works, but assistive technology receives no status update and keyboard users cannot reach the footer. Add an appropriate status message, preserve focus order and provide explicit navigation around the feed.
Test the system as four different clients
Start with a direct HTTP request. Fetch page two with no previous cookies or session state. Confirm a successful response, the correct items, a self-canonical, indexation policy and crawlable links. Repeat for a deep and final component.
Then inspect rendered HTML with JavaScript disabled. The component and navigation should remain usable if progressive enhancement is the goal. If the application requires JavaScript, server-rendered or pre-rendered output should still expose the content and anchor destinations you expect crawlers to find. The JavaScript SEO problems guide gives a wider diagnostic process for rendering failures.
Next, use the interface with a mouse, keyboard and browser history. Load several components, open an item, go Back, refresh and share the URL. Check that the list, address and position agree. Throttle the network and force an API error. The user should retain a working retry path.
Finally, test assistive technology. Verify the result-count announcement, focus order, landmarks, skip navigation and end-of-results state. Automated accessibility checks can find invalid roles and duplicate IDs, but they cannot tell you whether returning from a detail page feels coherent.
Add these cases to release checks rather than treating them as a one-off launch audit. A useful set includes:
- every sampled component URL returns its intended result slice;
- component canonicals are absolute and self-referencing;
- rendered anchors connect the sequence;
- fragments are not the only representation of state;
- a direct request and a history-generated URL return equivalent content;
- loading failure leaves a usable retry control;
- Back and Forward restore a meaningful state;
- status messages and focus order pass manual review;
- no item is systematically skipped or duplicated under the defined sort.
For larger teams, these checks fit naturally into technical SEO observability in CI/CD. Template fixtures can catch a lost canonical or link before a release; scheduled crawls can cover the full sequence later.
Frequently asked questions
Is pagination better than infinite scroll for SEO?
Pagination is easier to make crawlable because it exposes stable URLs and links by default. Infinite scroll can also work when it sits on top of the same crawlable paginated sequence, updates real URLs as users move, and does not depend on Googlebot clicking or scrolling. The better choice depends on the browsing task, not on a ranking advantage.
Should every paginated page canonicalise to page one?
No. Google recommends giving each component page its own canonical URL. Canonicalising pages two and beyond to page one can misrepresent distinct result sets as duplicates. A separate view-all page may be canonical only when it genuinely contains the same content and is the version you want indexed.
Does Google still use rel=next and rel=prev for pagination?
Google no longer uses rel="next" and rel="prev" as pagination signals. Those link relations may still have meaning for other consumers, but they do not replace crawlable anchor links, unique component URLs, sensible canonicals or internal linking in Google Search.
Can Google crawl content behind a load-more button?
Do not rely on it. Google documents that its crawler does not click buttons to load additional content. Keep the button for users if it suits the interface, but provide ordinary anchor links to every component URL in the rendered HTML so crawlers can discover the full sequence.
The implementation decision to record
Write down one contract before development begins: which result states have persistent URLs, how crawlers reach them, which states are indexable, how canonical URLs are generated, and what Back, Forward and refresh should restore. Add the accessibility behaviour and the final-component state to that same contract.
Once those decisions are explicit, pagination, load more and infinite scroll become interface options over a testable architecture. Without them, a polished list can hide most of its content and lose a visitor’s place at the same time.
Sources and references
-
Pagination, incremental page loading, and their impact on Google Search (developers.google.com)
-
Make your links crawlable (developers.google.com)
-
Understand JavaScript SEO basics (developers.google.com)
-
How to specify a canonical URL with rel=canonical and other methods (developers.google.com)
-
Working with the History API (developer.mozilla.org)
-
WAI-ARIA feed role (w3.org)
-
Intersection Observer API (developer.mozilla.org)
Share this article
If you found this content useful, share it with your colleagues.
Frequently Asked Questions
Is pagination better than infinite scroll for SEO?
Pagination is easier to make crawlable because it exposes stable URLs and links by default. Infinite scroll can also work when it sits on top of the same crawlable paginated sequence, updates real URLs as users move, and does not depend on Googlebot clicking or scrolling. The better choice depends on the browsing task, not on a ranking advantage.
Should every paginated page canonicalise to page one?
No. Google recommends giving each component page its own canonical URL. Canonicalising pages two and beyond to page one can misrepresent distinct result sets as duplicates. A separate view-all page may be canonical only when it genuinely contains the same content and is the version you want indexed.
Does Google still use rel=next and rel=prev for pagination?
Google no longer uses rel=next and rel=prev as pagination signals. Those link relations may still have meaning for other consumers, but they do not replace crawlable anchor links, unique component URLs, sensible canonicals or internal linking in Google Search.
Can Google crawl content behind a load-more button?
Do not rely on it. Google documents that its crawler does not click buttons to load additional content. Keep the button for users if it suits the interface, but provide ordinary anchor links to every component URL in the rendered HTML so crawlers can discover the full sequence.