Contents
Introducción
Objetivo: enseñar paso a paso cómo contar vistas de entradas (posts) en WordPress sin usar plugins, usando PHP y transients para minimizar operaciones de escritura en la base de datos y mantener un conteo eficiente y escalable.
Este método combina: detección de vistas válidas (evitando recuentos repetidos inmediatos, bots y administradores), uso de cookies para limitar recuentos por visitante en un periodo concreto, acumulación temporal con transients y volcado periódico (o por umbral) al post meta para conservar el dato de forma persistente.
Concepto y flujo general
- Registro rápido: cuando un visitante válido carga un post, se incrementa una entrada temporal (transient) que acumula vistas pendientes.
- Umbral/Volcado: si el acumulado llega a un umbral (por ejemplo 10) se actualiza la meta del post (post meta) con la suma y se reinicia el transient para seguir acumulando.
- Persistencia: la meta del post (ej. meta key post_views_count) contiene el total persistente. El transient reduce la frecuencia de escrituras a la base de datos en tráfico alto.
- Protecciones: cookie por post para evitar contar múltiples recargas en corto plazo exclusión de administradores, peticiones AJAX/cron, y comprobaciones básicas de bots.
Ventajas de usar transients
- Menos escrituras en postmeta en sitios con alto tráfico.
- Flexibilidad: ajustar umbral o expiración según tráfico y tolerancia a latencia en el conteo.
- Transients pueden almacenarse en objeto cache (memcached/redis) si están configurados, ayudando el rendimiento.
Consideraciones previas
- No contar vistas de administrador ni revisiones.
- Decidir si contar vistas por IP, por cookie o por sesión. Aquí se propone cookie para simplicidad.
- Precauciones de concurrencia: para entornos muy concurridos considerar incrementos en la base de datos mediante consultas atómicas o usar un layer de cache externo con soporte de incremento atómico.
Implementación práctica
1) Parámetros y lógica
- Meta key persistente: post_views_count
- Transient key: post_views_pending_{POSTID}
- Umbral de volcado: (ejemplo) 10 vistas
- Cookie: post_viewed_{POSTID} con expiración (ejemplo) 1 hora
2) Código: registrar una vista (añadir en functions.php del tema o en un mu-plugin)
Este código controla validaciones, cookies, transient y volcado al meta cuando corresponde.
ID ) ) { return } post_id = (int) post->ID // Evitar contar revisiones o autosaves if ( wp_is_post_revision( post_id ) ) { return } // Evitar contar para usuarios con capacidades de edición (opcional) if ( is_user_logged_in() current_user_can( edit_posts ) ) { return } // Cookie para evitar cuentas repetidas en corto plazo cookie_name = post_viewed_ . post_id if ( isset( _COOKIE[ cookie_name ] ) ) { return // Ya contado recientemente por este visitante } // Marcar cookie (HTTP only = false aquí, ajustar si prefieres secure/httponly) setcookie( cookie_name, 1, time() POST_VIEWS_COOKIE_LIFETIME, COOKIEPATH ? COOKIEPATH : / ) // Usa transient para acumular vistas pendientes transient_key = POST_VIEWS_TRANSIENT_PREFIX . post_id pending = get_transient( transient_key ) if ( false === pending ) { pending = 0 } pending // Si llegamos al umbral, volcamos al postmeta y reiniciamos el transient if ( pending >= POST_VIEWS_FLUSH_THRESHOLD ) { // Actualizar meta de manera segura current = (int) get_post_meta( post_id, POST_VIEWS_META_KEY, true ) new_total = current pending update_post_meta( post_id, POST_VIEWS_META_KEY, new_total ) // Borrar el transient delete_transient( transient_key ) } else { // Guardar el transient con un tiempo de expiración razonable // Expira en 12 horas por defecto (ajustable) set_transient( transient_key, pending, 12 HOUR_IN_SECONDS ) } } add_action( wp, my_count_post_views, 20 ) ?>
3) Código: función para obtener vistas (sé que puede haber contadores pendientes en transient)
Devuelve la suma entre meta persistente y pending transient para mostrar un número actualizado.
4) Código: inicializar meta si no existe (opcional)
Para evitar valores nulos en meta, se puede inicializar al guardar el post o al activarse el tema.
5) Mostrar las vistas en el tema (ejemplo en single.php o en un template part)
. intval( my_get_post_views() ) . vistas ?>
Mejoras y alternativas
- Conteo por IP en lugar de cookie: almacenar en transient un array de IPs recientes para el post. Esto consume memoria y puede crear problemas de privacidad. No recomendado si buscas escalabilidad sin un sistema centralizado de cache que soporte incrementos atómicos.
- Volcado por tiempo (cron): en vez de umbral, podrías volcar transients periódicamente usando WP Cron. Ventaja: escrituras regulares. Inconveniente: latencia en actualización del contador.
- Uso de cache externo con incrementos atómicos: si tienes Redis o Memcached, puedes usar incrementos atómicos y luego volcar periódicamente a la base de datos para máxima fiabilidad y rendimiento.
- Filtrado de bots: añadir listas de user agents o servicios como BotScout no existe un método perfecto, pero excluir usuarios con comportamiento no humano ayuda.
Concurrencia y atomicidad
La implementación mostrada usa get_transient / set_transient en PHP existe riesgo de condición de carrera (dos peticiones simultáneas leen el mismo pending y escriben incrementos duplicados). Con transients en cache persistente (Redis, Memcached), muchas implementaciones de incrementos atómicos son más seguras. Si tu sitio tiene alta concurrencia y consistencia estricta, considera:
- Usar un sistema de cache con operaciones atómicas (INCR en Redis/Memcached) y volcar periódicamente.
- O usar una consulta SQL atómica para incrementar postmeta: una consulta UPDATE que sume al meta_value existente (requiere manejar el caso en que la fila no exista).
Ejemplo de incremento atómico en DB (opcional, avanzado)
Atención: este método ejecuta SQL directo y debe manejarse con cuidado.
query( wpdb->prepare( UPDATE {wpdb->postmeta} SET meta_value = meta_value 1 WHERE post_id = %d AND meta_key = %s, post_id, meta_key ) ) // Si no se actualizó (no existía la fila), insertamos if ( updated === 0 ) { add_post_meta( post_id, meta_key, 1, true ) } ?>
Buenas prácticas y recomendaciones
- Ajusta POST_VIEWS_FLUSH_THRESHOLD según tu tráfico: mayor umbral = menos escrituras, pero mayor latencia en el conteo persistente.
- Usa cookies con vida razonable (por ejemplo 1 hora) para evitar contar recargas repetidas del mismo visitante en períodos cortos.
- Excluye usuarios con permisos de edición para no inflar métricas internas.
- Monitoriza la cantidad de transients creados y su expiración si usas base de datos para transients (worst-case: crecimiento en la tabla de opciones).
- Si se usa object cache (Redis/Memcached), verificar que los transients realmente se guardan ahí y no en opciones (wp_options) para evitar crecimiento descontrolado.
Comparativa rápida (tabla)
Enfoque | Ventajas | Inconvenientes |
---|---|---|
Post meta puro (update every view) | Simple, persistente inmediatamente | Muchas escrituras DB en sitios con tráfico alto |
Transients volcado por umbral | Reduce escrituras, buena para rendimiento | Latencia en persistencia y posible inconsistencia momentánea |
Cache externo (Redis) con INCR | Escalable y seguro para concurrencia | Requiere infraestructura adicional |
Conclusión
Contar vistas sin plugins en WordPress es completamente viable y, usando transients, se puede reducir significativamente la carga en la base de datos. La combinación de cookies para evitar recuentos repetidos, transient para acumulación y volcado periódico o por umbral al postmeta ofrece un equilibrio sólido entre rendimiento y precisión. Para sitios con gran volumen de tráfico o requisitos de consistencia estrictos, considera integrar un sistema de cache externo con operaciones atómicas o implementar un proceso de volcado más robusto.
Notas finales
- Adapta los valores (umbral, expiración de cookie, duración del transient) a las características de tu sitio.
- Prueba la solución en un entorno staging antes de pasar a producción y monitoriza el comportamiento inicial para ajustar parámetros.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |