WordPin archivo 008, analizando un tema hijo en WordPress que heredaba noindex en las páginas de cursos

El tema hijo de WordPress que heredaba noindex · WordPin 008

🎧 Escuchar: El tema hijo de WordPress que heredaba noindex · WordPin 008

La academia llevaba meses funcionando sin sobresaltos. Cursos publicados, fichas de profesores, landing de captación, blog con artículos semanales. Todo indexado, todo accesible, todo respondiendo como se esperaba. El tráfico orgánico crecía de forma estable y las URLs nuevas aparecían en Google en pocos días. No había razón para sospechar de nada.

El problema empezó justo después de activar un tema hijo para personalizar ciertas plantillas sin modificar el tema principal. Dos semanas más tarde, varias páginas de cursos habían desaparecido de los resultados de búsqueda. No todas: algunas seguían posicionadas con normalidad. El sitio no mostraba errores visibles, las páginas cargaban correctamente y el panel de WordPress no lanzaba ningún aviso. Pero Google había dejado de indexar contenido que antes sí recogía.

La caída no fue brusca. Fue lenta, parcial y silenciosa. Exactamente el tipo de síntoma que tarda en notarse y que, cuando se nota, ya lleva tiempo activo. La primera pregunta era directa: ¿qué había cambiado? Y la respuesta obvia era el tema. Pero lo obvio no siempre es lo real.

Representa un sello en estado abierto del archivo de WordPin 008
Ficha del archivo Nº: 008

Operario: WordPin

Archivo del caso: El tema hijo de WordPress que heredaba noindex

Empresa o negocio: Academia online con cursos indexables

Archivado en: Plugins, temas y conflictos

Nivel: Intermedio

El tema hijo y las páginas que Google dejó de ver

Lo primero que hice fue comprobar el estado de indexación desde Google Search Console. Las URLs afectadas aparecían como rastreadas pero no indexadas, y en varios casos el motivo era explícito: la página contenía una directiva noindex. El patrón no era aleatorio. Las URLs excluidas correspondían mayoritariamente a páginas de cursos individuales y a algunas páginas de archivo de categorías de formación.

Revisé el plugin SEO activo. Era la primera sospecha lógica, porque es el lugar donde normalmente se gestiona la visibilidad de cada tipo de contenido. Pero la configuración estaba limpia: los cursos tenían permitida la indexación, las categorías también, y no había reglas globales que aplicasen noindex a ningún tipo de entrada. Revisé también la configuración por URL individual en varias de las páginas afectadas, y todas mostraban index, follow como valor activo.

Esto no encajaba.

La pista que apuntaba a los ajustes de lectura

WordPress tiene una opción en Ajustes > Lectura que permite disuadir a los motores de búsqueda de indexar el sitio. Es una casilla que inyecta una meta etiqueta noindex global. Fui directamente a comprobarlo, porque más de una vez he visto esa casilla activada por error tras una migración o un cambio de entorno.

La casilla estaba desmarcada. Además, para confirmar, ejecuté una consulta rápida contra wp_options:

SELECT option_value FROM wp_options WHERE option_name = 'blog_public';

El resultado era 1, lo que significaba que WordPress no estaba bloqueando la indexación desde sus ajustes generales. Segundo descarte limpio. El sitio, desde su configuración interna, quería ser visible.

Abrí entonces las herramientas de desarrollo del navegador y fui al <head> de una de las páginas afectadas. Y ahí estaba la señal que no debería estar:

<meta name="robots" content="noindex, follow">

La etiqueta existía en el HTML renderizado. No venía del plugin SEO, no venía de los ajustes de lectura, pero estaba ahí. La pregunta ya no era si existía un noindex, sino quién lo estaba inyectando. Que una página cargue bien no significa que esté enviando las señales correctas a los buscadores.

Lo que el tema hijo escondía en sus cabeceras

Activé Query Monitor para inspeccionar lo que se estaba ejecutando durante la carga. Su panel de Hooks & Actions lista todos los hooks disparados en la petición en orden cronológico, y para cada uno muestra los callbacks registrados, su prioridad y el componente que los originó. Al localizar la entrada de wp_head dentro del listado y revisar sus callbacks, había uno que no procedía ni del plugin SEO ni del core: el componente apuntaba directamente al tema hijo activo, con prioridad 1.

En ese momento, la sospecha dejó de ser difusa. Pero antes de confirmar nada, necesitaba ver el código.

Un fragmento heredado que nadie había revisado

Accedí por FTP al directorio del tema hijo y abrí su functions.php. El archivo no era largo, apenas unas funciones de personalización visual y un par de filtros para el menú principal. Pero entre ellos había un bloque que no tenía relación con la apariencia del sitio:

add_action( 'wp_head', function() {
    if ( is_singular( 'curso' ) || is_tax( 'categoria_curso' ) ) {
        echo '<meta name="robots" content="noindex, follow">';
    }
}, 1 );

Esa función anónima se ejecutaba en cada carga de página y comprobaba si la URL correspondía a un curso individual o a una taxonomía de categoría de curso. Si se cumplía la condición, inyectaba directamente una meta etiqueta noindex en el <head>. Sin filtro intermedio, sin opción de sobreescritura, sin relación con el plugin SEO.

El fragmento no era nuevo. Al revisar el historial del archivo, el bloque había sido copiado del tema padre durante la creación del child theme. En su momento, el tema padre lo usaba como medida temporal para ocultar contenidos en fase de pruebas. Cuando se creó la plantilla derivada, alguien copió el functions.php completo en lugar de partir de un archivo limpio, y ese fragmento viajó con él sin que nadie lo detectase.

El plugin SEO configuraba las meta robots correctamente, pero el fragmento del tema activo se ejecutaba antes y con mayor prioridad. El resultado era que ambas etiquetas convivían en el <head>: una diciendo index y otra diciendo noindex. Google, ante la contradicción, aplicaba la directiva más restrictiva. WordPress no avisa cuando dos fuentes emiten señales opuestas sobre indexación. Solo las ejecuta en orden.

El efecto acumulado

El impacto no fue inmediato porque Google no recrawlea todas las URLs al mismo tiempo. A medida que el bot iba pasando por las páginas afectadas y encontraba la señal de noindex, iba retirando las URLs del índice. Por eso la caída fue gradual y difícil de detectar a simple vista: el sitio no cayó de golpe, sino que fue perdiendo visibilidad curso a curso, categoría a categoría.

Las páginas estáticas como la home, las landings y las entradas del blog no usaban las plantillas singular-curso ni la taxonomía categoria_curso, por lo que nunca activaban la condición del fragmento. Esas páginas seguían indexadas con normalidad, lo que reforzaba la sensación de que el sitio en general funcionaba bien. El error parcial siempre es más peligroso que una caída total, porque deja demasiadas cosas funcionando.

Retirar la señal sin alterar la herencia limpia

La corrección directa era eliminar el bloque del functions.php. Pero antes de hacerlo, revisé si la función usaba un nombre declarado o era una closure anónima, porque eso cambiaba las opciones disponibles. Era una función anónima. Eso significaba que no podía neutralizarse con remove_action() desde otro archivo sin una referencia directa al objeto, algo que en ese contexto no era práctico. La única vía limpia era editar el archivo y retirar el bloque directamente.

Antes de tocar nada en producción, activé WP_DEBUG en el entorno de staging que la academia tenía configurado. Copié el tema hijo tal cual estaba, retiré el bloque en staging y cargué varias páginas de cursos y categorías. Ningún error PHP, ningún warning, ningún cambio en la estructura visual. El fragmento era completamente independiente del resto de funciones del archivo.

Qué limpiar primero y qué dejar documentado

Una vez confirmado en staging, apliqué la misma corrección en producción: editar el functions.php del tema hijo por FTP y retirar el bloque completo del hook. Lo que sí tenía sentido añadir después era una nota en el propio archivo que documentase por qué ese espacio estaba vacío: qué función había existido ahí, qué hacía y por qué se retiró. No es un mecanismo técnico, pero en un entorno donde varias personas pueden tocar el código, esa documentación evita que alguien vuelva a pegar el mismo fragmento pensando que falta algo. Retirar código sin explicar el motivo es la mitad de la solución.

Tras aplicar la corrección, inspeccioné de nuevo el <head> de las páginas de cursos:

<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">

Una sola etiqueta. La del plugin SEO. Sin duplicados, sin contradicciones. Revisé también las cabeceras HTTP con curl -I para confirmar que no hubiese una directiva X-Robots-Tag a nivel de servidor que pudiese interferir. Todo limpio.

En Google Search Console solicité la reinspección de las URLs más importantes y monitoricé el estado de indexación durante los días siguientes. Las primeras páginas volvieron al índice en menos de 72 horas. En diez días, la cobertura de indexación del sitio había recuperado su estado anterior. Un tema hijo que hereda código sin revisión puede arrastrar directivas invisibles durante semanas sin que nadie mire en la dirección correcta.

El sello de archivo de WordPin 008 completado

💡 Qué he aprendido

He aprendido que un tema hijo no solo hereda estilos y plantillas. Hereda todo lo que alguien haya dejado dentro de su functions.php, incluidas funciones que ya no tienen sentido en el contexto actual del sitio. Este caso me confirmó que la creación de un child theme no debería partir de una copia directa del archivo de funciones del tema padre, sino de un archivo limpio al que se añade solo lo necesario. Lo que se copia sin revisar acaba actuando sin que nadie lo vigile.

También he aprendido a no confiar únicamente en la configuración del plugin SEO para validar el estado de indexación. El plugin puede estar perfectamente configurado y aun así convivir con señales que lo contradicen desde otra capa. Inspeccionar el <head> renderizado debería ser una comprobación rutinaria después de cualquier cambio de tema o de plantilla activa.

La próxima vez que revise un tema derivado, lo primero que haré será leer su functions.php de principio a fin antes de buscar en cualquier otro sitio.

Cuaderno de WordPin

Forense WordPress

Archivo Nº 008: El tema hijo de WordPress que heredaba noindex

🧩 Notas técnicas

⬋⬋

Una academia online perdió visibilidad orgánica de forma gradual tras activar un tema hijo para personalizar sus plantillas. Las páginas de cursos y categorías de formación dejaron de aparecer en Google, mientras que el resto del sitio seguía indexado con normalidad.

La causa era un fragmento de código heredado en el functions.php del tema hijo, que inyectaba una meta etiqueta noindex en las plantillas de cursos con prioridad 1 en wp_head. La directiva se ejecutaba antes que la del plugin SEO y Google priorizaba la señal más restrictiva. Se retiró el bloque directamente del archivo, se verificó en staging y se confirmó la recuperación de la indexación en los días siguientes.

🔎 Pistas detectadas

⬋⬋

  • Google Search Console mostraba URLs de cursos como rastreadas pero no indexadas, con motivo noindex explícito.
  • El plugin SEO tenía la indexación correctamente habilitada para todos los tipos de contenido afectados.
  • La opción blog_public en wp_options devolvía valor 1, descartando el bloqueo desde ajustes de lectura.
  • El <head> renderizado contenía dos etiquetas meta robots contradictorias: una con index y otra con noindex.
  • Query Monitor mostró en el listado de hooks disparados un callback registrado en wp_head con prioridad 1, cuyo componente de origen era el tema hijo activo.

🚫 Errores en WordPress detectados

⬋⬋

  • Fragmento heredado en functions.php del tema hijo inyectaba noindex en plantillas de cursos, bloqueando su indexación sin aviso visible en el panel.
  • Función anónima enganchada a wp_head con prioridad 1, ejecutándose antes que el plugin SEO e impidiendo cualquier sobreescritura posterior por configuración.
  • Duplicidad de meta etiquetas robots en el <head>, provocando que Google aplicase la directiva más restrictiva de las dos presentes.
  • Creación del tema hijo mediante copia completa del functions.php del padre, arrastrando lógica temporal que ya no tenía contexto en el sitio en producción.
  • Ausencia de validación del <head> renderizado tras la activación del nuevo tema, lo que permitió que el problema pasase inadvertido durante semanas.

📘 Glosario de WordPress

⬋⬋

  • tema hijo (child theme): tema que hereda funcionalidad y estilos de un tema padre, permitiendo personalizaciones sin modificar el original.
  • wp_head: acción de WordPress que permite a temas y plugins inyectar código dentro de la etiqueta <head> del HTML.
  • noindex: directiva de meta robots que indica a los buscadores que no incluyan la página en su índice de resultados.
  • functions.php: archivo del tema activo donde se registran funciones, hooks y filtros que modifican el comportamiento de WordPress.
  • closure anónima: función sin nombre declarado en PHP que, al registrarse con add_action(), no puede eliminarse posteriormente con remove_action() sin una referencia directa al objeto.

📏 Mini guía práctica

⬋⬋

  1. Revisa el functions.php del tema hijo línea por línea antes de activarlo, especialmente si fue creado copiando archivos del tema padre.
  2. Inspecciona el <head> renderizado en el navegador después de cada cambio de tema para detectar etiquetas duplicadas o contradictorias.
  3. Usa Query Monitor y localiza en su panel de hooks el listado de callbacks disparados durante wp_head: muestra prioridad y componente de origen para cada uno.
  4. Comprueba en Google Search Console el estado de indexación de los tipos de contenido principales tras cualquier cambio en el tema activo.
  5. Crea los temas hijo siempre desde un functions.php vacío, añadiendo únicamente las funciones que necesitas personalizar y documentando cualquier decisión de retirada de código.

Comparte el conocimiento. Comparte la historia

Expedientes y Archivos

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respetamos tu privacidad. Los datos que proporciones se utilizarán únicamente para gestionar y mostrar tu comentario, así como para prevenir el uso indebido o el spam. Puedes consultar más información en nuestra política de privacidad.

Subir