Skip to content
7 min lectura Desarrollo Web

JavaScript SEO: React, Next.js, Vue and the errors that kill your traffic

JavaScript SEO: React, Next.js, Vue and the errors that kill your traffic

JavaScript SEO: React, Next.js, Vue and the errors that kill your traffic

Modern JavaScript has transformed the way we build web experiences. Frameworks like React, Next.js, Vue, and Nuxt allow us to create fast, dynamic, and visually appealing interfaces. But there's a problem many development teams discover too late: what the user sees isn't necessarily what Google indexes.

In our experience with over 300 technical SEO projects, we've seen how brilliantly developed sites lose up to 70% of their organic traffic due to avoidable errors in JavaScript implementation. This article covers the most frequent pitfalls and the concrete solutions we apply for each framework.

SSR vs CSR: the decision that defines your visibility

Before diving into specific errors, it's crucial to understand the difference between Server-Side Rendering (SSR) and Client-Side Rendering (CSR), because that's where it all begins.

With CSR, the server sends a practically empty HTML — a root div and a JavaScript bundle — and the user's browser is responsible for rendering all the content. The problem is that Googlebot, although it can execute JavaScript, does so in a second wave of indexing that can take days or even weeks. In the meantime, Google sees an empty page.

With SSR, the server generates the complete HTML before sending it to the browser. Googlebot receives the final content from the very first moment, without waiting for any JavaScript execution. This means immediate indexing, correct metadata, and complete content from the crawler's first visit.

  • Pure CSR (React SPA, Vue SPA): High risk of indexing issues. Only recommended for private applications or dashboards.
  • SSR (Next.js with App Router, Nuxt 3): Content available to crawlers from the first request. The safest option for SEO.
  • SSG (Static Site Generation): HTML pre-generated at build time. Ideal for content that doesn't change frequently.
  • ISR (Incremental Static Regeneration): Combines the best of SSG and SSR. Static pages that regenerate on demand.

How Googlebot renders JavaScript (and its real limitations)

Google uses a version of Chromium to render JavaScript, but with significant restrictions that many developers are unaware of:

  • Rendering queue: JavaScript rendering is not immediate. Pages enter a queue and can take hours or even weeks to be processed.
  • No user interaction: Googlebot doesn't click, doesn't scroll, doesn't trigger hover events. Content that relies on user interaction is invisible to the crawler.
  • Time limit: If your JavaScript takes more than 5 seconds to render, Googlebot may abandon the page with incomplete content.
  • No local storage: localStorage, sessionStorage, and session cookies are not available between crawls.
  • Crawl budget: Each page with heavy JavaScript consumes more crawl budget resources than a page with static HTML.

The 7 most common errors that destroy organic traffic

1. Meta tags rendered client-side only

This is, by far, the most frequent and most damaging error. If your title, meta description, and Open Graph tags are injected via JavaScript on the client, Googlebot may not see them in the first indexing wave. We have audited sites where 100% of the snippets in Google showed the default template title instead of the actual title of each page.

Solution: Ensure all meta tags are rendered on the server. In Next.js App Router, use the metadata object or the generateMetadata function in your layouts and pages. In Nuxt 3, use useHead() or useSeoMeta() within the component's setup.

2. Aggressive lazy loading on above-the-fold content

Lazy loading is an excellent technique for improving performance, but applying it to content that appears on the first visible screen is counterproductive. We have seen e-commerce sites where main product images and H1 titles were lazy-loaded, resulting in a disastrous LCP (Largest Contentful Paint) and content that Google didn't always capture.

Solution: Never apply lazy loading to images, text, or elements that are above the fold. In Next.js, use priority on the Image component for main images. Reserve lazy loading for content that appears when scrolling.

3. Content loaded after user interaction

Tabs, accordions, "view more" buttons, and content that only appears after a click: Googlebot will not interact with these elements. If your most valuable content is behind an interaction, it is hidden from the search engine.

