Your Lazy Loading Is Hiding Content from Googlebot
On this page
If content that appears as visitors scroll is missing from Google’s index, look at what triggers it. Google’s guide to lazy-loaded content states the constraint plainly: Google Search does not interact with your page. Content that loads when it becomes visible in the viewport can be seen. Content that loads only after a scroll event or a click waits for an action that never comes. Change the trigger, keep indexable text in the HTML from the start, and give infinite scroll real URLs.
The trigger decides
The guide asks that lazy-loading load all relevant content whenever it is visible in the viewport, and it names three ways to do that. The difference between them and the ways that fail is a single question: does loading depend on a user action?
| Trigger | Example | Depends on a user action? |
|---|---|---|
| Element enters the viewport | the browser's built-in <!–INLINECODE0–> attribute on images and iframes | No |
| Element enters the viewport | the IntersectionObserver API, with a polyfill | No |
| Element enters the viewport | a JavaScript library that loads data as it enters the viewport | No |
| Scroll event or scroll depth | a handler that appends items after the user scrolls a set distance | Yes |
| Click | a "Load more" button | Yes |
The first three are the guide’s own methods, and it notes they don’t rely on user actions such as scrolling or clicking. The last two do, and for Google that means the content they add never enters the page it renders.
Text that already sits in the HTML inside a collapsed accordion or tab is a separate question. The lazy-loading problem is text that isn’t in the page at all until something happens.
Content versus images
“Lazy loading” covers two different things, and only one of them hides content.
- Deferred image bytes. An
<img>or<iframe>with theloadingattribute and a real URL insrcis present in the markup. Only the file download waits. The guide gives a direct test for this: if your image or video URLs appear in thesrcattribute of the<img>or<video>elements in the rendered HTML, the setup works. - Deferred content. Product cards, article sections or list items that a script adds only after a scroll are absent from the rendered HTML, so there is nothing to index.
The trouble starts when the image technique gets applied to content. A quick check keeps them apart: is the text a reader sees present in the markup before any scrolling? If the words are there and only the pictures arrive late, the text is safe. If the words themselves arrive with a scroll handler, they are outside what Google renders.
The server-rendering ceiling
Server rendering doesn’t settle the question on its own. The trap is a server render that copies the client’s first paint while the remaining items still wait for a scroll. If the client component shows 12 of 60 products on mount, the server emits the same 12 and the other 48 arrive only on scroll, your indexable ceiling is 12, however many products a scrolling visitor eventually sees.
Every item you want indexed has to be in the page without any interaction: in the server output, or added by scripts that run on load or when the element enters the viewport, rather than on a scroll event. The server output is the sturdier place for it. Google’s JavaScript SEO basics recommend server-side rendering or pre-rendering, partly because not all bots can run JavaScript. The client can then hydrate or reveal those items progressively without removing any from the markup. If your framework’s default is to server-render exactly what the first client paint shows, override it for indexable content.
To find your ceiling, start with the source of the production URL and count the items in the raw HTML, before any script runs. Then compare the rendered HTML in URL Inspection. Browsing the page won’t show you this problem, because scrolling fills in the rest.
The page-weight objection
One reason teams give for scroll-loading content is performance: sixty product cards feel like too much for the first response. Measure before accepting it. Compare the transfer size of the card markup (titles, prices, links, a handful of attributes) with the transfer size of the card images. The images can stay deferred with the loading attribute and a real src, so if the text is the light part, you can keep all of it in the first response and still defer the heavy files.
Infinite scroll needs real URLs
For long feeds, the guide asks for paginated loading behind the infinite scroll:
- give each chunk its own persistent, unique URL;
- make sure each URL shows the same content every time it loads, for example with absolute page numbers such as
?page=12, not relative values such as?date=yesterday; - link the URLs sequentially so search engines can discover the whole set.
The scroll stays the visitor’s experience. The paginated URLs give Google a path to the items beyond the first chunk.
Verify what Google renders
Inspect the URL in Search Console’s URL Inspection tool and read the rendered HTML. Count the items present. If a scrolling visitor sees 60 and the rendered HTML holds 12, you have found the ceiling: the other 48 are missing from what Google renders, and so from what it can index. For images, look for their URLs in the src attributes, as the guide suggests.
Don’t fix it with a bot-only version
Serving Googlebot a separate, fully loaded page based on its user agent is the wrong repair. Google’s spam policies define cloaking as presenting different content to users and search engines with the intent to manipulate search rankings and mislead users, and a bot-only variant puts you close to that line. Google’s dynamic rendering documentation calls bot-specific rendering a workaround and not a recommended solution. The durable fix is one response for everyone that already contains the indexable content.
Frequently asked questions
Is loading=”lazy” on images bad for SEO?
No. The browser’s built-in lazy loading for images and iframes is the first method in Google’s own list. The element and its URL are in the markup; only the download is deferred.
Does IntersectionObserver work for Googlebot?
It is one of the three methods Google’s lazy-loading guide lists, and it loads content when an element becomes visible rather than waiting for a scroll or a click.
How do I tell whether content is missing or just slow?
Read the rendered HTML in URL Inspection and count the items. If the rendered HTML holds fewer items than a scrolling visitor sees, the rest aren’t in what Google renders.