Cómo construir un modal de búsqueda para sitios de WordPress con contenido restringido por membresía
La mayoría de los tutoriales de búsqueda de WordPress terminan después de añadir un widget al encabezado.
Esto falla cuando tienes contenido restringido, como cursos de pago o videos privados. Una búsqueda predeterminada filtrará los títulos de tu material privado a los visitantes que no han iniciado sesión.
Construí un modal de búsqueda en vivo para un sitio de membresía de fitness. El sitio utiliza WordPress, WooCommerce, Divi, LearnDash y WishList Member.
Aquí te explico cómo construir una búsqueda que respete tu muro de pago (paywall).
La arquitectura
Utilicé un índice unificado con filtrado consciente del acceso. Elegí esto para asegurar que un usuario que no ha iniciado sesión nunca vea un título o un extracto de una publicación exclusiva para miembros.
La UI utiliza un icono que abre una superposición a pantalla completa. Esto ahorra espacio en dispositivos móviles y se ve más limpio que una barra de entrada estrecha.
El backend
Todo se ejecuta a través de una única ruta REST personalizada en un tema hijo (child theme).
Reglas técnicas clave:
- Proteger las dependencias: Utiliza una comprobación de función para plugins de búsqueda como Relevanssi. Si el plugin no está presente, la búsqueda debe recurrir al núcleo de WordPress en lugar de romper el sitio.
- Filtrado en el lado del servidor: Nunca filtres los resultados usando JavaScript. Si ocultas un resultado en el navegador, los datos ya estarán en la respuesta de red. Cualquier persona con DevTools podrá verlo. Filtra los datos antes de que el servidor envíe la respuesta.
- Exclusión de caché: Debes excluir tu ruta REST de búsqueda del almacenamiento en caché de páginas (page caching). Si guardas los resultados en caché, la búsqueda de un miembro podría ser servida a un invitado, filtrando contenido privado.
El frontend
El lado del cliente utiliza vanilla JavaScript.
Tres cosas hacen que la UX funcione:
- Debounce: Espera 250 ms después de una pulsación de tecla antes de enviar una solicitud. Esto evita una carga innecesaria en el servidor.
- AbortController: Cancela las solicitudes anteriores cuando el usuario sigue escribiendo. Esto evita que los resultados antiguos sobrescriban a los nuevos.
- Estados de error: Muestra un mensaje claro si falla un
fetch. Un indicador de carga que nunca deja de girar es una mala UX.
La lección móvil
Intenté inyectar el botón de búsqueda en el menú móvil de Divi. El tema interceptaba los clics, haciendo que el botón no se pudiera pulsar.
La solución fue sencilla: deja de luchar contra el tema.
En lugar de poner el botón dentro del menú, lo inyecté en el encabezado como un elemento independiente. Esto lo mantuvo fuera del control del tema y facilitó que se pudiera pulsar.
Resumen
- El control de acceso debe ocurrir en el servidor.
- Excluye los endpoints de búsqueda de tu caché.
- Utiliza
debounceyAbortControllerpara manejar las solicitudes. - Escapa todos los datos de la API antes de inyectarlos en el DOM para prevenir XSS.
- Si un constructor de páginas (page builder) se resiste a tu código, coloca tu elemento al lado en lugar de dentro.
Fuente: https://dev.to/highcenburg/building-a-search-modal-for-a-membership-gated-wordpress-site-b92
