Technical SEO

Headless CMS SEO: SSR, CSR, ISR, SSG, and What Google Actually Sees

By Reviewed by Hawrry Bhattarai
August 7, 2026 11 min read
Contents
TL;DR — the short answer

How server-side rendering, static generation, and client-side rendering affect Google crawling. Next.js and Nuxt.js SEO setup, hydration issues, and dynamic rendering fallbacks.

13 min read · Technical SEO · Last updated July 2026

Quick answer: Google can render JavaScript, but with a delay — pages using client-side rendering (CSR) may be indexed with incomplete content or a blank page if rendering fails. Server-side rendering (SSR) and static site generation (SSG) deliver fully rendered HTML on first request, which Google indexes immediately and completely. For SEO, SSG is the best default; SSR is strong but adds server load; CSR alone is risky without a fallback.

Introduction

Headless CMS architecture decouples your content management from your presentation layer. Your content lives in a CMS (Contentful, Sanity, Strapi, Prismic), and your frontend is built with a JavaScript framework — Next.js, Nuxt.js, Astro, SvelteKit, or similar.

This gives you frontend flexibility, performance potential, and content portability. It also introduces SEO challenges that did not exist with traditional server-rendered CMS platforms like WordPress.

When Google visits your React-based homepage, what does it see? If your page renders client-side, Google sees raw JavaScript on the first visit. If your framework handles SSR or SSG correctly, Google sees completed HTML. The difference between these two scenarios can be the difference between a page ranking and a page not being indexed at all.

What you’ll learn:
– What SSR, CSR, ISR, and SSG actually mean and how each affects Google
– Where hydration issues break SEO signals
– How to configure Next.js and Nuxt.js for correct SEO output
– When and how to use dynamic rendering as a fallback


Table of Contents

  1. The Four Rendering Approaches and Their SEO Implications
  2. How Google Crawls JavaScript
  3. Common Hydration Issues That Break SEO
  4. Next.js SEO Setup
  5. Nuxt.js SEO Setup
  6. Dynamic Rendering as a Fallback
  7. Technical SEO Checklist for Headless Sites
  8. Auditing Your Headless Site’s Rendered Output
  9. Frequently Asked Questions

The Four Rendering Approaches and Their SEO Implications

Rendering Type Comparison Matrix

Compare rendering approaches across key SEO and technical dimensions.

Dimension CSR SSR SSG ISR
What Google Sees on First Visit ⚠️ Raw JS or blank ✅ Full HTML ✅ Full HTML ✅ Full HTML
Indexation Speed Slow (2-stage crawl) Fast Fastest Fast
Content Freshness Real-time Real-time Build-time only Configurable TTL
Core Web Vitals Potential Poor (high TBT, LCP) Medium (TTFB varies) Excellent Excellent (after first visitor)
Server Load Minimal High (per-request render) None (static files) Low (TTL-based)
SEO Risk Level High Low Very Low Low
Best For Dashboards, apps behind login Dynamic personalised content Marketing sites, blogs, docs E-commerce, frequently updated content

Client-Side Rendering (CSR): the browser downloads a minimal HTML file (often just <div id="root"></div>), then JavaScript renders all the content. Google can render JavaScript but uses a two-wave process: it indexes the initial HTML first, then renders JavaScript in a second pass. The second pass can be delayed by days or weeks.

Server-Side Rendering (SSR): every page request triggers the server to run the JavaScript and return fully rendered HTML. Google sees complete content on the first visit. The trade-off is server load — every request requires a render cycle.

Static Site Generation (SSG): pages are rendered at build time and served as static HTML files. Google gets complete HTML instantly, TTFB is minimal, and Core Web Vitals are excellent. The trade-off is that content updates require a new build deployment.

Incremental Static Regeneration (ISR): Next.js’s hybrid approach. Pages are statically generated but regenerated in the background after a configurable time-to-live (TTL). Google still gets static HTML, but content stays reasonably fresh. Best of both worlds for most use cases.


How Google Crawls JavaScript

Google’s JavaScript crawling works in two waves:

Wave 1 (immediate): Googlebot requests the URL, receives the initial HTML response. If this is a CSR app, the initial HTML contains almost no content. Google indexes this skeleton — which means your page may appear in the index as essentially empty.

Wave 2 (delayed): Googlebot’s WRS (Web Rendering Service) queues the URL for JavaScript rendering. This rendering happens when resources allow — which can be hours to weeks after the first crawl. After rendering, Google indexes the fully rendered content.

The queue problem: the WRS queue is prioritised by page authority, crawl frequency, and server response time. For a new site or a newly published page, the render might happen within hours. For a low-authority site with slow response times, it can take weeks.

What this means practically: if you launch a new CSR blog post, it might appear in Google’s index as a blank page for 1-4 weeks before the JavaScript renders. SSR or SSG eliminates this lag entirely.


Common Hydration Issues That Break SEO

Hydration is the process where the browser attaches JavaScript event listeners and dynamic functionality to server-rendered HTML. When hydration fails or mismatches, you get SEO problems.

Hydration mismatch: the HTML returned by SSR does not match the HTML the JavaScript would generate on the client. React/Next.js logs a warning in the console and overwrites the server-rendered HTML with the client-rendered version. If this rewrite removes or changes your title tag, H1, or body content, Google may index the pre-rewrite version (correct) or the post-rewrite version (broken).

Common causes of hydration mismatch:
– Using Date() or Math.random() during SSR (produces different values on server vs client)
– Browser-only APIs (window, document, localStorage) accessed during SSR
– Content that depends on user state that does not exist during server render
– Third-party components that do not support SSR

The meta tag timing problem: in CSR apps, the <title> and meta description are often set by JavaScript after the page loads. If the initial HTML contains a generic <title> from a template, and JavaScript updates it, Google may index the generic title rather than the correct one.

The fix: always render your title, meta description, canonical, and structured data in the initial server response — never rely on client-side JavaScript to set these tags.


Next.js SEO Setup

Next.js is the most widely used React framework for SEO-aware JavaScript applications. It supports SSR, SSG, ISR, and client-side data fetching in a single application.

Page rendering choice in Next.js (Pages Router):

// SSG — getStaticProps runs at build time
export async function getStaticProps() {
  const data = await fetchFromCMS();
  return { props: { data }, revalidate: 3600 }; // ISR: regenerate every hour
}

// SSR — getServerSideProps runs on every request
export async function getServerSideProps(context) {
  const data = await fetchFromCMS();
  return { props: { data } };
}

For most content pages (blog posts, product pages, landing pages), use getStaticProps with revalidate for ISR. This gives you the fastest delivery with automatic freshness.

Metadata in Next.js 14+ (App Router):

// app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug);
  return {
    title: post.title,
    description: post.excerpt,
    alternates: { canonical: `https://example.com/blog/${params.slug}` },
    openGraph: {
      title: post.title,
      description: post.excerpt,
      url: `https://example.com/blog/${params.slug}`,
    },
  };
}

The App Router’s generateMetadata function renders metadata server-side, ensuring Google always sees correct title and meta tags on first visit.

Robots and sitemap in Next.js:

// app/robots.js
export default function robots() {
  return {
    rules: { userAgent: '*', allow: '/', disallow: '/private/' },
    sitemap: 'https://example.com/sitemap.xml',
  };
}

// app/sitemap.js
export default async function sitemap() {
  const posts = await getAllPosts();
  return posts.map(post => ({
    url: `https://example.com/blog/${post.slug}`,
    lastModified: post.updatedAt,
    changeFrequency: 'weekly',
    priority: 0.8,
  }));
}

Nuxt.js SEO Setup

Nuxt.js provides similar capabilities for Vue.js applications with a slightly different API.

Rendering mode configuration (nuxt.config.ts):

export default defineNuxtConfig({
  ssr: true, // Enable SSR (default in Nuxt 3)
  nitro: {
    prerender: {
      crawlLinks: true, // Pre-render all internal links
      routes: ['/', '/blog', '/about'] // Explicitly pre-render these
    }
  }
})

Dynamic metadata in Nuxt 3:

<script setup>
const route = useRoute();
const { data: page } = await useFetch(`/api/pages/${route.params.slug}`);

useHead({
  title: page.value.title,
  meta: [
    { name: 'description', content: page.value.description },
    { property: 'og:title', content: page.value.title }
  ],
  link: [
    { rel: 'canonical', href: `https://example.com${route.path}` }
  ]
});
</script>

Nuxt 3’s useHead composable renders metadata server-side by default when SSR is enabled, solving the meta tag timing problem.


Dynamic Rendering as a Fallback

Dynamic rendering is a technique where you serve pre-rendered HTML to search engine crawlers and regular JavaScript to users. It is not a long-term solution — Google has called it a workaround — but it is useful when migrating a CSR app to SSR is not immediately feasible.

How dynamic rendering works:
1. Detect whether the visitor is a search engine crawler (via User-Agent)
2. If crawler: serve pre-rendered static HTML (generated by a headless browser like Puppeteer)
3. If user: serve the normal JavaScript SPA

Implementation options:
Rendertron (Google’s open-source tool): a headless Chrome rendering service
Prerender.io (SaaS): hosted dynamic rendering service
Custom Puppeteer setup: your own rendering middleware

When dynamic rendering is appropriate:
– Your team cannot implement SSR/SSG on a short timeline
– You have a CSR app receiving crawler traffic that is not being indexed correctly
– As a bridge solution during a migration to SSR

When not to use dynamic rendering:
– As a permanent solution — it is additional complexity with ongoing maintenance
– If it requires showing different content to crawlers vs users (cloaking risk)
– If your framework already supports SSR easily (use SSR instead)

Key takeaway: dynamic rendering is a bridge, not a destination. Implement SSR or SSG as soon as feasible.

Headless SEO Checklist

Essential checks for any headless CMS or JavaScript framework site.

Progress0 / 12


Auditing Your Headless Site’s Rendered Output

The most important diagnostic tool for headless SEO: compare the initial server response to the JavaScript-rendered version.

Method 1: View Source vs Inspect Element
– View Source (Cmd+U on Mac) shows the initial HTML response from the server
– Browser DevTools Inspect shows the fully JavaScript-rendered DOM

If View Source shows the correct title, H1, and content — you are SSR/SSG and Google is getting good data. If View Source shows <div id="root"></div> — you are CSR and Google gets an empty page on first crawl.

Method 2: Google Search Console URL Inspection
GSC URL Inspection has two outputs: “Page is available to Google” shows what Googlebot received. The “More info” section shows the rendered page (after JavaScript execution). Compare these to find rendering gaps.

Method 3: curl command

curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://yoursite.com/page/ | grep -i "<title>"

This mimics what Googlebot sees on its first request. If the title is correct, your SSR is working. If it is blank or generic, you have a problem.


Frequently Asked Questions

Does Google render JavaScript the same as a browser?
Google’s WRS uses a version of Chromium but may not support the latest browser APIs. It also runs without certain browser features (no cookies in initial render, no localStorage, constrained JavaScript execution time). Polyfills and feature detection are important for broad compatibility.

Is Next.js App Router better for SEO than Pages Router?
The App Router has better built-in SEO primitives — server components, streaming, the metadata API — and is the active development track for Next.js. For new projects, use App Router. For existing Pages Router projects, the SEO difference is minimal if metadata is handled correctly.

What is the biggest SEO mistake on headless sites?
Setting metadata client-side using document.title or useEffect in React. This means Googlebot’s first visit sees the template title, not the page-specific title. Always use the framework’s metadata API (Next.js generateMetadata, Nuxt useHead) which renders server-side.

Can Google index a single-page application (SPA)?
Yes, but with the two-wave crawl delay described above. SPAs (pure CSR) require Google to render JavaScript before indexing content, which introduces significant lag. For any public-facing content that needs to rank, implement SSR or SSG.

How do I handle user-personalised content on SSR pages?
Render the non-personalised version server-side (what you want Google to index) and hydrate with personalised data client-side. This pattern is called “deferred hydration” or “progressive enhancement.” The server-rendered content serves crawlers; the client-rendered update serves logged-in users.


Conclusion

Headless architecture gives you flexibility, but it requires explicit SEO engineering. The framework choice matters less than whether you are shipping fully rendered HTML to Google on the first request. SSG is the safest default for marketing and content pages; SSR handles dynamic content; ISR bridges the gap.

If you are unsure what Google is seeing on your headless site, start with View Source and GSC URL Inspection. Those two checks answer the fundamental question: is Google getting your content, or just a JavaScript bundle?


Let Ignited Nepal Handle This

Auditing JavaScript rendering, configuring Next.js and Nuxt.js metadata, and resolving hydration issues requires both frontend engineering and technical SEO expertise. Our team works with headless CMS implementations across Nepal, Australia, UAE, and beyond.

→ Request a Free Technical SEO Audit


Written by the Ignited Nepal SEO team. We build organic search systems for businesses across Nepal, Australia, UAE, USA, UK, and beyond. ignitednepal.com

NR

Article by

Niraj Raut

Head of Search at Ignited Nepal. Drove 340% organic traffic growth for EzyDog (Australia), 4× revenue for The Turf Man (Australia), and 120% month-on-month traffic growth for ThemeGrill (Nepal). Keynote speaker at WordCamp Nepal 2023 and verified WordPress.org open-source contributor.