Skip to content
Searchpedia SEO field notes Callum Bennett Callum

Site ops

React SEO

If you are building a React site that depends on organic traffic, server-side rendering is your only safe bet for getting indexed properly.

Beginner5 min readUpdated 2026-07-27Notes by Callum Bennett

What I’d do first

  • Use server-side rendering or static generation for all public pages that need indexing.
  • Ensure every indexable route has a unique title tag, meta description, and canonical URL.
  • Switch from hash-based routing to HTML5 History API for clean, crawlable URLs.
  • Add JSON-LD structured data to help search engines understand your page content and earn rich results.

The path I'd take

I start by deciding which pages in the React app actually need search traffic. For public pages — blog posts, product listings, landing pages — I use server-side rendering (SSR) or static site generation (SSG). Next.js makes this straightforward, and the [JavaScript SEO](/javascript-seo/) guide from Google explains the trade-offs well. For anything behind a login or a dashboard, I keep client-side rendering (CSR) because those pages don't need indexing. Then I check each route: every indexable URL must have a unique title tag, meta description, and a [canonical tag](/canonical-tag/) pointing to itself. I also switch from hash-based routing to HTML5 History API so URLs look normal. Next, I generate an [XML sitemap](/sitemap/) that lists only the indexable routes and submit it via Search Console. I add [JSON-LD structured data](/schema-markup/) for each page type — Article, Product, FAQ — which helps with rich results. Finally, I focus on performance: code splitting routes with React.lazy, compressing images, and ensuring [Core Web Vitals](/core-web-vitals/) pass. I also make sure navigation links are standard <a> tags, not buttons with onClick handlers, so crawlers can follow them.

For a recent e-commerce client, the legacy React app was CSR-only. The homepage loaded but product pages had empty initial HTML. After switching to SSR with Next.js, indexation rose from 35% to 92% in two weeks. The key change was that product titles and prices were now in the initial response. I also implemented dynamic imports for the review carousel and image zoom, cutting the main bundle from 400KB to 180KB. LCP dropped from 6.2 seconds to 2.1 seconds. That directly improved organic click-through rates.

My choice for any SEO-reliant React page is SSR or SSG. CSR is fine for account pages, but for public content it introduces unnecessary risk. I also prefer SSG for content that doesn't change often — it saves server costs and is even faster than SSR.

Watch-outs

The biggest watch-out is assuming Google will render your CSR app the same way a browser does. Googlebot renders JavaScript lazily, after parsing the HTML, and it may not execute all scripts, especially for deep pages with low crawl priority. I use the URL Inspection tool in Search Console to check what Google sees. If the rendered HTML is empty or missing key content, indexing will fail. I have seen this happen on sites with lazy-loaded components that depend on user interaction to appear. Another common mistake: handling routing with hash fragments (e.g., /#/product/123). Hash fragments are not sent to the server and are often ignored by search engines. Use HTML5 History routes instead.

Watch out for missing or duplicate meta tags. In a React app, if you use a single <HelmetProvider> and forget to set unique values per route, every page could inherit the same title. I use react-helmet-async and ensure each route has its own useEffect or Helmet call. Also, be careful with 404 handling. In CSR, a missing route might render a 200 page with an error message. That confuses crawlers. I set up server-side 404 status codes for invalid routes.

Performance is another watch-out. Large bundle sizes delay the first render. I use Webpack Bundle Analyzer to find heavy dependencies and replace them with lighter alternatives. For example, swapping Moment.js for date-fns saved 200KB. Also, watch out for third-party scripts injecting content that shifts layout — that hurts CLS. I defer non-critical scripts.

Finally, mobile rendering matters. Google's mobile-first indexing uses a mobile user agent. Test your React app on a real mobile device and in Chrome DevTools with network throttling. If the mobile experience breaks, rankings will suffer.

What I got wrong

I got the rendering strategy wrong for two years. When I first started with React SEO, I believed the 'Google can execute JavaScript now' line verbatim. I built a marketing site with full CSR and hash routing. After launch, only the homepage appeared in search results. I waited three months — still no product pages. I used the URL Inspection tool and saw empty renders. That forced me to learn SSR. I migrated to Next.js static generation and saw indexation reach 100% within a month. I should have tested the rendering before launch instead of assuming.

I also ignored structured data initially. I thought it was a nice-to-have, not a priority. Then a client asked why competitors had star ratings in search results and they did not. After adding JSON-LD with aggregateRating and review fields, the client saw a 15% increase in click-through rate within weeks. Now I add structured data to every project from day one.

Another mistake: I prioritised code splitting but neglected server-side rendering. I thought lazy loading components would be enough to reduce initial load time. But without SSR, the initial HTML was still a blank shell, so the browser had to download and execute the entire React app before displaying anything meaningful. LCP remained high. Only when I moved critical content into the server-rendered HTML did LCP drop significantly. I now treat SSR as the foundation, not an afterthought.

I also failed to set proper canonical tags in an early project, causing duplicate content issues when pages were accessible via multiple URL parameters. A quick [SEO audit](/seo-audits/) revealed hundreds of indexed duplicates. Adding canonicals cleaned that up in weeks.

Next step

Quick answers

Does Google index client-rendered React content?

Yes, but unreliably. Googlebot renders JavaScript in a second wave, which may not happen for all pages, especially those with low crawl budget or deep links. For critical pages, server-side rendering ensures the content is present in the initial HTML immediately.

Do I need Next.js for React SEO?

No, but it helps. Alternatives include Gatsby (static sites), Remix, or custom SSR with Express and React. Next.js provides the easiest path with built-in SSR, SSG, and incremental static regeneration. I would pick Next.js unless you have strong reasons to customise.

How do I choose between SSR and SSG?

Use SSR for pages with frequently changing content, like e-commerce product pages or user-generated content. Use SSG for content that updates less often, like blog posts or documentation. SSG is faster and cheaper but requires a rebuild when content changes. Next.js allows both per route for hybrid sites.

Sources

Primary documentation is linked directly. Anything commercial is marked nofollow.

  • Google Search Central — Primary source for Google indexing, rendering, and sitemap guidance.
  • JavaScript SEO basics — Best reference for how Google handles JavaScript-rendered pages and when SSR helps.
  • SEO Starter Guide — Strong guidance on titles, content structure, links, and crawlable architecture.
  • Core Web Vitals — Explains Core Web Vitals metrics that affect React performance and SEO.

Notes from Callum Bennett.