Reference guide · technical-seo · Published 2026-08-16 · 4 min read
SEO for JavaScript-rendered sites
SEO for JavaScript sites: how Googlebot renders client-side apps, what stays invisible, and how to ship indexable initial HTML.
- ·How Google renders
- ·The initial HTML rules
- ·Verify in Search Console
Google does not "see nothing"
Googlebot runs an always-current Chromium to render pages. Client-side rendering does not automatically exclude a page from Google; what matters is where content lives relative to the render step. The pipeline (covered by the crawling and indexing guide) runs crawl, render, index. The render pass is for pages that require JavaScript.
The failures are specific, not universal:
- Content injected by JS is indexed after the render, so a page that renders its whole body in scripts may be indexed, but later and only if the render succeeds.
- A page whose initial HTML is empty (a
<div id="root">and a bundle) gives the crawler almost nothing before the render, and the render queue controls the timing. - A
noindexin the initial HTML cancels rendering: Google's docs note that when it encounters anoindextag, it may skip rendering and JS execution entirely, so a script that later removesnoindexhas no chance to run.
What the browser sees vs what the crawler gets
| Surface | What exists there |
|---|---|
view-source of the URL | The document Googlebot fetches first |
| DevTools Elements | The DOM after client scripts run |
| Google's rendered HTML | The result of its own render pass |
The shortest path to a JavaScript-SEO problem: open view-source on the live URL. If the title, meta description, main content and every internal link are in that raw document, the page is indexable before any script runs. If most of it renders in JavaScript only, the page depends on the render pass.
The rules for an indexable JS page
- Put the content in the initial HTML. Server-side rendering (SSR), static generation (SSG), or a pre-render of the public routes puts the text, the canonical, and the internal links into the document the crawler first reads. Google recommends this for everyone, and the effect on LCP is a second reason beyond SEO.
- Keep
hrefreal anchors. The crawler follows<a href>, not buttons with click handlers. SPA routers that render<a>with correcthrefmake the internal-link graph crawl normally. - Do not hide content behind interactions. Tabs, accordions, and infinite-scroll that require a click or scroll are not interacted with by Googlebot during render; serve that content in the document (or paginated URLs) instead.
- Canonical and metadata in the raw HTML head. A canonical injected by JS is often missed; keep the canonical (
<link rel="canonical">),title, meta description, androbotsmeta in the initial document. - Keep
robots.txtfrom blocking assets. A disallow on the JS or CSS files (e.g.Disallow: /*.js) stops Google rendering the page at all, because the renderer cannot see the content.
The render-queue budget on very large sites
On a large single-page application, every page requires a full JavaScript execution during the render pass. That makes crawling slow and can pile URLs into "Discovered, currently not indexed" because Google has fewer resources to process each one. The fix on big SPA sites is more content in the initial HTML (SSR/SSG per route), which converts the heavy render step into a plain fetch.
Verify your rendered state
- Open the URL Inspection tool in Search Console for a page.
- Click "View crawled page" / "Test live URL" and open the rendered result.
- Check the title, canonical, and whether main content and all internal links appear in the rendered HTML.
- If they do not, the page depends on the render pass (and is vulnerable to queue delay), or the content is gated behind interaction.
The honest priority
Search engines render JS every day. The decision is therefore not "will it index" but "how much does it cost and what can go wrong". A client-side-only page fights the render queue on large sites, silently loses content if the initial HTML is empty, and dies entirely if a script that removes noindex or injects rel-canonical runs in the wrong order. Shipping the content in the initial HTML eliminates all three at once, and it also makes the page faster for the LCP metric. If a markup decision to keep a CSR architecture, accept the render pass and verify each release; the render-blocking resources guide shows the browser-side cost of scripts that delay the first paint.