If your website is built on React and most of your content only appears after JavaScript runs, you’ve probably already asked yourself: “Is my site even fully indexed? Is React hurting my rankings?”
Here’s the direct answer before we go deep:
Quick answer: React itself is not bad for SEO. The problem is Client-Side Rendering (CSR), when your content, links and metadata exist only in JavaScript and not in the initial HTML. Google can render JavaScript, but it does so in a delayed second pass and most other crawlers (Bing and JavaScript-blind AI crawlers used by tools like ChatGPT and Perplexity) may not render it at all. The fix depends on how often your content changes: stable pages can use build-time pre-rendering, frequently-changing pages need server-side rendering or a dynamic prerendering service and new projects are usually best built on a hybrid SSR/SSG framework like Next.js.
Now let’s break this down properly, what CSR actually does to your SEO, how search engines and AI systems really process JavaScript and a step-by-step decision framework to fix it without necessarily rebuilding your entire website.
What Is Client-Side Rendering (CSR) and Why Does It Matter for SEO?
In a CSR React app, the server sends the browser a mostly empty HTML file, usually just a <div id=”root”></div>, along with a JavaScript bundle. The browser then downloads and executes that JavaScript, which builds the actual page content, injects meta tags and renders links.
For a human visitor with a fast connection, this happens in a second or two and feels seamless. For a crawler, it’s a different story, it has to execute your JavaScript before it can see your real content, headings, internal links or title tag.
This is where CSR SEO problems usually start:
- Delayed indexing, content takes longer to be discovered and indexed
- Incomplete crawling, some crawlers don’t wait for JS execution at all
- Weak internal linking signals, if links are added via onClick handlers instead of real <a href=””> tags, crawlers may never follow them
- Missing or duplicate metadata, every route shows the same generic title/description until JS overwrites it
- Poor Core Web Vitals, heavy client-side JavaScript often hurts LCP and INP, which are direct ranking factors
None of this means React is a bad technology choice. It means rendering strategy needs to be treated as a core part of your technical SEO, not an afterthought.
How Do Google and Other Search Engines Actually Handle JavaScript?
This is the part most explanations oversimplify with “Google can render JS, so you’re fine.” In reality, it’s more nuanced.
Google uses two-wave indexing
Googlebot generally processes JS-heavy pages in two passes:
- Crawl wave, Googlebot fetches the raw HTML first (your near-empty CSR shell) and indexes whatever text is already there.
- Render wave, the page is queued for a headless Chromium renderer, which executes your JavaScript and re-indexes the fully rendered content.
The gap between these two waves can range from a few hours to several days, depending on your site’s crawl budget and rendering queue. For large or frequently updated sites, that delay can genuinely hurt visibility, new pages, price changes or product updates may not reflect in search results right away.
Google engineers themselves have described JavaScript rendering workarounds like dynamic rendering as a temporary solution, not a permanent architecture choice, which is a useful reality check before treating any single fix as “done forever.”
Other crawlers don’t render JavaScript the same way
- Bingbot has much more limited and inconsistent JS rendering compared to Googlebot.
- AI/LLM crawlers, the bots behind tools like ChatGPT’s browsing/search, Perplexity and other AI answer engines, largely fetch raw HTML and generally do not execute JavaScript. If your content only exists after a JS render, these systems may simply never see it.
This second point matters more every year, because it’s not just about classic “10 blue links” SEO anymore, it’s about whether AI systems can read, understand and cite your content at all.
Common SEO Problems Specific to CSR React Websites
- Client-side routing without real URLs, hash-based routing (/#/about) instead of proper history API routing (/about) can confuse crawlers and break canonical/sitemap logic.
- Meta tags set only in JavaScript, if <title> and <meta name=”description”> are injected client-side without a fallback in the initial HTML, crawlers relying on the raw HTML see nothing useful.
- No structured data in the initial payload, JSON-LD schema added only after hydration may be missed by non-rendering crawlers entirely.
- Soft 404s and infinite loading states, a generic “Loading…” placeholder that never resolves for a bot looks like thin or empty content.
- Large JavaScript bundles hurting Core Web Vitals, heavy hydration delays LCP and INP, both of which are part of Google’s ranking signals.
Step-by-Step: How to Fix SEO for a CSR React Website
Step 1: Audit your current rendering situation first
Before choosing a fix, actually confirm what search engines see today:
- View your page’s raw HTML source (Ctrl+U or curl yourdomain.com), is your title, meta description and main content already there or is it empty?
- Use Google Search Console → URL Inspection → View Crawled Page → Screenshot/HTML to see exactly what Googlebot rendered.
- Run your key pages through the Rich Results Test to check if structured data is actually visible to Google’s renderer.
This single step tells you whether you have a minor metadata problem or a full rendering problem and that changes everything about which fix you need.
Step 2: Fix the technical fundamentals that don’t require a rendering overhaul
A lot of “CSR SEO problems” are really just missing basics, fixable without touching your rendering architecture:
- Use a library like react-helmet-async to manage per-route <title> and meta tags and make sure a sensible fallback exists in the base HTML for each important route.
- Use real browser (history API) routing instead of hash routing, so every page has a clean, crawlable, shareable URL.
- Make sure every internal link is a genuine <a href=”…”>, not just a JS onClick handler with no href.
- Generate a proper XML sitemap with real, canonical URLs and submit it in Search Console.
- Add canonical tags to prevent duplicate-content issues from parameter-based or trailing-slash variations.
Step 3: Choose your rendering fix based on how your content actually behaves, not on price
This is the mistake I see most often: picking a “free” fix first and a “paid” fix last, regardless of what the content needs. The better way to decide is by content type and update frequency:
| Content type | How often it changes | Recommended approach |
| Marketing pages, about, services, static blog posts | Rarely | Build-time pre-rendering |
| Product listings, pricing, inventory, frequently-updated pages | Often / real-time | Dynamic prerendering service or server-side rendering |
| New project, greenfield build | N/A | Next.js (or similar) with SSR/SSG hybrid from day one |
| Large existing React app already in production | Varies | Audit first, often a partial/incremental fix, not a full rebuild |
Step 4: Build-time pre-rendering (for stable content)
The idea: generate static HTML for your important routes at build time, so crawlers get real content immediately instead of an empty shell.
Tools like react-snap, prerender-spa-plugin or a custom Puppeteer-based build script can do this. A practical note: some of these open-source tools (React Snap included) are lightly maintained today, so before adopting one, check its recent activity and test it thoroughly on a staging environment, don’t assume it will “just work” on a modern React/Vite setup without configuration.
This approach works well for content that doesn’t need to change between deployments, but it breaks down quickly for anything that updates frequently, since every content change requires a full rebuild and redeploy.
Step 5: Dynamic prerendering services (for frequently changing content)
Third-party prerendering services detect crawler requests and serve them a rendered HTML snapshot on the fly, while regular users still get the normal React experience.
This is a genuinely good fit, not just a fallback, when:
- Content changes often (prices, stock, listings, personalized sections)
- Build-time rendering can’t realistically keep up
- Your team doesn’t want to manage rendering infrastructure in-house
The trade-off is an ongoing cost that scales with your page count and traffic, but for the right use case, that cost buys you something build-time pre-rendering simply cannot: near-real-time rendered content for crawlers.
Step 6: Server-side rendering without a full framework rewrite
If your dev team can modify the existing app, you can often render just the important SEO pages server-side (using ReactDOMServer or similar) without migrating the entire site to a new framework. This usually gives more control than pre-rendering or third-party services, but the amount of work depends heavily on how the current app is architected.
Step 7: A dedicated SSR/SSG framework (for new projects or a justified migration)
For a new build, a framework like Next.js is usually the strongest long-term choice, but it’s worth understanding that SSR and SSG solve different problems, not the same one:
- SSG (Static Site Generation): pages are built ahead of time. Best for content that doesn’t change often, fast, cheap to serve, great for SEO.
- SSR (Server-Side Rendering): pages are generated per request on the server. Better for dynamic or personalized content, at the cost of added server load.
- ISR (Incremental Static Regeneration): a hybrid, pages are statically generated but can be re-generated in the background on a schedule or on demand, without a full rebuild.
For an existing, large React application already in production, don’t default to “let’s rebuild everything in Next.js.” Audit the current architecture first and see whether the rendering problem can be solved with a lighter, incremental approach, a full migration is expensive and often unnecessary.
Optimizing for AI Search: Why GEO Matters as Much as Traditional SEO Now
Generative Engine Optimization (GEO) is the practice of making your content easy for AI systems, Google’s AI Overviews, ChatGPT, Perplexity and similar tools, to read, understand and cite. This is directly connected to your rendering strategy, because:
- Most AI/LLM crawlers fetch raw HTML and typically do not execute JavaScript.
- If your key facts, definitions and answers only exist after a JS render, these systems may never ingest them, meaning your content can’t be cited even if it’s genuinely the best answer available.
- Clean, pre-rendered or server-rendered HTML with clearly structured headings, direct answers and JSON-LD schema gives AI systems something they can actually parse and quote.
In short: fixing your CSR rendering problem isn’t just a “Google rankings” fix anymore, it directly affects whether AI answer engines can see your site at all.
Answer Engine Optimization (AEO): Structuring Content to Get Featured
AEO is about formatting your content so it’s easy to lift out as a direct answer, for Google’s featured snippets, “People Also Ask” boxes and voice/AI assistants. A few practical habits that work well alongside a good rendering setup:
- Open each major section with a direct, one-to-two sentence answer before expanding into detail (the way this article’s “Quick answer” box does).
- Use question-style H2/H3 headings that mirror how people actually search.
- Add FAQPage schema to a dedicated FAQ section, it significantly increases your chances of appearing in rich results and AI-generated answers.
- Keep answers self-contained, don’t require the reader to scroll elsewhere to understand the point.
SSR vs. SSG vs. CSR vs. ISR, Quick Comparison
| Rendering type | Content available to crawlers | Best for | Trade-off |
| CSR (Client-Side Rendering) | Only after JS executes | Highly interactive apps, dashboards, logged-in tools | Weakest default for public, SEO-critical pages |
| SSG (Static Site Generation) | Immediately, in HTML | Marketing pages, blogs, docs | Needs a rebuild to reflect new content |
| SSR (Server-Side Rendering) | Immediately, in HTML | Frequently changing or personalized pages | More server load per request |
| ISR (Incremental Static Regeneration) | Immediately, in HTML | Content that changes periodically, not instantly | Slightly more complex caching setup |
How to Verify Your Fix Actually Worked
Once you’ve implemented a fix, don’t just assume it worked, confirm it:
- Google Search Console → URL Inspection → Test Live URL → View Rendered HTML/Screenshot.
- Run the page through the Rich Results Test to confirm structured data is visible post-render.
- Do a site:yourdomain.com “exact phrase from your page” search to check if the content is actually indexed.
- Check Core Web Vitals in PageSpeed Insights or Search Console’s Core Web Vitals report, a rendering fix that adds JavaScript weight can accidentally hurt LCP/INP even as it helps indexing, so it’s worth checking both together.
Frequently Asked Questions
Is React bad for SEO?
No. React itself doesn’t hurt SEO, the issue is Client-Side Rendering (CSR), where content and metadata only exist after JavaScript runs. Many React websites rank well once rendering is handled properly.
Does Google index CSR (client-side rendered) websites?
Yes, but through a delayed two-wave process, Google first crawls the raw HTML, then later renders the JavaScript in a separate pass. This can delay indexing, especially for large or frequently updated sites.
Do ChatGPT, Perplexity and other AI search tools read JavaScript-rendered content?
Generally, no. Most AI/LLM crawlers fetch raw HTML and don’t execute JavaScript, so content that only appears after a JS render may be invisible to them entirely.
Should I migrate my React website to Next.js for SEO?
Only if it’s justified. For a new project, Next.js with SSR/SSG is usually the strongest long-term choice. For an existing, large React app, audit the current rendering setup first, a full migration is often unnecessary if a lighter fix (pre-rendering, partial SSR or a prerendering service) solves the actual problem.
Is a paid prerendering service worth it over a free option like build-time pre-rendering?
It depends on how often your content changes, not on price alone. Static, rarely-changing pages are fine with free build-time pre-rendering. Frequently changing content (pricing, inventory, listings) usually needs a dynamic prerendering service or server-side rendering, because build-time tools can’t keep up without constant rebuilds.
How do I check what Google actually sees on my React website?
Use Google Search Console’s URL Inspection tool and select “View Crawled Page” to see the rendered HTML and screenshot exactly as Googlebot processed it.
Final Thoughts
CSR is not automatically an SEO problem, it becomes one when important content, links and metadata are only available after JavaScript executes and no crawler or AI system waits around for that reliably. The right fix depends on your content’s update frequency, your site’s size and what your development team can realistically maintain, not on picking whatever sounds free or whatever sounds most modern.
Audit first. Fix the fundamentals. Then choose the rendering strategy that actually matches your content, not the other way around.
If you’d like a proper rendering and technical SEO audit for your React or JavaScript-heavy website, feel free to get in touch, this is exactly the kind of technical SEO work I do for clients day to day.



