JavaScript SEO

Is Googlebot Actually Seeing What Your React or Next.js Site Renders?

JavaScript SEO means closing the gap between what a browser renders after your JS runs and what a crawler indexes. On a site rendered in the browser or only partially hydrated, those two can diverge: content that's visible to a visitor can be invisible, delayed, or truncated for the crawler that decides whether the page ranks at all.

Dfeelings Team · GEO & Website Development Company, Amman, Jordan
Last updated: September 18, 2026

The problem

Most technical SEO advice assumes the HTML a server sends is the content search engines see. On sites rendered with JavaScript that assumption breaks: Googlebot has to execute your JS in a second rendering pass before it can index anything rendered in the browser, that pass is queued and can be delayed by days on a large or rarely crawled site, and any JS error, unhandled promise rejection, or blocked resource during that pass can silently drop content Google never retries. A page can look complete in a browser and still be indexed as an empty shell.

Symptoms

  • Google Search Console's URL Inspection tool shows a rendered screenshot that's missing content visible in a normal browser, or the "Page fetch" step succeeds while "Screenshot" or "More info" flags resources that blocked rendering.

  • The indexed content of a page (checked via `site:` search or the Inspection tool's rendered HTML) lags noticeably behind what's currently live, even weeks after a content update.

  • Content behind a fetch in the browser (data loaded after mount, e.g. `useEffect` + `fetch`) never appears in Google's cached or rendered HTML at all.

  • Internal links rendered only via `onClick` handlers or `<a>` tags injected by JS without a real `href` aren't discovered by crawlers that don't execute every event handler.

  • Core metadata (title, canonical, meta description) is set in the browser after hydration instead of being present in the initial server response, so what curl or view source shows is inconsistent with what the browser eventually renders.

How we diagnose it

We start with the same test that matters most: fetch the URL the way a crawler does (no browser, no JS execution, just a plain HTTP GET) and diff that against the fully rendered DOM in a headless browser. Anything present in the rendered DOM but absent from the raw response is a candidate for an indexing gap that depends on rendering. We cross check with Search Console's URL Inspection rendered screenshot and "View Crawled Page" HTML, check the Network tab for requests that block rendering or fail during first paint, and review Core Web Vitals field data (see our Core Web Vitals page) since slow hydration and JS SEO problems frequently share a root cause.

The fix

The fix is almost always to move content into the initial server response rather than leaving it dependent on JS executing in the browser: rendering on the server, static generation, or streaming server components for anything that matters for indexing (headings, body copy, canonical and meta tags, internal links with real hrefs). Content that is genuinely interactive only (a dashboard behind auth, for example) doesn't need this; content meant to rank does. We also make sure critical resources (fonts, images above the fold, scripts that block rendering) aren't accidentally disallowed in robots.txt, since a blocked resource during Google's rendering pass can cause the page to be indexed as incomplete even when the HTML itself is fine.

Implementation details

This site is itself built on Next.js's App Router: every canonical page under `src/app/[lang]/[...slug]/page.tsx` is a Server Component whose `generateMetadata()` resolves title, description, canonical and hreflang tags on the server before any client JS runs. It is the same pattern this page describes rather than something we only recommend to clients. Page bodies then hand off to client components (the `"use client"` files under `src/components/PageContent/`) only for interactivity (animations, accordions), not for the text content itself, which arrives in the initial HTML via the translations JSON consumed on the server. For Next.js sites specifically we check: the App Router's static vs. dynamic rendering choice per route (`generateStaticParams` coverage), whether client components are thin wrappers that only hydrate content already rendered on the server, or islands rendered in the browser that hold back content until JS loads, and whether `next/dynamic` imports used for code splitting (see the dynamic loader pattern used throughout this codebase) still render on the server (`ssr: true`) rather than only in the browser.

Common mistakes

  • Treating "it renders fine in Chrome DevTools" as proof it's indexable. That only confirms the browser can execute the JS, not that Google's rendering pass will pick it up on the same schedule or budget.

  • Fetching primary page content in the browser (`useEffect` + API call) instead of on the server, so there's a real chance a crawler indexes the loading state instead of the content.

  • Using `next/dynamic(..., { ssr: false })` for content that matters for SEO, which opts the whole chunk out of server rendering, not just its interactivity.

  • Blocking JS and CSS bundles in robots.txt (a legacy practice from the era before crawlers rendered pages) that actively prevents Google from rendering the page correctly today.

  • Assuming a JS framework migration (e.g. moving to a new meta framework or app architecture) preserves SEO by default. Rendering strategy, metadata generation, and route structure all have to be verified again, not assumed.

Validation

We validate with Search Console's URL Inspection tool (both the rendered screenshot and "View Crawled Page" HTML) on a sample of real URLs, a diff of raw HTTP responses against the rendered DOM across the site's main templates, a robots.txt check for accidentally blocked JS and CSS, and Core Web Vitals field data to confirm the fix didn't just move content into the DOM but also kept it fast enough for INP.

Bilingual JS SEO considerations

On a bilingual EN/AR site, JavaScript SEO issues can compound with locale routing: content fetched in the browser after a locale switch, or hreflang alternates computed only in a client effect, can leave one language's rendered response incomplete even when the other locale's is fine. We verify the raw HTTP responses of both locales independently, rather than checking just one and assuming symmetry.

Related service & solutions

JavaScript SEO is the rendering layer underneath schema markup, hreflang, and canonical tags. None of those signals matter if the content and metadata that carry them never reach the crawler intact.

Frequently asked questions

Common questions about JavaScript SEO

Google does execute JavaScript, but that rendering pass is a separate second step after the initial crawl, with limited resources. It can be delayed, it can fail on errors that a browser silently recovers from, and it doesn't guarantee the same outcome as loading the page in Chrome yourself. "Google can render JS" is not the same claim as "your specific page renders correctly, quickly, and consistently in Google's pipeline."
For content that needs to be indexed and ranked, yes: SSR, static generation, or server components ensure the crawler's first pass already has the content. For features that are genuinely interactive only, behind authentication or user action, client rendering is fine, since there's no indexing goal for that content.
Usually. Most JS SEO issues are fixable within the existing framework (changing which components render on the server versus in the browser, fixing metadata timing, unblocking resources in robots.txt) rather than requiring a full rewrite. We diagnose the specific gap before recommending anything that large.
Core Web Vitals is about how fast and stable the page is once it loads. JavaScript SEO is about whether the content is indexable at all. They frequently share root causes (heavy rendering in the browser hurts both), which is why we diagnose them together, but fixing one doesn't automatically fix the other.

Want your JavaScript rendering checked against what Google actually indexes?

Request a JavaScript SEO audit