Mejores prácticas de SEO para aplicaciones de una sola página

Vadim Kravcenko
Vadim Kravcenko
· 6 min read

TL;DR: Las SPA rompen el SEO por defecto. Google pone en cola las páginas con JavaScript para renderizarlas — un proceso que puede tardar de horas a días— y los rastreadores de IA (GPTBot, ClaudeBot, PerplexityBot) ni siquiera ejecutan JavaScript. La solución es usar renderizado del lado del servidor con Next.js, Nuxt, Angular SSR o SvelteKit. Esta guía cubre la configuración exacta para cada framework, con código, pasos de prueba y el panorama del renderizado en 2026.

Las SPA tienen un problema de SEO — y es más grande de lo que crees

Las aplicaciones de una sola página cargan una sola carcasa HTML y luego la rellenan con JavaScript. El usuario obtiene una experiencia rápida, tipo app. Googlebot obtiene un <div id="app"></div> vacío.

Comparación entre renderizado de JavaScript del lado del cliente y del lado del servidor usando la analogía de una hamburguesa
Renderizado del lado del cliente vs. del lado del servidor: elegir el enfoque correcto para SEO. Fuente: Lumar
Diagrama que muestra cómo funciona el renderizado de JavaScript del lado del cliente en aplicaciones de una sola página
Cómo funciona el renderizado de JavaScript del lado del cliente y por qué causa problemas de SEO. Fuente: Lumar

He auditado cientos de SPA a través de SEOJuice. El patrón se repite: el sitio se ve precioso en el navegador, JavaScript corre perfecto y los motores de búsqueda no ven nada. O peor: ven el contenido días después, tras quedarse atascado en la cola de renderizado de Google. Solo el bug de URLs con hash en Angular les ha costado a clientes más tráfico orgánico que cualquier actualización de algoritmo que recuerde. Un cliente de ecommerce que usaba Angular con HashLocationStrategy tenía 1,200 páginas de producto. Google vio exactamente una página: la home. Todo lo que venía después del # era invisible. Eso no es una caída sutil en rankings. Eso es 60% de sus ingresos orgánicos evaporados por una configuración de enrutamiento que toma dos minutos arreglar una vez que sabes que existe.

Así funciona realmente el pipeline de renderizado de Google:

  1. Rastreo — Googlebot solicita tu URL y recibe la respuesta HTML en bruto
  2. Cola — Si la página necesita JavaScript, entra en una cola de renderizado
  3. Renderizado — El Web Rendering Service de Google (una instancia headless de Chromium) ejecuta JavaScript
  4. Indexación — El HTML ya renderizado se analiza para extraer contenido y enlaces

¿Esa cola entre el paso 2 y el paso 3? Puede tardar desde segundos hasta días. Tus competidores con HTML renderizado en el servidor se saltan la cola por completo: su contenido se indexa en el primer rastreo.

Y todavía hay más. En 2025, Vercel analizó más de mil millones de solicitudes de rastreadores y encontró que la mayoría de los rastreadores de IA no ejecutan JavaScript en absoluto. GPTBot, ClaudeBot, PerplexityBot: leen HTML en bruto, sin renderizar. Un análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia alguna de ejecución de JavaScript. Si tu SPA depende del renderizado del lado del cliente, tu contenido es invisible para los sistemas que impulsan ChatGPT, Claude y la búsqueda de Perplexity.

"Si tu sitio en Next.js entrega páginas críticas como SPA dependientes de JavaScript, esas páginas quedan fuera del alcance de los sistemas que determinan cómo la gente descubre información."

— Vercel Engineering Blog (fuente)

Este no es un problema de nicho. Si quieres que tu contenido sea descubierto tanto por Google como por los motores de búsqueda con IA en 2026, el renderizado del lado del servidor ya no es opcional: es un requisito.

CSR vs SSR vs SSG vs ISR — la decisión de renderizado

Hay cuatro formas de renderizar una aplicación de una sola página. La elección determina si los motores de búsqueda ven tu contenido de inmediato, más tarde o nunca.

