Actividad de registro con la API de Web Beacon
Publicado: 2022-03-10 Beacon API es una API web basada en JavaScript para enviar pequeñas cantidades de datos desde el navegador al servidor web sin esperar una respuesta. En este artículo, veremos para qué puede ser útil, qué lo hace diferente de técnicas familiares como XMLHTTPRequest
('Ajax') y cómo puede comenzar a usarlo.
Si ya sabe por qué quiere usar Beacon, no dude en pasar directamente a la sección Primeros pasos.
¿Para qué sirve la API Beacon?
La API Beacon se utiliza para enviar pequeñas cantidades de datos a un servidor sin esperar una respuesta . Esa última parte es crítica y es la clave de por qué Beacon es tan útil: nuestro código nunca llega a ver una respuesta, incluso si el servidor envía una. Las balizas son específicamente para enviar datos y luego olvidarse de ellos. No esperamos una respuesta y no recibimos una respuesta.
Piense en ello como una postal enviada a casa cuando está de vacaciones. Pones una pequeña cantidad de datos en él (un poco de "Ojalá estuvieras aquí" y "Hace buen tiempo"), lo pones en el buzón y no esperas una respuesta. Nadie envía una postal de respuesta diciendo "Sí, me gustaría estar allí, ¡muchas gracias!"
Para los sitios web y las aplicaciones modernos, hay una serie de casos de uso que encajan perfectamente en este patrón de enviar y olvidar.
Seguimiento de estadísticas y datos analíticos
El primer caso de uso que le viene a la mente a la mayoría de las personas es el análisis. Las grandes soluciones como Google Analytics pueden brindar una buena visión general de cosas como las visitas a la página, pero ¿qué sucede si queremos algo más personalizado? Podríamos escribir algo de JavaScript para rastrear lo que está sucediendo en una página (tal vez cómo interactúa un usuario con un componente, hasta dónde se ha desplazado o qué artículos se han mostrado antes de seguir una CTA), pero luego necesitamos enviar esos datos. al servidor cuando el usuario abandona la página. Beacon es perfecto para esto, ya que solo estamos registrando los datos y no necesitamos una respuesta.
No hay razón por la que no podamos cubrir también el tipo de tareas mundanas que a menudo maneja Google Analytics, informando sobre el propio usuario y la capacidad de su dispositivo y navegador. Si el usuario tiene una sesión iniciada, incluso podría vincular esas estadísticas con una persona conocida. Independientemente de los datos que recopile, puede enviarlos de vuelta al servidor con Beacon.
Depuración y registro
Otra aplicación útil para este comportamiento es registrar información de su código JavaScript. Imagine que tiene un componente interactivo complejo en su página que funciona perfectamente para todas sus pruebas, pero que ocasionalmente falla en la producción. Sabe que está fallando, pero no puede ver el error para comenzar a depurarlo. Si puede detectar una falla en el código en sí, puede recopilar diagnósticos y usar Beacon para enviarlo todo para el registro.
De hecho, cualquier tarea de registro se puede realizar de manera útil con Beacon, ya sea creando puntos de guardado en un juego, recopilando información sobre el uso de funciones o registrando los resultados de una prueba multivariada. Si es algo que sucede en el navegador que desea que el servidor sepa, es probable que Beacon sea un competidor.
¿No podemos hacer esto ya?
Sé lo que estás pensando. Nada de esto es nuevo, ¿verdad? Hemos podido comunicarnos desde el navegador al servidor mediante XMLHTTPRequest
durante más de una década. Más recientemente, también tenemos Fetch API, que hace lo mismo con una interfaz más moderna basada en promesas. Dado eso, ¿por qué necesitamos la API Beacon?
La clave aquí es que debido a que no recibimos una respuesta, el navegador puede poner en cola la solicitud y enviarla sin bloquear la ejecución de ningún otro código. En lo que respecta al navegador, no importa si nuestro código aún se está ejecutando o no, o adónde ha llegado la ejecución del script, ya que no hay nada que devolver, puede enviar el envío de la solicitud HTTP hasta que sea conveniente. mándalo.
Eso podría significar esperar hasta que la carga de la CPU sea menor, o hasta que la red esté libre, o incluso enviarlo de inmediato si es posible. Lo importante es que el navegador pone en cola la baliza y devuelve el control inmediatamente. No detiene las cosas mientras envía la baliza.
Para comprender por qué esto es tan importante, debemos ver cómo y cuándo se emiten este tipo de solicitudes desde nuestro código. Tome nuestro ejemplo de un script de registro de análisis. Nuestro código puede medir el tiempo que los usuarios pasan en una página, por lo que es fundamental que los datos se envíen de vuelta al servidor en el último momento posible. Cuando el usuario va a salir de una página, queremos detener el tiempo y enviar los datos a casa.
Por lo general, usaría el evento unload
o beforeunload
para ejecutar el registro. Estos se activan cuando el usuario hace algo como seguir un enlace en la página para navegar. El problema aquí es que el código que se ejecuta en uno de los eventos de unload
puede bloquear la ejecución y retrasar la descarga de la página. Si la descarga de la página se retrasa, la carga de la página siguiente también se retrasa, por lo que la experiencia se siente realmente lenta.
Tenga en cuenta lo lentas que pueden ser las solicitudes HTTP. Si está pensando en el rendimiento, normalmente uno de los principales factores que intenta reducir son las solicitudes HTTP adicionales porque salir a la red y obtener una respuesta puede ser muy lento. Lo último que desea hacer es poner esa lentitud entre la activación de un enlace y el inicio de la solicitud de la página siguiente.
Beacon soluciona esto poniendo en cola la solicitud sin bloquear, devolviendo el control inmediatamente a su secuencia de comandos. El navegador luego se encarga de enviar esa solicitud en segundo plano sin bloquear. Esto hace que todo sea mucho más rápido, lo que hace que los usuarios estén más contentos y nos permite a todos conservar nuestros trabajos.
Empezando
Entonces entendemos qué es Beacon y por qué podríamos usarlo, así que comencemos con algo de código. Los conceptos básicos no podrían ser más simples:
let result = navigator.sendBeacon(url, data);
El resultado es booleano, true
si el navegador aceptó y puso en cola la solicitud, y false
si hubo algún problema al hacerlo.
Usando navigator.sendBeacon()
navigator.sendBeacon
toma dos parámetros. El primero es la URL para realizar la solicitud. La solicitud se realiza como HTTP POST, enviando cualquier dato proporcionado en el segundo parámetro.
El parámetro de datos puede estar en uno de varios formatos, todos si se toman directamente de la API Fetch. Puede ser un Blob
, un BufferSource
, FormData
o URLSearchParams
, básicamente cualquiera de los tipos de cuerpo utilizados al realizar una solicitud con Fetch.
Me gusta usar FormData
para datos básicos de valores clave, ya que no es complicado y es fácil de leer.
// URL to send the data to let url = '/api/my-endpoint'; // Create a new FormData and add a key/value pair let data = new FormData(); data.append('hello', 'world'); let result = navigator.sendBeacon(url, data); if (result) { console.log('Successfully queued!'); } else { console.log('Failure.'); }
Compatibilidad con navegador
El soporte de los navegadores para Beacon es muy bueno, con las únicas excepciones notables de Internet Explorer (funciona en Edge) y Opera Mini. Para la mayoría de los usos, eso debería estar bien, pero vale la pena probar el soporte antes de intentar usar navigator.sendBeacon
.
Eso es fácil de hacer:
if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }
Si Beacon no está disponible y su solicitud es importante, puede recurrir a un método de bloqueo como XHR. Dependiendo de su audiencia y propósito, también puede optar por no molestarse.
Un ejemplo: registro de tiempo en una página
Para ver esto en la práctica, creemos un sistema básico para cronometrar cuánto tiempo permanece un usuario en una página. Cuando se cargue la página, anotaremos la hora y, cuando el usuario abandone la página, enviaremos la hora de inicio y la hora actual al servidor.
Como solo nos importa el tiempo empleado (no la hora real del día), podemos usar performance.now()
para obtener una marca de tiempo básica a medida que se carga la página:
let startTime = performance.now();
Si envolvemos nuestro inicio de sesión en una función, podemos llamarla cuando se descarga la página.
let logVisit = function() { // Test that we have support if (!navigator.sendBeacon) return true; // URL to send the data to, eg let url = '/api/log-visit'; // Data to send let data = new FormData(); data.append('start', startTime); data.append('end', performance.now()); data.append('url', document.URL); // Let's go! navigator.sendBeacon(url, data); };
Finalmente, debemos llamar a esta función cuando el usuario abandona la página. Mi primer instinto fue usar el evento de unload
, pero Safari en una Mac parece bloquear la solicitud con una advertencia de seguridad, por lo que beforeunload
funciona bien para nosotros aquí.
window.addEventListener('beforeunload', logVisit);
Cuando la página se descargue (o, justo antes de que lo haga), se llamará a nuestra función logVisit()
y, siempre que el navegador sea compatible con Beacon API, se enviará nuestra baliza.
(Tenga en cuenta que si no hay compatibilidad con Beacon, devolvemos true
y pretendemos que todo funcionó bien. Devolver false
cancelaría el evento y detendría la descarga de la página. Eso sería desafortunado).
Consideraciones al realizar el seguimiento
Dado que muchos de los usos potenciales de Beacon giran en torno al seguimiento de la actividad, creo que sería negligente no mencionar las responsabilidades sociales y legales que tenemos como desarrolladores al registrar y rastrear la actividad que podría vincularse con los usuarios.
RGPD
Podemos pensar en las recientes leyes europeas de GDPR relacionadas con el correo electrónico, pero, por supuesto, la legislación se relaciona con el almacenamiento de cualquier tipo de datos personales. Si sabe quiénes son sus usuarios y puede identificar sus sesiones, debe verificar qué actividad está registrando y cómo se relaciona con sus políticas establecidas.
A menudo, no necesitamos rastrear tantos datos como nuestros instintos nos dicen los desarrolladores. Puede ser mejor no almacenar deliberadamente información que identificaría a un usuario, y luego reduce la probabilidad de equivocarse.
DNT: No rastrear
Además de los requisitos legales, la mayoría de los navegadores tienen una configuración que permite al usuario expresar su deseo de no ser rastreado. Do Not Track envía un encabezado HTTP con la solicitud que se ve así:
DNT: 1
Si está registrando datos que pueden rastrear a un usuario específico y el usuario envía un encabezado DNT
positivo, sería mejor seguir los deseos del usuario y anonimizar esos datos o no rastrearlos en absoluto.
En PHP, por ejemplo, puede probar fácilmente este encabezado de la siguiente manera:
if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... }
En conclusión
La API Beacon es una forma realmente útil de enviar datos desde una página al servidor, particularmente en un contexto de registro. El soporte del navegador es muy amplio y le permite registrar datos sin problemas sin afectar negativamente la experiencia de navegación del usuario y el rendimiento de su sitio. La naturaleza sin bloqueo de las solicitudes significa que el rendimiento es mucho más rápido que alternativas como XHR y Fetch.
Si desea obtener más información sobre Beacon API, vale la pena visitar los siguientes sitios.
- "Especificación W3C Beacon", Recomendación candidata W3C
- "Documentación de MDN Beacon", documentos web de MDN, Mozilla
- "Información de soporte del navegador", caniuse.com