Your shopping cart is empty!
Googlebot renders JavaScript in two stages: first it crawls the HTML, then executes JS — sometimes weeks later. This lag causes React/Vue/Angular sites to get incomplete indexation. Here is a full diagnostic and fix checklist.
Table of Contents
How Googlebot Processes JavaScript: WRS Explained
Googlebot uses the Wave Rendering System (WRS) — a two-stage page processing pipeline. Stage one: the crawler downloads the HTML and places the page in a rendering queue. Stage two: a Chromium engine executes JavaScript and builds the final DOM. The gap between stages can range from a few hours to several weeks, depending on the site's rendering budget and Google's infrastructure load.
We audited a React site with 800 pages — Googlebot was seeing only 12% of the content due to rendering failures. The root cause: critical body text was loaded via an API call after the component mounted, and Google simply didn't wait for the server response. After migrating to SSR, the same site gained +67% indexed pages within three months.
Googlebot's Chromium version consistently lags behind the current release — typically by 1–2 years. According to Google's official documentation, the crawler ran Chromium 112 as of 2024, while the current browser version had long surpassed 120. This means certain modern JS APIs may not be supported by the crawler at all.
SSR vs CSR vs SSG vs ISR — SEO Comparison Table
Choosing a rendering strategy is the single most important architectural decision for JavaScript SEO. Each model has a distinct impact on indexation reliability, page speed, and maintenance complexity.
| Rendering Type | How It Works | SEO Reliability | TTFB | Complexity |
|---|---|---|---|---|
| SSR (Server-Side Rendering) | HTML generated on server per request | High — Google gets ready HTML | Higher (server load) | Medium |
| CSR (Client-Side Rendering) | Empty HTML shell; JS builds DOM in browser | Low — depends on WRS success | Lower (static shell) | Low |
| SSG (Static Site Generation) | HTML pre-built at deploy time | Maximum — clean static HTML | Minimal (CDN) | Low |
| ISR (Incremental Static Regeneration) | Static pages regenerated on a schedule | High — HTML always ready | Minimal | Medium |
| Hydration / Islands | SSR + selective client-side hydration | High when implemented correctly | Low | High |
For eCommerce and large catalogues, we recommend ISR or SSR via Next.js / Nuxt.js. SSG suits blogs and landing pages where content changes infrequently. Pure CSR is acceptable only for authenticated apps (dashboards, SaaS behind login) where SEO is irrelevant.
JS Site Diagnostics Checklist: Tools and Steps
Diagnosing rendering issues requires working with several tools in sequence. Here is the workflow we follow during a technical SEO audit:
- Google Search Console → URL Inspection. Open any suspicious page, click "View Crawled Page". GSC shows a screenshot of what Google sees after rendering, plus a list of blocked resources.
- Screaming Frog in JavaScript mode. Enable Configuration → Spider → Rendering → JavaScript. Compare Word Count with JS on vs off — a gap over 20% signals a rendering problem.
- Rich Results Test (search.google.com/test/rich-results). Verifies whether Google can read structured data after JS rendering.
- Request Indexing via GSC → URL Inspection → Request Indexing. Forces a fresh render and crawl of a specific page.
- Chrome DevTools → Coverage. Shows how much JS actually executes on load — helps identify dead code bloating your render time.
- URL Inspection API. Programmatic indexation status checks via Google Search Console API — essential for mass audits of large sites.
The Rendering Budget Problem
The rendering budget is the limited resource Googlebot allocates to JS rendering for each domain. Google does not publish exact figures, but based on our audits of large sites (10,000+ pages): once the budget is exhausted, some pages get indexed from their HTML shell only — JavaScript never executes.
Factors that drain the rendering budget faster:
- Overall crawl budget — more popular domains get more rendering resources from Google
- JS bundle size and complexity — heavy bundles (2+ MB) burn through the budget quickly
- Number of third-party resources — fonts, tracking scripts, chat widgets all delay rendering
- JS execution time — if a script runs longer than ~5 seconds, Googlebot may abort rendering
- JavaScript errors — uncaught exceptions halt script execution entirely
Auditing a Vue.js store with 3,200 product pages: 41% of pages were indexed without JS rendering — that content was effectively invisible to search. The culprit: a 4.1 MB bundle and 23 third-party scripts loaded in the document head.
To detect budget exhaustion, check Google Search Console → Coverage → "Indexed, not submitted in sitemap" and "Discovered — currently not indexed". Cross-reference those URLs in Screaming Frog JS mode — if content exists but Google misses it, the rendering budget is the likely bottleneck.
Dynamic Content and data Attributes: What Google Actually Sees
Googlebot reads the DOM after rendering — so it can see content that appeared via JavaScript. But several common patterns cause content loss:
- Event-triggered content (scroll, click, hover) — the crawler does not interact with pages, so lazy content behind "Show More" buttons stays invisible
- Infinite scroll — Google sees only the first batch of content. Fix: pagination with real URLs
- Content in modals and popups — if hidden via
display:noneorvisibility:hidden, Google de-prioritises it - data attributes — Google reads them but does not index them as text content. Critical information (name, description, price) must live in the visible DOM, not only in data-*
- API-dependent content — if text comes via fetch(), Google sees it only if the request completes during the rendering window
Internal Linking in SPAs — Common Pitfalls
Single Page Applications are a high-risk zone for internal link equity. SPA frameworks use client-side routing, which introduces several crawlability traps:
- JavaScript event handler links:
<div onclick="navigate('/category')">— Googlebot does not follow these. The linked page never gets crawled and receives no PageRank. - Missing href attribute:
<a>without href, or withhref="#"— Google ignores them as link signals. - History API without server fallback: React Router or Vue Router change URLs via
pushState(), but if the server returns 404 on direct access — Googlebot logs an error and stops crawling that path. - Links inside Shadow DOM: content and links inside Web Components / Shadow DOM are read by Googlebot with limitations.
- JavaScript redirects: chains of JS-based redirects (via window.location) don't pass PageRank as efficiently as server-side 301s.
Correct approach: all navigational links use <a href="/real-path">. The client-side router can intercept clicks for SPA navigation, but the href must be a real URL. This solves two problems at once: Googlebot crawlability and correct behaviour when opening links in a new tab.
Structured Data in JS Sites — When Google Can't Read It
JSON-LD in the document body is typically readable by Google even without JavaScript rendering — one of the few areas where JS sites have a built-in advantage. But there are important exceptions:
- JSON-LD generated via JavaScript: the markup is only visible to Google after rendering. Until WRS completes, pages may have no structured data in the index.
- Template-generated JSON-LD with character errors: if values are injected via JS templates and contain unescaped quotes or special characters, the schema breaks silently.
- Duplicate schema from components: React/Vue component re-renders can easily produce multiple identical
<script type="application/ld+json">blocks on the same page. - Dynamic values (price, rating) from API: if a Product schema is built from an API response that hasn't arrived yet, Google sees empty fields — which can lead to rich result eligibility being revoked.
JavaScript SEO Fix Checklist
After diagnosis, here is the prioritised fix sequence — from critical to optimisation-level items.
- Implement SSR or SSG for critical pages. In Next.js: use
getServerSideProps(SSR) orgetStaticProps(SSG). In Nuxt.js: useasyncData. At minimum, cover the homepage, category pages and product/service pages. - Audit all internal links. Run Screaming Frog or Ahrefs Site Audit — identify all links missing href or using JavaScript in href.
- Set up a server-side fallback for SPA routing. Every URL accessible via the client router must return 200 with full HTML on direct access.
- Move critical meta tags to server-rendered HTML. Title, description, canonical and hreflang must be in the server response, not JS-generated at runtime.
- Optimise your JS bundle. Targets: under 150 KB for the initial bundle (gzip), code splitting for non-critical modules, lazy loading below-the-fold components.
- Defer or remove unnecessary third-party scripts. Every external script (pixels, live chat, analytics) adds to rendering time. Use
deferorasyncattributes. - Embed critical JSON-LD schemas in server HTML. Don't generate Product, Article or FAQ schema via client-side JS — include them in the SSR response.
- Replace infinite scroll with pagination. Or provide individual URL-addressable routes for each content batch, accessible via direct URL.
- Add JavaScript error handling and monitoring. Uncaught exceptions stop script execution. Add a global error handler and implement JS error monitoring (Sentry, LogRocket).
- Set up pre-rendering as a fallback. Tools like Rendertron or Prerender.io serve static HTML to bot requests — a viable interim solution while full SSR is in development.
After deploying fixes, re-audit with GSC and Screaming Frog. SSR migration results typically appear in GSC within 3–6 weeks: the count of indexed URLs rises and "Discovered — currently not indexed" errors decline.
If you need expert help with a technical SEO audit of your JS site, or a migration strategy to SSR — we run full rendering architecture diagnostics and deliver a prioritised fix plan with ROI estimates. Learn more about our website promotion services.
Frequently Asked Questions
Does Googlebot index React websites?
Yes, but with a delay. Googlebot renders JavaScript in two stages — first it crawls the HTML, then (days or weeks later) it renders the JS. Until rendering completes, pages may be indexed without some of their content.
Which is better for SEO: SSR or CSR?
SSR is more reliable for SEO because Google receives ready-made HTML without needing to execute JavaScript. CSR depends on successful rendering, which can fail due to rendering budget limits or uncaught JS errors.
How can I check what Googlebot sees on a page?
Use Google Search Console → URL Inspection → "View Crawled Page". Screaming Frog in JavaScript rendering mode shows the difference in content with and without JS. Rich Results Test verifies whether structured data is visible after rendering.
Does Google read content loaded via fetch/XHR?
Yes, if JavaScript executed successfully and the content is present in the DOM after rendering. If content loads after scroll or click events, Google won't see it — the crawler does not interact with pages.
Is your JS site being poorly indexed?
We run a technical SEO audit covering rendering, internal links, structured data and crawl budget. You get a report with specific fixes and impact-based prioritisation.
Order a technical audit or learn about our promotion services


