Skip to content
Novandri.

JavaScript SEO: SSR, CSR, SSG, and ISR Explained

A developer's guide to JavaScript SEO: comparing SSR, CSR, SSG, and ISR, how Google's Web Rendering Service processes client-side code, and avoiding indexing traps.

Rachmadwipa Novandri9 min read

For decades, search engine crawlers operated on a simple contract: send an HTTP GET request, receive a complete HTML document, parse the text, extract links, and index the content. The widespread adoption of modern JavaScript frameworks (React, Vue, Angular, Svelte) fundamentally disrupted this contract by shifting document compilation from origin servers to client-side browsers.

Direct Answer: JavaScript SEO is the engineering discipline of ensuring search engine crawlers can efficiently discover, execute, and index client-rendered content. While Googlebot renders JavaScript using an evergreen headless Chromium browser, client-side rendering (CSR) introduces significant latency because rendering is deferred to a secondary queue. Pre-rendered architectures—Server-Side Rendering (SSR), Static Site Generation (SSG), and Incremental Static Regeneration (ISR)—eliminate this delay by delivering complete HTML on the initial network response, ensuring predictable indexation.

Choosing the right rendering architecture requires balancing content velocity, server infrastructure costs, and search crawler reliability.

1. Client-Side Rendering (CSR):
Crawler ──► [GET /page] ──► Returns Empty <div id="root"></div> ──► [Queued for Render] ──► Weeks to Index

2. Server-Side Rendering (SSR):
Crawler ──► [GET /page] ──► Origin Server Compiles HTML on Request ──► Returns Complete HTML ──► Immediate Index

3. Static Site Generation (SSG):
Crawler ──► [GET /page] ──► Edge CDN Delivers Pre-Compiled HTML ────► Returns Complete HTML ──► Immediate Index

4. Incremental Static Regeneration (ISR):
Crawler ──► [GET /page] ──► Edge CDN Serves Cached Static HTML ─────► Revalidates in Background ──► Immediate Index

1. The Four Rendering Paradigms: Trade-offs for SEO

Modern web frameworks offer four distinct architectural strategies for assembling HTML and executing JavaScript.

Client-Side Rendering (CSR)

In a pure Client-Side Rendered application (traditional Single-Page Application or SPA), the web server returns an almost empty HTML shell containing little more than a root container (e.g., <div id="root"></div>) and script bundles:

<!DOCTYPE html>
<html>
  <head>
    <title>My Application</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="/static/js/bundle.a1b2c3.js"></script>
  </body>
</html>

The browser downloads the bundle, executes the JavaScript, queries backend REST or GraphQL APIs, and dynamically injects DOM nodes.

  • SEO Consequence: Highly vulnerable. If a search engine crawler cannot or does not execute the JavaScript bundle—due to resource limits, network timeouts, or JavaScript syntax errors—the page appears entirely blank to the crawler, leading to indexing failures or soft 404 classifications.

Server-Side Rendering (SSR)

With Server-Side Rendering, every incoming request triggers the origin server (typically a Node.js runtime) to fetch required data, render the React/Vue component tree into an HTML string, and stream the fully populated document back to the client.

  • SEO Consequence: Excellent indexability. The crawler receives all text, metadata, canonical links, and structured data in the initial HTTP response stream.
  • Infrastructure Trade-off: High server compute demand. Every crawler request consumes CPU cycles and memory on your origin server, potentially increasing Time to First Byte (TTFB) during traffic spikes.

Static Site Generation (SSG)

Static Site Generation compiles your entire application into static HTML, CSS, and client-side JavaScript assets at build time. When a user or crawler requests a URL, the edge CDN serves the pre-built HTML file directly from storage.

  • SEO Consequence: Optimal. Near-instantaneous TTFB, minimal origin server load, and guaranteed complete HTML payloads for search crawlers on the very first hop.
  • Infrastructure Trade-off: Build time scales with the number of pages. Modifying a single typo or updating a stock status requires rebuilding and redeploying the site (or utilizing dynamic webhooks).

Incremental Static Regeneration (ISR)

Pioneered in modern meta-frameworks like Next.js, ISR combines the performance of SSG with the elasticity of SSR. Pages are pre-rendered at build time and cached at the edge. When an incoming request arrives after a defined revalidation period (e.g., revalidate: 3600), the edge immediately serves the cached static page while triggering a background regeneration of the HTML.

  • SEO Consequence: The gold standard for content-heavy sites. Crawlers always receive a fast, fully rendered static HTML response with zero origin compute bottlenecks, while content stays fresh.

2. Googlebot’s Two-Wave Rendering Pipeline

To understand why client-side JavaScript creates search visibility risks, we must look at how Google processes web documents. Googlebot uses a multi-tier ingestion architecture known as Two-Wave Indexing:

[HTTP Response: Initial HTML Payload]
              │
              ▼
   (Wave 1: First-Pass Parsing)
   ├── Status & Header Evaluation
   ├── Parse Raw HTML Text & Title
   └── Extract Raw <a href="..."> Links ──► Queued to Crawl Frontier
              │
              ├─ Did the page rely heavily on JS?
              │     NO  ──► Indexed Immediately
              │     YES ──▼
              │   [Web Rendering Service (WRS) Queue]
              │     │  (May sit in queue hours to days)
              │     ▼
   (Wave 2: Chromium Headless Execution)
   ├── Download JS, CSS, and Fonts
   ├── Execute Script Bundles & Fetch APIs
   ├── Compute Rendered DOM
   └── Re-index Text, Links & Canonical Directives

Wave 1: The Initial Fast Path

In the first wave, Googlebot treats the response like a traditional document. It reads the raw HTTP headers and parses the static HTML string. If links are declared using standard <a href="/target-url"> tags within the initial HTML, they are immediately scheduled into the crawl queue.

Wave 2: The Deferred Web Rendering Service (WRS)

If the document requires client-side JavaScript execution to display core content, Googlebot defers the page to its Web Rendering Service (WRS). WRS executes an evergreen, headless version of Chromium.

Because running a full browser engine to execute JavaScript across billions of pages requires immense compute power, Wave 2 does not run in real time with crawling. Rendering can be delayed anywhere from several minutes to days after the initial fetch. If your site publishes breaking news, dynamic catalog updates, or time-sensitive inventory, relying on Wave 2 introduces unacceptable indexing latency.


3. High-Risk JavaScript SEO Anti-Patterns

When building modern web applications, subtle coding patterns frequently cause catastrophic indexing failures:

1. Client-Side Only Canonical and Meta Tags

If your application sets <title>, <meta name="description">, or <link rel="canonical"> using client-side libraries (like react-helmet) that run after component mounting, Googlebot evaluates Wave 1 without that metadata. If the initial HTML contains a generic fallback title or lacks canonical tags, search engines may pick an incorrect canonical URL or misclassify the page before Wave 2 ever executes.

Search crawlers navigate the web by finding valid URLs in the href attribute of anchor tags.

  • Bad: <button onClick={() => navigate('/category/shoes')}>Shoes</button> or <a onClick="fetchData()">Shoes</a>
  • Good: <a href="/category/shoes">Shoes</a>

Crawlers do not trigger mouse clicks, scroll events, or interactive form submissions. If navigation relies on JavaScript event handlers without valid anchor tags, the crawler's link extraction engine cannot discover child pages.

3. API Latency and Sub-Request Timeouts

When WRS renders a page, it places strict timeouts on network sub-requests (such as third-party APIs or microservice queries). If your client-side bundle depends on an un-cached API that takes more than 3 to 5 seconds to resolve, WRS terminates the execution context and renders the page in whatever partial state it has reached, resulting in missing content or broken layouts.

4. Client-Side 404 Routing

In Single-Page Applications, route resolution often happens in the client-side router (react-router or vue-router). When an invalid URL is accessed, the server still responds with an HTTP 200 OK serving the SPA shell, and the client router displays a "Page Not Found" component. As established in HTTP Status Codes for SEO, this produces a Soft 404 that pollutes search engine crawl budgets.


4. How to Inspect and Debug JavaScript Rendering

Never rely on browser inspection alone to determine what search engines see. Use this structured verification process:

Step 1: Inspect the Raw Initial HTML via Terminal

Run curl to examine exactly what is delivered during Wave 1:

curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
  https://example.com/product-page | grep -i "<h1"
  • Pass: The command outputs the complete <h1>Product Name</h1> with real content.
  • Fail: The command returns empty, or shows <div id="root"></div>. This confirms you are relying 100% on Wave 2 deferred rendering.

Step 2: Compare View-Source vs DevTools Elements

  • View-Source (view-source:https://example.com): Displays the raw byte stream returned by the server (Wave 1 equivalent).
  • DevTools Elements Tab: Displays the live, dynamic DOM after JavaScript has executed and mutated nodes (Wave 2 equivalent).

If critical paragraphs, links, or product details exist in the Elements Tab but are absent in View-Source, they depend on client execution.

Step 3: Google Search Console URL Inspection Live Test

Open Google Search Console, input the target URL, and run the Live Test.

  1. Click View Tested Page.
  2. Inspect the Screenshot to ensure lazy-loaded or API-driven elements rendered properly.
  3. Review the HTML tab to verify that your target content is present in Googlebot's parsed DOM.
  4. Check the More Info > Page Resources panel to identify if any crucial JavaScript bundles or API endpoints were blocked by robots.txt or timed out.

5. Architectural Decision Matrix for Web Rendering

Use the following framework to choose the appropriate rendering model based on business and technical constraints:

Rendering ModelInitial HTML ContentServer / Compute OverheadIndexing ReliabilityIdeal Content & Use Case
Pure CSREmpty shell (<div id="root">)Lowest (Static object storage)High Risk (100% dependent on Wave 2 WRS)Private dashboards, logged-in SaaS applications, account settings.
Full SSRFully populated documentHighest (Every request invokes runtime CPU/RAM)Optimal (Immediate Wave 1 indexation)Real-time auctions, live stock pricing, highly personalized user feeds.
SSGFully populated documentLow (Compute incurred once during CI/CD build)Optimal (Fastest TTFB, immediate Wave 1 indexation)Documentation, marketing landing pages, company blogs, static guides.
ISRFully populated documentModerate (Compute incurred only on cache expiration)Optimal (Immediate Wave 1 indexation with fresh content)High-volume e-commerce catalogs, news publications, large knowledge hubs.

Summary & Next Steps

Modern search engines can execute JavaScript, but relying on client-side rendering is an architectural gamble with crawl timing and server resource caps. By embracing pre-rendered paradigms like SSR, SSG, or ISR, engineering teams ensure their web applications deliver complete, crawlable HTML on the very first network response.

To continue through the Technical SEO series, explore: