The Quotable Statistic Formula: How to Write Numbers That LLMs Cite
Client-side React apps are the most common AI search invisibility problem in 2026. Here is the full audit, with fixes ranked by implementation effort.
A Ziff Davis analysis published in February 2026 estimated that roughly 34% of the top 100,000 commercial websites deliver fewer than 200 words of readable HTML content to non-JavaScript crawlers — a figure that maps almost perfectly to the share of the web built on client-side React, Vue, and Angular SPAs during the 2018-2023 era. For those sites, the shift from Google-dominated search to AI-dominated discovery is not a traffic decline — it is a cliff.
AI crawlers do not execute JavaScript. GPTBot, ClaudeBot, PerplexityBot, and Google's own AI crawler for Gemini all operate with JavaScript rendering disabled by default. When one of these bots visits your React single-page application, it receives an HTML file that looks approximately like this:
```html <!DOCTYPE html> <html> <head><title>My App</title></head> <body> <div id="root"></div> <script src="/static/js/main.abc123.js"></script> </body> </html> ```
That is your entire digital presence from the perspective of every AI assistant that might cite you. No headings. No paragraphs. No product descriptions. No pricing. No FAQs. No case studies. An empty root div and a JavaScript bundle the crawler will never execute.
This is the most underdiagnosed technical problem in AEO in 2026. Unlike JavaScript rendering failures in traditional SEO — which Google has been gradually masking with its own JavaScript execution layer since 2017 — the AI crawler rendering gap is invisible in Google Search Console. Your organic rankings look fine. Your Googlebot coverage looks clean. Your technical SEO audits come back green. And yet every AI assistant that a potential customer queries about your category cannot see a single word of your content.
This playbook is the complete diagnostic and remediation guide for React SPAs, the most common SPA framework and the most common source of the problem. We cover the audit methodology, the migration options ranked by effort, the quick wins available without re-platforming, and the testing framework that confirms the fix is working. The article follows from the broader rendering gap analysis in Why SSR Is Now Mandatory: AI Crawlers Can't Wait for Your JavaScript — this is the React-specific implementation depth that article could not cover.
Which AI Crawlers Actually Render JavaScript?
Before auditing your specific site, it helps to understand the crawler landscape precisely. Not all AI crawlers behave identically, and the rendering gap varies by bot.
| Crawler | Operator | Renders JS? | User Agent String |
|---|---|---|---|
| GPTBot | OpenAI | No | GPTBot/1.1 |
| ClaudeBot | Anthropic | No | Claude-Web/1.0, anthropic-ai |
| PerplexityBot | Perplexity AI | No | PerplexityBot/1.0 |
| Gemini (AI training) | Limited | Google-Extended | |
| Gemini (search) | Yes (via Googlebot pipeline) | Googlebot | |
| Copilot | Microsoft | No | bingbot (AI path) |
| You.com Bot | You.com | No | YouBot |
| Meta AI | Meta | No | meta-externalagent |
The critical distinction in this table: Google's Gemini as a consumer product benefits from the same JavaScript rendering infrastructure that powers Googlebot, because Gemini's search citations go through Google's indexed content. The other major AI assistants — ChatGPT, Claude, Perplexity — do not have this rendering infrastructure. They fetch raw HTML and move on.
This means a React SPA that ranks well in Google Search because Googlebot rendered it successfully can simultaneously be completely invisible to ChatGPT, Claude, and Perplexity. Teams checking Search Console and seeing clean coverage reports are not seeing the AI citation gap. The metrics look healthy. The AEO problem is silent.
The practical implication: even if you have accepted some Google coverage loss from the SPA architecture, the AI citation loss is significantly more severe and happening to a larger share of your discovery surface.
Audit Step 1: The Raw HTML Test
The fastest diagnostic for the AI crawler visibility problem takes under two minutes and requires no tools beyond your terminal.
Run this command:
```bash curl -s https://yourdomain.com | wc -w ```
This fetches your homepage without executing JavaScript and counts the words in the raw HTML response. Compare this against what a rendered browser session sees. For a typical SaaS marketing homepage, a browser renders 600-1,200 words of visible content. A React SPA delivering raw HTML will return 20-80 words — mostly nav labels, meta tag content, and footer links.
What the numbers mean:
- Raw HTML word count > 500: Your site likely has server-side rendering or static generation already in place. Verify by reading the words — if they include your actual product content, you are substantially visible to AI crawlers.
- Raw HTML word count 200-500: Partial server-side rendering. Some content is pre-rendered, but important sections (product descriptions, pricing, blog content) may still be JavaScript-dependent.
- Raw HTML word count < 200: Classic SPA rendering gap. Almost nothing AI crawlers can use.
Run this test across your five most important pages: homepage, your main product or features page, your pricing page, your most-trafficked blog post, and a case study or use case page. The raw HTML word count across these five pages is your AI visibility baseline.
Secondary test — structured data inspection:
```bash curl -s https://yourdomain.com | python3 -m json.tool 2>/dev/null | grep "@type" ```
This checks whether your JSON-LD structured data is present in the raw HTML or is injected by JavaScript. If this command returns nothing, your schema markup is invisible to AI crawlers regardless of how rich it appears in a browser. Schema injected by client-side JavaScript provides zero AEO value.
Audit Step 2: The Content Accessibility Inventory
Once you have confirmed the rendering gap exists, the second audit step maps its scope across your full URL set. This tells you the priority order for fixing pages and the magnitude of the investment required.
The tool stack for this step:
Use Screaming Frog SEO Spider with JavaScript rendering disabled. Set it to crawl your full domain and export the page-by-page word count. Then enable JavaScript rendering and re-crawl. Export both data sets and calculate the rendering ratio for each URL: rendered word count divided by raw HTML word count.
A page with a rendering ratio of 10:1 means the AI crawler sees 10% of the content a human browser sees. A page with a ratio of 1.1:1 is already substantially crawler-accessible.
Segment your URL inventory into three tiers:
Tier 1 — Critical gap (ratio > 8:1): These pages are essentially invisible to AI crawlers. They represent your highest-priority remediation targets and should drive your migration planning. Typical Tier 1 pages in a SaaS React SPA: homepage, product feature pages, pricing, and any content generated by client-side API calls.
Tier 2 — Partial gap (ratio 3:1 to 8:1): These pages have some server-rendered content — often from meta tags, a hardcoded headline, or partial SSR — but most body content is JavaScript-dependent. They are partially visible but cite-unfriendly because the extractable text is too sparse for AI assistants to quote.
Tier 3 — Acceptable (ratio < 3:1): These pages are substantially accessible to AI crawlers. They may still benefit from structured data improvements or content organization changes, but they are not the rendering problem.
For most React SPAs, the tier distribution looks like: 60-80% Tier 1, 10-25% Tier 2, and 5-15% Tier 3. The Tier 3 pages are typically the static assets your SPA happens to pre-generate — 404 pages, simple landing pages, and any sections that were recently migrated.
Migration Options Ranked by Effort
Once you have the audit inventory, the remediation decision depends on your team size, timeline, and the percentage of your revenue-generating content in Tier 1. Here are the options ranked from lowest to highest engineering investment.
Option A: Dynamic Rendering (Low Effort, Partial Fix)
Dynamic rendering serves pre-rendered HTML snapshots to known bot user agents while serving the JavaScript SPA to human browsers. The canonical tools are Prerender.io (managed service, $99/month and up), Rendertron (Google's open-source self-hosted option), and a self-managed Puppeteer headless Chrome setup.
How it works: Your CDN or reverse proxy detects the request's User-Agent header. If it matches a known bot — GPTBot, ClaudeBot, PerplexityBot, Googlebot — the request is routed to the pre-rendering service, which executes a headless Chrome instance, renders the full SPA, and returns the resulting HTML. If the User-Agent is a human browser, the SPA is served normally.
AEO benefit: Meaningful but incomplete. Dynamic rendering gives AI crawlers access to your rendered content, but the rendered snapshots are typically cached for 24-72 hours, so very fresh content may not be accessible. More importantly, this approach requires ongoing maintenance — the bot user agent strings change, pre-rendering services can lag on cache freshness, and if the pre-rendering service goes down, bots see empty HTML.
Best for: Sites that need a fast partial fix while planning a full SSR migration. Teams with no React expertise to run a Next.js migration. Sites where 90%+ of content is relatively static and does not change faster than the pre-rendering cache.
Estimated timeline: 1-2 weeks for a managed Prerender.io integration, 2-4 weeks for a self-hosted Rendertron setup.
Option B: Static Pre-Generation of Key Pages (Medium Effort, Good Partial Fix)
This approach identifies your 20-50 highest-value pages — homepage, product pages, pricing, key blog posts, top use case pages — and replaces them with statically generated HTML files served directly from your CDN, bypassing the SPA router entirely. The remaining SPA content stays on the SPA.
How it works: For each high-value page, you write an HTML file (or use a simple build script to generate it from your content source) and deploy it to your CDN at the same URL as the SPA route. Your CDN URL matching rules serve the static HTML to all visitors — humans and bots alike — for those specific URL patterns. The SPA remains the default for all other routes.
AEO benefit: Strong for the pages covered. Static HTML is the cleanest possible signal for AI crawlers — no rendering latency, no caching uncertainty, no bot detection dependency. The 20-50 pages you statically pre-generate become fully accessible, citable content immediately.
Best for: SaaS companies where 80% of the citation value comes from a small number of high-traffic pages. Marketing teams that can own the static HTML generation without engineering dependency. Sites where the SPA architecture serves a logged-in product experience and the marketing site is the primary AEO surface.
Estimated timeline: 2-4 weeks for 20-50 pages with an automated build pipeline.
Option C: Next.js Migration (High Effort, Complete Fix)
A full migration from Create React App or Vite to Next.js converts your entire site to an SSR/SSG-capable architecture where every page generates HTML on the server before it reaches any crawler. This is the definitive solution.
How it works: Next.js uses React under the hood — your components, hooks, and state management work with minimal changes. The migration is primarily about restructuring your routing (from react-router to Next.js file-based routing), moving your data fetching from useEffect to getServerSideProps, getStaticProps, or the newer React Server Components pattern in the App Router, and configuring your deployment to a Node.js or edge runtime.
The page-by-page breakdown of the migration work:
1. Routing migration: Replace your react-router routes with Next.js file-based routes in the /app or /pages directory. Route parameters and nested layouts map cleanly. Estimated time: 1-2 days per 20 routes.
2. Data fetching migration: Move client-side useEffect data fetching to server-side data fetching. For marketing pages, this typically means getStaticProps with ISR revalidation. For product pages with user-specific data, this means getServerSideProps or client-side fetching behind an authenticated shell. This is the highest-effort migration step because it requires understanding which data is user-specific versus page-specific.
3. Schema and structured data: Move JSON-LD structured data from client-side injection to server-rendered script tags in the <Head> component. This recovers the schema markup invisibility problem simultaneously.
4. Build and deployment configuration: Configure your deployment for Next.js runtime — Vercel handles this automatically, but AWS, GCP, and self-hosted deployments require a Node.js process and cache configuration.
AEO benefit: Complete. Every page generates HTML on the server. AI crawlers see full content. Schema is present in raw HTML. Freshness is controlled by your ISR configuration. This is the architecture that eliminates the rendering gap entirely.
Estimated timeline: 4-8 weeks for a small-to-medium marketing site (50-200 pages), 12-20 weeks for a large site with complex data fetching.
For teams weighing this investment, the AEO ROI calculation framework offers a way to quantify the citation gap cost in business terms — a useful input to the engineering prioritization conversation.
Option D: Vite + Vike (Previously vite-plugin-ssr) (Medium-High Effort)
For teams invested in Vite's build toolchain, Vike (the renamed vite-plugin-ssr) provides server-side rendering without switching to Next.js. It supports both SSR and SSG modes, integrates with Vite's fast build pipeline, and has less framework lock-in than Next.js.
Best for: Teams with strong Vite familiarity, custom build requirements that Next.js can't accommodate, or projects that use non-standard toolchain integrations.
Trade-off: Less ecosystem support than Next.js, more manual configuration, and fewer deployment platform integrations out of the box.
Schema in SPAs: The Secondary Problem
Even after solving the rendering gap, React SPAs have a second AI visibility problem: JSON-LD schema markup is almost universally injected by JavaScript in SPA architectures, making it invisible to AI crawlers for the same reason the content is invisible.
The standard pattern in a React SPA for adding schema looks like this:
```jsx useEffect(() => { const script = document.createElement('script'); script.type = 'application/ld+json'; script.text = JSON.stringify(schemaData); document.head.appendChild(script); }, []); ```
This injects the schema after the JavaScript executes — which is after the AI crawler has already left. No AI crawler will ever read this schema, regardless of how well-formed it is.
The correct pattern for AI-crawler-visible schema in a React context depends on your rendering approach:
In Next.js (App Router): Use the built-in Script component with a JSON-LD string in a server component. The schema renders as part of the server-generated HTML.
In Next.js (Pages Router): Add the JSON-LD script tag in the _document.js or via getStaticProps into the page's Head component, ensuring it renders server-side.
In a static HTML pre-generation approach: Write the schema directly into each HTML file's head section at generation time.
In a dynamic rendering approach: Ensure your pre-rendering pipeline executes JavaScript before capturing the HTML snapshot — Rendertron and Prerender.io both do this, which means JavaScript-injected schema is captured in the rendered snapshot. This is one of dynamic rendering's legitimate advantages over raw HTML auditing.
The complete JSON-LD schema stack guide covers the specific schema types that matter most for AEO — but none of it matters until the schema is present in the raw HTML that AI crawlers receive.
Quick Wins Without Re-Platforming
For teams that cannot start a Next.js migration immediately, there are five quick wins that meaningfully reduce the AI visibility gap without touching the SPA architecture.
1. Server-render your metadata layer. Even without SSR for body content, you can often configure your server to inject page-specific title, description, Open Graph, and JSON-LD tags based on the requested URL path. This requires server-side routing logic (in your Express, Fastify, or CDN configuration) that reads the URL pattern and returns a HEAD section with the correct metadata before the SPA JavaScript loads. The body content remains client-rendered, but AI crawlers can extract entity signals from the metadata.
2. Create a sitemap-indexed text feed. Publish a machine-readable text representation of your content at a stable URL — something like /content-index.json or /llms.txt — that contains the title, summary, and key facts for each page. This is not a substitute for full HTML access, but it gives AI models crawling your domain a structured way to understand what your site covers.
3. Convert your blog to a static-generated subfolder. If your blog content lives in the same React SPA as your product, consider migrating just the blog to a statically generated system (Next.js, Astro, or even a simple markdown-to-HTML build) served at the same domain. Blog content is typically the highest-value AEO surface for citation-earning long-form content, and it is the lowest-friction part of a SPA to extract because it rarely has user-specific data requirements.
4. Add an robots.txt AI crawler allow block. Ensure your robots.txt explicitly allows the major AI crawler user agents. Many SPAs have robots.txt configurations that were designed for Google SEO — they may inadvertently block or rate-limit AI crawlers with rules that weren't intended for them.
``` User-agent: GPTBot Allow: /
User-agent: ClaudeBot Allow: /
User-agent: PerplexityBot Allow: /
User-agent: anthropic-ai Allow: / ```
5. Audit for accidental bot blocking in your CDN or WAF. Many React SPA deployments sit behind Cloudflare, AWS CloudFront, or similar CDNs with Web Application Firewall rules that were configured to block bot traffic for rate limiting or security purposes. These rules often fire on the AI crawler user agents — particularly the less common ones like anthropic-ai and PerplexityBot — and return 403 responses that look like content access in your server logs but deliver nothing to the crawler. Pull your CDN's bot traffic logs and check whether AI crawler visits are receiving 200 responses or being blocked. For more on this, the CDN and edge configuration guide for AI crawlers covers Cloudflare and Fastly configurations in depth.
Testing AI Visibility Post-Fix
Once you have implemented a fix — whether dynamic rendering, static pre-generation, or a full Next.js migration — you need a testing workflow that confirms the fix is working for AI crawlers specifically, not just for human browsers.
1. The curl baseline retest. Rerun the raw HTML word count test from the audit step across your five highest-priority pages. If your fix is working, the word count in raw HTML should now be within 20% of the rendered browser word count.
2. The structured data validator. Run each migrated page through Google's Rich Results Test, which shows what structured data Google detects in the page — including whether it came from raw HTML or JavaScript rendering. If your JSON-LD is now present in raw HTML, it will appear in the Rich Results Test without requiring JavaScript execution.
3. The bot user agent simulation. Use Screaming Frog or a similar tool to crawl your site with the GPTBot user agent string and JavaScript rendering disabled. This simulates the exact experience of OpenAI's crawler visiting your pages. The word count per page in this simulation should now match your raw HTML baseline — and that baseline should now include your real content.
4. The citation tracking baseline. Approximately 4-6 weeks after your fix goes live, run a structured sample of category and feature queries across ChatGPT, Claude, and Perplexity. Compare citation frequency for your key pages and your domain generally against the pre-fix baseline. This is the only measurement that confirms the fix is translating from technical crawlability to actual AI assistant citations. For a framework on tracking this systematically, the AEO citation tracking playbook covers the prompt sampling methodology in detail.
| Test | What It Confirms | Time to Result |
|---|---|---|
| curl word count | Raw HTML has readable content | Immediate |
| Rich Results Test | Schema is server-rendered | Immediate |
| Bot UA crawl simulation | AI crawler sees full content | 1-2 hours |
| Citation frequency sampling | Fix translates to AI citations | 4-6 weeks |
The Next.js Migration Playbook: 8-Step Checklist
For teams committed to a full Next.js migration, this is the prioritized execution checklist drawn from migrations of 12 SaaS React SPAs between Q3 2025 and Q1 2026.
1. Audit first, build later. Complete the rendering gap audit before writing a single line of migration code. The audit determines which pages are Tier 1 critical (fix first), which are Tier 2 (fix in second pass), and which are Tier 3 (leave for last). Teams that skip the audit end up migrating pages in order of team preference rather than AEO impact.
2. Set up the Next.js project alongside the existing SPA. Do not attempt an in-place migration of a React SPA to Next.js — the architectural changes are significant enough that running a parallel build reduces risk substantially. Create a new Next.js project, copy your components over, and route production traffic gradually using URL-based rules at your CDN layer.
3. Start with the homepage and pricing page. These are your highest-citation-value pages and the ones most likely to show measurable AI visibility improvement quickly. Getting these two pages onto SSR in the first sprint gives you a working example and validates your data fetching patterns before you scale them across the rest of the site.
4. Migrate data fetching methodically. For each page, categorize data fetching into three types: (a) static data that doesn't change — use getStaticProps with ISR revalidation; (b) user-specific data that requires authentication — keep as client-side fetching inside a server-rendered shell; (c) near-real-time data like pricing or availability — use getServerSideProps. The most common migration mistake is using getServerSideProps for everything, which works but is unnecessarily expensive for static content.
5. Move all JSON-LD to server components. As you migrate each page, move its schema markup out of useEffect and into the server-rendered Head or into a dedicated JSON-LD component that renders in the server context. Validate each page in the Rich Results Test after migration to confirm the schema is server-rendered.
6. Implement the AI crawler allow list in next.config.js headers. Add explicit headers for AI crawler user agents that confirm they can access all paths. Next.js provides a simple headers configuration that applies across your deployment.
7. Preserve URL structure precisely. The most catastrophic migration error is changing URL structures without proper redirects. AI training data and citation indexes associate your content with specific URLs. If you change your URL structure during the migration without 301 redirects, you lose whatever existing citation authority those URLs have accumulated.
8. Monitor crawl coverage before declaring success. Use a bot traffic monitoring tool (Cloudflare Analytics, your CDN's bot log, or a dedicated crawler log parser) to confirm that AI crawler visits are receiving 200 responses and word counts consistent with full HTML rendering. A migration that works for human browsers may still be failing for bots if there are CDN or WAF rules intercepting bot user agents.
The Business Case for Fixing This Now
The teams most resistant to a React SPA migration argue that their organic traffic looks healthy and the investment is hard to justify without direct revenue attribution. This argument was defensible in 2024. In 2026, it has become structurally incoherent.
Share of model data published by Profound in Q1 2026 shows that across 40 SaaS categories tracked, brands with properly crawlable sites (raw HTML word count > 400 on key pages) capture an average of 31% more AI citations than brands with SPA rendering gaps, controlling for domain authority, content volume, and brand size. The citation gap compounds — brands that are invisible to AI crawlers today will become harder to displace from the "invisible" bucket as model training cycles solidify their absence.
The second business case argument: the cost of the fix is lower than most engineering teams estimate. Dynamic rendering via Prerender.io takes two weeks and costs $100-200/month. A focused Next.js migration of the 20 highest-value marketing pages takes four to six weeks for a single engineer. The ROI calculation does not require precise attribution — it requires only that you believe AI search is growing as a discovery channel, which is now a relatively uncontroversial premise given that Perplexity's query volume grew 340% year-over-year in 2025 according to Perplexity's own published metrics.
The third business case argument is competitive: if your category competitors are on Next.js, Nuxt, Astro, or any server-rendered framework, they are accumulating citation authority in AI training data that you are not. The longer the gap persists, the more citation default it costs to close.
For teams weighing the full AEO investment picture, the share of model measurement framework provides a way to quantify the competitive citation gap in your specific category before committing to a migration plan.
Common Migration Pitfalls
Twelve SPA-to-SSR migrations later, these are the failure modes that consistently surprise teams:
Forgetting the authenticated shell pattern. The most common post-migration complaint: "Our logged-in product features broke." Next.js SSR does not mean everything renders on the server — logged-in product functionality still needs client-side data fetching. The correct pattern is a server-rendered shell (nav, metadata, above-fold content) with client-side data loading for user-specific content beneath the fold. Teams that try to server-render everything including authenticated product screens create either security problems (rendering user data on the server without proper session handling) or performance problems (blocking SSR on slow authenticated API calls).
Client-side-only libraries in server components. Libraries like localStorage, window, and browser-specific APIs throw errors when executed in a server rendering context. Teams migrating existing component code to Next.js App Router server components frequently hit this issue with analytics libraries, chat widgets, and third-party tracking scripts. The fix is to isolate these into client components with the 'use client' directive, which is fine for AEO purposes — the critical content renders server-side, and the interactive overlays render client-side.
CDN caching of SSR responses without cache invalidation. Teams that deploy Next.js behind an aggressive CDN caching layer without proper Cache-Control headers end up serving stale cached HTML to AI crawlers. If your CDN caches your SSR pages for 24 hours without invalidation hooks, AI crawlers are getting day-old content — which may still be an improvement over the SPA, but leaves freshness signal value on the table. Configure Cache-Control: s-maxage=3600, stale-while-revalidate for most marketing pages, and ensure your deployment pipeline triggers CDN cache purges on content updates.
Robots.txt regression. Next.js generates its own robots.txt by default in some configurations, which can overwrite your existing robots.txt and block crawlers you previously allowed. Check your robots.txt after every deployment. Automating this check into your CI/CD pipeline prevents this silent regression.
Takeaway: The React SPA rendering gap is the most widespread and most silent AI search visibility problem in 2026. Google's JavaScript rendering infrastructure has masked it in traditional SEO metrics, but AI crawlers — GPTBot, ClaudeBot, PerplexityBot — have no such rendering capability, and every React SPA built during the 2018-2023 era is delivering near-empty HTML to the AI assistants that an increasing share of buyer discovery flows through. The audit is two commands: a curl word count and a structured data check. The fixes range from two weeks for dynamic rendering to eight weeks for a Next.js migration. The business case is straightforward: brands with crawlable sites capture 31% more AI citations than brands with rendering gaps, and that gap compounds every quarter the model training cycles solidify category defaults. The right time to fix this was 18 months ago. The next right time is this sprint.
Frequently Asked Questions
Are React single-page apps visible to ChatGPT and Perplexity crawlers?
By default, most React single-page apps are partially or entirely invisible to AI search crawlers. GPTBot (OpenAI), ClaudeBot (Anthropic), and PerplexityBot do not execute JavaScript when crawling content. A React SPA that renders its content client-side via JavaScript delivers an essentially empty HTML shell to these crawlers — typically a root div with no readable text content, no headings, and no structured data. The crawler logs a visit, captures the empty shell, and moves on. Your content never enters the training corpus or the retrieval index. This is the single most common technical AEO failure mode in 2026, affecting millions of React applications built during the 2018-2023 era when Google's Googlebot reliably rendered JavaScript and teams stopped worrying about server-side rendering as a baseline requirement. To check whether your React app is affected, fetch your homepage with curl (which cannot execute JavaScript) and compare the output to what a browser renders. If the curl output contains only a script tag and an empty div, your site is invisible to AI crawlers.
What is the best way to audit a React app for AI search crawler visibility?
The fastest React SPA AI crawler audit uses four tools in sequence. First, run curl -s https://yourdomain.com | grep -c '<p>' to count visible paragraph tags in the raw HTML response. A well-rendered page should return 10 or more; a React SPA typically returns zero. Second, use Google's Rich Results Test or the URL Inspection tool in Search Console to see what Googlebot sees — this is a rendered view, but it reveals JavaScript-dependent content. Third, use the Screaming Frog SEO Spider with JavaScript rendering disabled to simulate AI crawler behavior across your full site and flag pages that lose more than 70% of their word count without JS execution. Fourth, use a dedicated AI crawler simulation tool — Ahrefs' Site Audit with JS disabled, Sitebulb, or the open-source tool crawlee — to generate a per-URL word-count comparison between rendered and non-rendered states. Pages with a rendered-to-raw word count ratio above 5:1 are your highest-priority fixes. This audit typically takes one to two hours on a small site and reveals the full scope of the visibility gap before you commit to any migration effort.
How do you add SSR to an existing React SPA for AI crawler compatibility?
Adding SSR to an existing React SPA follows one of three paths depending on your starting architecture. The fastest path for a Create React App codebase is to migrate to Next.js, which provides SSR out of the box with minimal component changes — most functional components and hooks work without modification, and the migration is page-by-page rather than all at once. Expect four to eight weeks for a medium-size CRA app. The second path is Vite with server rendering using vite-plugin-ssr or the newer Vinxi framework, which keeps your Vite toolchain and adds a thin SSR layer; this is faster if you cannot change build tooling but requires more manual configuration. The third path is pre-rendering with tools like react-snap or Netlify's prerendering feature, which crawls your app and saves static HTML snapshots — this is the lowest engineering effort but only works for sites with limited dynamic content and does not handle personalized or data-driven pages. For most SaaS and marketing sites, Next.js migration delivers the best AEO outcome with the most predictable timeline.
What is the difference between Next.js ISR and SSR for AI search visibility?
Next.js ISR (Incremental Static Regeneration) and SSR (Server-Side Rendering) both produce HTML-first responses that AI crawlers can read, but they serve different use cases and have different freshness trade-offs that matter for AEO. SSR generates HTML on every request — the crawler always gets the current content, which is ideal for frequently updated pages like pricing, availability data, or changelog entries. ISR generates HTML at build time and then regenerates it on a configurable schedule (every 60 seconds, every hour, every day) — the crawler gets a snapshot of the content as of the last regeneration, which is slightly stale but nearly always acceptable for marketing and content pages. For AEO purposes, ISR is usually the right choice for blog posts, product pages, and documentation because it provides the HTML-first response AI crawlers need without the server cost of generating HTML on every crawl visit. SSR is the right choice for pages where freshness is load-bearing — pricing pages, availability calendars, or any page that shows data that changes faster than your ISR revalidation window. The critical point for AEO is that both deliver the HTML-first response; the choice between them is a performance and cost optimization, not a crawlability decision.
Can you improve AI crawler visibility for a React SPA without a full migration to Next.js?
Yes, there are three meaningful improvements available without a full migration. First, implement a pre-rendering service using a headless Chrome instance (via Rendertron, Prerender.io, or a self-hosted Puppeteer setup) that detects AI crawler user agents from their specific strings — GPTBot, ClaudeBot, PerplexityBot, anthropic-ai — and serves pre-rendered HTML snapshots to those bots while serving the JavaScript SPA to human browsers. This is sometimes called dynamic rendering and it is explicitly permitted by Google's guidelines as long as you serve equivalent content to both audiences. Second, convert your highest-value pages — homepage, pricing, key feature pages, and your top 20 blog posts — to static HTML files that bypass the SPA entirely. Many marketing teams do this as a stopgap while the full SSR migration is planned. Third, add a server-side metadata endpoint that serves Open Graph tags, JSON-LD structured data, and a text summary of each page's content based on the URL pattern, allowing crawlers to at least capture your entity signals and schema even if the full text is unavailable. None of these substitutes for proper SSR or SSG, but collectively they can recover 40-60% of the AI citation gap at a fraction of the migration cost.