Guides
React SEO Checklist: Making a React App Indexable
React is not bad for SEO. Client-side-only rendering is risky for SEO, and React happens to be the most common way people end up there.
Run a fresh DomainLens audit and use the report as your priority list.
Is React SEO-friendly?
The framework is neutral. What matters is what the server sends: a React app rendered on the server delivers complete HTML and behaves like any other site, while a client-rendered one sends an empty div and asks the crawler to run JavaScript to find out what the page is.
Google does render JavaScript, so the second case is not hopeless. It is simply dependent — on the render pass completing, on every resource loading, and on no script erroring midway. Server rendering removes that dependency entirely, which is the whole argument.
| Setup | First-pass HTML | Risk |
|---|---|---|
| Create React App / Vite SPA | Empty shell | High — everything depends on rendering |
| React with SSR | Complete | Low |
| Static generation | Complete | Lowest |
| React Server Components | Complete for server parts | Low |
| SPA with prerendering service | Complete for bots | Works; adds a dependency |
What actually breaks in a client-rendered React app
The soft 404 case is the most damaging and the least visible: every typo, every stale link, every probe from a bot returns a valid-looking 200 page, and Google slowly fills its crawl budget with URLs that were never real.
- Title and meta tags set by a client-side head manager, which may be evaluated after indexing decisions.
- Navigation built from onClick handlers or divs instead of anchors — nothing for a crawler to follow.
- Routes that return 200 with the app shell for URLs that do not exist, producing unbounded soft 404s.
- Content behind a data fetch that fails or times out during the render pass.
- Structured data injected by a component, arriving too late to be read.
The checklist
- 1Render the page server-side or generate it statically. Everything below is easier once this is true.
- 2Put the title, description, canonical and robots directives in the server HTML — never only in a client-side head manager.
- 3Make every navigational element a real anchor with an href. A Link component that renders an anchor is fine; a div with a click handler is not.
- 4Return a genuine 404 status for unmatched routes, from the server, rather than rendering a not-found component with a 200.
- 5Emit structured data server-side alongside the content it describes.
- 6Verify by fetching the URL with curl and reading what comes back before any JavaScript runs.
# What Googlebot indexes on the first pass
curl -s https://example.com/product/42 | head -c 1500
# An empty root div means everything depends on rendering
curl -s https://example.com/product/42 \
| grep -E '<div id="root"></div>'
# Are the links crawlable?
curl -s https://example.com/ | grep -oE '<a [^>]*href="[^"]+"' | head
# Does a nonexistent route return 404, or a 200 shell?
curl -sI https://example.com/definitely-not-a-page | head -n 1
React Helmet and the head-management problem
React Helmet and its successors manage the document head from within components. On the client that works. Whether it works for search depends entirely on whether the head is rendered on the server too — the same library used with SSR produces complete tags in the initial HTML, and used in an SPA produces tags that appear only after hydration.
That is why "we use Helmet" is not an answer to whether metadata is indexable. The question is where it runs, not which library it is.
If you cannot server-render
Sometimes the architecture is fixed. Prerendering — serving a static snapshot to crawlers while users get the app — works, and Google supports it while describing it as a workaround. Whatever you choose, the verification is the same: fetch the URL without JavaScript and see what a crawler sees. See JavaScript SEO for how rendering works and technical SEO for JavaScript sites for the framework-agnostic version.
How DomainLens contributes
DomainLens reads the served HTML — the first pass, before rendering — and reports whether the title, canonical, robots directives, content and links are present in it. For a React app that is the single most useful signal there is: if the audit finds an empty page that looks complete in your browser, the diagnosis is finished. See the Next.js checklist when the answer is a framework with rendering built in.
- Is React bad for SEO?
- No. Client-side-only rendering is risky, and React is a common route to it. Server-rendered or statically generated React is indistinguishable from any other site.
- Can Google index a Create React App site?
- Usually yes, after the render pass. It is slower and more fragile than server rendering, and any blocked resource or script error costs the whole page.
- Do I need React Helmet for SEO?
- You need the metadata in the server HTML. Helmet achieves that with SSR; in a client-only app it produces tags that arrive after the initial index.
- How do I return a real 404 from a React app?
- The server must send it. A component rendering a not-found message inside a 200 response is a soft 404 no matter what it displays.