Solution: Render all content in the initial HTML and use CSS to control visibility. Content in accordions and tabs must be present in the DOM from the start.

4. URLs dependent on hash or client state

Routes with a hash (#/products/shoes) or that depend on the browser's state are not crawlable by Google. Every URL you want to index must be accessible with a direct HTTP request.

5. Dynamically generated canonical tags incorrectly implemented

When the canonical tag is generated client-side, it can point to incorrect URLs during the first crawl wave. On sites with pagination or filters, this causes large-scale duplicate content issues.

6. Sitemaps pointing to pages that require JavaScript

It's useless to have a perfect sitemap if the URLs it contains return an empty HTML to the crawler. Google will discover them, visit them, see a skeleton, and categorise them as pages without content.

7. Hydration mismatch errors

When the server's HTML does not match what the JavaScript generates on the client, hydration errors occur. This can cause the content to be completely re-rendered on the client, losing the benefit of SSR.

Framework-specific guide

Next.js with App Router

  • Use Server Components by default. Only mark components as ‘use client’ if they genuinely need interactivity.
  • Implement generateMetadata for dynamic meta tags on each route.
  • Use generateStaticParams to pre-generate product or category pages.
  • Configure revalidate for ISR according to your content update frequency.
  • Next.js middleware runs at the edge: use it for redirects and hreflang, not for content.

Nuxt 3

  • Enable SSR by default in nuxt.config.ts (it comes enabled, but many disable it for convenience).
  • Use useFetch or useAsyncData instead of fetch calls in onMounted: the former execute on the server.
  • Implement useSeoMeta to manage meta tags cleanly and server-side.
  • Nuxt routes with prerender: true in routeRules generate static HTML at build time.

React SPA without an SSR framework

If you have a pure React SPA with React Router and cannot migrate to Next.js, your options are:

  • Pre-rendering with services like Prerender.io: Generates HTML snapshots for crawlers. Functional but adds complexity and cost.
  • Progressive migration to Next.js: This is the most profitable long-term investment.
  • React Server Components with a custom setup: Possible but complex to maintain without a framework.

Why ZDS builds with Astro

For our own projects and those of clients where SEO performance is a priority, we use Astro with SSR. Astro sends zero JavaScript to the browser by default, renders everything on the server, and allows integrating React, Vue, or Svelte components only where interactivity is needed. The result is perfect Core Web Vitals performance and immediate indexing without any additional tricks.

It's not that other frameworks are bad — Next.js and Nuxt are excellent tools — but they require careful configuration for SEO. Astro eliminates most of these problems by design.

Final Checklist: JavaScript SEO in 2026

  • Verify that your server-rendered HTML contains all content, meta tags, and links.
  • Use View Source (not Inspect Element) to see what Google receives.
  • Test your URLs with the Google Search Console URL Inspection tool.
  • Monitor the Crawl Stats report to detect rendering issues.
  • Ensure your sitemap only contains URLs that return complete HTML.
  • Avoid lazy loading on above-the-fold content.
  • Check that canonical tags are generated on the server.

JavaScript SEO is not a separate discipline: it's technical SEO applied to the reality of modern web development. If your technology stack isn't aligned with indexing requirements, no content or link strategy will compensate for the traffic you're leaving on the table.

Is your JavaScript website not performing on Google as it should? At ZDS, we've been solving exactly these types of problems for over a decade. Discover our technical SEO services or contact our team for an audit of your implementation.

Tip: Use server-side rendering (SSR) for critical content. Search engines have improved with JS but are not perfect.
Need help?Our team will analyse your situation and propose a personalised plan. Request a free consultation →

¿Necesitas ayuda con tu estrategia?

Nuestro equipo analiza tu situación y te propone un plan personalizado. Sin compromiso.

Solicitar consulta gratuita
Manuel Riveiro

Manuel Riveiro

CEO & Digital Strategist — ZDS

20+ años de experiencia en SEO, performance marketing y herramientas de IA. Fundador de ZDS y B2 Performance, con sede en Barcelona y Herdecke.