inicio/ noticias/ Tutoriales Avanzados

Hooks vs filtros en WordPress: guía técnica real

Laptop screen displaying code with orange glow

Entiende la diferencia entre hooks vs filtros WordPress, cuándo usar cada tipo y cómo aplicarlos con ejemplos reales en tus desarrollos.

Por qué entender la diferencia entre hooks vs filtros WordPress cambia tu forma de desarrollar

Cuando empiezas a escribir código personalizado en WordPress, hay un momento en el que todo parece funcionar «por arte de magia». Añades funciones en functions.php, copias fragmentos de Stack Overflow y, de alguna forma, el resultado aparece en pantalla. Pero llega un proyecto más complejo —una tienda WooCommerce con lógica de precios personalizada, un tema a medida con bloques dinámicos, una integración con un CRM externo— y ese enfoque se rompe. Es entonces cuando la comprensión real de hooks vs filtros WordPress deja de ser teoría académica y se convierte en la diferencia entre un desarrollo mantenible y uno que se desmorona con cada actualización.

WordPress ejecuta miles de líneas de código en cada carga de página. Lo hace siguiendo un orden predecible, y en puntos concretos de esa ejecución «avisa» a tu código para que intervenga. Ese mecanismo de aviso es lo que se conoce como hook. Pero no todos los hooks son iguales: los hay de acción (actions) y los hay de filtro (filters). Saber cuándo usar uno u otro —y por qué— es lo que separa a un desarrollador que entiende WordPress de uno que simplemente pega código.

Qué es un hook en WordPress: el concepto base

Un hook es un punto de enganche dentro del flujo de ejecución de WordPress. Piensa en él como una señal que WordPress emite en un momento específico: «Estoy a punto de guardar un post», «Acabo de cargar la cabecera», «Voy a mostrar el contenido del artículo». Tu código puede «escuchar» esas señales y ejecutar funciones propias cuando se emiten.

WordPress registra más de 2.500 hooks nativos entre su core, y los plugins y temas añaden cientos más. Cada uno tiene un nombre único —init, wp_head, the_content, save_post— que identifica el momento exacto en el que se dispara.

Lo esencial: un hook por sí solo no hace nada. Es tu función callback la que ejecuta la lógica. El hook simplemente le dice a WordPress «cuando llegues aquí, ejecuta esto».

La taxonomía real: actions y filters

Dentro del ecosistema de hooks existen exactamente dos tipos:

  • Actions (acciones): permiten ejecutar código en un punto concreto del flujo. No devuelven nada. Su propósito es «hacer algo»: enviar un email, registrar un dato en la base de datos, insertar un script.
  • Filters (filtros): permiten modificar un dato antes de que WordPress lo use o lo muestre. Reciben un valor, lo transforman y lo devuelven. Su propósito es «cambiar algo»: alterar el título de un post, modificar el precio de un producto, añadir una clase CSS a un elemento.

Esta distinción parece simple, pero sus implicaciones técnicas son profundas. Confundir un action con un filter —o usar uno donde debería ir el otro— genera bugs sutiles que son difíciles de rastrear.

Cómo funcionan las acciones: ejecutar sin devolver

📋 Checklist de desarrollo WordPress a medida

Recibe una checklist técnica para verificar la calidad de cualquier desarrollo WordPress antes de entregarlo.

Descargar checklist →

Una acción se registra con add_action() y se dispara con do_action(). El patrón es siempre el mismo:

add_action( 'wp_footer', 'mi_script_personalizado' );
function mi_script_personalizado() {
    echo '<script>console.log("Footer cargado");</script>';
}

En este ejemplo, WordPress llega al punto wp_footer durante la carga de la página, ve que hay una función enganchada y la ejecuta. La función no necesita devolver nada: simplemente hace su trabajo (en este caso, insertar un script).

Casos de uso reales para actions

Las acciones son el mecanismo correcto cuando necesitas:

  • Enviar notificaciones: usar save_post para disparar un email cuando se publica un artículo.
  • Registrar recursos: usar wp_enqueue_scripts para cargar hojas de estilo y scripts.
  • Crear estructuras de datos: usar init para registrar custom post types o taxonomías.
  • Ejecutar tareas programadas: usar hooks de wp_cron para limpiar transients o sincronizar datos.
  • Modificar el dashboard: usar admin_menu para añadir páginas de administración personalizadas.

El denominador común: en todos estos casos, estás haciendo algo. No estás modificando un dato que WordPress ya tiene preparado, sino añadiendo comportamiento nuevo al flujo.

El parámetro de prioridad y el número de argumentos

add_action() acepta cuatro parámetros: el nombre del hook, la función callback, la prioridad (por defecto 10) y el número de argumentos que acepta el callback. La prioridad determina el orden de ejecución cuando hay múltiples funciones enganchadas al mismo hook. Un valor más bajo se ejecuta antes. Esto es crítico en proyectos con muchos plugins, donde el orden de ejecución puede generar conflictos.

add_action( 'save_post', 'mi_funcion_urgente', 5, 2 );
add_action( 'save_post', 'mi_funcion_secundaria', 20, 2 );

En este caso, mi_funcion_urgente se ejecutará antes que mi_funcion_secundaria. Si ambas necesitan acceder al ID del post y al objeto WP_Post, el cuarto parámetro (2) les permite recibir ambos argumentos.

Cómo funcionan los filtros: recibir, transformar y devolver

Laptop screen displaying code with orange glow
Photo by Daniil Komov on Unsplash

Un filtro se registra con add_filter() y se dispara con apply_filters(). La diferencia fundamental con las acciones es que un filtro siempre recibe un valor y siempre debe devolver un valor:

add_filter( 'the_title', 'modificar_titulo' );
function modificar_titulo( $titulo ) {
    return $titulo . ' - Mi Sitio';
}

WordPress tiene preparado el título del post. Antes de mostrarlo, pasa ese título por el filtro the_title. Tu función lo recibe, le añade un sufijo y lo devuelve. WordPress usa el valor devuelto como el título final.

Si olvidas el return, el título desaparece. WordPress recibe null en lugar del título modificado. Este es el error más común al trabajar con filtros y puede provocar páginas en blanco, contenido vacío o comportamientos erráticos.

Casos de uso reales para filters

Los filtros son el mecanismo correcto cuando necesitas:

  • Modificar contenido antes de mostrarlo: usar the_content para añadir un aviso legal al final de cada post.
  • Alterar consultas de base de datos: usar pre_get_posts para cambiar el número de resultados o el orden.
  • Cambiar URLs: usar post_type_link para personalizar los permalinks de un custom post type.
  • Modificar datos de WooCommerce: usar woocommerce_get_price_html para cambiar cómo se muestra el precio.
  • Controlar el acceso: usar login_redirect para redirigir a los usuarios tras el login según su rol.

El denominador común: en todos estos casos, WordPress ya tiene un dato listo. Tú intervienes para modificarlo antes de que se use.

Diferencias técnicas clave entre actions y filters

Más allá de la explicación conceptual, hay diferencias técnicas que importan en el día a día del desarrollo:

Valor de retorno

Las acciones no necesitan devolver nada. Los filtros deben devolver un valor. Internamente, do_action() ignora cualquier valor devuelto por los callbacks. apply_filters() encadena los valores devueltos: el output de un callback se convierte en el input del siguiente.

Encadenamiento

Cuando múltiples funciones se enganchan al mismo filtro, forman una cadena. Cada función recibe el valor ya modificado por la anterior. Esto permite que distintos plugins modifiquen el mismo dato de forma acumulativa. En las acciones, cada función se ejecuta independientemente: no hay paso de datos entre ellas (salvo que uses variables globales, lo cual es una práctica desaconsejada).

Implementación interna

Técnicamente, WordPress implementa las acciones usando la misma clase WP_Hook que los filtros. De hecho, do_action() internamente llama a apply_filters() y simplemente descarta el valor devuelto. Esto significa que podrías usar add_filter() en un hook de acción y funcionaría… pero sería confuso para cualquier desarrollador que lea tu código. La convención existe por una razón: claridad de intención.

Tabla comparativa rápida

CaracterísticaActionFilter
Registroadd_action()add_filter()
Disparodo_action()apply_filters()
¿Devuelve valor?NoSí (obligatorio)
PropósitoEjecutar códigoModificar datos
EncadenamientoIndependienteSecuencial
Error típicoOrden de prioridadOlvidar return

Errores frecuentes al trabajar con hooks y filtros en WordPress

Después de años revisando código de otros desarrolladores y de agencias que externalizan sus proyectos, hay patrones de error que se repiten con una frecuencia sorprendente:

