What does Google say about SEO? /

Official statement

To properly manage errors in a single-page app, the server must be configured to respond with an appropriate error code for specific URLs (for example, /not-found returns a 404, /maintenance returns a 500), and then use JavaScript to redirect to the designated error URL.
4:47
🎥 Source video

Extracted from a Google Search Central video

⏱ 5:53 💬 EN 📅 14/10/2020 ✂ 8 statements
Watch on YouTube (4:47) →
Other statements from this video 7
  1. Can JavaScript really manage the entire lifecycle of a Single Page App for SEO?
  2. 2:05 How can you prevent indexing errors linked to code paths that Googlebot might reject?
  3. 2:38 What happens when Googlebot consistently misses your pages if the URL never changes?
  4. 2:38 How can you ensure your single-page app is crawlable by Google without losing its indexing?
  5. 3:09 Why does Google emphasize unique titles and meta descriptions for each view?
  6. 4:02 Why does sending a HTTP 200 on your errors sabotage your crawl budget?
  7. 4:47 Do JavaScript redirections to error pages really trigger an error signal for Googlebot?
📅
Official statement from (5 years ago)
TL;DR

Google states that a SPA must configure the server to return appropriate HTTP error codes (404, 500) on specific URLs, and then redirect via JavaScript to these error URLs. In practical terms, this means that client-side rendering is not enough: the server must communicate the error to the crawler. This hybrid server-side/client-side approach remains the only method validated by Google for Googlebot to understand that a page is truly in error within a SPA architecture.

What you need to understand

Why do HTTP codes matter so much in SPA architecture?

Single-page applications pose a fundamental challenge to crawling: everything happens on the client side. Googlebot arrives, loads the page, executes the JavaScript, and discovers... that there is nothing. However, without an explicit HTTP signal, the bot interprets this as a blank page with a 200 code.

This is not a theoretical problem. A poorly managed 404 error can remain indexed as a blank page, dilute crawl budget, and pollute the index. Google needs a server confirmation that the URL is dead — not just a JavaScript-rendered message saying 'Page not found'.

What method does Martin Splitt recommend?

The solution involves configuring the server to respond with the correct HTTP code on dedicated URLs. For example: /not-found returns a 404, /error returns a 500. Then, JavaScript redirects the user to this URL when it detects an error.

Specifically, if a user types /non-existent-article, the server loads the SPA (200 code), the JS detects that the article does not exist, and redirects to /not-found where the server returns a true 404. Googlebot follows this redirect and correctly logs the 404.

Are all SPA architectures affected by this?

Yes, as soon as we talk about client-side routing: React Router, Vue Router, Angular Router, etc. The issue is the same everywhere. If your SPA generates URLs dynamically without going through the server, you need to implement this hybrid logic.

SSR frameworks (Next.js, Nuxt, SvelteKit) handle this natively by rendering server-side with the correct HTTP code. But for a classic SPA with create-react-app or a standard Vite build, it’s up to you to connect server and client.

  • The server must be configured to return specific HTTP codes on dedicated URLs (/not-found, /error, etc.).
  • The JavaScript must redirect the user to these URLs when an error is detected on the client side.
  • Googlebot follows the redirect and interprets the HTTP code returned by the server, not the JS rendering.
  • This approach applies to any SPA with client-side routing, unless you use an SSR framework that natively manages HTTP codes.
  • Without this configuration, a 404 page may risk being indexed as a blank page with a 200 code.

SEO Expert opinion

Is this statement consistent with field practices observed?

Yes, and it’s even one of the few areas where Google is explicitly clear on SPAs. We regularly observe React or Vue sites with hundreds of 404s indexed as blank pages. The pattern of redirecting to a dedicated server URL is the only documented solution that works 100% of the time.

That said, the statement remains silent on alternatives. What about dynamic rendering with Puppeteer that injects a status code? What about meta refreshes or client-side 302 redirects? Google doesn’t say anything, so be cautious. [To verify] if other patterns are tolerated in practice.

What limitations or side effects should be anticipated?

The JavaScript redirect to a dedicated server URL has a cost: you break the browsing history. If a user types a dead URL, is redirected to /not-found, and then clicks 'Back', they return to /not-found, not the original URL. This can disrupt UX.

Another point: this logic requires maintaining two layers — server and client — in coherence. If your server returns a 404 on /not-found but your JS never redirects to that URL, you have an invisible dead-end. And if your JS redirects to /error but the server returns a 200, Googlebot logs a 200.

Finally, this approach only works if Googlebot executes the JavaScript and follows the redirect. If the JS crashes, if the redirect loops, or if the server is misconfigured, everything collapses. Test in Search Console with the 'URL Inspection' tool before deploying.

In which cases is this method not sufficient?

If you have soft 404 errors (empty content but not technically in error), this method does not resolve them. Google can still index a blank page if the server returns a 200 and the JS loads a component without content.

Similarly, if you want to manage transient server errors (503 during maintenance), the JS redirection is not enough: the server must return a 503 directly on the original URL, without going through a redirection. Otherwise, Googlebot interprets this as a permanently dead page.

Practical impact and recommendations

What exactly needs to be configured on the server?

First step: create dedicated routes for each type of error. For example, /not-found with a 404 code, /error with a 500 code, /maintenance with a 503. On Nginx, it looks like this:

location /not-found { return 404; }
location /error { return 500; }

On Apache, you use ErrorDocument directives or RewriteRule with the [R=404] flag. The goal is simple: force the server to return the correct status code without relying on JS rendering.

How to connect JavaScript redirection in the SPA?

In your client-side router, you detect the error (non-existent route, missing data) and redirect to the server URL. With React Router, it looks like:

if (!data) { window.location.href = '/not-found'; }

Be careful: use window.location.href, not navigate() or history.push(). These methods stay client-side and do not force the server to return the HTTP code. You want a full reload that passes through the server.

What technical errors should be absolutely avoided?

Never redirect to a URL that returns a 200 with an error message. This is the classic trap: your server loads the SPA on /not-found, the SPA displays '404', but the server returned a 200. Googlebot indexes this as a valid page.

Another mistake: not testing with the URL Inspection tool in Search Console. The desktop rendering may work, but the mobile rendering can fail if the JS doesn’t load. Check both.

Finally, don’t forget about temporary server errors. If your API is down, you want a 503, not a redirect to /error. Otherwise, Googlebot may permanently deindex the page.

  • Create dedicated server routes (/not-found, /error, /maintenance) that return the appropriate HTTP codes (404, 500, 503).
  • Use window.location.href to force a full redirection, not navigate() or history.push().
  • Test with the URL Inspection tool in Search Console on both Desktop AND Mobile.
  • Ensure that the server returns the correct HTTP code on the destination URL, not a 200 with an error rendering.
  • Distinguish between permanent errors (404) and temporary errors (503) to avoid accidental deindexing.
  • Monitor server logs for unhandled 500 errors that could pollute the crawl.
This hybrid server/client configuration is the only method officially validated by Google to manage errors in a SPA. It requires maintaining strict coherence between client routing and server configuration. If your infrastructure is complex or if you don’t have control over the server, it may be wise to consult a specialized SEO agency to implement this architecture without breaking UX or introducing SEO regressions.

❓ Frequently Asked Questions

Est-ce que je peux juste afficher un message 404 en JavaScript sans rediriger ?
Non. Googlebot verra un code 200 et indexera une page vide. Le serveur doit renvoyer le code HTTP approprié, pas juste le rendu JS.
Quelle différence entre window.location.href et navigate() dans React Router ?
window.location.href force un rechargement complet qui passe par le serveur. navigate() reste côté client et ne déclenche pas de requête HTTP, donc pas de code 404.
Est-ce que cette méthode fonctionne pour les erreurs 503 temporaires ?
Oui, mais il faut que le serveur renvoie un 503 directement sur l'URL d'origine, sans redirection JS. Sinon, Googlebot peut désindexer la page définitivement.
Les frameworks SSR comme Next.js ou Nuxt ont-ils ce problème ?
Non, ils gèrent nativement les codes HTTP côté serveur. Mais si tu utilises le mode export statique de Next.js, tu retombes dans le même problème qu'une SPA classique.
Comment vérifier que Googlebot voit bien le code 404 ?
Utilise l'outil d'inspection d'URL de Search Console. Vérifie le code HTTP retourné et le rendu HTML final. Si c'est un 200, la config est cassée.
🏷 Related Topics
Domain Age & History AI & SEO JavaScript & Technical SEO Domain Name

🎥 From the same video 7

Other SEO insights extracted from this same Google Search Central video · duration 5 min · published on 14/10/2020

🎥 Watch the full video on YouTube →

Related statements

💬 Comments (0)

Be the first to comment.

2000 characters remaining
🔔

Get real-time analysis of the latest Google SEO declarations

Be the first to know every time a new official Google statement drops — with full expert analysis.

No spam. Unsubscribe in one click.