Instalação
Adicione o snippet antes de</body>, substituindo SITE_ID pelo site_id do seu site (painel → Sites):
data-site-id é o único atributo obrigatório. Sem ele, o script não faz nada — nenhum banner, nenhuma chamada de rede.
Como funciona
Em cada carregamento de página, o script:- Deriva a base da API da própria URL do script (
document.currentScript.src, com fallback para uma busca porscript[src*="/api/v1/script.js"]). Se o script foi carregado dehttps://www.consentfly.com.br/..., todas as chamadas vão parahttps://www.consentfly.com.br/api/v1. - Reenvia silenciosamente qualquer consentimento pendente de uma visita anterior em que a rede falhou (ver Fila offline).
- Busca a configuração do site em
GET /api/v1/public/site/{siteId}— textos, link da política,policy_version,geo_enablede oscript_token. - Decide se exibe o banner (ver Quando o banner não aparece).
- Ao clicar em Aceitar, Recusar ou salvar preferências no modal, grava a decisão em
localStorageprimeiro, fecha o banner imediatamente e enviaPOST /api/v1/public/consentem segundo plano com o headerX-Site-Token.
Atributos de configuração
Todos opcionais, excetodata-site-id. Atributos de texto têm precedência sobre a configuração cadastrada no painel; os de política só são usados como fallback quando a busca de configuração falha.
Categorias de consentimento
O modal “Configurar cookies” expõe três categorias:- Aceitar envia
accepted: truecomanalytics: true, marketing: true. - Recusar envia
accepted: falsecom ambasfalse. - Salvar preferências (modal) envia
accepted: truecom os toggles escolhidos.
Armazenamento no navegador
O script usalocalStorage — nenhum cookie é criado — com fallback em memória quando localStorage está indisponível (modo privado restrito, etc.). Também não faz nenhuma requisição a terceiros: fala apenas com a origem de onde foi servido.
O prefixo
haldenhub- é permanente — chaves de armazenamento, ids de DOM (haldenhub-banner, haldenhub-modal) e classes CSS (haldenhub-button, …) mantêm esse nome para que decisões já gravadas nos navegadores dos visitantes continuem válidas. Não trate como erro nem espere renomeação.Quando o banner não aparece
O script encerra sem montar nada quando qualquer condição abaixo vale:- Já existe consentimento válido:
haldenhub-consentguarda uma decisão para o mesmosite_ide a mesmapolicy_version. Publicar uma nova versão da política reexibe o banner para todos. show_banner: falsena configuração do site (hoje o servidor sempre enviatrue; o campo existe para supressão futura sem nova versão do script).- Geofencing ativo e visitante fora da região (abaixo).
data-site-idausente ou o script já foi inicializado na página (guardawindow.haldenhubBannerInitializedcontra inclusão dupla).
Geofencing
Chave opcional por site (padrão desligado) que restringe a exibição do banner a visitantes da UE/EEE + Reino Unido + Suíça. Pensada para clientes que operam fora do Brasil e só querem o banner onde ele é expectativa legal. A decisão roda no navegador, não no servidor: o script comparaIntl.DateTimeFormat().resolvedOptions().timeZone com uma lista de zonas IANA dessas jurisdições. Fora da lista, o script encerra — sem DOM, sem chamadas.
Falha aberta, de propósito: zona desconhecida, navegador sem Intl ou qualquer exceção resultam em banner exibido. Mostrar o banner a quem não precisava é um incômodo; escondê-lo de quem precisava é falha de compliance — só um dos dois é aceitável.
Geofencing é uma decisão de exibição, não um controle de acesso. Um visitante pode mentir sobre o próprio fuso horário — a única coisa que ele muda com isso é ver ou não o banner. Territórios ultramarinos com fuso próprio (Guiana Francesa, Reunião) ficam fora da lista e caem no lado seguro: banner exibido. Para sites com público brasileiro, mantenha a chave desligada — a LGPD vale para todo visitante, independentemente da origem.
Personalização visual
O script injeta um CSS próprio (cores fixas, botão de aceite em azul escuro) e não há atributo de tema ou cor de destaque. A personalização é feita por CSS do seu site, sobrescrevendo as classeshaldenhub-* — que são estáveis (ver nota sobre o prefixo acima):
z-index: 2147483647 e o modal fica logo abaixo, para nunca serem cobertos pelo layout do site.
Token do site e rotação
Cada site tem umscript_token que autentica o POST /public/consent. O token viaja no header X-Site-Token (o fallback via navigator.sendBeacon usa o parâmetro ?script_token=). Ele é entregue ao navegador dentro do payload de GET /public/site/{siteId} — ou seja, não é um segredo: é uma chave por site que permite revogar um embed vazado sem invalidar os demais sites.
- A verificação falha fechada: token inválido ou ausente retorna
401com códigounauthorized(“Invalid or missing script token”). Nenhum consentimento é gravado. - Rotacione com
POST /api/v1/sites/{siteId}/rotate-script-token(autenticado) ou pelo painel. A rotação invalida o cache da configuração pública; visitantes recebem o token novo no próximo carregamento de página.
Fila offline
A decisão do visitante é gravada localmente antes de qualquer chamada de rede, então o clique sempre é honrado mesmo se o backend, a rede ou uma CSP bloquearem a requisição:- O payload é salvo em
haldenhub-consent-pendinge o banner fecha imediatamente. - O envio acontece em segundo plano; se o
fetchfalhar, o script tentanavigator.sendBeaconcomo último recurso. - Sucesso limpa a fila; falha mantém o payload, que é reenviado silenciosamente no próximo carregamento de página.
created_at do registro é o momento de recepção no servidor, não o do clique.
Limites e caching
POST /public/consenttem corpo limitado a 64 KiB (413acima disso) e rate limit de 30 req/min por cliente e 600 req/min por site (429comtoo_many_requests).- O
script.jsé servido comCache-Control: public, max-age=300e a configuração do site é cacheada no servidor. Mudanças de texto/política feitas no painel podem levar até ~5 minutos para aparecer nos visitantes. - O IP bruto do visitante nunca é persistido — o servidor resolve país/região e descarta o endereço antes da gravação.
Troubleshooting
O banner não aparece
- Consentimento já registrado neste navegador. Limpe
haldenhub-consent(e opcionalmentehaldenhub-consent-id) nolocalStoragee recarregue. É o motivo mais comum durante testes. data-site-idausente ou vazio na tag do script.site_idinexistente:GET /public/site/{siteId}retorna404e o script cai no modo fallback — nesse caso o banner ainda aparece com os textos padrão, mas os envios não serão aceitos. Confira o Network do DevTools.- Geofencing ligado e o fuso horário do navegador está fora da UE/EEE/UK/CH. Desligue a chave no painel ou teste com o fuso de um país coberto.
- Script incluído duas vezes: só a primeira inicialização roda (
window.haldenhubBannerInitialized). - Bloqueio por CSP ou adblock: verifique se
script-srcpermitewww.consentfly.com.bre se não há extensão bloqueando a requisição.
401 unauthorized no POST /public/consent
- Token rotacionado com página antiga aberta: abas carregadas antes da rotação seguram o token velho. O payload fica na fila offline e é reenviado — mas continuará falhando até o visitante recarregar a página e receber o token novo.
- Requisição manual sem
X-Site-Token: o endpoint exige o token em toda chamada (header,?script_token=ou camposcript_tokenno corpo). - Fallback ativo: se a busca de configuração falhou, o script monta o banner sem token e os envios retornam
401até a configuração voltar a carregar.
Erros de CORS
- Os endpoints públicos aceitam qualquer origem, sem credenciais — o script chama com
credentials: "omit". Se você vê erro de CORS, quase sempre a causa é a armadilha do proxy: o script foi servido de outro domínio e está chamando/api/v1nesse domínio, que não existe ou responde sem os headers de CORS. - Confira também
connect-srcna sua CSP: ele precisa permitirhttps://www.consentfly.com.br.
Dúvidas? suporte@consentfly.com.br
