Guide Infinite Scroll SEO

Comment implement infinite scroll sans losing votre indexation — pourquoi Googlebot ne fait pas scroll, le tall-viewport rendre trick que flattens deux pages dans un, le paginated-URL + History API corriger, et le ecommerce category-page cas.

Première publication : 3 juil. 2026 · Dernière mise à jour : 3 août 2026 · Avancé

«Infinite scroll loads more content as you scroll, instead of via numbered pages — and Googlebot never scrolls or clicks, so anything gated behind that action is invisible by default. Google renders in a very tall viewport (about 411×12,140px mobile, 1024×9,307px desktop) as a workaround, but that same tall viewport can trigger the scroll loader during rendering and fold two logical pages into one indexed URL — a failure mode where a 'not indexed' page is actually indexed as part of another. The fix is architectural: give every chunk a real, persistent, absolute URL (like ?page=2), link them with crawlable anchors, and update the address bar with the History API as the user scrolls. rel=next/prev is legacy (Google dropped it in 2019; Bing still supports it). On ecommerce category pages, back it all with sitemaps or a Merchant Center feed and verify in the URL Inspection Tool's rendered HTML. A production build also needs a real popstate/back-forward contract, distinct loading/error/end states, and deliberate accessibility — none of that comes for free just because the indexing fix is in place.» _(Traduction)_ (Résumé en français du champ tldr : le texte source est conservé pour relecture francophone.)

«> TL;DR — Googlebot never scrolls and never clicks, so scroll-gated content is

invisible by default. Google’s workaround is to render in a very tall viewport (roughly 411×12,140px mobile, 1024×9,307px desktop) — but that same height can trigger the scroll loader during rendering, folding the next logical page into the current one so two pages get indexed as a single URL. The durable fix is architectural: persistent, absolute, per-chunk URLs (e.g. ?page=12), linked with crawlable anchors, with the History API updating the address bar as each chunk becomes primary. rel=next/rel=prev is legacy for Google (dropped 2019) but still respected by Bing. On ecommerce PLPs, sitemaps or a Merchant Center feed are a discovery backstop. Verify everything in the URL Inspection Tool’s rendered HTML. » (Traduction) (Résumé en français de la section vingt, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Preuve à l’appui de cette affirmation Google Search does not generally interact with scrolling controls, so infinite-scroll content needs crawlable paginated URLs. Portée : Current official or standards documentation. Niveau de confiance : élevé · Vérifié : Google: Lazy-loaded content Preuve à l’appui de cette affirmation The History API can update URLs for loaded page chunks without a full navigation. Portée : Current official or standards documentation. Niveau de confiance : élevé · Vérifié : MDN: History API

Premier, a disambiguation

Si vous recherche “Google infinite scroll” vous’ll hit résultats à propos de Google’s propre continuous scroll on son résultats de recherche pages — a SERP fonctionnalité Google turned on et alors discontinued dans mid-2024. c’est a Google-produit UX décision et a rien à faire avec comment Googlebot explore votre site. Ce article est à propos de le latter: infinite scroll as a chargement modèle on votre propre pages, et si Google peut indexer ce que il charge.

Le core constraint: Google ne fait pas interact avec votre page

«Everything here follows from one fact. Google’s own lazy-loading docs say the recommended patterns “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.” The pagination doc says it even more plainly: “Google’s crawlers don’t ‘click’ buttons and generally don’t trigger JavaScript functions that require user actions to update the current page contents.” » (Traduction) (Résumé en français de la section vingt-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

As Je put il dans mon propre JavaScript SEO guide: “Googlebot ne fait pas prendre action on webpages. c’est pas going à click choses or scroll, mais que ne fait pas signifier il ne fait pas ont workarounds. Tant que contenu est chargé dans le DOM sans a nécessaire action, Google va voir il. Si c’est pas chargé dans le DOM jusqu’à après a click, alors le contenu ne va pas être 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 » (Traduction) (Résumé en français de la section vingt-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«Google doesn’t simulate scrolling. Instead it renders your page in an unusually tall viewport, so content a few screens down is already inside the rendered area without anyone scrolling. The earliest on-record hint of this was John Mueller’s 2017 note that “Googlebot renders with a very tall viewport, which skews some CSS (often images). Try in Chrome dev-tools, eg 9000px high viewport.” » (Traduction) (Résumé en français de la section vingt-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Le spécifique numbers j’ai documented: pour mobile, Google charge lune page à a screen size de 411×731 pixels et resizes le length à 12 140 pixels — “essentially, il becomes a vraiment long phone avec a screen size de 411×12140 pixels. Pour desktop, il fait le même et goes depuis 1024×768 pixels à 1024×9307 pixels.” (Je haven’t vu recent re-tests de ceux exact figures, et ils peut vary avec page length; le original dimensions trace back à independent testing par SEO researcher JR Oakes.) Le point n’est pas le exact pixel count — c’est que Google fakes “seeing far bas le page” avec height, pas avec movement.

Treat les deux le exact pixel dimensions et le deux-pages-merged behavior ci-dessous as dated, implementation-spécifique observations plutôt que a stable plateforme contract — Google ne fait pas publish an official spec pour soit number, et rendu behavior peut modifier. ne pas assume votre site behaves le même façon; confirmer actuel behavior pour votre propre URLs avec le rendu-HTML tester dans le suivant section au lieu de taking ces figures as a guarantee.

The échec mode nobody explique: two pages indexé as un

A height-triggered loader peut fire during rendu et merge deux logical pages sous un indexé URL. Source : /technical-seo/javascript-seo/

A normal navigateur viewport arrête après page un. Google's rendre viewport expands beaucoup taller, reaches le infinite-scroll trigger sans a réel utilisateur scroll, et appends page deux dans le même DOM. Le merged DOM est alors indexé as un URL au lieu de deux séparé pages.

© Patrick Stox LLC · CC BY 4.0 ·

Ici’s où le tall viewport bites back. Parce que le rendre viewport est donc tall, le scroll-triggered loader peut fire during rendu même though rien “scrolled” dans le human sense — le sheer DOM height peut être suffisant à satisfy an IntersectionObserver or a scroll-position vérifier. Quand que se produit, le loader appends le suivant logical page’s contenu dans le actuel page’s rendre, et Google indexes le merged résultat as a unique URL.

I’ve diagnosed ce several times. From my JavaScript SEO guide:

“Un autre problème j’ai vu avec ce setup est, occasionally, deux pages obtenir indexé as un. j’ai vu ce a quelques times quand personnes said ils ne pouvait pas obtenir leur page indexé. Mais j’ai trouvé leur contenu indexé as partie de un autre page c’est généralement le previous post depuis les.”

“Mon theory est que quand Google resized le viewport à être plus long, il triggered le infinite scroll et chargé un autre article dans quand il était rendu. Dans ce cas, ce que Je recommend est à bloquer le JavaScript fichier que handles le infinite scrolling donc le functionality ne peut pas trigger.”

John Mueller décrit le même mechanic depuis Google’s side dans a 2022 office-hours session: Google renders avec a élevé viewport, que “voudrait trigger some amount de infinite scrolling,” et “nous pourrait ont deux or three de ces pages chargé on un page avec infinite scroll, mais pas tout.” (Que office-hours citation est relayed via Moteur de recherche Journal’s écrire-up, pas confirmed contre le principal recording.)

Two consequences fall out of ce:

  1. il y a aucun guarantee de comment beaucoup obtient pulled dans. Pourrait être rien supplémentaire, pourrait être deux or three pages, jamais reliably tout. Infinite scroll alone n’est pas a dependable façon à obtenir deep contenu indexé.
  2. “Pas indexé” peut être a misdiagnosis. Le manquant page peut pas être manquant à tout — il peut être indexé as partie de an précédent URL. Que nécessite a différent corriger que a normal indexation bug.

How to diagnose it

Utiliser Search Console’s Inspection d’URL Outil et lire le rendu HTML, pas le raw source. Google’s docs sont explicit: “Vous pouvez utiliser le Inspection d’URL Outil dans Search Console à voir si tout contenu était chargé. Vérifier le rendu HTML à assurez-vous votre contenu est dans le rendu HTML par looking pour il dans Inspection d’URL Outil.” Recherche le rendu HTML pour contenu vous expect à être sur la page 1 seulement. Si vous trouver contenu depuis page 2 (or le suivant article) sitting à l’intérieur page 1’s rendre, vous avez reproduced le merge bug.

Vous pouvez aussi replicate le tall viewport locally: ouvrir Chrome DevTools, définir a very tall custom viewport (Mueller’s suggestion était ~9000px), et charger lune page à voir si votre loader fires avec aucun scrolling.

Le corriger: paginated URLs + le History API

Le durable corriger est architectural, straight depuis Google’s actuel lazy-loading doc. À faire infinite scroll indexable, “assurez-vous votre site web prend en charge paginated chargement de ces chunks”:

  • “Donner chaque chunk son propre persistent, unique URL.”
  • “Garantir que le contenu affiché on chaque URL remains le même chaque temps c’est chargé dans a navigateur” — Google suggests absolute page numbers comme ?page=12.
  • “Avoid en utilisant relative elements like ?date=yesterday dans ces URLs” — an adresse que renvoie différent contenu chaque charger est unusable as a canonical.
  • “Lien sequentially à le individual URLs donc que moteur de recherches peut découvrir le URLs dans a paginated définir” — réel <a href> liens, pas click handlers.
  • “Quand a nouveau page chunk est chargé dans réponse à le utilisateur scrolling, et il becomes le principal visible element pour le utilisateur, mettre à jour le affiché URL en utilisant le History API.”

Que dernier point est le elegant partie. history.pushState() / replaceState() swaps l’URL dans le adresse bar as le utilisateur scrolls past chaque boundary — donc le visible URL toujours matches le principal contenu, et le utilisateur peut refresh, share, et lien à exactly où ils sont. Meanwhile le crawlable ?page=N URLs exist independently, donc Google peut reach chaque chunk directement si or pas le renderer ever triggers le scroll.

Two implementation notes que matter:

  • Utiliser IntersectionObserver (or native navigateur lazy-loading), pas a raw scroll listener. Il performs far meilleur (aucun scroll-thrash) et c’est le “charger quand visible” mechanism Google endorses pour deferred contenu.
  • Garder le paginated définir discoverable independently de le JS. Réel anchors dans le DOM, et/or le ?page=N URLs listed dans votre XML sitemap. Whatever le renderer captures, le sitemap-et-liens couche est votre backstop.

Si a actif site est déjà exhibiting le merge bug et vous devez arrêter le bleeding avant vous pouvez rebuild, mon blunt emergency corriger est à bloquer le JavaScript fichier que triggers infinite scroll dans robots.txt donc il physically ne peut pas fire during rendu — buying temps à ship le proper paginated-URL architecture.

Le History API point ci-dessus covers half le contract — updating le adresse bar as a chunk becomes principal. Le autre half est making certain chaque entry chemin back dans que URL en réalité reconstructs le correct contenu, pas simplement le correct scroll position:

  • Utiliser pushState() quand a chunk becomes le principal visible contenu pour le premier temps — c’est a réel navigation étape, et c’est ce que rend le back button meaningful.
  • Utiliser replaceState() pour corrections que ne devrait pas créer leur propre back-button arrêter, comme syncing l’URL après a rapide scroll past plusieurs chunks à une fois.
  • Listen pour popstate et re-rendre (or re-récupérer) le chunk que matches l’URL dans le event. Le navigateur’s par défaut back/forward behavior restores scroll position, pas le dynamic liste state votre JavaScript construit — si a utilisateur hits back après votre loader appended 40 plus éléments, vous devez reconstruct qui éléments belong on que page, pas simplement scroll les là.
  • ne pas lean on automatic scroll restoration alone à solve ce. Il contrôle où le viewport lands, pas ce que contenu est présent — si le underlying liste peut modifier entre visits (nouveau produits ajouté, éléments out de stock), scroll position sans contenu reconstruction peut strand le utilisateur dans le incorrect context.

Ce est le même discipline le paginated-URL corriger déjà dépend on: a chunk’s URL a à retourner le contenu il promised on a fresh charger, a refresh, et a Recherche-Console actif tester — pas simplement le premier temps c’est 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 — le premier chunk devrait déjà être dans le raw HTML le serveur sends, pas assembled entirely par JS après le fact.
  • Suivant-chunk chargement — a visible dans-progress indicator donc utilisateurs (et anyone testing avec assistive tech) know a récupérer est underway.
  • Vide — a distinct state pour zero résultats, pas a blank space que semble broken.
  • Erreur / retry — a failed récupérer ne devrait pas silently strand lune page avec aucun façon à essayer à nouveau, et a retry ne devrait pas duplicate or reorder éléments déjà on lune page.
  • Fin de résultats — a clair signal, pas an infinite spinner, une fois il y a rien left à charger.

None de ce est Google-spécifique, mais c’est le même reliability le paginated-URL corriger dépend on: si le loader peut silently break mid-récupérer, vous pouvez’t confiance que quelconque donné explorer or utilisateur session en réalité captured le chunk il devrait ont.

Accessibility and performances: two choses infinite scroll doesn’t give vous pour free

Infinite scroll a aucun inherent Core Web Vitals résultat, bon or mauvais — c’est determined entirely par comment vous construire il. Chaque appended chunk grows le DOM, et a grand suffisant DOM raises layout et style-recalculation coût, donc watch append coût, image chargement, layout shift depuis contenu sans reserved space, et long tasks as le liste grows. On very long pages, considérer virtualizing chunks que ont scrolled far out de view (removing leur DOM nodes) au lieu de letting le DOM grow unbounded.

Accessibility nécessite its propre deliberate design, pas an assumption que “it renders, so it’s fine”:

  • Keyboard utilisateurs besoin à être able à reach nouveau contenu — et le footer or end-de-page navigation — sans lune page silently growing out depuis sous leur tab order.
  • Screen lecteur utilisateurs besoin nouveau contenu announced sans interrupting ce que ils sont doing — a polite status region, pas a disruptive alert, est le usual modèle.
  • Le WAI-ARIA feed design modèle est construit pour exactly ce cas: article-level regions à l’intérieur a feed container, avec défini keyboard behavior pour moving entre éléments et pour reaching contenu avant et après le feed.
  • Focus ne devrait pas silently jump or obtenir lost quand a nouveau chunk charge.

None de ce est optional cleanup. c’est le difference entre infinite scroll que fonctionne pour everyone et un que seulement fonctionne pour a mouse utilisateur avec JavaScript qui jamais strays depuis le happy chemin.

The historical context: rel=suivant/prev is legacy

«If you learned pagination years ago, you learned rel="next" / rel="prev". Google introduced them in 2011 and paired them with its original 2014 “infinite scroll search-friendly recommendations” (paginate the content, provide component pages). Then in 2019 Google announced it hadn’t been using those tags for years and formally dropped them. The pagination doc confirms it today: “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.” » (Traduction) (Résumé en français de la section soixante-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Donc le actuel Google recipe est unique URLs + crawlable liens + le History API — aucun rel=next/rel=prev requis. Mais “other search engines” inclut Bing, qui encore respects les, donc il y a aucun harm dans keeping les dans votre markup pour cross-moteur avantage et accessibility. Bing itself ne fait pas publish infinite-scroll-spécifique guidance; son stance reduces à le general JS-rendu caution son team laid out — bingbot peut rendre JavaScript mais “il est difficult pour bingbot à traiter JavaScript à scale,” donc a crawlable paginated fallback aide Bing pour exactly le même raison il aide Google.

Ecommerce category pages: le highest-stakes cas

Le la plupart courant real-world infinite scroll est on ecommerce category / produit listing pages (PLPs), et c’est où le risque coûts réel money. Si deep-catalog produits past le premier screenful jamais obtenir indexé, ils ne peut pas classer, et vous lose le long tail de produit-level trafic organique. Ce est le même territory covered dans depth dans le category-page material — infinite scroll est un plus raison ceux pages besoin a crawlable structure underneath le UX.

Two backstops matter ici:

  • XML sitemaps listing chaque canonical produit et paginated category URL, donc discovery ne fait pas depend on le renderer.
  • A Merchant Center produit feed, qui feeds Google produit données independently de whatever le category page’s renderer captures.

Lumar’s analysis de top UK fashion retailers trouvé infinite scroll à être, dans leur words, “le biggest loser quand il comes à indexability et SEO friendliness” parmi le pagination patterns — a utile reminder que ce n’est pas a theoretical edge cas, c’est le par défaut échec mode de a very popular PLP UX. (Lumar’s spécifique percentage figures devrait être lire depuis leur actif rapport avant citing an exact number.)

Infinite scroll vs. pagination vs. charger plus

«Google’s pagination doc frames three UX patterns and is honest about the tradeoffs. Infinite scroll “uses a single page for all content” and is “intuitive — the user just keeps scrolling,” but it “can lead to ‘scrolling fatigue’ because of unclear result size” and “can’t handle very large numbers of results.” Classic numbered pagination is the most robust for SEO because every page is inherently a real URL. “Load more” sits in between — fine if the button is (or wraps) a real link to a paginated URL, useless for SEO if it’s a pure click handler. » (Traduction) (Résumé en français de la section soixante-treize, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Le décision n’est pas “which is allowed” — tout three sont allowed. c’est “qui UX faire vous vouloir, et a fait vous construire le crawlable URL couche underneath il.” Mueller’s 2023 summary est le entier chose dans un line: “si chaque piece or virtual page est aussi accessible et findable via a unique URL, généralement il devrait être fine à ont infinite scroll.”

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.