El periódico provincial digital llevaba más de una década online. No era un medio grande, pero tampoco era pequeño: información municipal, deportes locales, agenda cultural, sucesos. Una redacción activa, varias publicaciones al día y una plataforma editorial desarrollada a medida por una agencia de la zona allá por 2011. El sistema funcionaba. Nadie lo tocaba si no hacía falta. Y precisamente por eso, nadie lo miraba.
El aviso llegó de forma indirecta. El responsable de contenidos notó que algunos artículos de las secciones de cultura y agenda dejaban de aparecer en Google dos o tres días después de publicarse, justo cuando más tráfico deberían atraer. No era una caída general. El resto del sitio funcionaba con normalidad. Pero esas páginas concretas parecían desvanecerse. La etiqueta canonical existía en el HTML de cada artículo, eso estaba claro. El problema era que nadie sabía a dónde apuntaba realmente.
Aquí había ruido, pero no era ruido cualquiera. Si las páginas tenían canonical implementado y el contenido era original, Google no debería tratarlas como copias de nada. Algo en esa instrucción estaba torcido, pero antes de asumir lo más obvio, necesitaba ver los datos.

Operario: Serpion
Expediente del caso: La etiqueta canonical que mentía
Empresa o negocio: Periódico digital provincial
Archivado en: Indexación
Nivel: Intermedio
Lo que la etiqueta canonical decía y lo que Google estaba leyendo
Lo primero fue cuantificar el problema. Abrí el informe de cobertura en Google Search Console y filtré por el estado de duplicados. El resultado: 53 URLs afectadas, concentradas casi en su totalidad en las secciones de cultura, agenda y ocio. La sección de deportes, noticias de municipio y sucesos no mostraba ningún estado similar. Eso me decía algo importante desde el principio: no era un problema global del sitio. Era algo específico de esas secciones.
Antes de ir al código, quise descartar la hipótesis más inmediata. El periódico tenía una versión imprimible de cada artículo, accesible desde un parámetro en la URL del tipo ?formato=impresion. Si el rastreador de Google hubiera llegado a esas variantes y las hubiera tomado como versiones alternativas del mismo contenido, podría haber generado los duplicados que veía en Search Console. Era una hipótesis técnicamente sólida para un medio de esa antigüedad.
Revisé los logs del servidor durante los últimos 45 días filtrando las visitas de Googlebot a URLs con ese parámetro. El bot había accedido a algunas de ellas, sí, pero en proporciones muy bajas y únicamente en las secciones de deportes y sucesos, que eran exactamente las secciones que no tenían el problema. Las URLs afectadas de cultura y agenda no mostraban visitas de Googlebot con ese parámetro. La hipótesis se caía. El origen no iba por ahí.
El problema no estaba en lo que Google encontraba al rastrear. Estaba en la instrucción que el sitio le daba después de entrar.
Lancé entonces un rastreo con Screaming Frog limitado a las 53 URLs en estado de duplicado. Exporté los valores del campo canonical de cada una y los comparé con sus propias URLs. Lo que salió en la hoja de cálculo me hizo detenerme un momento.
Muestra extraída del rastreo — URLs afectadas vs. canonical declarado
URL rastreada:
/cultura/exposicion-fotografica-convento-agosto-2024
Canonical en el HTML:
/agenda/feria-medieval-septiembre-2024
---
URL rastreada:
/agenda/mercado-artesania-plaza-mayor
Canonical en el HTML:
/cultura/ciclo-teatro-otono-programa
---
URL rastreada:
/cultura/concierto-banda-municipal-parque
Canonical en el HTML:
/agenda/verbena-barrio-norte-horariosLos canonicals no apuntaban a variantes de las mismas URLs. Apuntaban a artículos completamente distintos dentro del propio sitio, sin ninguna relación temática entre sí. Una exposición fotográfica señalando a una feria medieval. Un mercado de artesanía apuntando a un ciclo de teatro. Desde el punto de vista de Google, cada uno de esos artículos le estaba diciendo: «no me indexes a mí, indexa este otro». Y Google, obediente, hacía exactamente eso.
Por qué la etiqueta canonical apuntaba a artículos que no tenían nada que ver
Con esa evidencia sobre la mesa, la pregunta dejaba de ser «¿hay un problema de etiqueta canonical?» y pasaba a ser «¿quién o qué está escribiendo esos valores?». La plataforma editorial generaba los canonicals de forma automática a través de un módulo de plantilla. Nadie los introducía a mano. Lo que significaba que el error no era puntual: era sistemático y estaba reproduciendo ese mismo fallo en cada artículo nuevo publicado en esas secciones.
Que una etiqueta exista en el HTML no garantiza que su valor sea correcto. Esa diferencia, que parece obvia, es exactamente la que hace que este tipo de error pase desapercibido durante meses.
Los datos del rastreo confirmaban el patrón con suficiente claridad como para pasar al siguiente nivel: inspeccionar cómo la plataforma construía esos valores internamente.
El módulo que llevaba meses escribiendo mal su propia instrucción
Accedí al panel de administración de la plataforma editorial con el equipo técnico del periódico. El sistema de gestión de contenidos había sido desarrollado a medida y llevaba funcionando desde 2011 con actualizaciones parciales a lo largo de los años. El módulo responsable de generar el bloque <head> de cada artículo incluía una función específica para construir el campo canonical.
Esa función no tomaba la URL del artículo que se estaba renderizando. Consultaba una tabla de configuración interna donde cada sección del sitio tenía asignada una URL de referencia para el canonical. La lógica original pretendía generar automáticamente el valor del canonical a partir de una tabla de configuración interna. Sin embargo, la implementación nunca llegó a utilizar la URL del propio artículo como canonical, sino una URL de referencia almacenada para cada sección. Era un planteamiento incorrecto desde el origen, aunque permaneció oculto mientras la configuración interna siguió siendo coherente.
El problema apareció cuando, hacía aproximadamente dieciséis meses, el equipo creó dos nuevas subsecciones —cultura y agenda— separando lo que antes era una única sección llamada «ocio y cultura». Al añadir esas subsecciones en el panel, alguien insertó las entradas en la tabla de configuración con los IDs de sección intercambiados. Cultura apuntaba a la URL de referencia de agenda, y agenda apuntaba a la de cultura.
Tabla de configuración interna — estado durante el período afectado
| ID sección | Nombre sección | URL canonical de referencia asignada |
|------------|----------------|---------------------------------------------|
| 14 | cultura | /agenda/feria-medieval-septiembre-2024 | ← incorrecto
| 15 | agenda | /cultura/ciclo-teatro-otono-programa | ← incorrectoPero había un segundo nivel de daño. La URL de referencia no era fija. El módulo la actualizaba automáticamente cada vez que se publicaba un artículo nuevo en esa sección, apuntando al último artículo publicado como referencia. Eso significaba que el canonical de todos los artículos de cultura apuntaba al artículo más reciente de agenda, y viceversa. Y ese valor cambiaba con cada publicación, de modo que en cada nueva pasada de rastreo, Google se encontraba con una instrucción distinta para las mismas URLs, acumulando confusión en el índice con el tiempo.
El resultado era una cadena de señales contradictorias que se renovaba sola. Cada artículo nuevo que entraba en esas secciones no solo estaba mal declarado: también actualizaba el destino incorrecto al que apuntaban todos los artículos anteriores. Google recibía instrucciones distintas cada vez que volvía a rastrear las mismas páginas. No estaba ante contenido duplicado real. Estaba ante un sitio que le pedía, de forma constante y equivocada, que redistribuyera la prioridad de indexación entre artículos sin ninguna relación entre sí.
Las páginas de cultura y agenda no estaban perdiendo visibilidad porque su contenido fuera débil. Estaban perdiendo visibilidad porque el sitio les ordenaba a Google que mirara a otro lado.
Reescribir la instrucción sin desestabilizar lo que sí funcionaba
El alcance del problema estaba claro: la tabla de configuración tenía los IDs cruzados, el módulo actualizaba el valor dinámicamente con cada publicación, y 53 artículos ya tenían canonicals erróneos registrados en el índice de Google. La corrección tenía que actuar en dos frentes: la fuente del error y las páginas ya afectadas.
Cuánto tocar y por dónde empezar sin abrir otro frente
La tentación inicial del equipo técnico era intervenir directamente en la lógica del módulo y cambiar el comportamiento completo de la función: en lugar de consultar la tabla de referencia, que el canonical de cada artículo apuntara a su propia URL. Era la solución más limpia a largo plazo y técnicamente la más correcta. El problema era el riesgo de ejecución: ese módulo afectaba al <head> de todos los artículos del sitio, no solo de las secciones con el error. Un fallo en el despliegue podía introducir canonicals vacíos o mal formados en cientos de páginas que en ese momento estaban indexadas correctamente.
Hacer ese cambio de golpe, en un sitio con publicación diaria y sin entorno de preproducción documentado, era asumir un riesgo desproporcionado al problema que se quería resolver.
Así que la decisión fue otra: corregir primero los valores de la tabla de configuración para que cada sección apuntara a su propia URL de portada, y además desactivar el comportamiento dinámico que sobreescribía ese valor con cada nueva publicación. Ese segundo ajuste era imprescindible: sin él, el módulo seguiría actualizando la referencia con el último artículo publicado, aunque ahora dentro de la sección correcta. El resultado no sería un canonical autorreferente —cada artículo apuntando a sí mismo— sino un canonical estable que señalaba a la portada de su sección.
No era la solución ideal, pero sí era coherente y predecible. Google recibiría una instrucción consistente en lugar de una que cambiaba con cada publicación. La refactorización completa del módulo, para que cada artículo generara su propio canonical autorreferente, quedaba para la segunda fase.
Esa segunda fase era importante, pero no urgente. Detener el daño activo era lo primero.
Una vez aplicadas las dos correcciones —los IDs de la tabla y la desactivación del comportamiento dinámico— todos los artículos nuevos publicados en cultura y agenda empezaron a generar la etiqueta canonical apuntando de forma estable a la portada de su propia sección. No era un canonical autorreferente, pero era consistente y correcto: Google dejaba de recibir una instrucción diferente en cada visita y empezaba a leer una señal que no se movía.
Para la supervisión continua, se configuró un rastreo programado semanal con Screaming Frog sobre los últimos 30 artículos publicados en cada sección, verificando que el valor del canonical coincidía con la URL de portada asignada a esa sección. Cualquier desviación respecto a ese valor esperado activaría una alerta antes de que el problema pudiera volver a acumularse. La comprobación de autorreferencia —que cada artículo apuntara a su propia URL— quedaba pendiente para después de la segunda fase, una vez refactorizado el módulo. Supervisar algo distinto a lo que el sistema estaba produciendo habría generado falsas alarmas en cada rastreo.
Cuatro semanas después de la corrección, el estado «Duplicada, Google ha elegido una versión canónica diferente a la del usuario» había desaparecido en 48 de las 53 URLs. Las cinco restantes correspondían a artículos publicados durante el período de mayor frecuencia de actualización dinámica, que Google tardaba más en re-rastrear. Sin intervención adicional, ese número siguió bajando solo en las semanas siguientes.
Una corrección que no tiene supervisión posterior es una corrección que puede volver a romperse en silencio. Eso no cambia aunque el origen del error quede resuelto.

💡 Qué he aprendido
Este caso me dejó algo claro que antes tenía a medias: verificar que una instrucción de canonicalización existe en el HTML no es lo mismo que verificar que funciona. Durante meses, el periódico tenía una declaración canonical en cada artículo. Todo parecía correcto desde fuera. Pero el valor que contenía esa instrucción era incorrecto, y eso era lo único que importaba para Google. Aprendí a exportar siempre los valores reales antes de asumir que la implementación es correcta.
También aprendí algo sobre los sistemas a medida: el código desarrollado hace años para un contexto concreto no desaparece cuando ese contexto cambia. Sigue ejecutándose. Sigue escribiendo HTML. Y si nadie lo revisa cuando el proyecto crece o cambia su estructura, sigue generando señales que ya no corresponden a la realidad del sitio. En este expediente, el error no era técnicamente complejo. Era invisible porque nadie había mirado dentro del módulo que generaba el campo canonical desde que se crearon las nuevas subsecciones.
Desde entonces, cualquier reorganización de secciones o categorías en un sitio con canonicals dinámicos entra directamente en mi lista de puntos a auditar. No como precaución genérica, sino porque ya sé lo que ocurre cuando esa revisión no se hace.
Bitácora de Serpion
Analista Digital
🧩 Notas del caso
⬋⬋
Periódico digital provincial con plataforma editorial a medida, activa desde 2011. Tras crear dos nuevas subsecciones hace dieciséis meses, 53 artículos de cultura y agenda aparecieron en Search Console con el estado «Duplicada, Google ha elegido una versión canónica diferente a la del usuario». El contenido era original y el sitio publicaba con normalidad, por lo que el problema pasó desapercibido durante meses.
La causa fue una tabla de configuración interna con los IDs de las dos subsecciones intercambiados, lo que provocaba que el módulo de canonicals generara declaraciones que apuntaban a artículos de la sección contraria, actualizando ese valor con cada nueva publicación. La corrección consistió en reescribir los valores de la tabla y establecer supervisión automática sobre los canonicals de nuevas publicaciones.
🔎 Pistas SEO extraídas del caso
⬋⬋
- 53 URLs en estado «Duplicada, Google ha elegido una versión canónica diferente a la del usuario» concentradas exclusivamente en las secciones de cultura y agenda, sin afectar al resto del sitio.
- El valor del canonical en cada artículo afectado apuntaba a un artículo publicado recientemente en la sección contraria, sin relación temática entre ambos.
- El valor del canonical cambiaba con cada nueva publicación, porque el módulo actualizaba la referencia dinámicamente al último artículo de la sección asignada.
- Los logs del servidor descartaron la hipótesis de parámetros de versión imprimible: Googlebot no accedía a esas variantes en las secciones afectadas.
- El error se originó dieciséis meses antes de la detección, coincidiendo con la creación de las subsecciones de cultura y agenda en el panel de administración.
🚫 Errores SEO detectados en el caso
⬋⬋
- IDs de sección intercambiados en la tabla de configuración: al crear las subsecciones, las URLs de referencia quedaron asignadas a las secciones equivocadas, generando canonicals cruzados desde el primer artículo publicado.
- Canonical dinámico sin validación de destino: el módulo actualizaba el valor automáticamente sin comprobar que la URL de referencia correspondía a la sección del artículo que se estaba publicando.
- Ausencia de auditoría tras reorganización de secciones: ningún proceso de revisión técnica acompañó la creación de las nuevas subsecciones, dejando el error sin detectar durante meses.
- Sin supervisión de valores canonical en producción: el equipo comprobaba la presencia de la etiqueta en el HTML, pero no el valor que contenía ni si ese valor era coherente con la URL de la página.
- Señales de indexación redistribuidas de forma involuntaria: cada artículo nuevo publicado en cultura o agenda reforzaba el canonical incorrecto de todos los artículos anteriores de esa sección, amplificando el daño progresivamente.
📘 Glosario SEO del expediente
⬋⬋
- Etiqueta canonical: instrucción en el HTML que indica a Google cuál es la URL preferida cuando varias páginas tienen contenido igual o muy similar.
- Canonical dinámico: valor de canonical generado automáticamente por el sistema a partir de una variable o tabla de referencia, en lugar de un valor fijo introducido de forma manual.
- Duplicada, Google ha elegido una versión canónica diferente a la del usuario: estado de Search Console que salta cuando el sitio sí declara un canonical, pero Google decide ignorarlo y agrupar la URL bajo otra que considera más relevante.
- Tabla de configuración interna: estructura de base de datos que almacena parámetros de comportamiento del sistema, como las URLs de referencia para la generación automática de canonicals por sección.
- Señal de indexación: cualquier instrucción o dato que Google recibe de un sitio para decidir cómo rastrear, interpretar o priorizar sus páginas en el índice.
📏 Mini guía práctica
⬋⬋
- Exporta siempre los valores reales del campo canonical con un rastreador antes de asumir que la implementación es correcta: verifica que cada URL apunta a sí misma o a su versión preferida declarada.
- Tras cualquier reorganización de secciones o creación de nuevas categorías, audita inmediatamente los canonicals generados en los primeros artículos publicados en esas secciones.
- Si tu sistema genera canonicals dinámicamente desde una tabla de configuración, revisa esa tabla cada vez que añadas nuevas secciones o cambies la estructura del sitio.
- Configura un rastreo programado semanal sobre los últimos artículos publicados para comparar el valor del canonical con la URL de la página y detectar desviaciones antes de que se acumulen.
- Separa la corrección urgente (detener el daño activo) de la refactorización completa del módulo: actuar en dos fases reduce el riesgo de introducir nuevos errores en páginas que ya funcionan correctamente.
Deja una respuesta
La migración de staging a URLs antiguas · WordPin 004
5 juegos educativos de código web y SEO: Forensic Game
Expedientes y Archivos