Guide Infinite Scroll SEO
How to implement infinite scroll sans losing votre indexation — pourquoi Googlebot doesn't scroll, the tall-viewport render trick que flattens two pages into un, the paginated-URL + History API fix, and the ecommerce category-page cas.
Langues
Infinite scroll loads plus content as vous scroll, au lieu de via numbered pages — and Googlebot jamais scrolls or clicks, so anything gated behind que action is invisible by par défaut. Google renders in a very tall viewport (à propos de 411×12,140px mobile, 1024×9,307px desktop) as a workaround, but que même tall viewport peut trigger the scroll loader during rendering and fold two logical pages into un indexé URL — a échec mode où a 'non indexée' page is en réalité indexé as partie of un autre. The fix is architectural: give every chunk a réel, persistent, absolute URL (comme ?page=2), lien les with crawlable anchors, and mettre à jour the adresse bar with the History API as the utilisateur scrolls. rel=suivant/prev is legacy (Google dropped it in 2019; Bing encore supports it). On ecommerce category pages, back it tout with sitemaps or a Merchant Center feed and vérifier in the Inspection d’URL Tool's rendered HTML. A production construire aussi nécessite a réel popstate/back-forward contract, distinct chargement/error/fin states, and deliberate accessibility — none of que comes pour free simplement parce que the indexation fix is in placer.
Evidence for this claim Google Search does not generally interact with scrolling controls, so infinite-scroll content needs crawlable paginated URLs. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Lazy-loaded content Evidence for this claim The History API can update URLs for loaded page chunks without a full navigation. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: History APITL;DR — Infinite scroll loads plus content as vous scroll bas, au lieu de making vous click to page 2, page 3, and so on. The catch: Googlebot doesn’t scroll and doesn’t click. So si votre products or articles seulement apparaître une fois a visitor scrolls, Google may jamais voir les. The fix is to give every “page” of content a réel URL of its propre, so moteur de recherches have something to explorer même though ils jamais touch votre scroll.
Ce que infinite scroll is
You’ve utilisé it a hundred times sans naming it. On a social feed, a shopping category, or a long article, vous garder scrolling and plus stuff garde appearing — aucun “Next page” button, aucun page numbers. That’s infinite scroll: JavaScript watches how far you’ve scrolled and, as vous near the bottom, quietly récupère and adds the suivant batch of content.
It feels seamless pour personnes. The problem is que moteur de recherches aren’t personnes.
Pourquoi it’s risky pour le SEO
Google trouve and reads votre pages with an automated program appelé Googlebot. Googlebot loads votre page, but it fait pas behave comme a human visitor:
- It doesn’t scroll bas lune page.
- It doesn’t click buttons.
So quelconque content que seulement loads après someone scrolls (or clicks “Load more”) simply isn’t là as far as Googlebot is concerned. Si votre category page montre 24 products up front and loads the rest on scroll, Google may seulement ever voir ceux premier 24.
The un rule que garde it safe
Here’s the whole trick in un sentence: every chunk of content nécessite its propre réel web adresse.
Au lieu de relying seulement on scrolling, a search-friendly setup aussi has plain,
crawlable pages behind the scenes — example.com/shoes?page=2,
?page=3, and so on — lié ensemble with normal liens Google peut follow. The
infinite scroll is the nice experience pour humans; the numbered URLs are the
safety net pour moteur de recherches. Modern implementations même swap the adresse in
votre navigateur bar as vous scroll, so si vous copy l’URL vous land back in the exact
même spot.
Ce que la plupart personnes obtenir incorrect
- “Google can render JavaScript now, so it’ll figure it out.” Google peut run votre JavaScript — but it encore won’t scroll or click to trigger the loader. Being able to render isn’t the même as taking action.
- “A ‘Load more’ button is safer than auto-scroll.” Seulement si que button is a réel lien to a réel page. A button que simplement runs a click handler is invisible to Google aussi.
- “If a page isn’t indexed, Google is ignoring it.” With infinite scroll, “pas indexé” parfois signifie le contenu got merged into un autre page by accident — qui is a différent problem with a différent fix.
Infinite scroll isn’t banned or penalized. Fait correct — with réel URLs underneath — it’s complètement fine. Vouloir the mechanics of pourquoi two pages parfois obtenir indexé as un, plus the réel code pattern to implement it? Switch to the Avancé tab.
Evidence for this claim Google Search does not generally interact with scrolling controls, so infinite-scroll content needs crawlable paginated URLs. Scope: Current official or standards documentation. Confidence: high · Verified: Google: Lazy-loaded content Evidence for this claim The History API can update URLs for loaded page chunks without a full navigation. Scope: Current official or standards documentation. Confidence: high · Verified: MDN: History APITL;DR — Googlebot jamais scrolls and jamais clicks, so scroll-gated content is invisible by par défaut. Google’s workaround is to render in a very tall viewport (roughly 411×12,140px mobile, 1024×9,307px desktop) — but que même height peut trigger the scroll loader during rendering, folding the suivant logical page into the current un so two pages obtenir indexé as a unique URL. The durable fix is architectural: persistent, absolute, per-chunk URLs (e.g.
?page=12), lié with crawlable anchors, with the History API updating the adresse bar as chaque chunk becomes principal.rel=next/rel=previs legacy pour Google (dropped 2019) but encore respected by Bing. On ecommerce PLPs, sitemaps or a Merchant Center feed are a discovery backstop. Vérifier everything in the Inspection d’URL Tool’s rendered HTML.
Premier, a disambiguation
Si vous search “Google infinite scroll” you’ll hit results à propos de Google’s propre continuous scroll on its résultats de recherche pages — a SERP fonctionnalité Google turned on and alors discontinued in mid-2024. That’s a Google-product UX decision and has nothing to do with how Googlebot crawls votre site. Ce article is à propos de the latter: infinite scroll as a chargement pattern on votre propre pages, and si Google peut index ce que it loads.
The core constraint: Google doesn’t interact with votre page
Everything ici follows from un fact. Google’s propre lazy-loading docs dire the recommended patterns “don’t rely on utilisateur actions, tel as scrolling or clicking, to charger content, qui is important as Recherche Google ne fait pas interact with votre page.” The pagination doc dit it même plus plainly: “Google’s robots d’exploration don’t ‘click’ buttons and généralement don’t trigger JavaScript functions que exiger utilisateur actions to mettre à jour the current page contents.”
As I put it in my propre JavaScript SEO guide: “Googlebot doesn’t prendre action on webpages. It’s pas going to click choses or scroll, but que doesn’t mean it doesn’t have workarounds. Tant que content is chargé in the DOM sans a nécessaire action, Google va voir it. Si it’s pas chargé into the DOM jusqu’à après a click, alors le contenu won’t be trouvé.”
So infinite scroll que seulement triggers on a réel scroll event is a content-discovery problem avant it’s anything sinon.
Google’s workaround: a very tall viewport
Google doesn’t simulate scrolling. À la place it renders votre page in an unusually tall viewport, so content a few screens bas is déjà à l’intérieur the rendered area sans anyone scrolling. The earliest on-record hint of ce was John Mueller’s 2017 remarque que “Googlebot renders with a very tall viewport, qui skews some CSS (souvent images). Essayer in Chrome dev-tools, eg 9000px élevé viewport.”
The spécifique numbers I’ve documented: pour mobile, Google loads lune page at a screen size of 411×731 pixels and resizes the length to 12 140 pixels — “essentially, it becomes a really long phone with a screen size of 411×12140 pixels. Pour desktop, it fait the même and goes from 1024×768 pixels to 1024×9307 pixels.” (I haven’t seen recent re-tests of ceux exact figures, and ils may vary with page length; the original dimensions trace back to independent testing by SEO researcher JR Oakes.) The point isn’t the exact pixel count — it’s que Google fakes “seeing far bas the page” with height, pas with movement.
Treat les deux the exact pixel dimensions and the two-pages-merged behavior ci-dessous as dated, implementation-specific observations plutôt que a stable platform contract — Google doesn’t publish an official spec pour soit number, and rendering behavior peut modifier. Don’t assume votre site behaves the même façon; confirmer current behavior pour votre propre URLs with the rendered-HTML tester in the suivant section au lieu de taking ces figures as a guarantee.
The échec mode nobody explique: two pages indexé as un
A normal browser viewport stops after page one. Google's render viewport expands much taller, reaches the infinite-scroll trigger without a real user scroll, and appends page two into the same DOM. The merged DOM is then indexed as one URL instead of two separate pages.
© Patrick Stox LLC · CC BY 4.0 ·
Here’s où the tall viewport bites back. Parce que the render viewport is so tall,
the scroll-triggered loader peut fire during rendering même though nothing
“scrolled” in the human sense — the sheer DOM height peut be suffisant to satisfy an
IntersectionObserver or a scroll-position vérifier. Quand que se produit, the loader
appends the suivant logical page’s content into the current page’s render, and
Google indexes the merged result as a unique URL.
I’ve diagnosed ce several times. From my JavaScript SEO guide:
“Un autre problème I’ve seen with ce setup is, occasionally, two pages obtenir indexé as un. I’ve seen ce a few times quand personnes said ils couldn’t obtenir leur page indexé. But I’ve trouvé leur content indexé as partie of un autre page that’s usually the previous post from les.”
“My theory is que quand Google resized the viewport to be plus long, it triggered the infinite scroll and chargé un autre article in quand it was rendering. In ce cas, ce que I recommend is to block the JavaScript fichier que handles the infinite scrolling so the functionality can’t trigger.”
John Mueller décrit the même mechanic from Google’s side in a 2022 office-hours session: Google renders with a élevé viewport, que “voudrait trigger some amount of infinite scrolling,” and “we pourrait have two or three of ces pages chargé on un page with infinite scroll, but pas everything.” (Que office-hours quote is relayed via Moteur de recherche Journal’s write-up, pas confirmed contre the principal recording.)
Two consequences fall out of ce:
- There’s aucun guarantee of how beaucoup obtient pulled in. Pourrait be nothing supplémentaire, pourrait be two or three pages, jamais reliably everything. Infinite scroll alone n’est pas a dependable façon to obtenir deep content indexé.
- “Not indexed” peut be a misdiagnosis. The manquant page may pas be manquant at tout — it may be indexé as partie of an précédent URL. Que nécessite a différent fix que a normal indexation bug.
How to diagnose it
Utiliser Search Console’s Inspection d’URL Outil and lire the rendered HTML, pas the raw source. Google’s docs are explicit: “Vous pouvez utiliser the Inspection d’URL Outil in Search Console to voir si tout content was chargé. Vérifier the rendered HTML to assurez-vous votre content is in the rendered HTML by looking pour it in Inspection d’URL Outil.” Search the rendered HTML pour content vous expect to be on page 1 seulement. Si vous trouver content from page 2 (or the suivant article) sitting à l’intérieur page 1’s render, you’ve reproduced the merge bug.
Vous pouvez aussi replicate the tall viewport locally: ouvrir Chrome DevTools, définir a very tall custom viewport (Mueller’s suggestion was ~9000px), and charger lune page to voir si votre loader fires with aucun scrolling.
The fix: paginated URLs + the History API
The durable fix is architectural, straight from Google’s current lazy-loading doc. To faire infinite scroll indexable, “assurez-vous votre website supports paginated chargement of ces chunks”:
- “Give each chunk its own persistent, unique URL.”
- “Garantir que le contenu affiché on chaque URL remains the même every temps it’s
chargé in a navigateur” — Google suggests absolute page numbers comme
?page=12. - “Avoid using relative elements like
?date=yesterdayin these URLs” — an adresse que renvoie différent content chaque charger is unusable as a canonical. - “Lien sequentially to the individual URLs so que moteur de recherches peut découvrir the
URLs in a paginated définir” — réel
<a href>liens, pas click handlers. - “Quand a nouveau page chunk is chargé in réponse to the utilisateur scrolling, and it becomes the principal visible element pour the utilisateur, mettre à jour the affiché URL en utilisant the History API.”
Que dernier point is the elegant partie. history.pushState() / replaceState() swaps
l’URL in the adresse bar as the utilisateur scrolls past chaque boundary — so the visible
URL toujours matches the principal content, and the utilisateur peut refresh, share, and lien to
exactly où ils are. Meanwhile the crawlable ?page=N URLs exist independently, so
Google peut reach every chunk directement si or pas the renderer ever triggers the
scroll.
Two implementation notes que matter:
- Utiliser
IntersectionObserver(or native navigateur lazy-loading), pas a rawscrolllistener. It performs far meilleur (aucun scroll-thrash) and it’s the “charger quand visible” mechanism Google endorses pour deferred content. - Garder the paginated définir discoverable independently of the JS. Réel anchors in the
DOM, and/or the
?page=NURLs listed in votre XML sitemap. Whatever the renderer captures, le sitemap-and-links couche is votre backstop.
Si a live site is déjà exhibiting the merge bug and vous devez arrêter the bleeding
avant vous pouvez rebuild, my blunt emergency fix is to block the JavaScript fichier que
triggers infinite scroll in robots.txt so it physically can’t fire during
rendering — buying temps to ship the proper paginated-URL architecture.
Navigation state: back, forward, refresh, and share have to reconstruct the même view
The History API point ci-dessus covers half the contract — updating the adresse bar as a chunk becomes principal. The autre half is making certain every entry chemin back into que URL en réalité reconstructs the correct content, pas simplement the correct scroll position:
- Utiliser
pushState()quand a chunk becomes the principal visible content pour the premier temps — that’s a réel navigation step, and it’s ce que rend the back button meaningful. - Utiliser
replaceState()pour corrections que shouldn’t créer leur propre back-button arrêter, comme syncing l’URL après a fast scroll past several chunks at une fois. - Listen pour
popstateand re-render (or re-fetch) the chunk que matches l’URL in the event. Le navigateur’s par défaut back/forward behavior restores scroll position, pas the dynamic liste state votre JavaScript construit — si a utilisateur hits back après votre loader appended 40 plus items, vous devez reconstruct qui items belong on que page, pas simplement scroll les là. - Don’t lean on automatic scroll restoration alone to solve ce. It contrôle où the viewport lands, pas ce que content is présent — si the underlying liste peut modifier entre visits (nouveau products ajouté, items out of stock), scroll position sans content reconstruction peut strand the utilisateur in the incorrect context.
Ce is the même discipline the paginated-URL fix déjà dépend on: a chunk’s URL has to retourner le contenu it promised on a fresh charger, a refresh, and a Search-Console live tester — pas simplement the premier temps it’s récupéré mid-scroll.
Chargement, error, and end-of-results states
A production implementation nécessite plus states que “loading” and “loaded”:
- Initial charger — the premier chunk devrait déjà be in the raw HTML le serveur sends, pas assembled entirely by JS après the fact.
- Next-chunk chargement — a visible in-progress indicator so utilisateurs (and anyone testing with assistive tech) know a récupérer is underway.
- Vide — a distinct state pour zero results, pas a blank space que semble broken.
- Error / retry — a failed récupérer shouldn’t silently strand lune page with aucun façon to essayer à nouveau, and a retry shouldn’t duplicate or reorder items déjà on lune page.
- Fin of results — a clair signal, pas an infinite spinner, une fois there’s nothing left to charger.
None of ce is Google-specific, but it’s the même reliability the paginated-URL fix dépend on: si the loader peut silently break mid-fetch, vous pouvez’t trust que quelconque donné explorer or utilisateur session en réalité captured the chunk it devrait have.
Accessibility and performances: two choses infinite scroll doesn’t give vous pour free
Infinite scroll has aucun inherent Core Web Vitals outcome, bon or bad — it’s determined entirely by how vous construire it. Every appended chunk grows the DOM, and a grand suffisant DOM raises layout and style-recalculation cost, so watch append cost, image chargement, layout shift from content sans reserved space, and long tasks as the liste grows. On very long pages, considérer virtualizing chunks que have scrolled far out of view (removing leur DOM nodes) au lieu de letting the DOM grow unbounded.
Accessibility nécessite its propre deliberate design, pas an assumption que “it renders, so it’s fine”:
- Keyboard utilisateurs besoin to be able to reach nouveau content — and the footer or end-of-page navigation — sans lune page silently growing out from sous leur tab order.
- Screen reader utilisateurs besoin nouveau content announced sans interrupting ce que they’re doing — a polite status region, pas a disruptive alert, is the usual pattern.
- The WAI-ARIA feed design pattern is construit pour exactly ce cas: article-level regions à l’intérieur a feed container, with défini keyboard behavior pour moving entre items and pour reaching content avant and après the feed.
- Focus shouldn’t silently jump or obtenir lost quand a nouveau chunk loads.
None of ce is optional cleanup. It’s the difference entre infinite scroll que fonctionne pour everyone and un que seulement fonctionne pour a mouse utilisateur with JavaScript who jamais strays from the happy chemin.
The historical context: rel=suivant/prev is legacy
Si vous learned pagination années ago, vous learned rel="next" / rel="prev". Google
introduced les in 2011 and paired les with its original 2014 “infinite scroll
search-friendly recommendations” (paginate le contenu, provide component pages).
Alors in 2019 Google announced it hadn’t been en utilisant ceux tags pour années and formally
dropped les. The pagination doc confirms it today: “In the past, Google utilisé
<link rel="next" href="..."> and <link rel="prev" href="..."> to identifier suivant page
and previous page relationships. Google ne … plus uses ces tags, although ces liens
may encore be utilisé by autre moteur de recherches.”
So the current Google recipe is unique URLs + crawlable liens + the History API — aucun
rel=next/rel=prev requis. But “other search engines” inclut Bing, qui
encore respects les, so there’s aucun harm in keeping les in votre markup pour cross-engine
benefit and accessibility. Bing itself doesn’t publish infinite-scroll-specific
guidance; its stance reduces to the general JS-rendering caution its team laid out —
bingbot peut render JavaScript but “it is difficult pour bingbot to traiter JavaScript at
scale,” so a crawlable paginated fallback helps Bing pour exactly the même raison it
helps Google.
Ecommerce category pages: the highest-stakes cas
The la plupart courant real-world infinite scroll is on ecommerce category / product listing pages (PLPs), and it’s où the risk costs réel money. Si deep-catalog products past the premier screenful jamais obtenir indexé, ils can’t rank, and vous lose the long tail of product-level trafic organique. Ce is the même territory covered in depth in the category-page material — infinite scroll is un plus raison ceux pages besoin a crawlable structure underneath the UX.
Two backstops matter ici:
- XML sitemaps listing every canonical product and paginated category URL, so discovery doesn’t depend on the renderer.
- A Merchant Center product feed, qui feeds Google product données independently of whatever the category page’s renderer captures.
Lumar’s analysis of top UK fashion retailers trouvé infinite scroll to be, in leur words, “the biggest loser when it comes to indexability and SEO friendliness” among the pagination patterns — a utile reminder que ce isn’t a theoretical edge cas, it’s the par défaut échec mode of a very popular PLP UX. (Lumar’s spécifique percentage figures devrait be lire from leur live report avant citing an exact number.)
Infinite scroll vs. pagination vs. charger plus
Google’s pagination doc frames three UX patterns and is honest à propos de the tradeoffs. Infinite scroll “uses a single page for all content” and is “intuitive — the utilisateur simplement garde scrolling,” but it “peut lead to ‘scrolling fatigue’ parce que of unclear result size” and “can’t handle very grand numbers of results.” Classic numbered pagination is the la plupart robust pour le SEO parce que every page is inherently a réel URL. “Load more” sits in entre — fine si the button is (or wraps) a réel lien to a paginated URL, useless pour SEO si it’s a pure click handler.
The decision isn’t “which is allowed” — tout three are allowed. It’s “qui UX do vous vouloir, and did vous construire the crawlable URL couche underneath it.” Mueller’s 2023 summary is the whole chose in un line: “si chaque piece or virtual page is aussi accessible and findable via a unique URL, généralement it devrait be fine to have infinite scroll.”
AI summary
A condensed prendre on the Avancé version:
- Root constraint: Googlebot doesn’t scroll or click. Content gated behind a scroll or click event is invisible to it by par défaut (“Recherche Google ne fait pas interact with votre page”).
- Google’s workaround: it renders in a very tall viewport (~411×12,140px mobile, ~1024×9,307px desktop) au lieu de scrolling.
- The échec mode: que tall viewport peut trigger the scroll loader during rendering, folding the suivant logical page into the current un — so two pages obtenir indexé as a unique URL. A “not indexed” page may en réalité be indexé as partie of un autre URL.
- Aucun guarantee: per Mueller, Google pourrait charger “two or three of ces pages … but pas everything.” Infinite scroll alone n’est pas a reliable deep-indexing méthode.
- The fix (architectural): persistent, unique, absolute per-chunk URLs (e.g.
?page=12), lié with crawlable<a href>, with the History API (pushState/replaceState) updating the adresse bar as chaque chunk becomes principal. - Trigger mechanism:
IntersectionObserver/ native lazy-load, pas a rawscrolllistener. - Legacy remarque:
rel=next/rel=prevdropped by Google in 2019; Bing encore supports it, so garder it pour cross-engine benefit. - Ecommerce: PLPs are the highest-stakes cas; back les with sitemaps and a Merchant Center feed. Vérifier in the Inspection d’URL Tool’s rendered HTML.
- Emergency fix on a live merge bug: block the infinite-scroll JS fichier so it can’t fire during rendering pendant que vous rebuild.
- Navigation state:
pushStatepour a réel navigation step,replaceStatepour in-place corrections, and apopstatehandler que reconstructs the chunk’s content — pas simplement its scroll position — on back/forward. - Chargement/error/fin states: distinct initial-load, next-chunk-loading, vide, error/retry, and end-of-results states; a broken loader is a reliability problem avant it’s an SEO un.
- Accessibility and performances: infinite scroll has aucun inherent Core Web Vitals outcome (it’s ce que vous construire); keyboard reachability, non-disruptive announcements, and the WAI-ARIA feed pattern are separate design fonctionner from the indexation fix.
- Dated observations: treat the exact viewport pixel dimensions and the merge-bug mechanics as implementation-specific, pas a stable spec — vérifier per URL.
Documentation officielle
Primary-source documentation on infinite scroll, pagination, and JS rendering.
- Fix lazy-loaded content — inclut the “Support paginated loading for infinite scroll” section (unique per-chunk URLs, absolute page numbers, History API) and the Inspection d’URL testing step. Dernier mis à jour 2025-12-10.
- Pagination, incremental page chargement, and leur impact on Recherche Google — the three UX patterns (pagination / charger plus / infinite scroll), leur pros/cons, the crawler-interaction remarque, and the
rel=next/rel=prevdeprecation. - Infinite scroll search-friendly recommendations — the original 2014 blog post (historical; the
rel=next/rel=prevpairing it décrit is now superseded). - September 2023 SEO Office Hours Transcript — Mueller’s on-the-record restatement of the unique-URL rule.
- Comprendre the JavaScript SEO basics — the broader rendering context infinite scroll sits à l’intérieur.
Bing / Microsoft
- bingbot Series: JavaScript, Dynamic Rendering, and Cloaking. Oh My! — Bing’s general JS-rendering guidance (aucun infinite-scroll-specific page exists; Bing encore respects
rel=next/rel=prev).
Quotes from the source
On-the-record statements from Google and Bing. Chaque lien is a deep lien que jumps to the quoted passage on the source page.
Google — infinite scroll & the paginated-loading rule
- “To implement infinite scroll in an indexable way, make sure your website supports paginated loading of these chunks.” … “Give each chunk its own persistent, unique URL.” — Recherche Google Central, “Fix lazy-loaded content.” Jump to quote
- “When a new page chunk is loaded in response to the user scrolling, and it becomes the primary visible element for the user, update the displayed URL using the History API.” Jump to quote
- “The methods mentioned don’t rely on user actions, such as scrolling or clicking, to load content, which is important as Google Search does not interact with your page.” Jump to quote
- “You can use the URL Inspection Tool in Search Console to see if all content was loaded. Check the rendered HTML to make sure your content is in the rendered HTML by looking for it in URL Inspection Tool.” Jump to quote
Google — pagination doc: robot d’exploration behavior & rel=suivant/prev
- “Google’s crawlers don’t ‘click’ buttons and generally don’t trigger JavaScript functions that require user actions to update the current page contents.” Jump to quote
- “In the past, Google used
<link rel="next" href="...">and<link rel="prev" href="...">to identify next page and previous page relationships. Google no longer uses these tags, although these links may still be used by other search engines.” Jump to quote
John Mueller, Google — September 2023 office hours
- “It depends how you implement infinite scrolling. if each piece or virtual page is also accessible and findable through a unique URL, generally it should be fine to have infinite scroll.” Jump to quote
John Mueller, Google — the “9000px viewport” tweet (Nov 2017)
- “Googlebot renders with a very tall viewport, which skews some CSS (often images). Try in Chrome dev-tools, eg 9000px high viewport.” — reproduced by Moteur de recherche Roundtable. Lire the coverage
Bing — general JS rendering (aucun infinite-scroll-specific page)
- “As we shared last week at SMX East, bingbot is generally able to render JavaScript. However, bingbot does not necessarily support all the same JavaScript frameworks that are supported in the latest version of your favorite modern browser.” — Fabrice Canel & Frédéric Dubut, Microsoft Bing. Jump to quote
Qui pagination pattern devrait vous utiliser?
Fonctionner top to bottom.
1. Fait le contenu past the premier screen besoin to rank in search?
- Aucun (e.g. an internal-only feed, a logged-in dashboard) → quelconque pattern is fine; optimize purely pour UX.
- Yes → garder going.
2. Do vous déjà have (or peut vous construire) a réel per-chunk URL pour every batch?
- Aucun, and vous pouvez’t → utiliser classic numbered pagination. Every page is a réel URL by par défaut, so it’s the lowest-risk pattern pour le SEO.
- Yes → infinite scroll or “load more” are les deux fine, continuer.
3. How grand is the définir?
- Very grand (thousands of items, deep catalog) → préférer numbered pagination or infinite-scroll-over-real-URLs; pure infinite scroll “can’t handle very grand numbers of results.” Ajouter sitemaps as a discovery backstop.
- Moderate → infinite scroll or charger plus, backed by paginated URLs, is fine.
4. Building infinite scroll — is it wired to réel URLs + History API?
- Aucun (scroll event seulement, aucun URLs) → ne faites pas ship. Ce is the setup que obtient deep content merged/unindexed.
- Yes (
?page=NURLs + crawlable anchors +pushState) → ship it, alors vérifier in the Inspection d’URL Tool’s rendered HTML.
5. Déjà live and a deep page “isn’t indexed”?
- Vérifier the Inspection d’URL Tool’s rendered HTML of the previous page/post premier — the “missing” content may be merged là.
- Si it is → emergency fix: block the infinite-scroll JS fichier so it can’t fire during rendering, alors rebuild on paginated URLs.
Search-friendly infinite scroll checklist
- Every content chunk has its propre persistent, unique, absolute URL (e.g.
?page=2, pas?date=yesterday). - Chaque URL renvoie the même content every temps it loads (stable, pas session-dependent).
- Chunks are lié with réel
<a href>liens, discoverable sans running JS. - The visible URL updates via the History API (
pushState/replaceState) as chaque chunk becomes the principal content. - The scroll loader uses
IntersectionObserver(or native lazy-loading), pas a rawscrollevent listener. - Paginated URLs are listed in the XML sitemap (and, pour ecommerce, backed by a Merchant Center feed).
-
rel=next/rel=prevoptionally présent pour Bing (harmless pour Google, qui ignores it). - Inspection d’URL Outil → rendered HTML confirms deep content is présent and pas merged from an adjacent page.
- Locally reproduced with a tall DevTools viewport (~9000px) to confirmer the loader doesn’t over-fire during render.
- A
popstatehandler reconstructs chunk content on back/forward, pas simplement scroll position. - Distinct chargement, error/retry, vide, and end-of-results states exist — a failed récupérer doesn’t silently strand lune page.
- Keyboard utilisateurs peut reach nouveau content and lune page footer; nouveau content is announced via a polite status region, pas a disruptive alert.
Ce que breaks infinite scroll pour le SEO
Scroll-event-only chargement with aucun réel URLs. The classic mistake. Content lives seulement in the DOM après a scroll fires — Googlebot jamais scrolls, so it’s invisible. There’s nothing to explorer and nothing to fall back on.
A “Load more” button that’s a pure click handler.
Feels safer que auto-scroll, isn’t. Google doesn’t click buttons soit. It seulement helps
si the button is (or wraps) a réel <a href> to a paginated URL.
Fragment/hash URLs pour pagination (#page=2).
Fragments don’t créer distinct crawlable URLs. Utiliser réel query-parameter or path-based
URLs à la place.
Relative or unstable URLs (?date=yesterday, session-scoped content).
Si the même URL renvoie différent content on différent loads, it can’t serve as a stable,
indexable page. Utiliser absolute page numbers.
Ignoring the tall-viewport merge bug. Assuming “not indexed” signifie Google is ignoring lune page. In infinite scroll it souvent signifie le contenu got folded into an adjacent URL by the render-time trigger — a différent problem needing a différent fix.
Blocking votre JS/CSS globally as a “fix.” Blocking the spécifique infinite-scroll trigger fichier is a deliberate emergency mesurer. Blocking tout JS/CSS n’est pas — it wrecks rendering à travers the whole page.
Infinite scroll SEO — cheat sheet
The three UX patterns
| Pattern | Inherently crawlable? | SEO risk | Meilleur pour |
|---|---|---|---|
| Numbered pagination | Yes (réel URLs) | Lowest | Grand sets, deep catalogs |
| Charger plus (button) | Seulement si button = réel lien | Medium | Moderate sets |
| Infinite scroll | Aucun — nécessite URL couche ajouté | Highest sans URLs | Feeds, browsing UX |
The non-negotiables pour infinite scroll
- Persistent, unique, absolute URL per chunk (
?page=12). - Même content on every charger (aucun
?date=yesterday). - Crawlable
<a href>liens entre chunks. - History API (
pushState/replaceState) to sync the adresse bar. IntersectionObserver, pas a rawscrolllistener.
Fast facts
- Googlebot: doesn’t scroll, doesn’t click.
- Render viewport (reported): ~411×12,140px mobile, ~1024×9,307px desktop.
- Merge bug: tall viewport peut fire the loader mid-render → two pages indexé as un.
rel=next/rel=prev: Google dropped it in 2019; Bing encore uses it.- Vérifier: Inspection d’URL Outil → rendered HTML.
- Emergency fix on a live merge bug: block the infinite-scroll JS fichier.
Ce que bon and bad implementations regarder comme
Bad — scroll-only, invisible to Google
The category page ships 24 products in the HTML. A scroll listener récupère the suivant
24 and appends les. Là are aucun ?page=N URLs anywhere, aucun anchors, aucun History API.
Googlebot loads lune page, jamais scrolls, and indexes 24 products. The autre 300 in the
catalog are undiscoverable via ce page.
Bad — the merge bug in the wild
A publisher’s blog uses infinite scroll to append the suivant post ci-dessous the current un. A writer complains leur nouveau article “won’t index.” It’s en réalité indexé — as partie of the previous post’s URL, parce que Google’s tall render viewport triggered the loader and folded the suivant article into the current page’s render. Fix: paginate correctement, and in the meantime block the infinite-scroll trigger script.
Bon — infinite scroll over réel URLs
The même category exists at /shoes?page=1, /shoes?page=2, … chaque a réel URL returning
stable content, tout listed in the XML sitemap and lié with <a href> at the foot of the
listing. Pour humans, IntersectionObserver loads the suivant chunk as ils approach the bottom
and history.pushState() updates the adresse bar to ?page=2 quand que batch becomes the
principal content. Google reaches every page directement via the liens and sitemap; the scroll UX
is pure enhancement on top.
Implementation and diagnostic snippets
The History API pattern (client-side)
Charger chaque chunk quand it’s à propos de to enter view with IntersectionObserver, alors swap the
visible URL quand que chunk becomes principal. The clé is que the ?page=N URLs are réel
pages que exist server-side regardless of ce script.
// A sentinel element sits at the bottom of the current chunk.
const sentinel = document.querySelector('#load-more-sentinel');
let nextPage = 2;
const io = new IntersectionObserver(async (entries) => {
if (!entries[0].isIntersecting) return;
const res = await fetch(`/shoes?page=${nextPage}&partial=1`);
const html = await res.text();
document.querySelector('#product-grid').insertAdjacentHTML('beforeend', html);
// Update the address bar so refresh/share/link land on this chunk.
// pushState adds a history entry; replaceState if you don't want back-button steps.
history.pushState({ page: nextPage }, '', `/shoes?page=${nextPage}`);
nextPage++;
}, { rootMargin: '600px' }); // start loading before the user hits the very bottom
io.observe(sentinel);And crucially, the crawlable fallback encore lives in the DOM — ce is ce que Google follows:
<nav aria-label="Pagination">
<a href="/shoes?page=2" rel="next">Next</a>
<!-- rel="next"/"prev" is ignored by Google since 2019 but still used by Bing -->
</nav>DevTools console: fait votre loader fire sans a réel scroll?
Simulate Google’s tall viewport locally, alors vérifier si supplémentaire chunks chargé on leur propre. In Chrome DevTools, définir a very tall custom device viewport (~1024×9000), reload, and run ce in the Console to count how nombreux chunks are présent with aucun manual scrolling:
// Count rendered product cards (adjust the selector to your markup)
console.log('cards rendered without scrolling:', document.querySelectorAll('#product-grid .product-card').length);
// If this is much higher than your per-page count, the loader is over-firing on height alone.DevTools console: confirmer the paginated URLs en réalité exist
Avant trusting the fallback, vérifier chaque ?page=N renvoie réel, distinct content
server-side (pas a JS-only route):
// Run in the console; a real paginated URL should return HTML containing products.
for (const n of [2, 3, 4]) {
const html = await (await fetch(`/shoes?page=${n}`)).text();
console.log(`page ${n}: ${html.includes('product-card') ? 'has products ✅' : 'EMPTY — JS-only? ❌'}`);
}Bookmarklet: jump straight to une page’s rendered-HTML vérifier
Drag ce to votre bookmarks bar to ouvrir the current URL in Search Console’s Inspection d’URL Outil, où vous alors lire the rendered HTML (pas the source) to voir how far bas Google captured content:
javascript:(()=>{const u=encodeURIComponent(location.href);open('https://search.google.com/search-console/inspect?resource_id=&id='+u,'_blank');})();You’ll encore pick votre verified property à l’intérieur Search Console; the bookmarklet simplement
saves the copy-paste of the current URL. Prove infinite scroll is indexable après launch
Tester a lazy-loaded product grid sans conflating navigateur states
A unique screenshot from a tall navigateur window n’est pas suffisant. Run the même category URL via ce matrix and commencer chaque fresh-navigation cas with an vide page cache or a documented, consistent cache state:
| Run | Viewport | Entry méthode | Interaction |
|---|---|---|---|
| A | Standard mobile or desktop height | Fresh navigation | None |
| B | Very tall height | Fresh navigation at que height | None |
| C | Standard height, alors resized tall | Navigation premier, resize second | None |
| D | Standard height | Fresh navigation | Incremental scrolling to the fin |
Fresh navigation and resizing are différent tests. A component may register its observer, calculate thresholds, or récupérer its premier batch seulement during initialization; resizing an already-running page peut therefore réussir quand a crawler-style navigation at the final dimensions fails, or vice versa. Incremental scrolling is a user-path contrôler, pas a substitute pour the no-interaction runs.
Pour every run, record:
- la requêteed URL and final address-bar URL;
- viewport dimensions and si lune page was chargé or resized at ceux dimensions;
- product cards rendered après chaque charger;
- unique product URLs in réel
<a href>attributes; - duplicate, manquant, or cross-page product URLs;
- network requêtes and the trigger que initiated chaque additional batch;
- si page/chunk boundaries mettre à jour l’URL and survive refresh;
- the relevant accessibility-tree nodes, noms, roles, and lien destinations.
Reconcile ceux counts contre the attendu catalog or paginated-chunk inventory. Visible card count and unique lien count are separate assertions: a grid peut paint 48 cards pendant que exposing fewer crawlable product liens, duplicated destinations, or contrôle que are absent from the accessibility tree. Garder a distinctive premier and dernier SKU pour chaque chunk so vous pouvez detect a tall viewport silently merging page 2 into page 1.
Tester every chunk as a standalone URL
Tester to run: Requête the premier, middle, and dernier paginated URLs directement with JavaScript disabled. Attendu result: Chaque renvoie stable, unique content and a successful réponse sans requiring a scroll. Échec interpretation: L’URL couche is cosmetic or encore dépend on client interaction. Monitoring window: Immediate après deployment. Rollback trigger: Quelconque listed chunk redirections to the premier page, renvoie the shared shell, or changements content entre requêtes.
Tester robot d’exploration discovery sans interaction
Tester to run: Inspect the rendered DOM avant scrolling and extract the pagination
liens. Attendu result: Sequential chunks are lié via réel absolute or
root-relative href valeurs. Échec interpretation: The robot d’exploration has aucun chemin au-delà
the premier chargé définir. Monitoring window: Immediate. Rollback trigger: The suivant
chunk exists seulement behind a button handler or scroll event.
Tester pour the tall-viewport merge bug
Tester to run: Render the premier chunk in a very tall Chrome viewport, alors search the DOM pour a distinctive item from the suivant chunk. Attendu result: The premier URL ne fait pas absorb the suivant URL’s principal content. Échec interpretation: The loader fires during rendering même sans utilisateur interaction. Monitoring window: Immediate locally, alors recheck Inspection d’URL après Google recrawls. Rollback trigger: Two logical chunks apparaître as un document or the adresse bar ne fait pas track the principal visible chunk.
Testez vos connaissances: Infinite Scroll SEO
Five rapide questions on making infinite scroll indexable. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
My connexe writing
- JavaScript SEO Problèmes & Meilleur Practices — my complet write-up, notamment the “Infinite scroll issues” section (two pages indexé as un) and the “What Googlebot sees” viewport figures.
- The Beginner’s Guide to SEO technique — où rendering and crawlability fit in the bigger picture.
My speaking
- How Search Fonctionne (SlideShare) — my walkthrough of exploration, rendering, indexation, and ranking, qui is the backdrop to every infinite-scroll decision. (My standing disclaimer s’applique: “This is my understanding of systems… not going to be 100% complete or accurate.”)
From autour the industry
- Recherche Google Central, Fix lazy-loaded content — the current, authoritative “Support paginated loading for infinite scroll” guidance.
- Recherche Google Central, Pagination, incremental page chargement, and leur impact on Recherche Google — the three UX patterns and the
rel=next/rel=prevdeprecation. - Matt G. Southern, How Google Crawls Pages With Infinite Scrolling (Moteur de recherche Journal) — the Mueller “two or three pages loaded on one page” explanation of the merge risk.
- Matt G. Southern, Google’s Martin Splitt Explique Pourquoi Infinite Scroll Causes SEO Problems (Moteur de recherche Journal) — “Googlebot doesn’t scroll,” IntersectionObserver vs. scroll, and “test your implementations.”
- Barry Schwartz, GoogleBot Crawls & Renders Tall, With 9000px Élevé Viewport? (Moteur de recherche Roundtable) — the origin of the tall-viewport explanation.
- Matthew Edgar, SEO Friendly Infinite Scroll — the “component pages” framing (chunks que fonctionner independently, même with JS off).
- Go Fish Digital, How To Implement Infinite Scroll Pour le SEO — an implementation-oriented walkthrough.
- Lumar, State of Pagination in eCommerce — the top-UK-fashion-retailer indexability analysis que rated infinite scroll the worst-performing pattern.
Journal des modifications
Mis à jour le 29 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.
Mis à jour le 18 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.