EnfoqueCómo funcionaImpacto en SEOTiempo hasta el primer byteIdeal para
CSR (Client-Side Rendering)El navegador descarga una carcasa HTML vacía y JavaScript construye la páginaMalo — Google la pone en cola para renderizar y los rastreadores de IA no ven nadaRápido (pero vacío)Dashboards internos, paneles de administración, páginas autenticadas
SSR (Server-Side Rendering)El servidor genera HTML completo en cada solicitud y envía la página terminadaExcelente — contenido completo en el primer rastreoVariable (tiempo de procesamiento del servidor)Contenido dinámico: ecommerce, noticias, contenido generado por usuarios
SSG (Static Site Generation)Las páginas se generan por adelantado en el despliegue como HTML estáticoExcelente — carga más rápida y totalmente rastreableLa más rápida (servida desde CDN)Blogs, documentación, páginas de marketing, landing pages
ISR (Incremental Static Regeneration)Páginas estáticas que se regeneran según un horario o bajo demandaExcelente — velocidad de SSG con contenido frescoRápido (en caché con recompilación en segundo plano)Sitios grandes con contenido que cambia periódicamente (catálogos de productos, listados)

Conclusión clave

Cualquier página que quieras que Google o los motores de búsqueda con IA posicionen debe renderizarse en el servidor o generarse por adelantado. CSR está bien para páginas autenticadas y dashboards. Para todo lo público, usa SSR, SSG o ISR.

La regla es simple: si una URL necesita posicionarse en buscadores, debe entregar HTML completo en la respuesta inicial. Sin excepciones. Sin “pero Google ya renderiza JavaScript”. Google sí lo hace, pero a veces tarda, a veces falla y no es fiable; y los rastreadores de IA ni siquiera lo intentan. He tenido esta discusión con desarrolladores de frontend más veces de las que puedo contar. La conversación normalmente termina cuando les muestro su sitio en la herramienta URL Inspection de Google y ven una página en blanco donde debería estar su hermosa interfaz.

Guía por framework: React / Next.js

React puro (Create React App, Vite con React) es solo CSR. Google va a sufrir con eso. Next.js es la respuesta y, desde que App Router pasó a ser la opción predeterminada en Next.js 13+, la historia del SEO mejoró muchísimo.

React Server Components — el estándar por defecto en 2026

Con App Router, los componentes se renderizan en el servidor por defecto. Solo agregas 'use client' cuando un componente necesita APIs del navegador o interactividad. Eso significa que la mayor parte del contenido de tu página se entrega como HTML puro, sin necesidad de renderizar JavaScript.

// app/blog/[slug]/page.tsx — Server Component (default)
import { Metadata } from 'next'

// Dynamic metadata for each blog post
export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPost(params.slug)
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: 'article',
      publishedTime: post.publishedAt,
    },
    alternates: {
      canonical: `https://example.com/blog/${params.slug}`,
    },
  }
}

// This component runs on the server — zero JS shipped to the browser
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)

  return (
    <article>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  )
}

Generación estática con generateStaticParams

Para contenido que no cambia con frecuencia (posts de blog, landing pages), genera las páginas por adelantado durante la compilación:

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map((post) => ({ slug: post.slug }))
}

// Combined with the page component above,
// Next.js generates static HTML at build time for every post

ISR para catálogos grandes

Para sitios de ecommerce con miles de productos, usa ISR para revalidar páginas según un horario:

// app/products/[id]/page.tsx
export const revalidate = 3600 // Regenerate every hour

export default async function ProductPage({ params }) {
  const product = await getProduct(params.id)
  return <ProductDetail product={product} />
}

Si estás atrapado en React puro y no puedes migrar a Next.js, usa un servicio de prerenderizado como Prerender.io como solución temporal. Pero entiende que esto es cinta adhesiva, no una solución real. Cada mes que retrasas la migración es un mes de indexación subóptima.

Guía por framework: Vue / Nuxt 3

La misma historia, distinto ecosistema. Vue puro con Vue Router es solo CSR. Nuxt 3 te da SSR, SSG, ISR y edge rendering con Nitro: todo en un solo framework.

Renderizado universal (SSR por defecto)

Nuxt 3 usa renderizado universal desde el inicio. No necesitas configuración: tus páginas se renderizan en el servidor en la primera carga y luego se hidratan para la navegación del lado del cliente.

<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)

// Per-page SEO metadata
useHead({
  title: post.value.title,
  meta: [
    { name: 'description', content: post.value.excerpt },
    { property: 'og:title', content: post.value.title },
    { property: 'og:description', content: post.value.excerpt },
  ],
  link: [
    { rel: 'canonical', href: `https://example.com/blog/${route.params.slug}` }
  ]
})
</script>

<template>
  <article>
    <h1>{{ post.title }}</h1>
    <div v-html="post.content" />
  </article>
</template>

Renderizado híbrido — distintas estrategias por ruta

Las routeRules de Nuxt 3 te permiten mezclar estrategias de renderizado dentro de la misma app. Esto es potentísimo para sitios que tienen tanto páginas estáticas de marketing como contenido dinámico:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/':          { prerender: true },           // SSG — homepage
    '/blog/**':   { isr: 3600 },                 // ISR — blog posts regenerate hourly
    '/products/**': { ssr: true },               // SSR — dynamic product pages
    '/dashboard/**': { ssr: false },             // CSR — authenticated dashboard
  }
})

Edge rendering con Nitro

Nitro, el motor de servidor de Nuxt 3, soporta despliegue en plataformas edge (Cloudflare Workers, Vercel Edge, Netlify Edge). Eso significa que tus páginas SSR se renderizan en ubicaciones edge del CDN cercanas al usuario: un TTFB por debajo de 50ms es realista. Para SEO, eso significa cargas más rápidas, mejores Core Web Vitals y rastreos más frecuentes por parte de Google.

Guía por framework: Angular SSR

Históricamente, Angular ha sido el framework más difícil de optimizar para SEO. Eso cambió bastante desde Angular 17, que convirtió SSR en una capacidad de primera clase con soporte de hydration integrado. Ya no hace falta pegar Angular Universal como si fuera una ocurrencia de último minuto.

Cómo configurar SSR en Angular 17+

Los proyectos nuevos obtienen SSR por defecto cuando usas el CLI:

# New project with SSR enabled
ng new my-app --ssr

# Add SSR to an existing project
ng add @angular/ssr

Meta tags dinámicos con los servicios de Angular

// product-page.component.ts
import { Component, OnInit } from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-product-page',
  template: `
    <article>
      <h1>{{ product.name }}</h1>
      <p>{{ product.description }}</p>
    </article>
  `
})
export class ProductPageComponent implements OnInit {
  product: any;

  constructor(
    private meta: Meta,
    private title: Title,
    private route: ActivatedRoute,
    private productService: ProductService
  ) {}

  ngOnInit() {
    const id = this.route.snapshot.paramMap.get('id');
    this.productService.getProduct(id).subscribe(product => {
      this.product = product;
      this.title.setTitle(product.name);
      this.meta.updateTag({ name: 'description', content: product.description });
      this.meta.updateTag({ property: 'og:title', content: product.name });
    });
  }
}

Hydration incremental (Angular 19+)

Angular 19.2 introdujo hydration incremental, construyendo sobre la API @defer. Los componentes renderizan HTML completo en el servidor, pero solo se hidratan en el cliente cuando se activan (al entrar en viewport, al interactuar, etc.). Esto reduce el JavaScript enviado al navegador mientras mantiene todo el contenido SSR disponible para los rastreadores.

Trampa específica de Angular

El enrutamiento basado en hash (HashLocationStrategy) produce URLs como example.com/#/products. Google ignora todo lo que viene después del #. Tu catálogo de productos de 500 páginas parece una sola página. Cambia a PathLocationStrategy de inmediato: es la opción predeterminada en Angular, pero algunos proyectos legacy todavía usan hash routing. Este es exactamente el bug que le costó al cliente de ecommerce que mencioné arriba 60% de su tráfico orgánico. Llevaban dos años funcionando con hash routing. Dos años de páginas de producto que Google nunca supo que existían. El arreglo tomó 20 minutos. La recuperación tomó cuatro meses.

Guía por framework: SvelteKit

SvelteKit se ha convertido silenciosamente en uno de los mejores frameworks para SEO desde el inicio. SSR viene activado por defecto: tendrías que desactivarlo a propósito. El framework compila el framework fuera del resultado final, enviando mucho menos JavaScript que React o Angular.

SSR por defecto — sin configuración

Cada página de SvelteKit se renderiza en el servidor por defecto. Tus archivos +page.svelte generan HTML completo en la primera solicitud:

<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
  export let data;
</script>