1. Usar una acción donde debería ir un filtro

El ejemplo clásico: quieres modificar el extracto de un post y usas add_action( 'the_excerpt', ... ) con un echo dentro. Puede parecer que funciona, pero estás imprimiendo contenido directamente en lugar de devolver el extracto modificado. El resultado es contenido duplicado o fuera de lugar. La solución: add_filter( 'the_excerpt', ... ) con un return.

2. No devolver el valor original en un filtro condicional

Imagina que quieres modificar el título solo en posts de una categoría específica:

add_filter( 'the_title', 'titulo_especial' );
function titulo_especial( $titulo ) {
    if ( is_category( 'ofertas' ) ) {
        return '🔥 ' . $titulo;
    }
    // Si no es la categoría, no devuelves nada → el título desaparece
}

La solución es siempre incluir un return $titulo; al final de la función, fuera del condicional. Si no se cumple la condición, el valor original debe pasar intacto.

3. Ignorar la prioridad en proyectos con múltiples plugins

Dos plugins que modifican el mismo filtro con la misma prioridad (10, por defecto) se ejecutan en el orden en que fueron cargados. Si necesitas que tu modificación se aplique después de la de un plugin concreto, debes usar una prioridad más alta. Herramientas como Query Monitor permiten visualizar exactamente qué callbacks están enganchados a cada hook y en qué orden.

4. Crear hooks personalizados sin documentarlos

WordPress permite crear tus propios hooks con do_action() y apply_filters(). Es una práctica excelente para hacer temas y plugins extensibles. Pero si no documentas esos hooks —su nombre, los argumentos que pasan, el momento de ejecución—, nadie podrá usarlos. En proyectos de agencia, he visto temas con más de 40 hooks personalizados sin una sola línea de documentación. El tema era técnicamente bueno, pero imposible de extender sin leer cada archivo fuente.

Criterios para decidir entre action y filter en cada situación

Cuando te enfrentas a un requisito nuevo, hay una secuencia de preguntas que aclara qué tipo de hook necesitas:

  1. ¿Necesitas modificar un dato que WordPress ya tiene? → Filter.
  2. ¿Necesitas ejecutar código en un momento concreto sin modificar datos existentes? → Action.
  3. ¿El hook nativo que estás usando se dispara con apply_filters()? → Úsalo como filter. Devuelve siempre un valor.
  4. ¿El hook nativo se dispara con do_action()? → Úsalo como action. No necesitas devolver nada.
  5. ¿Estás creando un hook propio para que otros desarrolladores lo extiendan? → Si quieres que puedan modificar un dato, usa apply_filters(). Si quieres que puedan añadir comportamiento, usa do_action().

Esta lista parece obvia, pero en la práctica muchos desarrolladores eligen el tipo de hook «por intuición» en lugar de por análisis del flujo de datos. Esa intuición falla cuando el proyecto crece.

Ejemplo avanzado: combinar actions y filters en un flujo real

Supongamos que gestionas una tienda WooCommerce y necesitas:

  1. Modificar el texto del botón «Añadir al carrito» según la categoría del producto.
  2. Registrar en un log cada vez que un usuario añade un producto al carrito.

El primer requisito es un filter: estás modificando un dato (el texto del botón) antes de que se muestre.

add_filter( 'woocommerce_product_single_add_to_cart_text', 'texto_boton_personalizado' );
function texto_boton_personalizado( $texto ) {
    global $product;
    if ( has_term( 'servicios', 'product_cat', $product->get_id() ) ) {
        return 'Solicitar presupuesto';
    }
    return $texto;
}

El segundo requisito es una action: estás ejecutando código (escribir en un log) cuando ocurre un evento, sin modificar ningún dato.

add_action( 'woocommerce_add_to_cart', 'registrar_en_log', 10, 4 );
function registrar_en_log( $cart_item_key, $product_id, $quantity, $variation_id ) {
    error_log( 'Producto añadido: ' . $product_id . ' | Cantidad: ' . $quantity );
}

Ambos hooks trabajan en el mismo flujo (el proceso de carrito) pero con propósitos completamente distintos. El filter modifica lo que el usuario ve. El action registra lo que el usuario hace.

Herramientas para depurar y explorar hooks en WordPress

