Search Engineering

JavaScript SEO: what a crawler actually sees

Client-rendered content is not automatically invisible, and server-rendered content is not automatically visible. The gap between what a browser shows and what a crawler receives has to be measured, and then closed at the layer that caused it.

The problem

Rendering failures present as indexation failures

When content depends on client-side execution, the symptom is usually a page that exists, is linked, is not blocked and does not rank. That reads as an indexing problem and is frequently worked as one, while the actual fault is that the crawler receives a document containing none of the content the page is about. Establishing this takes a comparison rather than a diagnosis; resolving it takes an application change rather than an SEO one.

  • Content visible in a browser that does not appear in the crawled HTML
  • A framework migration after which organic visibility fell and never returned
  • Metadata that differs between the served document and the rendered page
  • Internal links that resolve only after JavaScript executes
  • Indexed pages whose titles and descriptions come from the application shell
  • Correct behaviour in testing and different behaviour when the crawler arrives
Who this is for

The people who usually bring us this problem

CTO / VP Engineering

An SEO problem has been escalated to you and the answer depends on rendering architecture. You need the trade-offs stated as engineering decisions rather than as an SEO requirement.

Head of SEO / SEO Director

You suspect client-side rendering and cannot prove it. You need a rendering comparison that identifies exactly which content and which links are affected.

Head of Product

You are choosing or have chosen a front-end approach and need to know what it costs in discoverability, before it is expensive to change.

What it costs

What this costs while it goes unfixed

Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.

Content investment with no discoverable surface

Content that never reaches the crawler cannot rank, and the spend behind it produces nothing. The failure is invisible from inside the CMS because the pages look correct to everyone editing them.

Rendering changes are cheaper before a migration than after

Choosing the rendering model is a decision with search consequences. Discovering those consequences once traffic has fallen means re-architecting under pressure.

Second-order effects get mistaken for separate problems

Metadata, internal link equity, canonical resolution and pagination all behave differently under client-side rendering. They surface as a cluster of unrelated faults rather than as one cause.

What we do about it

Capabilities

Each of these is work we carry out, not an area we advise on.

Crawler-versus-browser comparison

Fetching pages as a crawler receives them and comparing against the rendered result — which content, which links and which metadata differ, established rather than inferred.

Rendering strategy assessment

Which of server-side rendering, static generation, incremental generation, pre-rendering or client-side hydration suits the site's content and update model — and what each costs.

Metadata and canonical correctness

Titles, descriptions, canonicals, hreflang and structured data that are generated at the right time, in the document, rather than injected after execution.

Internal link crawlability

Navigation and pagination that resolve to crawlable anchors in the served HTML, so link discovery does not depend on execution completing.

Hydration and content-parity faults

Content that changes on hydration, differs between server and client renders, or depends on a fetch that a crawler will not complete.

Framework-specific remediation

Practical fixes within the framework already in use rather than a proposed replatform — the rendering model is usually adjustable without replacing the stack.

How we work

Engineering methodology

The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.

  1. Measure before recommending

    The comparison is run first and produces a list of specific differences. Rendering advice given before that step is guesswork, and the guess is wrong often enough that it is worth the fetch.

  2. Fix at the layer that caused it

    If metadata is injected client-side, the fix belongs in the rendering path, not in a plugin that patches the output. Patching symptoms across a large estate leaves the next new template broken in the same way.

  3. Prefer the smallest sufficient change

    A full SSR replatform is a large answer to a problem that frequently has a smaller one — server-rendering the templates that matter, or moving a specific fetch to the server. The heaviest option is proposed when it is genuinely the only one.

  4. Preserve what already works

    Client-side rendering is not a defect in itself, and interactive parts of a site are often better left alone. The target is a document that carries the content and links, not the removal of JavaScript.

  5. Verify against the crawler, not the browser

    Every change is checked by re-fetching as a crawler rather than by opening the page. A fix confirmed in a browser has not been confirmed at all.

Deliverables

What an engagement produces

Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.

Diagnosis

  • Crawler-versus-browser content comparison, per template
  • Affected metadata, canonical and hreflang inventory
  • Internal link reachability analysis in served HTML
  • Rendering-model assessment with cost per option

Remediation

  • Server-side or pre-rendering for affected templates
  • Metadata generation moved into the served document
  • Crawlable navigation and pagination markup
  • Framework-level changes alongside the client's engineers

Verification

  • Re-fetch comparison confirming parity
  • Indexation monitoring per template
  • Checks that new templates inherit the fix rather than repeating the fault
Under the hood

Architecture and technology

Rendering path

  • Where content is generated: build, server or client
  • Metadata emission point
  • Link markup in the served document
  • Data dependencies that must resolve without execution

Governance

  • Template review before launch
  • Automated crawler-parity check in CI where feasible
  • Documentation of which templates render how, and why
Adjacent problems

If this is not quite your problem

These overlap at the edges. Sending you to the right page is more useful than having you work it out.

Pages render correctly and are still not indexed

See Crawl and Indexation. Rendering is one of four possible causes, and it is worth ruling the other three out before changing the architecture.

Organic visibility fell after a platform or framework change

See Website Migrations, which covers the wider set of causes a migration can introduce.

Questions

Frequently asked

Have you done this on an engagement you can show?

We can demonstrate the rendering comparison and crawl-path analysis on your own stack during discovery. That gives you a concrete view of the problem before committing to implementation.

Do we need to move to server-side rendering?

Usually not as a whole. Most sites need the content-bearing templates to render server-side while interactive areas stay client-side. A full replatform is occasionally correct, but it is a large answer to what is often a local problem, and it carries its own migration risk — which is its own way of losing organic visibility.

Which frameworks does this apply to?

Any that render on the client: React and Next.js, Vue and Nuxt, Angular, and any single-page application. The rendering comparison is framework-agnostic because it measures the served document, and the remedies differ by framework but the diagnosis does not.

Does Google not render JavaScript anyway?

It does, and that is why the situation is more nuanced than "JavaScript content is invisible". Rendering is deferred, sometimes unreliable, and the second pass it depends on is not guaranteed on a schedule you control. The practical consequence is that client-rendered content is discovered later and less completely — which for time-sensitive content is equivalent to not being discovered at all.

Bring us the problem you have not been able to fix

Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.