<svelte:head>
  <title>{data.post.title}</title>
  <meta name="description" content={data.post.excerpt} />
  <link rel="canonical" href={`https://example.com/blog/${data.post.slug}`} />
</svelte:head>

<article>
  <h1>{data.post.title}</h1>
  {@html data.post.content}
</article>
// src/routes/blog/[slug]/+page.server.ts
export async function load({ params }) {
  const post = await getPost(params.slug);
  return { post };
}

Renderizado híbrido por ruta

Como Nuxt, SvelteKit te permite controlar el renderizado por ruta:

// src/routes/blog/[slug]/+page.ts
export const prerender = true;  // SSG — generate at build time

// src/routes/dashboard/+page.ts
export const ssr = false;       // CSR-only for authenticated content

Por qué SvelteKit merece atención para SEO: El compilador elimina el runtime del framework. Una página de SvelteKit envía una fracción del JavaScript que enviaría una página equivalente en Next.js o Nuxt. Menos JavaScript significa LCP más rápido, mejores puntuaciones de INP y Core Web Vitals más felices: todas señales de ranking.

Checklist SEO para SPA

Toda SPA debe pasar estas verificaciones. Están ordenadas por impacto: arregla primero los puntos de arriba.

#VerificaciónPor qué importaCómo solucionarlo
1SSR o SSG activado para todas las páginas públicasSin eso, Google pone tus páginas en cola y los rastreadores de IA no ven nadaNext.js App Router, Nuxt 3, Angular SSR o SvelteKit
2URLs limpias (sin fragmentos hash)Las URLs con hash (#/page) son invisibles para los motores de búsquedaUsa enrutamiento basado en history — la opción predeterminada en todos los frameworks modernos
3Title tag único por páginaEl mismo título en cada ruta hace que Google elija uno e ignore el restogenerateMetadata (Next.js), useHead() (Nuxt), servicio Meta (Angular), <svelte:head>
4Meta description única por páginaControla tu snippet en los resultados de búsquedaLas mismas librerías que para title tags — configúralo por ruta
5Canonical tags en cada páginaEvita problemas de contenido duplicado por query params y trailing slashesAgrega <link rel="canonical"> por página en tus metadatos
6Jerarquía correcta de headings (H1 > H2 > H3)Le indica la estructura del contenido a los rastreadoresUn H1 por página y anidación lógica en los componentes
7Los enlaces internos usan etiquetas reales <a href>La navegación solo con JavaScript (handlers onClick) bloquea a los rastreadoresUsa componentes Link del framework: <Link>, <NuxtLink>, routerLink
8XML sitemap enviadoAyuda a Google a descubrir páginas a las que no se llega mediante enlacesGenéralo con next-sitemap, nuxt-simple-sitemap o herramientas específicas del framework
9Code splitting y lazy loadingReduce el bundle inicial de JS, mejora LCP e INPImports dinámicos (next/dynamic, defineAsyncComponent, @defer)
10Schema markup (JSON-LD) en páginas claveActiva rich snippets y ayuda a los rastreadores de IA a entender el contenidoJSON-LD en <head> o <body> — renderizado en el servidor, no inyectado vía JS

Errores comunes de SEO en SPA — con ejemplos de código

Estos son los errores que veo en casi todas las auditorías de SPA. Todos y cada uno matan rankings.

Error 1: depender de CSR para páginas públicas

“¡Pero Google renderiza JavaScript!” Sí, a veces, con suerte, si tu JS no lanza un error, si la cola de renderizado no está saturada, si tu JavaScript no hace timeout y si ninguno de tus scripts de terceros interfiere con el renderizado. Son demasiados “si” como para apostar tu tráfico orgánico ahí. Y los rastreadores de IA ni siquiera lo van a intentar.

// WRONG — CSR-only React app
// Google sees: <div id="root"></div>
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);

// RIGHT — Next.js Server Component
// Google sees: fully rendered HTML with all content
export default async function Page() {
  const data = await fetchData();
  return <Article data={data} />;
}

Error 2: enrutamiento basado en hash

HashLocationStrategy de Angular y el modo hash de Vue Router producen URLs como example.com/#/products/shoes. Google ignora todo lo que viene después del #. Toda tu aplicación parece una sola página.

// WRONG — Vue Router hash mode
const router = createRouter({
  history: createWebHashHistory(),  // URLs: example.com/#/about
  routes
})

