The Modern SEO Guide to JavaScript-Rendered Content

Most modern websites-especially B2B SaaS products-use React, Vue, or Angular. Content renders client-side, meaning the initial HTML is nearly empty. Traditional SEO tools fetch raw HTML, see nothing, and report problems that don't exist. More critically, they miss problems that do exist: headings that never make it to the DOM, content hidden behind JavaScript state, and metadata that fails to render.

LLMs encounter the same challenge. If your content requires JavaScript execution to appear, you need tools that actually run JavaScript to see what gets indexed. The gap between "what you built" and "what search engines see" determines whether your React app ranks-or disappears entirely.

This guide covers how JavaScript rendering affects SEO and AEO, what breaks, and how to audit JavaScript-heavy sites properly.

How Search Engines Handle JavaScript (The Technical Reality)

The Three Rendering Approaches

1. Server-Side Rendering (SSR)

HTML generated on server, sent complete to browser. Search engines see full content immediately. Best for SEO, but more complex infrastructure.

Example: Next.js with getServerSideProps

2. Static Site Generation (SSG)

HTML pre-built at build time, deployed as static files. Search engines see full content in initial response. Excellent for SEO, limited for dynamic content.

Example: Next.js with getStaticProps, Gatsby

3. Client-Side Rendering (CSR)

HTML shell sent to browser, JavaScript builds page client-side. Search engines must execute JavaScript to see content. Riskiest for SEO without proper testing.

Example: Create React App, Vue CLI default

How Googlebot Handles JavaScript

According to Google's JavaScript SEO documentation, Googlebot processes JavaScript web apps in three main phases:

  1. Crawling - Fetches raw HTML
  2. Rendering - Executes JavaScript using headless Chrome
  3. Indexing - Adds rendered content to index

The problem? Rendering happens later-sometimes hours or days after crawling. If rendering fails or times out, your content never gets indexed.

How LLMs Handle JavaScript

Current limitations:

ChatGPT web browsing has limited JavaScript execution. Perplexity fetches rendered content but may timeout on heavy JS. Google AI Overviews pulls from already-indexed pages (Google's rendering applies).

The takeaway: If Googlebot doesn't render your content properly, LLMs can't cite it either. Even if indexed, extraction accuracy matters.

What Breaks in JavaScript-Rendered Content

Common SEO Issues with SPAs

1. Missing Headings

H1-H6 generated by JavaScript after initial load. Traditional crawlers see empty <div id="root"></div>. Content exists for users but not for indexing.

2. Metadata Problems

Title tags and meta descriptions added by client-side routing. React Helmet or Vue Meta execute after page load. Initial HTML missing critical SEO metadata.

3. Internal Linking

JavaScript-driven navigation (React Router). Links might not be in initial HTML. Crawlers may miss site architecture.

4. Content Flash/Hydration Issues

Content appears, then changes during hydration. Search engines may index "Loading..." states. Inconsistent content between renders.

The Heading Extraction Problem

Why this matters specifically:

LLMs use heading hierarchy to understand content structure. Tools like Screaming Frog only see initial HTML:

Initial HTML (what traditional tools see):

<div id="root"></div>

Rendered HTML (what users see):

<div id="root">
  <h1>Complete React Performance Guide</h1>
  <h2>Understanding Rendering</h2>
  <h3>Virtual DOM Mechanics</h3>
  ...
</div>

Your carefully structured H1→H2→H3 hierarchy is invisible to tools that don't execute JavaScript.

Content LLM Analyzer executes JavaScript before extracting headings-exactly like a real browser. You see the actual heading hierarchy that LLMs process, not an empty shell.

Testing JavaScript Content Visibility

Manual Testing Methods

1. View Source vs Inspect Element

View Source (Ctrl+U): Shows initial HTML
Inspect Element (F12): Shows rendered DOM

Mismatch = potential SEO problem.

Test: Can you find your H1 in View Source? If not, it's JavaScript-rendered.

2. Disable JavaScript in Browser

Chrome DevTools: Cmd/Ctrl + Shift + P → "Disable JavaScript"

Reload page. See what remains. Whatever disappears = at risk for indexing issues.

3. Google Search Console URL Inspection

Go to GSC → URL Inspection → Enter your page URL → Click "View crawled page" → Check "Rendered HTML"

Search for your headings. If missing in rendered HTML, even Google might struggle to extract them.

Automated Testing Tools

Tools that DON'T execute JavaScript:

  • Screaming Frog (default mode)
  • Most traditional crawlers
  • cURL, wget

Tools that DO execute JavaScript:

  • Screaming Frog (JavaScript rendering mode - paid)
  • Sitebulb
  • ContentKing
  • Content LLM Analyzer (via Chrome extension)

The Chrome Extension Advantage

Browser extensions work better because they:

  • Run in actual browser context
  • Get full JavaScript execution
  • Access rendered DOM
  • See exactly what users see

What Content LLM Analyzer extracts:

  • Title (from rendered <title> tag)
  • Meta description (after JavaScript execution)
  • All headings (H1-H6 from final DOM)
  • Content structure (paragraphs, lists, sections)

Traditional tools report missing headings on your React site? Install the Content LLM Analyzer extension, click the icon on your page, and see the actual heading hierarchy that exists in the rendered DOM.

Fixing JavaScript Rendering for SEO

Solution 1: Server-Side Rendering (Best)

When to use:

  • Content changes frequently
  • Personalized content
  • Authentication required

Frameworks:

  • Next.js (React)
  • Nuxt.js (Vue)
  • Angular Universal

How it helps:

  • Initial HTML includes all headings
  • No JavaScript execution needed
  • Works with all crawlers/tools

Solution 2: Static Site Generation (Good)

When to use:

  • Content doesn't change often
  • Blog, documentation, marketing pages
  • Predictable page count

Frameworks:

  • Next.js with getStaticProps
  • Gatsby
  • Astro

How it helps:

  • Headings pre-rendered at build time
  • Deployed as static HTML
  • Perfect for crawlers

Solution 3: Hybrid Approach (Practical)

The modern pattern:

  • Static generation for marketing pages
  • SSR for dynamic content
  • Client-side rendering for interactive features

Example architecture:

Homepage → SSG
Blog posts → SSG (rebuilt on publish)
Product pages → SSR (real-time pricing)
Dashboard → CSR (requires auth)

Solution 4: Testing with Real Rendering

If you must use CSR:

  • Test with tools that execute JavaScript
  • Content LLM Analyzer (Chrome extension)
  • Screaming Frog (JavaScript rendering mode)
  • Sitebulb

Verify headings actually extract before assuming SEO is working.

Quick Fixes for Common SPA Issues

Fix #1: Remove "Loading..." H1s

Problem:

const [title, setTitle] = useState('Loading...');
return <h1>{title}</h1>;

Crawler might capture "Loading..." as your H1.

Fix:

const [title, setTitle] = useState(null);
return title ? <h1>{title}</h1> : null;

Don't render heading until real content available.

Fix #2: Ensure Headings in Initial Render

Problem: Lazy-loaded headings that only appear after interaction

Fix: Move critical headings above lazy boundary. Load heading data eagerly.

Fix #3: Use Proper Routing

Problem: Hash routing (/#/page) - crawlers struggle with this

Fix: Browser history routing (/page) - configure server to handle SPA routes

Fix #4: Generate Sitemap with All Routes

Problem: Dynamic routes not discoverable

Fix:

  • Generate sitemap at build time
  • Include all SPA routes
  • Submit to Google Search Console

The Reality Check: What Actually Gets Indexed

When JavaScript Rendering Works

Most modern sites using React, Vue, or Angular do get indexed by Google-eventually. But "eventually" might mean:

  • Hours or days of delay
  • Incomplete rendering if JavaScript is complex
  • Missing content if rendering times out

When It Fails

JavaScript rendering fails when:

  • Timeouts on slow/complex scripts
  • Errors in JavaScript execution
  • Missing dependencies
  • Overly dynamic content

The problem: You won't know it failed unless you test. Google's documentation recommends testing with their tools, but those tools show you Google's perspective-not necessarily what LLMs extract.

Testing Checklist for SPA Headings

Before assuming your SPA is SEO-ready:

  • [ ] View Source test: Headings in initial HTML? (Ideal: yes)
  • [ ] JavaScript disabled test: Headings still visible? (SSR/SSG only)
  • [ ] Google Search Console: Headings in rendered HTML tab?
  • [ ] Chrome extension test: Content LLM Analyzer extracts headings?
  • [ ] Multiple route test: All SPA routes have extractable headings?
  • [ ] Mobile test: Headings extract on mobile Googlebot?
  • [ ] Slow connection test: Headings load on throttled connection?

Pass all 7? Your SPA headings are properly extractable.

Fail any? Use SSR/SSG or fix rendering issue.

Key Takeaways

  • Modern websites use JavaScript - CSR creates SEO challenges
  • Search engines CAN render JavaScript - but with delays and limitations
  • LLMs need rendered content - hidden = doesn't exist
  • Heading extraction is critical - traditional tools miss JavaScript-rendered headings
  • SSR/SSG solve this completely - headings in initial response
  • If stuck with CSR, test properly - use tools that execute JavaScript
  • Chrome extensions work best - they render exactly like users see

JavaScript rendering isn't an SEO problem if you test properly and choose the right architecture. The gap between what you built and what search engines see is measurable-and fixable.

Install Content LLM Analyzer's Chrome extension, click the icon on any SPA page. If headings appear in the popup, they're extractable. If not, you have a rendering issue that needs fixing.


Related reading:

Ready to test if your JavaScript content is actually visible? Content LLM Analyzer runs in your browser, executes all JavaScript, and shows you exactly what gets extracted-just like an LLM would see it.

Subscribe to DiscoverdbyAI

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe