Rendering & JavaScript SEO Guide | Symaxx
Understand how rendering affects SEO. Covers CSR, SSR, SSG, ISR, hydration costs, and how to ensure search engines can see your JavaScript-rendered content.
Modern websites are built with frameworks like React, Next.js, and Vue — and how these frameworks render content fundamentally affects what search engines see. If Googlebot cannot see your content because it is rendered entirely in JavaScript, your pages effectively do not exist in the search index. Understanding rendering strategies and their SEO implications is essential for any site built with a JavaScript framework.
- Server-Side Rendering (SSR) sends fully rendered HTML to the browser/crawler — best for SEO on dynamic pages.
- Static Site Generation (SSG) pre-renders pages at build time — best for SEO and performance on content that does not change frequently.
- Client-Side Rendering (CSR) renders content in the browser with JavaScript — riskiest for SEO because crawlers may not execute JavaScript fully.
- Incremental Static Regeneration (ISR) combines SSG with on-demand updates — ideal for large sites with frequently changing content.
- Google can render JavaScript, but with delays and resource limitations. SSR/SSG removes this risk entirely.
- Use Next.js App Router with server components as the default — it provides SSR by default with no extra configuration.
If you want the full breakdown, continue below.
How Search Engines Render Pages
The Two-Wave Indexing Process
Google indexes in two waves:
Wave 1 — HTML Crawl: Googlebot fetches the raw HTML response. Any content visible in the initial HTML is immediately available for indexing.
Wave 2 — JavaScript Rendering: Google's Web Rendering Service (WRS) executes JavaScript to see dynamically loaded content. This happens later — hours, days, or even weeks after the initial crawl.
SEO implication: Content that depends on Wave 2 rendering may be indexed with significant delay, or not at all if rendering fails.
What Google's WRS Can and Cannot Do
Can do:
- Execute modern JavaScript (ES6+)
- Process React, Vue, Angular components
- Follow JavaScript-generated links
- Read dynamically loaded content
Cannot reliably do:
- Handle infinite scroll without intersection observers
- Process content behind user interactions (click to reveal, tabs)
- Execute code that depends on user-specific data (cookies, localStorage)
- Handle all third-party JavaScript perfectly
Rendering Strategies Compared
| Strategy | When HTML is Generated | SEO Risk | Performance | Best For |
|---|---|---|---|---|
| SSG | At build time | ✅ None | ⚡ Fastest | Blog posts, docs, marketing pages |
| SSR | At request time | ✅ None | 🔄 Good | Dynamic pages, personalised content |
| ISR | At build + revalidation | ✅ None | ⚡ Fast | Large catalogues, frequently updated content |
| CSR | In browser (JS) | 🔴 High | ⏳ Slow initial | Dashboards, authenticated apps |
Static Site Generation (SSG)
Pages are generated at build time and served as static HTML.
// Next.js App Router — default behavior for pages without dynamic data
export default function BlogPost() {
return <article>This is fully rendered at build time</article>
}
SEO benefits:
- Full content in initial HTML — no rendering delay
- Fastest possible page load (served from CDN)
- Best Core Web Vitals scores
- Content is always crawlable
When to use: Blog posts, documentation, service pages, marketing pages — any content that does not change on every request.
Server-Side Rendering (SSR)
Pages are rendered on the server at each request.
// Next.js App Router — dynamic rendering
export const dynamic = 'force-dynamic'
export default async function ProductPage() {
const product = await fetchProduct()
return <article>{product.description}</article>
}
SEO benefits:
- Full content in initial HTML
- Dynamic data is always fresh
- No JavaScript rendering delay for crawlers
When to use: Pages with real-time data (pricing, inventory, user-specific content).
Client-Side Rendering (CSR)
Content is rendered in the browser by JavaScript.
'use client'
export default function Dashboard() {
const [data, setData] = useState(null)
useEffect(() => { fetchData().then(setData) }, [])
return <div>{data ? <Chart data={data} /> : 'Loading...'}</div>
}
SEO risks:
- Googlebot may not execute JavaScript or may timeout
- Content may be indexed empty or partially
- Delayed indexing (Wave 2 process)
When to use: Authenticated dashboards, admin panels, interactive tools — pages that do NOT need to be indexed.
Incremental Static Regeneration (ISR)
Static pages that re-generate after a specified interval.
// Next.js — revalidate every 60 seconds
export const revalidate = 60
export default async function ProductCatalogue() {
const products = await fetchProducts()
return <div>{products.map(p => <ProductCard key={p.id} {...p} />)}</div>
}
SEO benefits:
- Static HTML (fast, crawlable)
- Content stays fresh with automatic revalidation
- No build-time bottleneck for large sites
When to use: Product catalogues, news feeds, content that updates frequently.
Common Rendering Mistakes
Mistake 1: Critical Content Behind 'use client'
Marking a page component as 'use client' without data in the initial server render means crawlers may see empty content.
Fix: Keep page-level components as server components. Use 'use client' only for interactive sub-components.
Mistake 2: Content Behind Click Events
Content inside tabs, accordions, or "show more" buttons that requires user interaction is often invisible to crawlers.
Fix: Render all indexable content in the initial HTML. Use CSS to show/hide for user experience, not JavaScript.
Mistake 3: Lazy Loading Above-the-Fold Content
Lazy loading images and content below the fold is good practice. Lazy loading above-the-fold content (including the main heading and first paragraph) delays rendering of your most important content.
Fix: Ensure all above-the-fold content, images, and LCP elements load eagerly.
Mistake 4: No Server-Side Metadata
If <title> and <meta description> are set via client-side JavaScript, crawlers may not see them.
Fix: Use Next.js metadata or generateMetadata exports — these render on the server.
Performance Impact on SEO
Core Web Vitals Connection
Rendering strategy directly affects Core Web Vitals:
| Metric | SSG/SSR Impact | CSR Impact |
|---|---|---|
| LCP (Largest Contentful Paint) | Fast — content in initial HTML | Slow — content loads after JS |
| INP (Interaction to Next Paint) | Good — less JavaScript to process | Variable — heavy JS can block |
| CLS (Cumulative Layout Shift) | Low — layout defined in HTML | High — content shifts as JS loads |
Hydration Cost
Even SSR/SSG pages need "hydration" — the process of making server-rendered HTML interactive in the browser. Large component trees increase hydration time.
Mitigation:
- Use React Server Components (Next.js App Router default) — no hydration needed
- Code-split heavy client components
- Defer non-critical interactivity
Key Takeaways
- Use SSG or SSR for all public, indexable pages — never CSR.
- CSR is only appropriate for authenticated pages that do not need indexing.
- ISR provides the best of both worlds for large, dynamic catalogues.
- Next.js App Router with server components provides optimal SEO rendering by default.
- Always validate your pages show full content with JavaScript disabled.
- Core Web Vitals are directly impacted by rendering strategy.
Quick Rendering SEO Checklist
- All public pages use SSG, SSR, or ISR (not CSR)
- Page content visible in View Source (no JavaScript required)
- Metadata rendered server-side (Next.js metadata API)
- No critical content behind click interactions
- Above-the-fold content loads eagerly
- Client components used sparingly and only for interactivity
- Core Web Vitals passing on all public pages
- JavaScript disabled test confirms content is visible
Related SEO Documentation
Was this helpful?