// RIGHT — Vue Router history mode
const router = createRouter({
  history: createWebHistory(),      // URLs: example.com/about
  routes
})

Error 3: el mismo title tag en cada página

Las SPA salen con un solo <title> en la carcasa HTML inicial. Si no lo actualizas dinámicamente por ruta, cada página tendrá el mismo título. Google indexará una versión e ignorará el resto.

<!-- WRONG — static HTML shell with one title -->
<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>  <!-- Same for every route -->
  </head>
  <body><div id="app"></div></body>
</html>

<!-- RIGHT — dynamic metadata per route (Nuxt example) -->
<script setup>
useHead({
  title: `${product.name} | MyStore`,
  meta: [{ name: 'description', content: product.summary }]
})
</script>

Error 4: errores de JavaScript que bloquean el renderizado

Un solo error no capturado en tu aplicación puede impedir que se renderice toda la página. El Web Rendering Service de Google no vuelve a intentarlo. La página se queda vacía en el índice.

Veo esto constantemente: un script de analytics de terceros lanza un error, o una respuesta faltante de la API rompe el árbol de componentes. ¿El resultado? Google indexa una página en blanco. Un cliente tenía un snippet de Hotjar que fallaba ocasionalmente en el renderer de Google. Sus páginas de producto aparecían aleatoriamente en blanco en la herramienta URL Inspection de GSC. La solución fue agregar un error boundary alrededor de la inicialización de analytics. Tomó 10 minutos. Llevaba meses dañando silenciosamente su indexación.

Solución: agrega error boundaries en React (componentes ErrorBoundary), usa NuxtErrorBoundary en Nuxt y prueba siempre con JavaScript desactivado (más sobre esto abajo).

Error 5: no tener sitemap

Las SPA con enrutamiento del lado del cliente no exponen su estructura de URLs mediante enlaces HTML como sí lo hacen los sitios multipágina. Sin un sitemap, Google descubre páginas solo a través de enlaces rastreables y, si tu enlazado interno depende de JavaScript, puede que no encuentre nada.

# Install next-sitemap for Next.js
npm install next-sitemap

# next-sitemap.config.js
module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
  changefreq: 'weekly',
  // Exclude routes that shouldn't be indexed
  exclude: ['/dashboard/*', '/api/*', '/admin/*'],
}

Error 6: bloquear JavaScript en robots.txt

Si tu robots.txt bloquea archivos CSS o JS, el renderer de Google no puede construir tu página. Lo vemos sorprendentemente seguido; normalmente por una configuración predeterminada que quedó olvidada.

# WRONG — blocking JS and CSS
User-agent: *
Disallow: /static/js/
Disallow: /static/css/

# RIGHT — allow all resources needed for rendering
User-agent: *
Disallow: /api/
Disallow: /dashboard/
Allow: /static/

Cómo probar el SEO de tu SPA paso a paso

Informe de auditoría de rendimiento de Google Lighthouse que muestra puntuaciones de rendimiento, accesibilidad, mejores prácticas y SEO
Un informe de auditoría de rendimiento de Lighthouse. Las SPA cargadas de JavaScript suelen obtener puntuaciones más bajas en métricas de rendimiento debido a la sobrecarga del renderizado del lado del cliente. Fuente: Shopify

No asumas que tu SPA es rastreable solo porque funciona en Chrome. Así es como verificas lo que realmente ven los motores de búsqueda.

Prueba 1: URL Inspection de Google Search Console

La herramienta URL Inspection es tu mejor diagnóstico individual. Ingresa cualquier URL y haz clic en “Test Live URL”. Google solicitará tu página, la renderizará con su Web Rendering Service y te mostrará el resultado.

Qué debes revisar:

  • Pestaña Screenshot — ¿Muestra tu contenido real o una página en blanco / spinner de carga?
  • Pestaña Rendered HTML — ¿Tu contenido está en el DOM? Busca cadenas de texto clave.
  • Pestaña More Info — Revisa errores de consola de JavaScript. Cualquier error no capturado puede significar que el renderizado falló.
  • Page resources — Verifica que ningún archivo crítico de JS/CSS esté bloqueado o devolviendo errores.

Prueba 2: ver el HTML sin JavaScript

Abre tu página con JavaScript desactivado en el navegador o usa curl para inspeccionar la respuesta inicial:

curl -s https://example.com/product/123 | head -100

Si no ves el contenido principal, tienes un problema. Para páginas públicas, el HTML inicial debe incluir el título, el cuerpo del contenido, enlaces internos y metadatos clave. Si lo único que ves es un contenedor vacío y varios scripts, sigues dependiendo de CSR.

Prueba 3: usar la prueba de resultados enriquecidos o una auditoría de Lighthouse

La prueba de resultados enriquecidos de Google te ayuda a confirmar si el HTML renderizado contiene tus datos estructurados. Lighthouse, por su parte, te da una lectura rápida de rendimiento, accesibilidad y SEO técnico. No es una herramienta de indexación (y no sustituye a Search Console), pero sí detecta señales obvias de que tu SPA está enviando demasiado JavaScript o retrasando el contenido visible.

Prueba 4: ejecuta una auditoría SEO completa

Nuestra herramienta gratuita de auditoría SEO escanea tu SPA en busca de problemas de renderizado, meta tags faltantes, enlaces rotos y problemas de accesibilidad. Te muestra exactamente lo que ven los motores de búsqueda: sin login, con resultados en 30 segundos.

Prueba 5: revisa el acceso de los rastreadores de IA

Dado que los rastreadores de IA no renderizan JavaScript, revisa si pueden acceder a tu contenido usando el AI Crawler Inspector. Simula cómo GPTBot, ClaudeBot y otros bots de IA ven tus páginas.

SEO para SPA en 2026: qué cambió

El panorama del SEO para SPA en 2026 es materialmente distinto al de hace apenas dos años. Esto es lo que importa.

React Server Components son la nueva opción predeterminada

Con Next.js App Router, los componentes se renderizan en el servidor por defecto. Tú eliges explícitamente el renderizado del lado del cliente con 'use client'. Esto invierte el modelo viejo: en lugar de que todo sea CSR con SSR pegado encima, todo es SSR con CSR agregado donde hace falta. Las implicaciones para SEO son profundas: la mayor parte de tu aplicación se entrega automáticamente como HTML puro.

El edge rendering ya está listo para producción

Nuxt 3 con Nitro, Next.js Edge Runtime y los adapters de SvelteKit ahora despliegan SSR en ubicaciones edge del CDN (Cloudflare Workers, Vercel Edge Functions). Tus páginas se renderizan en el nodo edge más cercano al usuario o al rastreador. Un TTFB por debajo de 50ms es alcanzable a nivel global.

Angular por fin tiene SSR de primera clase

Angular 17+ integró SSR en el CLI con ng new --ssr. Angular 19 agregó hydration incremental. Los días del doloroso setup de Angular Universal ya terminaron. Si todavía estás ejecutando una app Angular solo con CSR, el camino de migración ahora es bastante directo.

Los rastreadores de IA son un canal SEO real

GPTBot, ClaudeBot, PerplexityBot y otros están rastreando la web para construir datos de entrenamiento y alimentar la búsqueda con IA. Ninguno de ellos ejecuta JavaScript. El análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia de ejecución de JS. Si quieres que tu contenido aparezca citado en respuestas generadas por IA, SSR es la única opción.

"Ver HTML renderizado, no solo el código fuente, es importante para diagnosticar si hay un problema de indexación. Google solo puede descubrir tus enlaces si son elementos HTML <a> con un atributo href."

— Martin Splitt, Developer Advocate at Google (source)

Core Web Vitals siguen importando

LCP, INP y CLS siguen siendo señales de ranking. Las SPA que envían bundles grandes de JavaScript son penalizadas en LCP (la página tarda demasiado en mostrar contenido significativo) e INP (las interacciones se sienten lentas). Code splitting, lazy loading y JavaScript mínimo del lado del cliente no son opcionales: son requisitos de rendimiento que impactan directamente los rankings.

"Pre-renderizar tu sitio de forma estática o en el servidor es la mejor práctica para SEO: hace que los rastreadores estén más dispuestos a reindexar tu sitio con mayor frecuencia."

— Vercel Engineering Blog (fuente)

Comparación rápida de frameworks

¿No tienes claro qué framework elegir? Así se comparan específicamente para SEO.

FunciónNext.js (React)Nuxt 3 (Vue)Angular SSRSvelteKit
SSR por defectoSí (App Router)Sí (desde v17)
Generación estáticagenerateStaticParamsprerender: trueng build --prerenderexport const prerender = true
Soporte para ISRIntegrado (revalidate)Integrado (isr: seconds)Manual vía service workerVía configuración específica del adapter
Edge renderingVercel Edge, CloudflareNitro (multiplataforma)LimitadoMúltiples adapters
API de metadatos por páginagenerateMetadatauseHead()Meta + servicios Title<svelte:head>
JavaScript del cliente enviadoModerado (RSC ayuda)ModeradoPesadoMínimo (compilado fuera)
Comunidad/ecosistemaLa más grandeSólidoEnfocado en enterpriseCreciendo rápido

Preguntas frecuentes

¿Google puede rastrear aplicaciones de una sola página?

Sí, pero con matices. El Web Rendering Service de Google usa un navegador headless Chromium para ejecutar JavaScript y renderizar SPA. Sin embargo, ese renderizado ocurre en una cola separada después del rastreo inicial, lo que puede retrasar la indexación de horas a días. Las páginas con errores de JavaScript pueden no renderizarse nunca. Para una indexación confiable, usa SSR o SSG; no dependas de la cola de renderizado de Google para contenido sensible al tiempo.

¿Una aplicación de una sola página es mala para SEO?

Una SPA solo con CSR sí es mala para SEO. Una SPA con renderizado del lado del servidor no lo es. El framework no importa: lo que importa es si la respuesta HTML inicial contiene tu contenido. Next.js, Nuxt, Angular SSR y SvelteKit producen SPA totalmente rastreables. El problema de “SPA vs. SEO” se resolvió hace años; el problema real son los desarrolladores que no implementan la solución.

¿Necesito renderizado del lado del servidor para una app en React?

¿Para cualquier página que necesite posicionarse en buscadores? Sí. React por sí solo (vía Vite o Create React App) es solo CSR: los motores de búsqueda ven una página vacía. Next.js agrega SSR, SSG e ISR. Con React Server Components en App Router, la mayoría de los componentes se renderizan en el servidor por defecto. Si tu app en React sirve contenido público, Next.js es la solución estándar.

¿Cómo manejan las SPA los motores de búsqueda con IA?

No lo hacen. GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot y otros rastreadores de IA no ejecutan JavaScript. Solo analizan HTML en bruto. El análisis de más de medio billón de solicitudes de GPTBot no encontró evidencia de renderizado con JavaScript. Si tu contenido se renderiza del lado del cliente, es invisible para los motores de búsqueda con IA. SSR es la única forma de aparecer en respuestas y citas generadas por IA.

¿Cuál es la diferencia entre SSR, SSG e ISR?

SSR (Server-Side Rendering) genera HTML en cada solicitud: ideal para contenido dinámico. SSG (Static Site Generation) genera HTML durante la compilación: es lo más rápido, pero requiere nuevas compilaciones cuando cambia el contenido. ISR (Incremental Static Regeneration) genera páginas estáticas que se regeneran automáticamente según un horario: combina la velocidad de SSG con contenido fresco. Los tres entregan HTML completo a los motores de búsqueda en la primera solicitud. Elige según la frecuencia con la que cambia tu contenido.

En resumen

Las SPA no son inherentemente malas para SEO. Pero las SPA solo con CSR sí lo son y, en 2026, también son invisibles para los motores de búsqueda con IA.

La solución existe desde hace años. Next.js, Nuxt 3, Angular SSR y SvelteKit entregan HTML renderizado en el servidor desde el primer momento. React Server Components mejoró todavía más la configuración predeterminada: la mayor parte de tu app se renderiza automáticamente en el servidor. No hay excusa para lanzar una SPA pública sin renderizado del lado del servidor.

Si no estás seguro de si tu SPA es rastreable, haz una auditoría gratuita: toma 30 segundos y te muestra exactamente lo que ve Google. Para visibilidad ante rastreadores de IA, revisa el AI Crawler Inspector.

Lecturas relacionadas:

SEOJuice
Stay visible everywhere
Get discovered across Google and AI platforms with research-based optimizations.
Works with any CMS
Automated Internal Links
On-Page SEO Optimizations
Get Started Free

no credit card required

More articles

No related articles found.