Contents
Introducción
Este tutorial explica paso a paso cómo implementar un sistema de favoritos en WordPress que funcione para usuarios invitados (no registrados) mediante cookies. La idea es permitir que visitantes marquen/desmarquen entradas como favoritas en su navegador. La información de favoritos se almacena en una cookie JSON en el cliente y, opcionalmente, el servidor mantiene un contador por entrada en post meta para mostrar el número total de favoritos (con las limitaciones que explico más abajo).
Requisitos y consideraciones
- WordPress (tema hijo o plugin personalizado donde puedas añadir código PHP/JS/CSS).
- Conocimientos básicos de PHP, JavaScript y cómo encolar scripts en WordPress.
- Limitaciones: una solución basada en cookies es por navegador/dispositivo. No es fiable para consenso global (varios visitantes pueden inflar contadores) y es vulnerable a manipulaciones del lado cliente. Para mejorar la integridad habría que añadir controles adicionales en servidor o exigir inicio de sesión.
Resumen del flujo
- Al renderizar cada post, el servidor lee la cookie (si existe) y marca el botón como activo si el ID del post está en la cookie.
- El visitante hace clic en el enlace Favorito (ancla). El JavaScript actualiza la cookie (añade o quita el ID) y cambia el aspecto del enlace.
- Opcional: al mismo tiempo se envía una petición AJAX al servidor para incrementar/decrementar un contador en post meta (solo para mostrar un número global, con las advertencias mencionadas).
Coloca este código en el template de tu loop (por ejemplo, single.php o content.php) o en una función que añada el enlace en los lugares deseados. El ejemplo lee la cookie wp_favorites (JSON) y marca el enlace con la clase is-active si el post está en la lista.
lt?php
// Dentro del loop
post_id = get_the_ID()
// Leer cookie y decodificarla
fav_cookie = isset(_COOKIE[wp_favorites]) ? wp_unslash( _COOKIE[wp_favorites] ) :
favs = array()
if ( fav_cookie ) {
decoded = json_decode( fav_cookie, true )
if ( is_array( decoded ) ) {
favs = array_map( intval, decoded )
}
}
is_fav = in_array( post_id, favs, true )
// Output: usamos un enlace porque las etiquetas button no están permitidas aquí.
// data-post-id servirá para JS y para la petición AJAX.
?>
data-post-id= aria-pressed=>
Paso 2 — Encolar scripts y pasar variables desde PHP a JS
En functions.php de tu tema hijo o en un plugin, encola el script de JavaScript e inyecta variables necesarias como admin-ajax.php y un nonce para seguridad.
lt?php
function wpfav_enqueue_assets() {
// Encola script principal (crea un archivo js/fav.js en tu tema o plugin)
wp_enqueue_script( wpfav-main, get_stylesheet_directory_uri() . /js/fav.js, array( jquery ), 1.0, true )
// Localizar datos para AJAX y nonce
wp_localize_script( wpfav-main, WPFavData, array(
ajax_url =gt admin_url( admin-ajax.php ),
nonce =gt wp_create_nonce( wp_fav_nonce ),
cookieName =gt wp_favorites,
cookieDays =gt 365,
) )
}
add_action( wp_enqueue_scripts, wpfav_enqueue_assets )
Este script maneja los clics en los enlaces, modifica la cookie (JSON con array de IDs) y envía una petición AJAX al backend para actualizar el contador de favoritos. En el ejemplo uso jQuery por compatibilidad con WordPress.
(function(){
use strict
// Helpers: leer/escribir cookie con JSON
function getCookie(name) {
var match = document.cookie.match(new RegExp((?:^ ) name.replace(/([.?{}()[]/ ^])/g, 1) =([^])))
return match ? decodeURIComponent(match[1]) : null
}
function setCookie(name, value, days) {
var expires =
if (days) {
var date = new Date()
date.setTime(date.getTime() (days2460601000))
expires = expires= date.toUTCString()
}
document.cookie = name = encodeURIComponent(value ) expires path=/
}
function parseFavs(cookieName) {
var raw = getCookie(cookieName)
if (!raw) return []
try {
var arr = JSON.parse(raw)
if (Array.isArray(arr)) return arr.map(function(i){ return parseInt(i,10) }).filter(Boolean)
} catch(e){
// cookie corrupta: limpiar
return []
}
return []
}
function saveFavs(cookieName, arr, days) {
setCookie(cookieName, JSON.stringify(arr), days)
}
// Toggle favorito
(document).on(click, .fav-toggle, function(e){
e.preventDefault()
var el = (this)
var postId = parseInt(el.data(post-id), 10)
if (!postId) return
var cookieName = (typeof WPFavData !== undefined WPFavData.cookieName) ? WPFavData.cookieName : wp_favorites
var cookieDays = (typeof WPFavData !== undefined WPFavData.cookieDays) ? parseInt(WPFavData.cookieDays,10) : 365
var favs = parseFavs(cookieName)
var index = favs.indexOf(postId)
var action =
if (index === -1) {
// añadir
favs.push(postId)
action = add
el.addClass(is-active).attr(aria-pressed,true).text(Favorito)
} else {
// quitar
favs.splice(index, 1)
action = remove
el.removeClass(is-active).attr(aria-pressed,false).text(Añadir a favoritos)
}
saveFavs(cookieName, favs, cookieDays)
// Petición AJAX opcional para actualizar contador en el servidor
if (typeof WPFavData !== undefined WPFavData.ajax_url) {
.post(WPFavData.ajax_url, {
action: wpfav_toggle,
post_id: postId,
op: action,
nonce: WPFavData.nonce
}, function(response){
// response handling opcional
// console.log(response)
}, json)
}
})
})(jQuery)
Paso 4 — Handler AJAX en PHP (invitados y registrados)
Este handler recibe la operación (add/remove) y actualiza un contador simple en post meta llamado _fav_count. Se registran las acciones para usuarios anónimos con wp_ajax_nopriv. Usa un nonce para evitar peticiones CSRF desde otros orígenes.
lt?php
function wpfav_ajax_toggle() {
// Validar nonce
check_ajax_referer( wp_fav_nonce, nonce )
post_id = isset( _POST[post_id] ) ? intval( _POST[post_id] ) : 0
op = isset( _POST[op] ) ? sanitize_text_field( _POST[op] ) :
if ( ! post_id ! in_array( op, array( add, remove ), true ) ) {
wp_send_json_error( array( message =gt Parámetros inválidos ), 400 )
}
// Obtener contador actual
count = intval( get_post_meta( post_id, _fav_count, true ) )
if ( op === add ) {
count
} else {
count = max( 0, count - 1 )
}
update_post_meta( post_id, _fav_count, count )
wp_send_json_success( array( count =gt count ) )
}
add_action( wp_ajax_wpfav_toggle, wpfav_ajax_toggle )
add_action( wp_ajax_nopriv_wpfav_toggle, wpfav_ajax_toggle )
Paso 5 — Estilos (CSS)
Unos estilos simples para mostrar el estado visual del favorito.
.fav-toggle {
display: inline-block
padding: 6px 10px
background: #f2f2f2
color: #333
text-decoration: none
border-radius: 4px
font-size: 14px
margin-right: 6px
}
.fav-toggle.is-active {
background: #ffefef
color: #d33
font-weight: bold
}
.fav-toggle:hover {
opacity: 0.9
}
Consideraciones de seguridad y limitaciones
- Una cookie del lado cliente puede ser manipulada por el usuario. No confíes en ella para sistemas críticos.
- El contador en post meta es opcional y puede ser inflado por usuarios maliciosos (click farms, scripts automatizados). Para mitigar: añadir verificación por IP, rate-limiting o exigir inicio de sesión para afectar el contador real.
- Las cookies son por navegador/dispositivo. Si el usuario borra cookies o cambia de dispositivo, perderá la lista de favoritos.
- Si necesitas sincronización entre dispositivos, guarda la lista en user meta para usuarios logueados y haz un merge en el servidor al iniciar sesión (ej. al hacer login, enviar contenido de la cookie al servidor y fusionarlo con user meta).
Mejoras opcionales
- Persistir favoritos para usuarios registrados: al iniciar sesión, enviar la cookie al servidor y guardar en user meta (merge).
- Usar signed cookies (HMAC) o tokens para comprobar que la cookie no fue manipulada fácilmente.
- Implementar rate-limiting por IP y/o checks anti-bot para que el contador en post meta sea más confiable.
- Ofrecer una UI para ver la lista de favoritos leyendo la cookie y mostrando las entradas (usar WP REST API para obtener títulos/previews).
Checklist de archivos y dónde colocar el código
- functions.php (tema hijo) o plugin: encolar scripts (Paso 2) y handler AJAX (Paso 4).
- Template del loop (single.php / content.php): añadir el enlace de favoritos (Paso 1).
- js/fav.js: código JavaScript (Paso 3).
- css/fav.css o style.css: estilos (Paso 5).
Notas finales
Esta solución es práctica y rápida de implementar para añadir favoritos a visitantes sin registro mediante cookies. Tiene limitaciones inherentes a su naturaleza cliente-centrica para proyectos donde la integridad del dato sea crítica conviene combinarlo con almacenamiento en servidor para usuarios autenticados y medidas anti-abuso.
|
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |
