Estrategias para migrar tu sitio de depender de la string de usuario-agente a las nuevas sugerencias de clientes de usuario-agente
La cadena de usuario-agente es una superficie de creación de huellas digitales pasiva significativa en los navegadores, además de ser difícil de procesar. Sin embargo, existen muchos tipos de motivos válidos para recopilar y procesar datos de usuario-agente, por lo que lo que se necesita es una ruta a una mejor solución. Las Sugerencias de clientes de usuario-agente proporcionan una forma explícita de declarar la necesidad de datos de usuario-agente y métodos para mostrar los datos en un formato fácil de usar.
En este artículo, se explica cómo auditar tu acceso a los datos de usuarios-agentes y cómo migrar el uso de cadenas de usuarios-agentes a User-Agent Client Hints.
Auditar la recopilación y el uso de los datos del usuario-agente
Al igual que con cualquier forma de recopilación de datos, siempre debes comprender por qué los recopilas. El primer paso, independientemente de si vas a realizar o no alguna acción, es comprender dónde y por qué usas los datos del usuario-agente.
Si no sabes si se usan los datos del usuario-agente o dónde se usan, busca en tu código de frontend para usar navigator.userAgent
y en tu código de backend para usar el encabezado HTTP User-Agent
. También debes verificar tu código de frontend para ver si usas funciones que ya no están disponibles, como navigator.platform
y navigator.appVersion
.
Desde un punto de vista funcional, piensa en cualquier parte del código en la que estés grabando o procesando:
- Nombre o versión del navegador
- Nombre o versión del sistema operativo
- Marca o modelo del dispositivo
- Tipo de CPU, arquitectura o cantidad de bits (por ejemplo, 64 bits)
También es probable que utilices una biblioteca o un servicio de terceros para procesar el usuario-agente. En este caso, verifica si se están actualizando para admitir User-Agent Client Hints.
¿Solo usas datos básicos de usuario-agente?
El conjunto predeterminado de User-Agent Client Hints incluye lo siguiente:
Sec-CH-UA
: Indica el nombre del navegador y la versión principal o significativa.Sec-CH-UA-Mobile
: Es un valor booleano que indica un dispositivo móvil.Sec-CH-UA-Platform
: Es el nombre del sistema operativo.- Ten en cuenta que esto se actualizó en la especificación y pronto se reflejará en Chrome y en otros navegadores basados en Chromium.
La versión reducida de la string usuario-agente que se propone también retendrá esta información básica de una manera retrocompatible. Por ejemplo, en lugar de Chrome/90.0.4430.85
, la string incluiría Chrome/90.0.0.0
.
Si solo verificas el nombre del navegador, la versión principal o el sistema operativo de la string de usuario-agente, tu código seguirá funcionando, aunque es probable que veas advertencias de baja.
Si bien puedes y debes migrar a User-Agent Client Hints, es posible que tengas código heredado o restricciones de recursos que impidan esta acción. La reducción de información en la string usuario-agente de esta manera retrocompatible tiene el objetivo de garantizar que, si bien el código existente recibirá información menos detallada, aún debe mantener la funcionalidad básica.
Estrategia: API de JavaScript del cliente a pedido
Si actualmente usas navigator.userAgent
, debes hacer la transición a priorizar navigator.userAgentData
antes de analizar la string usuario-agente.
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
Si quieres comprobar si tu app es para dispositivos móviles o computadoras, usa el valor booleano mobile
:
const isMobile = navigator.userAgentData.mobile;
userAgentData.brands
es un array de objetos con propiedades brand
y version
en el que el navegador puede indicar su compatibilidad con esas marcas. Puedes acceder a él directamente como un array, o bien puedes usar una llamada a some()
para verificar si hay una entrada específica:
function isCompatible(item) {
// In real life you most likely have more complex rules here
return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
// browser reports as compatible
}
Si necesitas uno de los valores de usuario-agente más detallados y con alta entropía, deberás especificarlo y verificar el resultado en el Promise
que se muestra:
navigator.userAgentData.getHighEntropyValues(['model'])
.then(ua => {
// requested hints available as attributes
const model = ua.model
});
También puedes usar esta estrategia si deseas pasar del procesamiento del servidor al procesamiento del cliente. La API de JavaScript no requiere acceso a los encabezados de solicitudes HTTP, por lo que los valores de usuario-agente se pueden solicitar en cualquier momento.
Estrategia: Encabezado estático del servidor
Si usas el encabezado de la solicitud User-Agent
en el servidor y tus necesidades para esos datos son relativamente coherentes en todo tu sitio, puedes especificar las sugerencias de clientes deseadas como un conjunto estático en tus respuestas. Este es un enfoque relativamente simple, ya que, por lo general, solo necesitas configurarlo en una ubicación. Por ejemplo, puede estar en la configuración del servidor web si ya agregaste encabezados allí, la configuración de hosting o la configuración de nivel superior del framework o la plataforma que usas para tu sitio.
Considera esta estrategia si transformas o personalizas las respuestas que se entregan en función de los datos del usuario-agente.
Los navegadores y otros clientes pueden optar por proporcionar diferentes sugerencias predeterminadas, por lo que se recomienda especificar todo lo que necesitas, incluso si generalmente se proporciona de forma predeterminada.
Por ejemplo, la configuración predeterminada actual de Chrome se representa de la siguiente manera:
⬇️ Encabezados de respuesta
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
Si también quisieras recibir el modelo de dispositivo en las respuestas, deberías enviar lo siguiente:
⬇️ Encabezados de respuesta
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA
Cuando procesas esto en el servidor, primero debes verificar si se envió el encabezado Sec-CH-UA
deseado y, luego, recurrir al análisis del encabezado User-Agent
si no está disponible.
Estrategia: Delegación de sugerencias a solicitudes de origen cruzado
Si solicitas subrecursos de origen cruzado o entre sitios que requieren que se envíen sugerencias de clientes de usuario-agente en sus solicitudes, deberás especificar de forma explícita las sugerencias deseadas mediante una política de permisos.
Por ejemplo, supongamos que https://blog.site
aloja recursos en https://cdn.site
, que pueden mostrar recursos optimizados para un dispositivo específico.
https://blog.site
puede solicitar la sugerencia Sec-CH-UA-Model
, pero necesita delegarla explícitamente a https://cdn.site
con el encabezado Permissions-Policy
. La lista de sugerencias controladas por políticas está disponible en el borrador de infraestructura de Clients Hints.
⬇️ Respuesta de blog.site
delegando la pista
Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")
⬆️ La solicitud a los subrecursos en cdn.site
incluye la sugerencia delegada
Sec-CH-UA-Model: "Pixel 5"
Puedes especificar varias sugerencias para varios orígenes, y no solo para el rango ch-ua
:
⚠️ Respuesta de blog.site
para delegar varias sugerencias a varios orígenes
Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
ch-dpr=(self "https://cdn.site" "https://img.site")
Estrategia: Delegación de sugerencias a iframes
Los iframes de origen cruzado funcionan de manera similar a los recursos de origen cruzado, pero debes
especificar las sugerencias que deseas delegar en el atributo allow
.
⬇️ Respuesta de blog.site
Accept-CH: Sec-CH-UA-Model
↪️ HTML para blog.site
<iframe src="https://widget.site" allow="ch-ua-model"></iframe>
⬆️ Solicitud a widget.site
Sec-CH-UA-Model: "Pixel 5"
El atributo allow
del iframe anulará cualquier encabezado Accept-CH
que
widget.site
pueda enviarse a sí mismo. Por lo tanto, asegúrate de especificar todo lo que
necesitará el sitio del iframe.
Estrategia: Sugerencias dinámicas del servidor
Si tienes partes específicas del recorrido del usuario en las que necesitas una selección más amplia de sugerencias que en el resto del sitio, puedes solicitarlas a pedido en lugar de solicitarlas de manera estática en todo el sitio. Esto es más complejo de administrar, pero es posible que ya hayas configurado diferentes encabezados por ruta.
Lo importante que debes recordar aquí es que cada instancia del encabezado Accept-CH
reemplazará de manera efectiva el conjunto existente. Por lo tanto, si configuras el encabezado de forma dinámica, cada página debe solicitar el conjunto completo de sugerencias necesarias.
Por ejemplo, puedes tener una sección en tu sitio en la que quieras proporcionar íconos y controles que coincidan con el sistema operativo del usuario. Para ello, te recomendamos que extraigas Sec-CH-UA-Platform-Version
a fin de entregar los subrecursos adecuados.
⬇️ Encabezados de respuesta para /blog
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
⬇️ Encabezados de respuesta para /app
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA
Estrategia: Se requieren sugerencias del servidor en la primera solicitud
Puede haber casos en los que necesites más que el conjunto predeterminado de sugerencias en la primera solicitud. Sin embargo, es probable que esto sea poco frecuente, así que asegúrate de revisar el motivo.
En realidad, la primera solicitud se refiere a la primera solicitud de nivel superior para ese origen enviada en esa sesión de navegación. El conjunto predeterminado de sugerencias incluye el nombre del navegador con la versión principal, la plataforma y el indicador de dispositivos móviles. La pregunta que debes hacerte es si necesitas datos extendidos en la carga inicial de la página.
Para obtener sugerencias adicionales en la primera solicitud, hay dos opciones. Primero, puedes usar el encabezado Critical-CH
. Esto toma el mismo formato que Accept-CH
, pero le indica al navegador que debe reintentar la solicitud de inmediato si la primera se envió sin la sugerencia crítica.
⬆️ Solicitud inicial
[With default headers]
⬇️ Encabezados de respuesta
Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model
🔃 El navegador reintenta la solicitud inicial con el encabezado adicional
[With default headers + …]
Sec-CH-UA-Model: Pixel 5
Esto generará la sobrecarga del reintento en la primera solicitud, pero el costo de implementación es relativamente bajo. Envía el encabezado adicional, y el navegador se encargará del resto.
Para situaciones en las que lo que necesitas realmente requieren sugerencias adicionales en la primera carga de la página, la propuesta de confiabilidad de Client Hints establece una ruta para especificar sugerencias en la configuración de nivel de conexión. De esta manera, se usa la extensión Configuración del protocolo de la capa de la aplicación(ALPS) en TLS 1.3 para habilitar la transmisión anticipada de sugerencias en las conexiones HTTP/2 y HTTP/3. Esto aún se encuentra en una etapa muy temprana, pero si administras de forma activa tu propia TLS y configuración de conexión, este es el momento ideal para contribuir.
Estrategia: Asistencia heredada
Es posible que tengas código heredado o de terceros en tu sitio que depende de navigator.userAgent
, incluidas las partes de la cadena usuario-agente que se reducirán. A largo plazo, deberías planear pasar a las llamadas equivalentes a navigator.userAgentData
, pero existe una solución provisional.
UA-CH retrofill es una biblioteca pequeña que te permite reemplazar navigator.userAgent
por una nueva cadena compilada a partir de los valores navigator.userAgentData
solicitados.
Por ejemplo, este código generará una string usuario-agente que además incluye la sugerencia de “modelo”:
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
La cadena resultante mostraría el modelo Pixel 5
, pero aún mostrará el 92.0.0.0
reducido, ya que no se solicitó la sugerencia uaFullVersion
:
Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36
Asistencia adicional
Si estas estrategias no cubren tu caso de uso, inicia un debate en el repositorio de privacy-sandbox-dev-support para que podamos explorar tu problema juntos.
Foto de Ricardo Rocha en Unsplash