Scripts versus search

JavaScript SEO: How Google Renders Your Pages, and Where React Sites Go Blank

The new site demoed beautifully. It loaded like an app, the menus glided, the agency got a round of applause. Three months later Search Console lists forty pages Google knows about and has never properly read. The page your customers see and the page a crawler receives are not always the same document.

October 26, 2026 · 11 min read

The short answer

JavaScript SEO is making sure search engines can find, render and index pages built with JavaScript. Google fetches the HTML, queues the page, runs its scripts in a headless Chromium browser and indexes the result. It does not click, scroll or follow links without an href. Server-side rendering or static generation puts the words in the HTML, where every crawler can read them.

On this page
  1. Google reads a JavaScript page twice, and the second read waits in line
  2. CSR, SSR, static generation and hydration, translated for owners
  3. Six mistakes that hide JavaScript pages from Google
  4. Reading the rendered HTML in Search Console
  5. Next.js renders on the server, with traps in the fine print
  6. Bing renders too. Most AI crawlers, by the best evidence, do not
  7. Patch, prerender or rebuild: pricing a rendering problem

Google reads a JavaScript page twice, and the second read waits in line

Google's JavaScript SEO basics describe three phases: crawling, rendering and indexing. First Googlebot requests the URL and reads whatever HTML the server sends back, collecting the links it finds. Then the page joins a queue. When Google has capacity, a headless Chromium loads it, runs the scripts and produces the finished page, and that finished version is what gets indexed. Every page answering with a 200 status is queued this way unless a robots tag says not to index it, so rendering is routine, not a favor.

The catch is time. Google does not promise a number; a page might sit in the queue briefly or much longer, depending on its resources. A page whose words arrive in the first response is understood on the first read. A page that ships an empty shell must wait for the second, and anything that fails during rendering, such as a blocked script, an error or a slow API, leaves Google holding the shell. Our guide to how search engines work places this step in the larger journey, and the technical SEO checklist covers the gates around it.

What Google's renderer will not do for you

  • Click, scroll or type. Google's lazy-loading guidance states that Search does not interact with your page, so content waiting on a tap never loads.
  • Grant permissions. A store locator that asks for the visitor's location shows Googlebot nothing, because it declines the request.
  • Remember anything. Cookies, local storage and session storage are cleared between page loads, so content gated on a saved preference may never appear.
  • Respect your cache settings. Google says its renderer may ignore caching headers and use an older script, which is why it recommends content hashes in file names.
  • Open WebSockets or WebRTC connections. Data delivered that way needs an ordinary HTTP fallback.
  • Run scripts from files or pages that robots.txt blocks. Disallow your JavaScript folder and the page renders without it.

CSR, SSR, static generation and hydration, translated for owners

Developers argue about rendering in acronyms. The question underneath is plain enough for any owner to ask in a meeting: when the first response leaves our server, are the words already in it? Here is how each approach answers, and what the two kinds of crawler receive.

Rendering approaches and what crawlers receive
What the server sendsWhat Google gets on the first readWhat a crawler that skips scripts gets
Client-side rendering (CSR)A near-empty HTML shell and a bundle that builds the page in the browserLittle; the content waits for the render queueThe shell: a title, a menu, an empty box
Server-side rendering (SSR)Finished HTML built for each request, plus scripts for interactivityThe full pageThe full page
Static generation (SSG) or prerenderingFinished HTML built ahead of time, often served from a CDNThe full page, usually fastestThe full page
HydrationNot a separate method: the step where scripts attach to server-built HTML so buttons workUnaffected, since the words were already thereUnaffected
Dynamic renderingPrerendered HTML to bots, the JavaScript app to peopleA rendered copy, if the prerender service keeps upA rendered copy, if the service recognizes the bot

That last row deserves a note. Google's page on dynamic rendering now calls it a workaround and not a recommended solution, and points sites to server-side rendering, static rendering or hydration instead. Google adds that it generally does not treat dynamic rendering as cloaking, as long as both versions show similar content. An agency pitching a prerender service as the permanent plan is selling a bridge Google has already labeled temporary.

The React world has moved the same way. On February 14, 2025, the React team deprecated Create React App for new apps and recommended starting with a framework such as Next.js or React Router. Its announcement notes that server rendering is not only for SEO: it cuts the JavaScript a visitor downloads before seeing anything. In 2026, React SEO mostly means choosing a framework that renders on the server, then not fighting it.

Six mistakes that hide JavaScript pages from Google

Links that are not links

Google says it can reliably extract URLs only from an a element with an href. A span with an onclick handler, an a tag carrying only a routerLink, or an href starting with javascript: may never be followed, and the page behind it becomes an orphan. Our guide to HTML links and rel values shows the anatomy of one that works.

Hash routes

Addresses like example.com/#/services. Google's documentation says not to use fragments to load different content. Use the History API so every view has a real path that can be crawled, linked and ranked.

Content behind a tap

Reviews in a tab fetched on click, a load more button, an endless feed with no page addresses. For infinite scroll, Google asks for a persistent, unique URL for each chunk, linked in sequence.

A noindex that a script removes

If the HTML ships with noindex and JavaScript deletes it later, Google may skip rendering the moment it sees the tag, so the deletion never happens. Send the robots tag you want in the original HTML.

Not found pages that answer 200

A single-page app shows Page not found with a success status, and Google files it as a soft 404 or, worse, indexes it. Google suggests a JavaScript redirect to a URL that returns a real 404, or a noindex on the error view.

Head tags rewritten after load

Google can read a title or canonical set by script, but a canonical changed by JavaScript should match the one in the HTML, and there should be only one. Put them in the server template; our meta tags and canonical tags guides cover what belongs there.

Lazy-loaded images belong on this list only when they are built wrong. Browser-native lazy loading and the IntersectionObserver API both load an image when it enters the viewport, which Google handles. A script that waits for a scroll event does not. The image SEO guide covers the right setup. JavaScript redirects are a similar story: Google follows them only when rendering succeeds, so server redirects, explained in our redirects guide, stay the first choice.

Reading the rendered HTML in Search Console

Opinions about rendering are cheap. Googlebot's verdict is free, and Search Console shows it to anyone with a verified property; our Google Search Console guide covers setup. If you do not own the site, Google's Rich Results Test also shows the rendered HTML. Pick the five pages that earn the most money and run each one through these steps.

  1. 1

    Inspect the URL, then test it live

    Paste the address into URL Inspection and choose Test live URL. The default view describes the indexed copy from Google's last crawl, and it has no screenshot.

  2. 2

    Open View tested page

    You get the HTML Google produced, a screenshot of the rendered page, and a More info panel listing JavaScript console messages and the page resources Google loaded.

  3. 3

    Search the HTML for the words that sell

    A price, a service name, a line from a review, the phone number. If it shows in your browser and not in the tested HTML, Google is not indexing it.

  4. 4

    Check the navigation for hrefs

    Find your menu and footer links in the tested HTML. Labels without an href are text to Google, not paths to follow.

  5. 5

    Read the resources and the console

    Files that failed to load or were blocked, and errors thrown during the render, explain most blank sections.

  6. 6

    Compare with the server's first response

    If the words appear in the tested HTML but not in the raw source, Google can read them and many other crawlers cannot. Our page on JavaScript and AI crawlers walks through that comparison.

Then step back to the site-wide view. In the Page indexing report, a pile of template pages under Crawled, currently not indexed, or real products flagged as soft 404s, often traces to rendering. If pages are missing outright, our fix for a site not indexed by Google covers the other usual causes.

Next.js renders on the server, with traps in the fine print

Next.js, the framework DataCram builds on, makes server rendering the default. In its App Router, layouts and pages are Server Components unless a file opts out, routes that do not need request data are prerendered at build time, and its Link component extends the HTML a element, so navigation ships as real anchors with real hrefs. That clears most of the mistakes above before anyone writes a line. Three details in the framework's own documentation still catch teams.

  • Status codes freeze once streaming starts. If a page calls notFound() after a Suspense boundary has begun streaming, Next.js cannot turn the 200 into a 404, so it injects a noindex robots tag instead. A redirect() at that point becomes a client-side redirect. Check whether the record exists before any await or Suspense boundary.
  • Metadata can stream. For browsers and crawlers that run scripts, Next.js may send titles and descriptions alongside the content instead of first. Bots that read only static HTML get them resolved up front in the head; the htmlLimitedBots setting decides which bots those are, so confirm the ones you care about are covered.
  • Browser-side fetching is still invisible. Client Components are prerendered to HTML too, but data they request after load, such as reviews pulled from an API in an effect, exists only in the browser. Fetch it in a Server Component.

Bing renders too. Most AI crawlers, by the best evidence, do not

Bing says Bingbot renders pages with an evergreen version of Microsoft Edge, so the Google advice above carries over. Apple's crawler renders as well, and Apple warns that blocking scripts or stylesheets in robots.txt can stop Applebot rendering a page properly. The answer engines are a different story. Vercel examined AI crawler traffic on its network in December 2024 and found the crawlers behind ChatGPT, Claude and Perplexity fetched pages without executing their JavaScript. That is one study, from one host, and it may have aged.

Google will wait for your scripts. Most of the machines writing answers will not.

So client-rendered content costs you time with Google and may cost you the mention entirely in an AI answer. We keep the crawler-by-crawler evidence on the JavaScript and AI crawlers page and what each bot is for on the AI crawlers page, rather than repeat it here. To see whether the engines name your business once the words are readable, run the free AI visibility check.

Patch, prerender or rebuild: pricing a rendering problem

A patch usually does it when

  • Only a few widgets or sections load by script
  • Menu and footer links lack hrefs but pages render on the server
  • Error views return 200 and need a real 404
  • Titles and canonicals are set by script and can move into the template

A rebuild usually costs less when

  • The whole site is a client-rendered single-page app
  • Every URL depends on a hash fragment
  • A prerender service is all that stands between you and a blank index
  • The app sits on Create React App, which React no longer recommends for new projects

Patching is developer hours, and the first job is knowing which column you are in. Our free website audit checks SEO, speed signals, mobile, security and content and emails a PDF with the fixes. On an existing site, rendering repairs sit inside the technical work of our SEO programs. Rendering also drives load time, which is why it belongs in any site speed and Core Web Vitals project.

When a rebuild is cheaper, custom sites on Next.js start at $1,750, fixed price, and sites with a store, portal or web app start at $3,500, per our web design pricing. Leaving WordPress has its own playbook in WordPress to Next.js. For the rest of the fundamentals, the SEO guide maps every topic in this library.

Questions owners ask about SEO

No. Google renders JavaScript and indexes what it produces. The trouble comes from content and links that exist only after rendering or after a click, from blocked script files, and from error pages that return a success code. Put the words and links in the server HTML and use JavaScript for interaction, and Google has nothing to wait for.

Usually, if the links are real anchors with hrefs, routes use the History API instead of hash fragments, nothing important needs a click, and robots.txt does not block the bundle. It still waits for the render queue, and crawlers that skip scripts may see a shell. A framework that renders on the server, such as Next.js, removes the doubt.

Google calls it a workaround, not a recommended solution, and suggests server-side rendering, static rendering or hydration instead. It also says it generally does not consider dynamic rendering cloaking when both versions show similar content. It can buy time on a large legacy app while a proper fix is built, but treat it as a bridge.

You need the words in the HTML, however you get there. A standard WordPress page already arrives built on the server. A site built as a React or Vue app with no server rendering does need it, or static generation. Run one page through URL Inspection and compare it with the raw source to know which you have.

Often because the app shows an error or an empty template while the server answers 200. Google sees a page that looks missing and says so. Return a real 404 for missing records, or redirect to a URL that does, and make sure the real page renders its content without a click or a stored cookie.

Not by itself, and nobody can promise a ranking. Moving removes rendering obstacles and usually speeds pages up, which helps Google read and serve them. Rankings still come from content, links and relevance. The move has to keep URLs or redirect them; our guide to migrating WordPress to Next.js without losing SEO covers the risk.

Keep reading

Free · No obligation

See the page Google actually indexed

Send us the address. We will compare the HTML your server sends with what Googlebot renders and reply with the gaps that cost you pages, in plain English.

Which of these sounds like you? (pick any)

Rather talk now? Call (210) 346-0848.

CallGet a quote