SEO for React: What Actually Works (and What Quietly Breaks)

seo for react

SEO for React is mostly a rendering problem, not a keyword problem. A plain React app built with Create React App or a bare Vite setup ships an almost empty HTML file and paints everything with JavaScript in the browser — which means the first thing a crawler often sees is a blank <div id="root">. Get the rendering right and the rest of SEO for React looks like SEO anywhere else. Get it wrong and no amount of good content will save you.

This guide is specific to React: where you genuinely control URLs, titles, and page speed, where the framework fights you, and the highest-leverage fixes that move rankings instead of just feeling productive.

The core problem: client-side rendering

Default React renders on the client. The server returns a shell, then the browser downloads your bundle, runs it, and builds the DOM. Google can execute JavaScript, so a well-built single-page app often does get indexed eventually — but it goes into a slower render queue, spends crawl budget you didn’t need to spend, and any bot that doesn’t run JS well (many AI crawlers, social preview scrapers, older tooling) sees nothing.

The honest fix isn’t a plugin. It’s moving rendering off the client. That means server-side rendering (SSR) or static generation (SSG), usually through a framework like Next.js, Remix, or Astro, or a build-time prerender step for a smaller site. If you’re starting a content-driven React project today and care about search, start on Next.js or Astro rather than retrofitting SSR onto Create React App later — the retrofit is real work. A quick test tells you where you stand: open your live page, view source, and look for actual paragraphs. If all you see is a script tag and an empty root element, every crawler that skips JavaScript sees the same nothing, and that is the first thing to fix.

Titles and meta tags: you control them, but not by default

React has no built-in concept of a document head, so every page in a naive SPA inherits the same <title> and meta description from index.html. That’s the most common React SEO mistake: fifty routes, one title. You get full control back, but you have to add it.

On plain React, use react-helmet-async to set a unique title, meta description, canonical, and Open Graph tags per route. The catch: Helmet writes those tags with JavaScript, so they only help crawlers that render. On Next.js App Router, use the built-in metadata export or generateMetadata so tags are in the server HTML from the first byte — this is strictly better for SEO and you should prefer it. Whichever you use, make canonical tags explicit; React apps are prone to duplicate URLs from trailing slashes and query params.

URLs and routing: real routes, not just history state

React Router gives you clean paths like /blog/react-seo, but in an SPA those are illusions — the server only really has index.html, and the router fakes the rest with the History API. That’s fine for users and fine for Google once rendered, with two hard requirements. First, your host must serve index.html for every path (a catch-all rewrite) or deep links return a real 404. Second, avoid hash routing (/#/blog/post) — search engines treat everything after the # as the same URL, so hash routes are effectively one page to Google. Use browser/history routing, not hash routing.

Redirects are another place the SPA model bites. A client-side redirect done inside a component is not a 301 — the crawler has already loaded the old URL and no link equity transfers. Real redirects have to happen at the server or CDN edge (Next.js redirects(), a Vercel or Netlify config, or your host’s rules). Never redirect purely in React and expect it to consolidate ranking signals.

Page speed: the JavaScript is the problem

React’s SEO tax is weight. Ship one big bundle and Largest Contentful Paint suffers, Interaction to Next Paint suffers, and Core Web Vitals — a real ranking input — drag. Even with SSR, hydration means the browser re-runs your component tree to attach interactivity, so a heavy app can paint fast and still feel sluggish while it hydrates.

The moves that actually help are concrete: code-split by route with React.lazy and dynamic import() so a visitor downloads one page’s code, not the whole app; audit your bundle and cut heavy dependencies (a date library or animation package can outweigh your content); serve images through a real image pipeline rather than raw <img> tags; and lean on server components in the Next.js App Router to keep interactive JavaScript off pages that don’t need it. Measure with Lighthouse and field data, not vibes — synthetic scores lie about hydration cost.

Structured data and the crawl basics

Structured data works fine in React as long as it reaches the crawler. Inject JSON-LD as a script tag through your head manager or, better, render it server-side so it’s in the initial HTML — an Article, Product, or FAQ block that only appears after hydration is a coin flip for rich results. The same rule covers your fundamentals: your sitemap.xml should be generated at build time and list real, server-reachable URLs, and robots.txt must not block the JavaScript and CSS bundles Google needs to render the page. Blocking your own /static/ assets is a classic self-inflicted React wound.

A React SEO checklist

Run this before you call a React build search-ready.

  • Rendering — SSR, SSG, or prerender in place; “View Source” shows real content, not an empty root div.
  • Titles & meta — unique title, description, and canonical per route, ideally in server HTML.
  • Routing — history routing (no hashes); server serves a catch-all so deep links don’t 404.
  • Redirects — handled server/edge as 301s, never client-side only.
  • Speed — route-level code splitting, trimmed bundle, optimized images, healthy Core Web Vitals.
  • Structured data — JSON-LD present in the initial response.
  • Crawl — build-time sitemap, robots.txt allows JS/CSS assets.

Where SEO Rocket fits

Once rendering is fixed, the work becomes ordinary SEO, and that’s where the tooling earns its keep. SEO Rocket’s site audit crawls your deployed React app and flags the exact failures above — missing or duplicate titles, thin server HTML, blocked assets, slow pages — so you’re checking what a bot really sees, not what your dev server shows you.

Site Explorer in SEO Rocket — a full domain profile: Domain Rating, organic traffic and backlinks.
Site Explorer in SEO Rocket — a full domain profile: Domain Rating, organic traffic and backlinks.

From there you can ask, in plain language, for the keyword gaps against your competitors, track how your fixes move rankings over the following weeks, and draft the content those newly-crawlable pages need. Because search is splitting toward AI answers, the Brand Radar view also shows whether your React pages get cited in tools like ChatGPT and Perplexity — surfaces that punish client-only rendering hardest, since many of their crawlers don’t run your JavaScript at all.

The bottom line

React can rank as well as any stack, but only after you stop shipping a blank page. Move rendering to the server, give every route its own head tags and a real URL, keep the bundle lean, and put structured data in the first response. Do those five things and you’ve handled the 80% of SEO for React that most sites get wrong — then let your content and links do the rest.

Questions? Chat with us