Estratégias para migrar seu site da dependência da string do user agent para as novas dicas de cliente HTTP do user agent.
A string User-Agent é uma superfície de impressão digital passiva importante nos navegadores, além de ser difícil de processar. No entanto, há vários motivos válidos para coletar e processar dados de user agent. Portanto, o que é necessário é um caminho para uma solução melhor. As dicas do cliente do user-agent oferecem uma maneira explícita de declarar sua necessidade de dados de user-agent e métodos para retornar os dados em um formato fácil de usar.
Neste artigo, você vai aprender a auditar seu acesso aos dados do user agent e migrar o uso da string do user agent para as dicas de cliente do user agent.
Auditoria da coleta e do uso de dados de user-agent
Como em qualquer forma de coleta de dados, é importante entender por que você está coletando. A primeira etapa, independente de você realizar ou não uma ação, é entender onde e por que você está usando dados de user-agent.
Se você não souber se ou onde os dados do user-agent estão sendo usados, procure
no código front-end o uso de navigator.userAgent
e no código back-end o
uso do cabeçalho HTTP User-Agent
. Também verifique se o código front-end
usa recursos já descontinuados, como navigator.platform
e
navigator.appVersion
.
De um ponto de vista funcional, pense em qualquer lugar do código em que você está gravando ou processando:
- Nome ou versão do navegador
- Nome ou versão do sistema operacional
- Marca ou modelo do dispositivo
- Tipo, arquitetura ou bitness da CPU (por exemplo, 64 bits)
Também é provável que você esteja usando uma biblioteca ou um serviço de terceiros para processar o user-agent. Nesse caso, verifique se eles estão sendo atualizados para oferecer suporte às dicas de cliente do user agent.
Você está usando apenas dados básicos do user-agent?
O conjunto padrão de dicas de cliente HTTP do user agent inclui:
Sec-CH-UA
: nome do navegador e versão principal/significativaSec-CH-UA-Mobile
: valor booleano que indica um dispositivo móvelSec-CH-UA-Platform
: nome do sistema operacional- Observe que isso foi atualizado na especificação e será refletido no Chrome e em outros navegadores baseados em Chromium em breve.
A versão reduzida da string do user-agent proposta também vai manter
essas informações básicas de forma compatível com versões anteriores. Por exemplo, em vez de
Chrome/90.0.4430.85
, a string incluiria Chrome/90.0.0.0
.
Se você estiver verificando apenas a string do user-agent para nome do navegador, versão principal ou sistema operacional, o código continuará funcionando, mas é provável que você receba avisos de descontinuação.
Embora seja possível e recomendável migrar para as dicas de cliente do user agent, você pode ter restrições de código legado ou de recursos que impedem isso. A redução de informações na string do user agent com essa compatibilidade com versões anteriores tem como objetivo garantir que, embora o código atual receba informações menos detalhadas, ele ainda possa manter a funcionalidade básica.
Estratégia: API JavaScript sob demanda do lado do cliente
Se você estiver usando navigator.userAgent
, faça a transição para
preferir navigator.userAgentData
antes de voltar a analisar a
string do user-agent.
if (navigator.userAgentData) {
// use new hints
} else {
// fall back to user-agent string parsing
}
Se você estiver verificando para dispositivos móveis ou computadores, use o valor booleano mobile
:
const isMobile = navigator.userAgentData.mobile;
userAgentData.brands
é uma matriz de objetos com propriedades brand
e version
,
em que o navegador pode listar a compatibilidade com essas
marcas. É possível acessá-lo diretamente como uma matriz ou usar uma
chamada some()
para verificar se uma entrada específica está presente:
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
}
Se você precisar de um dos valores de user-agent mais detalhados e de alta entropia, especifique-o e verifique o resultado no Promise
retornado:
navigator.userAgentData.getHighEntropyValues(['model'])
.then(ua => {
// requested hints available as attributes
const model = ua.model
});
Você também pode usar essa estratégia se quiser mudar do processamento do lado do servidor para o do lado do cliente. A API JavaScript não exige acesso aos cabeçalhos de solicitação HTTP. Portanto, os valores de user-agent podem ser solicitados a qualquer momento.
Estratégia: cabeçalho estático do lado do servidor
Se você estiver usando o cabeçalho de solicitação User-Agent
no servidor e suas necessidades
para esses dados forem relativamente consistentes em todo o site, poderá
especificar as dicas de cliente desejadas como um conjunto estático nas respostas. Essa é uma
abordagem relativamente simples, já que geralmente você só precisa configurá-la em um
local. Por exemplo, pode estar na configuração do servidor da Web, se você já
adicionou cabeçalhos, na configuração de hospedagem ou na configuração de nível superior do
framework ou da plataforma que você usa para o site.
Considere essa estratégia se você estiver transformando ou personalizando as respostas fornecidas com base nos dados do user-agent.
Navegadores ou outros clientes podem fornecer dicas padrão diferentes. Por isso, é uma boa prática especificar tudo o que você precisa, mesmo que seja fornecido por padrão.
Por exemplo, os padrões atuais do Chrome seriam representados como:
⬇️ Cabeçalhos de resposta
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
Se você também quiser receber o modelo do dispositivo nas respostas, envie:
⬇️ Cabeçalhos de resposta
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA
Ao processar isso no servidor, primeiro verifique se o cabeçalho
Sec-CH-UA
desejado foi enviado e, em seguida, use a análise do cabeçalho
User-Agent
se ele não estiver disponível.
Estratégia: delegar dicas para solicitações de origem cruzada
Se você estiver solicitando subrecursos de origem cruzada ou entre sites que exigem que as dicas de cliente do user agent sejam enviadas nas solicitações, será necessário especificar explicitamente as dicas desejadas usando uma política de permissões.
Por exemplo, digamos que https://blog.site
hospede recursos em
https://cdn.site
, que podem retornar recursos otimizados para um dispositivo específico.
O https://blog.site
pode solicitar a sugestão Sec-CH-UA-Model
, mas precisa
delegar isso explicitamente para https://cdn.site
usando o cabeçalho
Permissions-Policy
. A lista de dicas controladas por políticas está disponível no rascunho da infraestrutura
de Client Hints.
⬇️ Resposta de blog.site
delegando a dica
Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")
⬆️ A solicitação para subrecursos em cdn.site
inclui a sugestão delegada
Sec-CH-UA-Model: "Pixel 5"
É possível especificar várias dicas para várias origens, e não apenas do intervalo ch-ua
:
⬇️ Resposta de blog.site
delegando várias dicas para várias origens
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")
Estratégia: delegar dicas para iframes
Os iframes entre origens funcionam de maneira semelhante aos recursos entre origens, mas você
especifica as dicas que gostaria de delegar no atributo allow
.
⬇️ Resposta de blog.site
Accept-CH: Sec-CH-UA-Model
↪️ HTML para blog.site
<iframe src="https://widget.site" allow="ch-ua-model"></iframe>
⬆️ Solicitação para widget.site
Sec-CH-UA-Model: "Pixel 5"
O atributo allow
no iframe vai substituir qualquer cabeçalho Accept-CH
que
o widget.site
possa enviar. Portanto, especifique tudo o que o
site do iframe vai precisar.
Estratégia: dicas dinâmicas do lado do servidor
Se você tiver partes específicas da jornada do usuário em que precisa de uma seleção maior de dicas do que no restante do site, solicite essas dicas sob demanda em vez de estaticamente em todo o site. Isso é mais complexo de gerenciar, mas se você já definiu cabeçalhos diferentes por rota, pode ser viável.
O importante a lembrar aqui é que cada instância do cabeçalho Accept-CH
vai substituir o conjunto atual. Portanto, se você estiver definindo o cabeçalho
de forma dinâmica, cada página precisará solicitar o conjunto completo de dicas necessárias.
Por exemplo, você pode ter uma seção no seu site em que quer fornecer
ícones e controles que correspondem ao sistema operacional do usuário. Para isso, talvez seja necessário
usar Sec-CH-UA-Platform-Version
para fornecer subrecursos
adequados.
⬇️ Cabeçalhos de resposta para /blog
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA
⬇️ Cabeçalhos de resposta para /app
Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA
Estratégia: dicas do lado do servidor necessárias na primeira solicitação
Pode haver casos em que você precisa de mais do que o conjunto padrão de dicas na primeira solicitação. No entanto, isso é raro, então verifique se você analisou o raciocínio.
A primeira solicitação significa a primeira solicitação de nível superior para essa origem enviada nessa sessão de navegação. O conjunto padrão de dicas inclui o nome do navegador com a versão principal, a plataforma e o indicador de dispositivo móvel. A pergunta a ser feita aqui é: você precisa de dados estendidos no carregamento inicial da página?
Para mais dicas sobre a primeira solicitação, há duas opções. Primeiro, você pode
usar o cabeçalho Critical-CH
. Ele tem o mesmo formato de Accept-CH
,
mas informa ao navegador que ele precisa tentar a solicitação imediatamente se a primeira
foi enviada sem a dica crítica.
⬆️ Solicitação inicial
[With default headers]
⬇️ Cabeçalhos de resposta
Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model
🔃 O navegador tenta novamente a solicitação inicial com o cabeçalho extra
[With default headers + …]
Sec-CH-UA-Model: Pixel 5
Isso vai gerar a sobrecarga da nova tentativa na primeira solicitação, mas o custo de implementação é relativamente baixo. Envie o cabeçalho extra, e o navegador fará o resto.
Para situações em que você realmente precisa de dicas adicionais na primeira carga da página, a proposta de confiabilidade de dicas do cliente está definindo uma rota para especificar dicas nas configurações de nível de conexão. Isso usa a extensão Application-Layer Protocol Settings(ALPS) para TLS 1.3 para permitir essa transmissão antecipada de dicas em conexões HTTP/2 e HTTP/3. Isso ainda está em um estágio muito inicial, mas se você gerencia ativamente suas próprias configurações de TLS e conexão, este é o momento ideal para contribuir.
Estratégia: suporte legado
Talvez seu site tenha um código legado ou de terceiros que depende de
navigator.userAgent
, incluindo partes da string do user-agent que serão
reduzidas. A longo prazo, planeje migrar para as chamadas
navigator.userAgentData
equivalentes, mas há uma solução provisória.
O retrofill do UA-CH é uma pequena
biblioteca que permite substituir navigator.userAgent
por uma nova string
criada com base nos valores navigator.userAgentData
solicitados.
Por exemplo, este código gera uma string de user-agent que também inclui a sugestão "model":
import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
.then(() => { console.log(navigator.userAgent); });
A string resultante mostraria o modelo Pixel 5
, mas ainda mostraria o 92.0.0.0
reduzido, porque a sugestão uaFullVersion
não foi solicitada:
Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36
Mais suporte
Se essas estratégias não atenderem ao seu caso de uso, inicie uma discussão no repo privacy-sandbox-dev-support e podemos analisar o problema juntos.
Foto de Ricardo Rocha no Unsplash