[Next.js] ¿La causa de que OGP no aparezca fue la 'pantalla de carga'? Errores de implementación que matan el SEO y soluciones

[Next.js] ¿La causa de que OGP no aparezca fue la 'pantalla de carga'? Errores de implementación que matan el SEO y soluciones のビジュアル

¿Ha encontrado problemas en un sitio construido con Next.js como que 'OGP no aparece aunque es visible en el navegador' o 'no se indexa en Google'? La causa, de hecho, podría residir en 'cómo se implementa la pantalla de carga'.
En este artículo, explicaremos una historia de fracaso en la que se devolvió 'HTML vacío' a los rastreadores durante el SSR (Server-Side Rendering), un método de investigación usando el comando curl, y el patrón de implementación correcto con código.

  • 見えざるSEO事故ブラウザで正常でも、SSRの記述ミスによりクローラーにコンテンツが渡っていないケースがある
  • 調査の鍵はcurlブラウザの検証ツールではなく、curlコマンドでボット視点の「生のHTML」を確認することが重要
  • 条件付きレンダリングの罠認証チェックなどで安易に return を分けると、サーバー側でコンテンツ描画がスキップされる
  • 解決策はオーバーレイコンテンツを常にレンダリングしつつ、ローディング画面をCSSで前面に「重ねる」実装が正解

Introducción: ¿Un sitio web perfectamente funcional pero sin OGP?

Uno de los errores más aterradores en el desarrollo web es aquel en el que el sitio funciona perfectamente en el navegador, pero hay un problema fatal ocurriendo en segundo plano.

En esta ocasión, compartiré una experiencia real que tuve en un proyecto de Next.js: la historia de cómo un error de implementación en la pantalla de carga casi aniquila el SEO.

Si te enfrentas a síntomas como 'mi sitio hecho con Next.js no muestra el OGP' o 'no aparece el favicon en los resultados de búsqueda de Google', este artículo podría ser la clave para la solución.

Incidente: Código de estado 200 pero "no reconocido"

La construcción del sitio se completó y se desplegó en producción. Realicé pruebas de funcionamiento en el navegador. Las animaciones eran fluidas, la transición entre páginas rapidísima. Pensé: "Es perfecto".

Sin embargo, en el momento en que intenté compartirlo en redes sociales, noté algo extraño.

  • Aunque pegaba la URL en Twitter (X) o Facebook, la imagen OGP no se mostraba.
  • El favicon y la descripción nunca aparecían en los resultados de búsqueda de Google.

Al introducir la URL en la herramienta de depuración de Facebook, el código de estado HTTP devolvía 200 OK. El servidor estaba activo. Sin embargo, la información de título e imagen decía "no se pudo obtener".

Depuración errática: Días de dudar de la autenticación y el caché

Al principio, sospeché de la configuración de Next.js y Vercel.

  • "¿La autenticación de Vercel (como la autenticación básica) estaba activada por error?" → Lo verifiqué y estaba DESACTIVADA.
  • "¿El encabezado CSP (Content Security Policy) era demasiado estricto y bloqueaba los rastreadores?" → Lo deshabilité, pero no hubo cambios.
  • "¿Era solo que el caché del bot persistía?" → Accedí cambiando los parámetros de la URL, pero la situación no cambió.

Revisé los archivos de configuración y no encontré nada sospechoso. Estaba a punto de entrar en un laberinto sin salida.

Prueba decisiva: El mundo del "vacío" visto por el comando curl

"¿Por qué lo que veo en el navegador no lo ven los rastreadores?"

Volví al punto de partida y decidí ver el sitio "desde la perspectiva de un bot". Lo que me ayudó aquí no fue la herramienta de inspección del navegador, sino el comando curl ejecutado en el terminal.

Intenté acceder simulando el rastreador de Facebook (facebookexternalhit) con el siguiente comando.

Me quedé estupefacto al ver el HTML devuelto.

¡Estaba completamente vacío! No había título ni etiquetas OGP dentro del <head>, solo el texto "Loading...". Así, es imposible que los rastreadores entendieran el contenido del sitio.

La trampa que no se detecta solo con las herramientas de inspección del navegador

Normalmente tendemos a verificar el HTML con las "Herramientas de inspección (DevTools)" de Chrome, etc. Sin embargo, los navegadores modernos son inteligentes y muestran el DOM "después" de ejecutar JavaScript.

En cambio, muchos rastreadores (especialmente los bots que obtienen OGP) juzgan basándose en el primer HTML devuelto por el servidor (la respuesta inicial). Aquí residía una discrepancia fatal.

El verdadero culpable: Renderizado condicional durante el SSR

La causa fue la forma en que se escribió el renderizado condicional (Conditional Rendering) en _app.tsx, la raíz de la aplicación.

Al verificar el estado de autenticación, se había implementado una lógica para "mostrar solo la pantalla de carga durante la verificación" en un intento de mejorar la experiencia del usuario.

❌ Código del culpable

¿Por qué esto es incorrecto?

  1. Los hooks como useAuth o useEffect se ejecutan solo en el lado del cliente (navegador).
  2. En el momento del SSR (Renderizado del Lado del Servidor) de Next.js, isChecking procede con su valor inicial (por ejemplo, true).
  3. El servidor, siguiendo if (true), genera y devuelve una respuesta HTML que contiene solo <Preloader />.
  4. El rastreador recibe ese "HTML solo con el Preloader" y lo interpreta como "una página sin contenido", por lo que se va.

Aunque los humanos no lo notan en el navegador porque el JavaScript se ejecuta después y cambia al contenido, para los bots era "una página permanentemente en estado de carga".

Solución: "Superponer" en lugar de "alternar"

La solución era sencilla. Consistía en "renderizar siempre el contenido (Component) sin importar si está cargando o no". Además, se cambió la implementación para que la pantalla de carga se superpusiera (overlay) con CSS.

⭕️ Código correcto

Control con CSS (Preloader)

El componente Preloader se estiliza para cubrir toda la pantalla con propiedades como position: fixed; z-index: 9999;. De esta manera, se mantiene el comportamiento visual (el contenido no es visible durante la carga) mientras que, a nivel de estructura HTML, el contenido está presente.

Inmediatamente después de desplegar esta corrección, al verificar con el comando curl, el <title> y <meta property="og:image"> se mostraban correctamente, y la visualización en redes sociales se restableció con éxito.

Resumen: Tratar el SSR con una mentalidad de React puede matar el SEO.

Si estás acostumbrado al desarrollo de SPA (Single Page Applications) o solo con React, es frecuente usar la forma de "separar los return por condiciones". Sin embargo, en frameworks que incorporan SSR como Next.js, debes estar siempre consciente de "qué contiene el HTML inicial que devuelve el servidor".

Lecciones de esta experiencia:

  1. Precaución con el renderizado condicional: Asegúrate de que el contenido no se excluya durante el SSR.
  2. El comando curl es tu amigo: Para la resolución de problemas relacionados con SEO, acostúmbrate a verificar el HTML puro con curl en lugar de con el navegador.

Si te preocupa que "por alguna razón no aparece el OGP", intenta acceder a tu sitio desde el terminal una vez. Puede que encuentres un "vacío" inesperado.

Desarrollo práctico de aplicaciones web con TypeScript y React/Next.js [ Takuya Teshima ]

Desarrollo práctico de aplicaciones web con TypeScript y React/Next.js [ Takuya Teshima ]

参考リンク

¿Fue útil este artículo?