The page that ranked for nothing
A SaaS company we reviewed had spent six figures rebuilding its marketing site as a sleek React single page app. In the browser it looked perfect: animated pricing tables, a searchable resource library, detailed product pages. Then organic traffic fell off a cliff. When we pulled the rendered HTML that Google actually stored, the body of nearly every page was a single empty div. The content was real, but it only existed after JavaScript executed in the user’s browser. To a crawler, the site was a stack of blank pages.
This is the central problem of JavaScript SEO rendering. Modern frameworks build pages in the browser, but search engines and AI assistants do not experience your site the way a human does. If your content depends on JavaScript that the crawler never runs, that content effectively does not exist for ranking or for citation. Understanding how rendering works, where it breaks, and which architecture to choose is now a core part of technical SEO, not an edge case.
How Google actually processes a JavaScript page
Google does not read your page in one pass. It works in three distinct stages: crawling, rendering, and indexing. First, Googlebot fetches the raw HTML and extracts any links and content already present in that response. Then, if the page returns a 200 status code and is not blocked from indexing, the URL is placed in a render queue. When resources free up, Google opens the page in a headless version of Chrome, executes the JavaScript, and only then indexes whatever content appears in that final rendered DOM. Google’s own JavaScript SEO basics documentation confirms that “Googlebot queues all pages with a 200 HTTP status code for rendering, unless a robots meta tag or header tells Google not to index the page.”
Two consequences follow from this design. First, anything present in the initial HTML response can be indexed immediately, before rendering ever happens. Second, anything that only appears after JavaScript runs has to survive the render queue to be seen at all.
The render queue is faster than its reputation, but not free
The myth that Google waits weeks to render JavaScript is mostly outdated. Vercel analyzed more than 100,000 Googlebot fetches and found that, excluding error codes and non-indexable pages, 100 percent of HTML pages resulted in full-page renders, including complex JavaScript interactions. The delay between crawl and render had a median of just 10 seconds, with 25 percent of pages rendered within 4 seconds.
The tail, however, is long. The same study put the 90th percentile at roughly 3 hours, the 95th at about 6 hours, and the 99th at around 18 hours. Pages with query string URLs fared worse, hitting roughly 8.5 hours at the 90th percentile versus about 2.5 hours for clean URLs. For a fast-moving site (a publisher pushing breaking news, an ecommerce store changing prices, a launch you want indexed today) a multi-hour rendering gap can mean Google ranks a stale or empty version of the page well after it matters.
What gets hidden, and why
Several common patterns cause content to vanish during this process:
- Blocked resources. If your robots.txt blocks the JavaScript or API files needed to build the page, Google cannot render the content. As Google puts it, “Google Search won’t render JavaScript from blocked files or on blocked pages.”
- Fragment-based routing. Hash URLs (for example, /#/products) are unreliable because Googlebot cannot consistently resolve them as separate pages. Google recommends the History API for client-side routing instead.
- Client-side meta tags and noindex. A critical trap: if a noindex tag is present in the initial HTML response, the page will not be rendered at all, so removing that tag later with JavaScript has no effect. Vercel’s research is blunt that “client-side removal of noindex tags is not effective for SEO purposes.”
- Soft 404s and wrong status codes. Pages returning a 200 status for content that is actually missing confuse indexing. Status codes need to be meaningful at the server level, not faked in the client.
Hydration: the pitfall hiding inside frameworks that do everything right
Even teams that adopt server-side rendering can get burned by hydration. Hydration is the step where the browser takes the server-rendered HTML and attaches JavaScript behavior to make it interactive. The problem arises when the HTML the server produced does not match what the client expects to render. The Next.js documentation describes this hydration error as occurring when “the server-rendered HTML did not match what was rendered on the client,” and the usual culprits are browser-only APIs like window or localStorage, random values, time-dependent code such as new Date(), and locale differences.
The SEO damage is subtle because the page still looks fine to a human. When a mismatch occurs, React may tear down the server-rendered markup and rebuild it on the client. If that rebuild is slow or depends on data the crawler never fetches, Googlebot can end up indexing a skeleton or loading state instead of your real content. You ship server rendering, you assume you are safe, and you still serve crawlers an empty shell. This is exactly the kind of gap a proper SEO and GEO audit is designed to catch, because it only shows up when you compare the rendered DOM against what humans see, not when you eyeball the live site.
To avoid hydration problems, keep server and client output deterministic. Defer anything that depends on the browser environment to a post-mount effect rather than the initial render, and lean on server components (in modern React and Next.js) to render content as HTML that ships with zero client JavaScript for that piece. The less work the browser has to redo, the less surface area there is for content to disappear.
SSR, static, or dynamic rendering: making the architecture decision
For years, dynamic rendering was the recommended fix: detect the bot, serve it a pre-rendered HTML snapshot, and serve humans the JavaScript app. Google has since reversed that guidance. Its dynamic rendering documentation now states plainly that “dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines,” and that it “creates additional complexities and resource requirements.” Google instead recommends server-side rendering, static rendering, or hydration.
Here is how we frame the decision for clients:
Static rendering (SSG) for stable content
If a page’s content does not change per user and does not change often (blog posts, documentation, landing pages, evergreen guides) pre-render it to static HTML at build time. This is the safest option for SEO because the full content is in the initial response with no rendering step required. It is also the fastest to serve. Most content that drives organic search falls into this category, which is why content marketing programs perform best on statically generated pages.
Server-side rendering (SSR) for dynamic content
If content changes frequently or depends on the request (personalized dashboards, live inventory, search results, frequently updated catalogs) render the HTML on the server for each request. SSR is the most direct replacement for dynamic rendering: the crawler receives complete HTML without needing to execute anything, while interactivity is layered on through hydration for human users. The tradeoff is server cost and the hydration discipline discussed above.
Client-side rendering only when content does not need to rank
Pure client-side rendering still has a place: authenticated app interiors, account settings, tools behind a login. None of that needs to be indexed. The mistake is using client-only rendering for pages you want to rank or be cited for. Reserve it for surfaces where search visibility is irrelevant. Decisions like this are where site design and development and SEO have to be made together rather than bolted on afterward.
Why this matters more in the AI search era
There is a new and underappreciated reason to get rendering right. Google built more than a decade of infrastructure to execute JavaScript, but the AI crawlers feeding ChatGPT, Perplexity, and Claude largely did not. Current analysis indicates that none of the major AI crawlers (including GPTBot, OAI-SearchBot, ClaudeBot, and PerplexityBot) render JavaScript at all. They fetch raw HTML and stop. If your content only appears after client-side execution, these systems simply cannot see it.
This is no longer a niche concern. Search Engine Journal reported that, across 24.4 million proxy requests on 69 sites, ChatGPT-User made 3.6 times more requests than Googlebot over a 55-day window in early 2026. The crawlers most likely to be reading your site for AI answers are the ones least equipped to render JavaScript. A client-side app that Google eventually indexes after a render delay may be permanently invisible to the AI assistants your customers increasingly ask for recommendations.
The practical takeaway is that server-rendered or static HTML is now table stakes for both classic rankings and AI search optimization. The same fix (getting real content into the initial HTML response) serves Googlebot, Bing, and every AI crawler at once.
A checklist to make sure crawlers see your SPA
- View the rendered HTML, not just the live page. Use the URL Inspection tool in Search Console to confirm your main content appears in Google’s rendered output.
- Disable JavaScript in your browser and reload key pages. If the body goes blank, crawlers and AI bots are seeing the same emptiness.
- Put titles, meta descriptions, canonical tags, and any noindex directives in the server response, never inject or remove them with client-side JavaScript.
- Use History API routing with real, crawlable URLs, not hash fragments.
- Return honest HTTP status codes from the server, including genuine 404s for missing pages.
- Audit for hydration mismatches and ensure server and client render the same initial markup.
- Choose static rendering for stable content and SSR for dynamic content; retire any dynamic rendering setup.
JavaScript and search visibility are no longer in tension, but only if rendering is treated as a first-class architectural decision rather than something to patch after launch. The companies that win organic and AI search are the ones whose content reaches the crawler in the very first byte of HTML. If you are not sure what Google (or ChatGPT) currently sees on your site, that is the first thing worth measuring.
Sources
- Google Search Central: Understand JavaScript SEO Basics
- Google Search Central: Dynamic Rendering as a Workaround
- Vercel: How Google Handles JavaScript Throughout the Indexing Process
- Search Engine Journal: ChatGPT Now Crawls 3.6x More Than Googlebot
- Next.js Documentation: Text Content Does Not Match Server-Rendered HTML
See where you are cited today
A free snapshot audit of your rankings and AI citations before we ever talk.