Como excluir tipos de contenido del feed con hooks en PHP en WordPress

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

  1. Visita la URL del feed principal: /feed/ o /?feed=rss2.
  2. Prueba feeds de categoría y autor para comprobar condiciones específicas: /category/mi-categoria/feed/ /author/mi-autor/feed/.
  3. Usa el plugin Query Monitor para inspeccionar la consulta SQL del feed y comprobar que el post_type está filtrado.
  4. 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 🙂



Deja una respuesta

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