JavaScript SEO: rendering, hydration, and indexing
CSR, SSR, or SSG? The technical call that decides whether Googlebot sees your content or just an empty HTML shell.
January 2025, a fashion e-commerce called us in a panic: 18,000 PDP URLs indexed as 'soft 404'. The served HTML had three lines inside
, and the real content only appeared after React mounted on the client. Googlebot did run the JS, but with an average 9-day delay in the render queue. The result: an invisible catalog for almost two weeks after every deploy. This is the kind of issue that never shows up in copy audits or backlink reports. Before anything else, it pays to revisit How to audit on-page SEO without falling into guesswork to see where JS rendering fits into the diagnosis.The confusion starts with terminology. CSR (Client-Side Rendering) ships a near-empty HTML and delegates everything to the browser. SSR (Server-Side Rendering) builds HTML on each request, per user. SSG (Static Site Generation) builds everything at build time and serves ready files. ISR (Incremental Static Regeneration), popularized by Next.js, is hybrid: static output that revalidates on demand. Each carries trade-offs in TTFB, cache complexity, and server cost. For SEO, the right question isn't 'which is best', it's 'in which of my templates does the critical content need to live in the initial HTML'.
Hydration is where most teams slip. You serve perfect SSR HTML, Google indexes it, but the JavaScript that 'hydrates' the page weighs 800 KB and blocks interactivity for 4 seconds on 4G. The content ranks, then LCP tanks the ranking. Frameworks like Astro, Qwik, and React Server Components attack exactly this with partial hydration and resumability. Before migrating stacks, measure: how much of the current JS is needed above the fold? Most teams discover 70% can be static HTML. Crews who run this audit typically harvest a double win in Core Web Vitals: beyond LCP, what actually moves the needle and indexing throughput.
The 'Google runs JavaScript now' myth needs to die with nuance. Yes, the Web Rendering Service uses an up-to-date headless Chromium. But there are two queues: crawl (raw HTML) and render (with JS). On large sites, the render queue can lag for days. Worse: links discovered only in the post-JS DOM only enter the crawl queue after rendering. That means pure SPA architectures penalize discovery of new URLs. Combine that with Crawl budget: when to worry and how to measure it issues and you get catalogs where 30% of pages never get indexed, even when they sit in the sitemap.
How to decide in practice? Use a simple per-template matrix. Institutional landing pages with low change frequency: SSG, no debate. E-commerce PLPs with filters: SSR with edge cache (Vercel Edge, Cloudflare Workers) keyed by the most-used filter, fallback to pure SSR. PDPs: SSG with 1-hour ISR solves 90% of cases. Logged-in areas (dashboards, checkout): CSR is fine because you don't want it indexed anyway. The classic mistake is applying the same strategy to the whole site because the framework 'recommends it'. This mapping ties directly into E-commerce on-page: PLP vs PDP without cannibalization decisions.
Tools to validate before shipping: URL Inspection in Search Console shows the exact rendered HTML Google saw, with a timestamp. Rich Results Test uses the same renderer. For audits at scale, Screaming Frog in 'JavaScript rendering' mode compares raw vs rendered HTML and surfaces content that only exists post-JS. Server logs are ground truth: filter by Googlebot user-agent and watch the actual ratio between Googlebot Smartphone and Googlebot. People who've never opened logs usually get a shock from Log file analysis: what Googlebot is actually doing in their first month.
Three traps I still see in 2026: lazy-load with IntersectionObserver on main content (Googlebot doesn't scroll, so nothing loads), client-side routing without proper History API (hash # URLs don't index), and meta tags injected via JS after load (titles and canonicals swapped in the DOM may or may not be honored, depending on timing). For the third case, it's worth revisiting Canonical tags: common mistakes bleeding your organic traffic because the issue is rarely the canonical itself, it's when it appears in the document.
Practical takeaway: run a 10-URL audit on strategic pages today. Compare 'view-source' with 'Inspect Element' in Chrome. If critical content, navigation links, and meta tags aren't in view-source, you have a rendering problem, not a content problem. Document the gap by template, prioritize SSR or SSG on templates that drive organic revenue, and leave CSR where it doesn't matter. A modern stack is no excuse for empty HTML on a page that needs to rank.