Trabajar con hooks se vuelve mucho más manejable cuando tienes visibilidad sobre qué está enganchado a dónde. Estas herramientas son imprescindibles:

  • Query Monitor: muestra todos los hooks que se disparan en cada carga de página, sus callbacks, prioridades y tiempos de ejecución. Es la herramienta de referencia para depuración en WordPress.
  • WordPress Developer Reference: la documentación oficial de hooks. Incluye el nombre, los parámetros, el archivo fuente donde se dispara y los changelogs. Debería ser tu primera parada antes de buscar en Google.
  • Debug Bar: complemento que añade un panel de depuración en la barra de administración con información sobre consultas, caché y hooks.

En proyectos de agencia donde múltiples desarrolladores tocan el mismo código, tener Query Monitor activo en el entorno de desarrollo no es opcional: es un requisito mínimo de calidad.

Preguntas frecuentes sobre hooks y filtros en WordPress

¿Puedo usar add_filter en un hook de acción?

Técnicamente sí, porque internamente WordPress usa el mismo mecanismo. Pero no deberías. Si un hook se documenta como acción, trátalo como tal. Usar add_filter() en un hook de acción confunde a otros desarrolladores y puede causar problemas si el core de WordPress cambia su implementación interna en el futuro.

¿Cuántos hooks puedo enganchar al mismo punto?

No hay límite técnico. WordPress encadena todos los callbacks registrados y los ejecuta en orden de prioridad. Sin embargo, un número excesivo de callbacks en un mismo hook (especialmente en init o wp_head) puede degradar el rendimiento. Monitoriza con Query Monitor si sospechas que un hook se ha convertido en un cuello de botella.

¿Es posible eliminar un hook registrado por un plugin?

Sí, con remove_action() o remove_filter(). Necesitas conocer el nombre exacto de la función callback y la prioridad con la que fue registrada. Si el callback es un método de una clase instanciada, necesitas acceso a esa instancia, lo cual puede complicarse con plugins que usan singletons o contenedores de dependencias.

¿Debo crear hooks personalizados en mis temas y plugins?

Sí, especialmente si otros desarrolladores van a extender tu código. Un tema bien construido incluye do_action() antes y después de secciones clave (cabecera, footer, sidebar) y apply_filters() en valores que podrían necesitar personalización (colores, textos, opciones por defecto). Esto convierte tu código en una plataforma extensible.

¿Cuál es la diferencia entre prioridad 1 y prioridad 999?

La prioridad determina el orden de ejecución. Prioridad 1 se ejecuta casi al principio; prioridad 999 casi al final. En filtros, esto es especialmente importante: si necesitas que tu modificación sea la «última palabra» sobre un dato, usa una prioridad alta. Si necesitas que otros plugins puedan sobreescribir tu cambio, usa una prioridad baja.

Entender a fondo los hooks y filtros de WordPress no es un ejercicio teórico: es la base sobre la que se construye cualquier desarrollo personalizado que aspire a ser robusto y mantenible. Si estás trabajando en un proyecto que requiere desarrollo WordPress a medida, puedes ver los servicios que ofrezco para agencias y empresas que necesitan un enfoque técnico sólido.

Mi opinión como desarrollador WordPress

Desde mi experiencia profesional, la confusión entre actions y filters es una de las causas más frecuentes de bugs en proyectos WordPress que llegan a mis manos para revisión o rescate. No se trata de un concepto difícil, sino de uno que muchos desarrolladores dan por sabido sin haberlo interiorizado realmente. He visto temas premium con filtros que no devuelven valor, plugins que usan acciones para intentar modificar contenido, y desarrollos enteros construidos sobre copiar-pegar sin entender el porqué detrás de cada hook. Dedicar tiempo a dominar este mecanismo no es perder el tiempo; es exactamente lo que diferencia un desarrollo que sobrevive a las actualizaciones de uno que se rompe cada trimestre.

¿Necesitas ayuda con tu proyecto? Trabajo con negocios y agencias en WordPress, WooCommerce, IA e integraciones. Escríbeme y lo vemos juntos.

fernandodomecq
// Sobre el autor

fernandodomecq

Desarrollador WordPress freelance especializado en WooCommerce, integraciones e IA. Escribo sobre proyectos web, agencias y buenas prácticas técnicas.

Ver todos los artículos
// Compartir
// contacto — respuesta en < 24h

¿Hablamos de
tu proyecto?

hola@fernandomecq.com