Technical SEO for JavaScript Applications: The 2026 Field Guide
← All insights
Field GuideAugust 2026· 16 min read

Technical SEO for JavaScript Applications: The 2026 Field Guide

VVerensoft TeamGrowth Engineering

The standard reassurance is that Google renders JavaScript now, so build with whatever framework you like and stop worrying. It is technically accurate and practically misleading, in the way that saying a car can drive uphill is accurate without telling you anything about fuel consumption.

Rendering happens, but it happens on a second pass, at a time the crawler chooses, subject to a budget, and only for pages the crawler decided were worth returning to. Every one of those qualifiers is a place where a client rendered site loses ground against one that served its content in the initial response. And the other engines, including the AI systems now assembling answers, are considerably less patient than Google is.

This is a field guide to the specific problems we find on React and similar applications, in the order we usually find them, with the fixes. It is written for engineers, because that is who has to implement them, and it reflects how we run technical SEO engagements: diagnosis, then a pull request.

Rendering strategy is the decision that dominates everything else

Almost every serious search problem on a JavaScript application traces back to how the page is produced. The other issues are real but they are second order, and fixing them on top of a broken rendering strategy is polishing something that will not run.

Client side rendering

The browser receives an empty container and builds the page. This is the worst option for search and it is still extremely common, because it is the default in several popular toolchains and nobody revisited it. Content depends on a render pass that may be delayed, metadata is set after load rather than in the document, and any crawler that does not execute JavaScript sees nothing at all.

It remains a perfectly reasonable choice for an authenticated application behind a login, where search visibility is irrelevant. It is a poor choice for anything you want found.

Static generation

Pages are built to HTML ahead of time and served as files. For content that does not change per request, this is close to ideal: fastest possible response, complete markup in the first byte, no rendering dependency at all. The constraint is build time on very large sites and staleness on frequently changing content, both of which incremental regeneration largely solves.

Server rendering

HTML is produced per request on the server. This is the right default for anything personalised, frequently updated, or too numerous to prebuild. It costs server capacity and introduces a latency component you have to manage, but it delivers complete markup to every client regardless of what that client can execute.

The practical recommendation for most commercial sites is a mix, decided per route rather than per project. Marketing and content pages statically generated. Catalogue and listing pages server rendered with caching. Authenticated application routes client rendered, and excluded from indexing entirely. Choosing one strategy for the whole site is the mistake, because the requirements genuinely differ by route.

2 passes
How Google indexes a client rendered page
First byte
Where content should be, not after hydration
Per route
The right granularity for a rendering decision

The failures we find most often

Metadata set after hydration

Titles, descriptions, and canonical tags injected by client side code are frequently missed or captured in their default state. Every page ends up sharing one generic title, which is both a ranking problem and an appalling click through rate in results. Metadata must be in the server response, per route, without exception.

Navigation that is not links

A clickable element with an onClick handler that programmatically routes is invisible as a link. Crawlers follow anchors with href attributes and nothing else. This one is easy to introduce accidentally in a component library and easy to miss, because the site works perfectly for humans while whole sections are unreachable to a crawler.

Infinite scroll with no paginated equivalent

Content loaded on scroll is content a crawler will not see, because crawlers do not scroll. If your catalogue or archive uses infinite scroll, it needs real paginated URLs underneath it that render server side. The scroll behaviour is a progressive enhancement layered on top, not the only way to reach the content.

Soft errors that return a success status

A missing record renders a message saying nothing was found while the server returns a two hundred status. The crawler treats it as a valid page and indexes an empty result. On a large catalogue this can generate thousands of near duplicate empty pages that dilute the whole domain. Missing content must return a genuine not found status from the server.

Faceted navigation generating unbounded URLs

Filters and sort options combine into a URL space that grows combinatorially, and a crawler will happily spend its entire budget on the fourth page of an obscure filter combination. Decide which facet combinations have genuine search demand, make those indexable and canonical, and exclude the rest from crawling rather than only from indexing. Excluding from indexing alone still spends the budget.

Crawl budget is not an abstraction on a large site. It is a fixed amount of attention, and faceted navigation will consume all of it on pages that could never rank if you let it.

Pagination, canonicals, and the duplicate URL problem

Duplicate URLs are the quietest of these failures because nothing looks broken. The site works, every page renders, and search engines are meanwhile choosing between four addresses for the same content and splitting the signals across them.

The usual sources on a modern application are predictable. Trailing slash and slashless forms both resolving. Uppercase and lowercase paths both resolving. Tracking parameters producing a new URL for every campaign. Sort and view parameters that change presentation rather than content. And a sitemap listing one form while internal links use another.

Fix this at the edge rather than in the application. Pick one canonical form, redirect everything else to it with a permanent redirect at the server or CDN, and then ensure your internal links, your canonical tags, and your sitemap all emit that same form. A canonical tag alone is a hint; a redirect is a rule, and on this particular problem you want the rule.

Paginated archives deserve their own decision. Each page should be self canonical rather than pointing at page one, which loses everything after the first screen. Give every paginated URL a distinct title, and if you also offer a view all page, canonicalise the sequence to that instead. What does not work is leaving it undecided, which is the default state on most sites we audit.

Core Web Vitals on a JavaScript application

Performance is a genuine ranking factor and a much larger conversion factor, and JavaScript applications have a characteristic set of problems that a generic performance checklist does not address well.

  • Largest contentful paint suffers when the main visual element depends on client fetched data. Render it on the server, or at minimum reserve its space and prioritise its image so the layout does not wait.
  • Interaction to next paint is where frameworks lose ground. Long tasks during hydration block the main thread precisely when a user first tries to interact. Reduce the JavaScript that must run before the page is usable, and defer everything that can wait.
  • Cumulative layout shift comes from content arriving after paint. Reserve dimensions for images, embeds, and any element that loads asynchronously, including cookie banners and chat widgets.
  • Third party scripts are consistently the largest single cost and the one nobody owns. Audit them quarterly, load them after interactive, and be willing to remove the ones nobody can name a purpose for.
  • Measure with field data from real users, not only with a lab tool on a fast connection. The lab score and the score that counts routinely disagree, and only one of them affects rankings.

The most effective performance work on a JavaScript site is almost always reducing how much JavaScript runs before the page becomes usable. Code splitting by route, deferring non critical components, and honestly reassessing which dependencies earn their weight will outperform any amount of image optimisation on a site that ships a large bundle.

Structured data on a component driven site

Schema markup on a traditional page is a block of JSON in the template. On a component driven application it is harder, because the data that belongs in the markup is spread across several components that render at different times, and the naive solution is for each component to emit its own fragment.

That produces duplicated and conflicting entities: three separate organisation declarations on one page, two of them incomplete. Assemble the structured data once at the route level, from the same data the page was rendered with, and emit a single graph. It is less elegant from a component ownership perspective and it is the only version that produces valid output.

Emit it server side, in the initial HTML. Structured data injected after hydration is frequently missed, and it is missed by exactly the crawlers that were already struggling with your JavaScript. Validate it in continuous integration rather than by pasting URLs into a testing tool occasionally, because markup silently breaks whenever someone refactors the component that fed it.

Internal linking, which frameworks make easy to get wrong

Internal links are how authority moves around a site and how crawlers discover what matters. On a component driven site the link graph is an emergent property of your component tree rather than something anyone designed, and the results are frequently poor.

The typical symptoms: important commercial pages reachable only through a search interface, deep content four or five clicks from anywhere, a footer carrying the entire link burden, and related content modules that pull randomly rather than by topic. Meanwhile the pagination component links to page fifty of an archive nobody will ever read, spending crawl budget generously on it.

Treat the link graph as something to design. Decide which pages are your priority set, ensure each is reachable within three clicks from the homepage through real anchors, and build related content modules that select by genuine topical relationship rather than by recency or randomness. Then crawl your own site and look at the graph, because the difference between the intended structure and the actual one is usually instructive.

Measuring the right things

Technical work needs verification or it is just activity. Four measurements tell you almost everything about whether a JavaScript site is healthy, and none of them is a ranking position.

  • Index coverage over time. How many of your pages are actually indexed, trending. A gap between submitted and indexed is the clearest signal that something structural is wrong.
  • Crawl statistics from server logs. Which pages are being fetched, how often, and how much budget is going to pages that cannot rank. Log analysis is unfashionable and it answers questions nothing else can.
  • Rendered versus raw comparison. Periodically diff what the server returns against what the browser produces. Growing divergence means content is drifting behind hydration.
  • Field performance by template. Aggregate Core Web Vitals per page type rather than per URL, because a regression usually arrives in a component shared by one whole template.

Put the first three into automated checks that run against production on a schedule and alert on movement. A deployment that accidentally breaks server rendering on one route is otherwise discovered weeks later, when the traffic decline is large enough for someone to investigate. This is the same regression discipline you would apply to anything else in production, and it belongs alongside your other platform monitoring rather than in a separate marketing tool nobody checks.

Migrations, where the traffic actually disappears

The single most expensive search event in a site's life is a replatform done without a redirect plan. We are called in to recover from these regularly, and the recovery always costs more than the prevention would have.

  1. 01Crawl the existing site completely before anything changes, and store the result. You cannot map what you did not record, and the old site stops being available the moment you launch.
  2. 02Map every old URL to exactly one new URL. Not to the homepage, which is treated as a soft failure and passes almost nothing, and not through a chain of two or three hops.
  3. 03Preserve titles, descriptions, headings, and structured data on the pages that already rank. A redesign that rewrites all the copy is two experiments at once, and when traffic moves you will not know which caused it.
  4. 04Launch the redirects at the same moment as the new site, tested beforehand against the recorded crawl rather than spot checked by hand.
  5. 05Monitor index coverage, crawl errors, and rankings daily for the first month. Most migration damage is recoverable if caught in week one and considerably harder after quarter one.

One additional note specific to modern frameworks. Trailing slash behaviour, case sensitivity, and query parameter handling frequently change between platforms, and each difference silently produces a duplicate URL space. Decide the canonical form explicitly, enforce it with a redirect at the edge, and verify that your sitemap, your internal links, and your canonical tags all agree on it.

Rendering for AI crawlers specifically

This is the newest section of this work and the one most sites have not addressed. The crawlers used by AI assistants are, as a group, considerably less capable than Googlebot. Several do not execute JavaScript at all. Others have short timeouts and will abandon a slow response rather than wait.

The practical consequence is that a site relying on client rendering may be adequately indexed by Google and completely invisible to the systems now answering a growing share of research queries. Serving complete HTML in the first response is no longer a Google optimisation, it is the price of entry to a second channel entirely.

Check your robots directives for the specific AI user agents rather than assuming, verify with a plain request that returns markup rather than a shell, and treat first byte content as a hard requirement on any page you want represented in an AI answer.

Why these problems keep being shipped

It is worth saying plainly that none of this happens because engineers are careless. It happens because the incentives during a build point elsewhere, and nobody in the room is accountable for the consequences that appear four months after launch.

A framework's defaults optimise for developer experience, which is a legitimate goal and not the same as crawlability. A component library optimises for reuse, which is why a button that navigates ends up not being an anchor. A product team optimises for the authenticated experience, where search visibility genuinely does not matter, and the marketing pages inherit the same architecture by default rather than by decision.

The organisational fix is small: put someone who understands search consequences in the architecture conversation, once, at the start. Not as a reviewer with a checklist afterwards, which produces a list of findings arriving into a full roadmap, but as a participant when the rendering strategy is chosen. That conversation takes an afternoon and routinely saves a quarter of remedial work.

Where that did not happen, the recovery sequence is the one below. It is entirely doable, and the reason we keep restating that these are engineering decisions is that the alternative framing, where SEO is something applied to a finished site, is what produced the problem in the first place.

Publishing consistently and still stuck?

The constraint is usually architectural rather than editorial. We will diagnose what is genuinely capping your visibility, rank the fixes by impact, and ship them into your codebase ourselves.

Get a technical audit

A pragmatic order of work

If you are looking at a long list of findings and wondering where to start, this is the sequence we use, and it is ordered by how much of the list becomes irrelevant once the earlier items are fixed.

  1. 01Confirm important pages return complete HTML with correct metadata in the first response. Everything else is secondary to this.
  2. 02Fix navigation so every important page is reachable by a real anchor within three clicks of the homepage.
  3. 03Resolve duplicate URL spaces: trailing slashes, case, parameters, and facets. One canonical form, enforced.
  4. 04Control crawl budget on large sites so attention goes to pages that can rank.
  5. 05Then performance, then structured data, then the long tail of individually small findings.

Notice that four of those five are architectural and were decided by engineers, usually for good reasons that had nothing to do with search. That is the honest summary of technical SEO on a JavaScript application: it is a set of engineering decisions with search consequences, made by people who were not thinking about search at the time, and it is fixed by engineers rather than by a report describing what they should have done.

Which is also the argument for involving someone who understands both sides during a platform build rather than after it. Every item on that list is close to free if decided at architecture time and expensive to retrofit into a shipped application, and the difference between those two costs is usually larger than the entire audit would have been.

V
Verensoft TeamGrowth Engineering

We build AI systems and custom software for businesses that want results, not decks. Questions about this article? Get in touch.

Brand Systems That Scale: Building an Identity That Survives Growth
Read next

Brand Systems That Scale: Building an Identity That Survives Growth

Chat on WhatsApp