Learn
JavaScript SEO Debugging Guide: Rendered HTML, Hydration, and Crawlable Links
A debugging guide for React, Vue, Nuxt, and Next.js SEO: how Google renders JavaScript, why content and links go missing, and how to make them crawlable.
Run a fresh DomainLens audit and use the report as your priority list.
How Google actually renders JavaScript
Google processes a JavaScript page in two waves. First it crawls the raw HTML response; then, when rendering resources are available, it runs the page in a headless Chromium and indexes the rendered DOM. The gap between those waves is why JavaScript SEO problems are subtle: the page works perfectly in your browser, but the crawler indexed something different — or rendered late, or not at all.
The single most important habit is to stop trusting "View Source." What matters is the rendered HTML: what exists in the DOM after JavaScript has run, because that is what Google indexes. Most JS SEO bugs are just a mismatch between the two.
The failures that hide content from crawlers
- Content that only mounts after a client-side data fetch, so the initial and rendered HTML are empty and rendering may time out before it arrives.
- Links built as <span> or <div> with onclick handlers or javascript: URLs — Google follows <a href> only, so those pages are undiscoverable.
- Metadata (title, canonical, robots, hreflang) set by client-side JavaScript, which can be missed or arrive after the first crawl wave.
- Routing that relies on the History API without server-rendered URLs, so deep pages have no crawlable entry point.
- Blocking Googlebot from the JS or CSS bundles in robots.txt, so it cannot render the page at all.
How to check the rendered HTML
Debugging JS SEO is mostly about comparing what you ship with what the crawler sees.
- Use Search Console URL Inspection → "Test live URL" → View rendered HTML and screenshot; this is Google’s own render, not your browser’s.
- Compare the raw response (curl or "View Source") with the rendered DOM (DevTools Elements) — content in the DOM but not the response is JS-dependent.
- Disable JavaScript in DevTools and reload: whatever disappears is invisible to the first crawl wave and at risk if rendering is delayed.
- Check that title, canonical, and robots meta exist in the rendered HTML and match what you intend.
- Confirm internal links are real <a href> elements in the DOM, not click handlers.
How to make a JavaScript site crawlable
- Server-render or pre-render the content and metadata so it exists in the initial HTML — SSR (Next.js, Nuxt), static generation, or hydration on top of server output.
- Emit real <a href> links for every route you want crawled and indexed.
- Set critical SEO tags (title, canonical, robots, hreflang) server-side, not after hydration.
- Never block JS/CSS resources in robots.txt; Google needs them to render.
- Keep the rendered output stable and fast — a render that times out is treated as if the content is not there.
Mistakes that make JS SEO worse
- Assuming "Google renders JavaScript now" means every JS pattern is safe — rendering is deferred, budgeted, and can fail.
- Testing SEO tags in the browser DevTools instead of Google’s rendered HTML.
- Using a soft 404 (200 status with an empty SPA shell) for routes that do not exist.
- Serving different content to Googlebot than to users to "help" rendering — that is cloaking.
How to validate the fix
Re-run URL Inspection and confirm the rendered HTML now contains the content, the correct canonical and robots tags, and crawlable links. Then check the Page Indexing report over the following days to confirm the affected URLs move into the index.
In DomainLens, treat the rendered HTML as the source of truth: it fetches and reads the page the way a crawler does, so a title, canonical, or link that only exists after hydration shows up as missing — which is exactly how Google may see it.