Contents
Introducción
Este tutorial explica, paso a paso y con todo lujo de detalles, cómo excluir uno o varios tipos de contenido (post types) del feed de WordPress usando hooks en PHP. Se muestran varias implementaciones, desde la más simple hasta soluciones robustas que cubren diferencias entre tipos de feed, contextos de administración y rendimiento.
Por qué y cuándo excluir tipos de contenido del feed
- Claridad para los suscriptores: evitar que contenidos de tipo producto, evento o portfolio llenen un feed pensado para entradas de blog.
- SEO y distribución: controlar qué se indexa o consume por canales de agregación.
- Seguridad/privacidad: impedir que contenidos privados o específicos aparezcan en fuentes públicas.
- Compatibilidad con lectores de RSS: preservar el propósito del feed (por ejemplo: solo entradas del blog).
Enfoque recomendado: usar el hook pre_get_posts
El hook pre_get_posts permite modificar la consulta antes de que se ejecute. Es la forma recomendada porque brinda acceso al objeto WP_Query y es eficiente si se aplican condiciones adecuadas (is_admin, is_main_query, is_feed, etc.).
Regla básica
Antes de tocar la consulta, siempre comprobar:
- Que no estamos en el área de administración (is_admin()).
- Que la consulta es la principal (is_main_query()).
- Que la consulta corresponde a un feed (is_feed()).
Ejemplo 1 — Exclusión sencilla de tipos concretos
Este snippet excluye los tipos page y event (ejemplo de CPT) de todos los feeds públicos, dejando solo los tipos públicos válidos restantes.
is_main_query() ! query->is_feed() ) { return } // Tipos que quieres excluir del feed excluir = array( page, event ) // Obtener tipos públicos (puedes ajustar el args a tus necesidades) tipos_publicos = get_post_types( array( public => true ), names ) // Quitar los excluidos tipos_finales = array_diff( tipos_publicos, excluir ) // Si no queda ninguno, por seguridad dejar post como predeterminado if ( empty( tipos_finales ) ) { tipos_finales = array( post ) } // Establecer los tipos de post que se mostrarán en el feed query->set( post_type, tipos_finales ) // Evitar que los sticky posts alteren el orden del feed query->set( ignore_sticky_posts, true ) } add_action( pre_get_posts, mi_excluir_tipos_del_feed ) ?>
Explicación del ejemplo
- is_admin() evita que la modificación afecte a consultas del backend (por ejemplo, vista de feeds del admin).
- is_main_query() garantiza que solo se toque la consulta principal y no subconsultas que puedan romper plugins o widgets.
- is_feed() asegura que solo actuamos en feeds (RSS, RSS2, Atom).
- get_post_types(array(public => true)) devuelve post types públicos así no dependemos de una lista estática.
- ignore_sticky_posts limpia el orden para que el feed siga el orden cronológico establecido.
Ejemplo 2 — Excluir tipos solo del feed principal (home) o en feeds específicos
Si quieres que la exclusión afecte solo al feed de la página principal (/feed/) y no a feeds de categorías o autor, puedes comprobar is_home() además de is_feed().
is_main_query() ! query->is_feed() ) { return } // Aplicar solo si es el feed de la página principal if ( ! is_home() ) { return } excluir = array( producto, evento ) tipos = get_post_types( array( public => true ), names ) tipos = array_diff( tipos, excluir ) if ( empty( tipos ) ) { tipos = array( post ) } query->set( post_type, tipos ) } add_action( pre_get_posts, excluir_cpt_solo_feed_principal ) ?>
Ejemplo 3 — Excluir por post type pero permitiendo consultas explícitas
Si un consumidor solicita explícitamente un tipo (por ejemplo ?post_type=eventoampfeed=rss2) quizá quieras respetar esa solicitud. La siguiente variante solo actúa cuando no existe un post_type explícito en la query vars.
is_main_query() ! query->is_feed() ) { return } // Si el query ya especifica post_type (por ejemplo feed de CPT), no interferir vars = query->query_vars if ( ! empty( vars[post_type] ) ) { return } excluir = array( curso, evento ) tipos = get_post_types( array( public => true ), names ) tipos = array_diff( tipos, excluir ) if ( empty( tipos ) ) { tipos = array( post ) } query->set( post_type, tipos ) } add_action( pre_get_posts, excluir_tipos_feed_respetando_explicit ) ?>
Método alternativo: filtrar request para feeds
Otra opción es filtrar la matriz request con add_filter(request, …). Es menos habitual pero útil en ciertos contextos donde pre_get_posts no es viable. Se debe tener cuidado porque manipula variables antes de crear la consulta.
Qué más tener en cuenta
- Prioridad del hook: por lo general la prioridad 10 está bien, pero si otro plugin modifica la consulta más tarde, puedes aumentar (ej. 20) o disminuir según necesites.
- Plugins y themes: algunos themes o plugins registran feeds personalizados o realizan modificaciones de consulta prueba tus cambios con Query Monitor para ver la SQL y las condiciones que se aplican.
- REST API: Estas técnicas afectan únicamente al sistema de feeds clásico (RSS/Atom). La REST API no usa is_feed() si necesitas excluir CPTs de endpoints REST debes ajustar el registro del CPT o filtrar sus endpoints en la API.
- Feeds personalizados: si tienes feeds personalizados (por ejemplo feed-eventos.php) revisa si tu lógica debe aplicarse también a esos templates.
- Cache: si tu sitio usa cache de objetos o de página, recuerda purgar o invalidar las cachés del feed tras cambios en la lógica.
Cómo probar y depurar
- Visita la URL del feed principal: /feed/ o /?feed=rss2.
- Prueba feeds de categoría y autor para comprobar condiciones específicas: /category/mi-categoria/feed/ /author/mi-autor/feed/.
- Usa el plugin Query Monitor para inspeccionar la consulta SQL del feed y comprobar que el post_type está filtrado.
- Activa WP_DEBUG y define SAVEQUERIES para revisar las consultas si es necesario.
Buenas prácticas y rendimiento
- Siempre comprobar is_admin() y is_main_query() para no introducir sobrecarga ni efectos colaterales.
- No ejecutar consultas costosas dentro del hook si necesitas obtener listas grandes, considera cachearlas en transients.
- Evitar loops adicionales dentro de pre_get_posts: solo modificar query vars.
- Probar en un entorno de staging antes de aplicar en producción.
Implementación recomendada (snippet final robusto)
Snippet completo y robusto que puedes pegar en el functions.php de tu child theme o en un plugin pequeño. Incluye comentarios y opciones fáciles de modificar.
is_main_query() ! query->is_feed() ) { return } // 2) Lista de tipos a excluir (modifica según tus CPTs) excluir = array( page, producto, evento ) // 3) Obtener tipos públicos por defecto (puedes ajustar el get_post_types si lo prefieres) tipos = get_post_types( array( public => true ), names ) // 4) Si se especificó un post_type explícito en la query (p.ej. feed de un CPT), respetarlo query_vars = query->get( post_type ) if ( ! empty( query_vars ) ) { // Si es string y está en los excluidos, dejar post como fallback explicit_pt = (array) query_vars explicit_pt = array_diff( explicit_pt, excluir ) if ( empty( explicit_pt ) ) { query->set( post_type, array( post ) ) } else { query->set( post_type, explicit_pt ) } // No seguir cambiando más return } // 5) Aplicar la exclusión tipos_finales = array_diff( tipos, excluir ) if ( empty( tipos_finales ) ) { tipos_finales = array( post ) } query->set( post_type, tipos_finales ) // 6) Ajustes adicionales recomendados para feeds query->set( ignore_sticky_posts, true ) // Opcional: controlar número de ítems en el feed (opcional) // query->set( posts_per_rss, 20 ) } add_action( pre_get_posts, robust_excluir_tipos_del_feed, 10 ) ?>
Resumen
La forma más segura y flexible de excluir tipos de contenido del feed es mediante pre_get_posts, aplicando comprobaciones estrictas (is_admin, is_main_query, is_feed) y definiendo claramente qué tipos excluir. Ajusta la lista de tipos, la condición del feed (feed principal vs. todos los feeds) y prueba cuidadosamente en staging antes de llevarlo a producción.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |