Eventos JavaScript¶
Lista completa de eventos customizados disparados pelo Complyr para reagir a mudanças de consentimento, identificação de usuários e outras ações importantes.
📋 Visão Geral¶
O Complyr dispara eventos customizados usando a API nativa CustomEvent do JavaScript. Você pode escutar esses eventos para:
- Reagir a mudanças de consentimento
- Executar código após identificação de usuário
- Monitorar revogação de consentimento
- Rastrear aceitação de políticas
- Detectar quando o Complyr carrega completamente
Características: - ✅ Padrão Web: Usa window.addEventListener() - ✅ Detalhes Tipados: Cada evento inclui event.detail com dados relevantes - ✅ Não-bloqueante: Eventos são assíncronos - ✅ Bubbling: Eventos propagam pelo DOM
🎯 Lista de Eventos¶
O Complyr dispara 5 eventos principais:
| Evento | Quando Dispara | Dados (event.detail) |
|---|---|---|
| complyr:loaded | Script carregou completamente | { version: string } |
| complyr:consent-updated | Consentimento foi atualizado | { purposes: {...}, status: string } |
| complyr:consent-revoked | Consentimento foi revogado | { reason?: string, timestamp: Date } |
| complyr:user-identified | Usuário foi identificado | { type: string } |
| complyr:policy-accepted | Política foi aceita | { policyType: string, user: string } |
🔔 Eventos Detalhados¶
complyr:loaded¶
Disparado quando o script Complyr carrega completamente e window.complyr está disponível.
Quando usar: - Executar código que depende da API Complyr - Inicializar integrações que requerem consentimento - Validar que o script carregou corretamente
Dados do Evento:
Exemplo:
window.addEventListener('complyr:loaded', function(event) {
console.log('Complyr carregado - Versão:', event.detail.version);
// Agora é seguro usar window.complyr
if (window.complyr) {
console.log('API disponível:', window.complyr);
}
});
Caso de Uso: Identificação Automática
// Identificar usuário assim que Complyr carregar
window.addEventListener('complyr:loaded', function() {
const user = getCurrentUser(); // Sua função de autenticação
if (user && user.email) {
window.complyr.identify('email', user.email);
}
});
complyr:consent-updated¶
Disparado sempre que o consentimento do usuário é atualizado (aceite inicial, mudança de preferências).
Quando usar: - Ativar/desativar scripts de rastreamento - Atualizar interface do site baseado em consentimento - Registrar mudanças de consentimento - Integrar com analytics
Dados do Evento:
interface ComplyrConsentUpdatedDetail {
purposes: {
essential: boolean;
analytics: boolean;
marketing: boolean;
personalization: boolean;
third_party: boolean;
};
status: 'GRANTED' | 'PARTIAL' | 'DENIED';
timestamp: Date;
}
Exemplo Básico:
window.addEventListener('complyr:consent-updated', function(event) {
const consent = event.detail;
console.log('Consentimento atualizado:', consent.status);
console.log('Marketing permitido:', consent.purposes.marketing);
// Reagir a mudanças
if (consent.purposes.marketing) {
console.log('✅ Carregar scripts de marketing');
loadMarketingScripts();
} else {
console.log('❌ Marketing bloqueado');
}
});
Exemplo Avançado: Gerenciar Scripts
window.addEventListener('complyr:consent-updated', function(event) {
const { purposes, status } = event.detail;
// Analytics
if (purposes.analytics) {
if (!window.gtag) {
loadGoogleAnalytics();
}
} else {
// Remover cookies de analytics se revogado
deleteAnalyticsCookies();
}
// Marketing
if (purposes.marketing) {
if (!window.fbq) {
loadFacebookPixel();
}
} else {
// Remover cookies de marketing
deleteFacebookCookies();
}
// Personalização
if (purposes.personalization) {
enablePersonalizedContent();
} else {
disablePersonalizedContent();
}
// Log para auditoria
logConsentChange({
status,
purposes,
timestamp: event.detail.timestamp
});
});
Exemplo: Atualizar UI
window.addEventListener('complyr:consent-updated', function(event) {
const { purposes } = event.detail;
// Atualizar badge de consentimento no footer
const badge = document.getElementById('consent-badge');
if (badge) {
const count = Object.values(purposes).filter(Boolean).length;
badge.textContent = `${count}/5 finalidades ativas`;
}
// Atualizar switches de preferências
document.getElementById('analytics-toggle').checked = purposes.analytics;
document.getElementById('marketing-toggle').checked = purposes.marketing;
document.getElementById('personalization-toggle').checked = purposes.personalization;
});
complyr:consent-revoked¶
Disparado quando o usuário revoga todo o consentimento via window.complyr.revokeConsent().
Quando usar: - Limpar dados de rastreamento - Desativar features que requerem consentimento - Registrar revogação para auditoria LGPD - Redirecionar usuário ou exibir mensagem
Dados do Evento:
interface ComplyrConsentRevokedDetail {
reason?: string; // Motivo da revogação (se fornecido)
timestamp: Date; // Quando foi revogado
}
Exemplo Básico:
window.addEventListener('complyr:consent-revoked', function(event) {
console.log('⚠️ Consentimento revogado');
if (event.detail.reason) {
console.log('Motivo:', event.detail.reason);
}
// Limpar todos os scripts de rastreamento
removeAllTrackingScripts();
// Limpar cookies
clearAllConsentCookies();
// Exibir mensagem ao usuário
showNotification('Seus dados foram excluídos com sucesso.');
});
Exemplo Avançado: Auditoria LGPD
window.addEventListener('complyr:consent-revoked', function(event) {
const { reason, timestamp } = event.detail;
// Registrar revogação no backend para compliance
fetch('/api/audit/consent-revoked', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: getCurrentUserId(),
reason: reason || 'Não especificado',
timestamp: timestamp,
userAgent: navigator.userAgent,
ipAddress: null // Backend adiciona IP
})
});
// Limpar localStorage
const keysToRemove = Object.keys(localStorage).filter(key =>
key.startsWith('analytics_') ||
key.startsWith('marketing_') ||
key.startsWith('fbp_')
);
keysToRemove.forEach(key => localStorage.removeItem(key));
// Desabilitar features
disablePersonalization();
disableRecommendations();
// Recarregar página para garantir limpeza
setTimeout(() => {
window.location.reload();
}, 2000);
});
Exemplo: Botão "Excluir Dados"
// HTML
// <button id="delete-data-btn">Excluir Meus Dados</button>
document.getElementById('delete-data-btn').addEventListener('click', async function() {
if (confirm('Tem certeza que deseja excluir todos os seus dados?')) {
// Revogar consentimento
window.complyr.revokeConsent('Usuário solicitou exclusão de dados - LGPD Art. 18, VI');
// Escutar confirmação
window.addEventListener('complyr:consent-revoked', function handler(event) {
// Remover listener após uso
window.removeEventListener('complyr:consent-revoked', handler);
// Chamar API de exclusão de conta
deleteUserAccount();
// Redirecionar
window.location.href = '/conta-excluida';
}, { once: true });
}
});
complyr:user-identified¶
Disparado quando um usuário é identificado via window.complyr.identify().
Quando usar: - Confirmar que identificação foi processada - Ativar Advanced Matching - Registrar identificação no analytics - Sincronizar identificação com outros sistemas
Dados do Evento:
interface ComplyrUserIdentifiedDetail {
type: 'email' | 'phone' | 'name'; // Tipo de identificação usado
timestamp: Date;
}
Exemplo Básico:
window.addEventListener('complyr:user-identified', function(event) {
console.log('✅ Usuário identificado via:', event.detail.type);
// Confirmar que Advanced Matching está ativo
if (event.detail.type === 'email') {
console.log('Facebook Pixel Advanced Matching ativo');
}
});
Exemplo Avançado: Múltiplos Identificadores
// Identificar com múltiplos dados após login
async function handleLogin(user) {
// Identificar por email
window.complyr.identify('email', user.email);
// Aguardar confirmação
await new Promise(resolve => {
window.addEventListener('complyr:user-identified', function handler(event) {
if (event.detail.type === 'email') {
window.removeEventListener('complyr:user-identified', handler);
resolve();
}
});
});
// Identificar por telefone (se disponível)
if (user.phone) {
window.complyr.identify('phone', user.phone);
}
// Identificar por nome
if (user.name) {
window.complyr.identify('name', user.name);
}
console.log('✅ Usuário completamente identificado');
}
Exemplo: React Hook com Evento
// hooks/useComplyrIdentification.ts
import { useEffect, useState } from 'react';
import { useAuth } from '@/contexts/auth-context';
export function useComplyrIdentification() {
const { user } = useAuth();
const [identified, setIdentified] = useState(false);
useEffect(() => {
if (!user?.email || !window.complyr) return;
// Identificar
window.complyr.identify('email', user.email);
// Escutar confirmação
const handler = (event: CustomEvent) => {
if (event.detail.type === 'email') {
setIdentified(true);
console.log('✅ Usuário identificado no Complyr');
}
};
window.addEventListener('complyr:user-identified', handler as EventListener);
return () => {
window.removeEventListener('complyr:user-identified', handler as EventListener);
};
}, [user]);
return { identified };
}
// Uso
export default function Dashboard() {
const { identified } = useComplyrIdentification();
return (
<div>
{identified && <div>Advanced Matching ativo ✅</div>}
</div>
);
}
complyr:policy-accepted¶
Disparado quando uma política é aceita via window.complyr.acceptPolicy().
Quando usar: - Confirmar registro de aceite - Avançar fluxo de cadastro - Registrar auditoria de aceite - Habilitar features após aceite de termos
Dados do Evento:
interface ComplyrPolicyAcceptedDetail {
policyType: 'privacy-policy' | 'terms-of-service' | 'cookie-policy' | 'data-processing';
userIdentifier: string; // Email ou ID do usuário
timestamp: Date;
}
Exemplo Básico:
window.addEventListener('complyr:policy-accepted', function(event) {
const { policyType, userIdentifier } = event.detail;
console.log(`✅ Política aceita: ${policyType}`);
console.log(`Usuário: ${userIdentifier}`);
});
Exemplo: Fluxo de Cadastro
// Formulário de cadastro
async function handleRegister(formData) {
try {
// 1. Criar conta
const user = await api.register({
name: formData.name,
email: formData.email,
password: formData.password
});
// 2. Registrar aceite de Termos de Uso
if (formData.acceptedTerms) {
window.complyr.acceptPolicy('terms-of-service', user.email);
// 3. Aguardar confirmação
await new Promise(resolve => {
window.addEventListener('complyr:policy-accepted', function handler(event) {
if (event.detail.policyType === 'terms-of-service') {
window.removeEventListener('complyr:policy-accepted', handler);
resolve();
}
});
});
}
// 4. Registrar aceite de Política de Privacidade
if (formData.acceptedPrivacy) {
await window.complyr.acceptPolicy('privacy-policy', user.email);
}
// 5. Sucesso - redirecionar
showSuccess('Conta criada com sucesso!');
window.location.href = '/dashboard';
} catch (error) {
console.error('Erro no cadastro:', error);
showError('Erro ao criar conta');
}
}
Exemplo: Auditoria de Aceites
// Monitorar todos os aceites de políticas
window.addEventListener('complyr:policy-accepted', function(event) {
const { policyType, userIdentifier, timestamp } = event.detail;
// Registrar no backend para auditoria LGPD
fetch('/api/audit/policy-acceptance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
policyType,
userIdentifier,
timestamp,
userAgent: navigator.userAgent,
referrer: document.referrer
})
});
// Log local
console.log(`📋 [AUDIT] Política ${policyType} aceita por ${userIdentifier}`);
});
🎓 Padrões de Uso¶
Aguardar Carregamento do Complyr¶
Sempre verifique se Complyr está carregado antes de usar a API:
// ❌ ERRADO: Pode falhar se script não carregou
window.complyr.identify('email', 'user@example.com');
// ✅ CORRETO: Aguarda evento de carregamento
window.addEventListener('complyr:loaded', function() {
window.complyr.identify('email', 'user@example.com');
});
// ✅ ALTERNATIVA: Verificação condicional
if (window.complyr) {
window.complyr.identify('email', 'user@example.com');
} else {
window.addEventListener('complyr:loaded', function() {
window.complyr.identify('email', 'user@example.com');
});
}
Escutar Apenas Uma Vez¶
Use { once: true } para eventos que devem executar apenas uma vez:
// Executar apenas no primeiro consentimento
window.addEventListener('complyr:consent-updated', function(event) {
console.log('Primeira vez que usuário deu consentimento');
initializeTrackingScripts();
}, { once: true });
// Equivalente a removeEventListener manual
function handler(event) {
console.log('Evento disparado');
window.removeEventListener('complyr:consent-updated', handler);
}
window.addEventListener('complyr:consent-updated', handler);
Remover Listeners¶
Sempre remova listeners quando não forem mais necessários (especialmente em SPAs):
// Salvar referência ao handler
function consentHandler(event) {
console.log('Consentimento:', event.detail);
}
// Adicionar listener
window.addEventListener('complyr:consent-updated', consentHandler);
// Remover quando não precisar mais
window.removeEventListener('complyr:consent-updated', consentHandler);
React Cleanup:
useEffect(() => {
const handler = (event: CustomEvent) => {
console.log('Consentimento:', event.detail);
};
window.addEventListener('complyr:consent-updated', handler as EventListener);
// Cleanup ao desmontar
return () => {
window.removeEventListener('complyr:consent-updated', handler as EventListener);
};
}, []);
Promises com Eventos¶
Converter eventos em Promises para uso com async/await:
function waitForConsentUpdate() {
return new Promise((resolve) => {
window.addEventListener('complyr:consent-updated', function handler(event) {
window.removeEventListener('complyr:consent-updated', handler);
resolve(event.detail);
});
});
}
// Uso
async function handleConsentFlow() {
console.log('Aguardando consentimento...');
const consent = await waitForConsentUpdate();
console.log('Consentimento recebido:', consent);
}
Combinar Múltiplos Eventos¶
// Monitorar identificação E consentimento
let identified = false;
let consented = false;
window.addEventListener('complyr:user-identified', function() {
identified = true;
checkReady();
});
window.addEventListener('complyr:consent-updated', function(event) {
consented = event.detail.purposes.marketing === true;
checkReady();
});
function checkReady() {
if (identified && consented) {
console.log('✅ Usuário identificado E consentiu marketing');
enableAdvancedMarketing();
}
}
🔍 Debug de Eventos¶
Monitorar Todos os Eventos¶
// Debug: Log de todos os eventos Complyr
const complyrEvents = [
'complyr:loaded',
'complyr:consent-updated',
'complyr:consent-revoked',
'complyr:user-identified',
'complyr:policy-accepted'
];
complyrEvents.forEach(eventName => {
window.addEventListener(eventName, function(event) {
console.log(`[${eventName}]`, event.detail);
});
});
Chrome DevTools: Event Listener Breakpoints¶
- Abrir DevTools (F12)
- Ir em Sources → Event Listener Breakpoints
- Expandir Control
- Marcar load (para complyr:loaded)
- Expandir Custom
- Adicionar breakpoint:
complyr:consent-updated
Verificar Listeners Ativos¶
// Verificar se há listeners ativos
function getEventListeners(target, eventName) {
// Somente funciona no DevTools Console
return getEventListeners(target)[eventName] || [];
}
// No DevTools Console:
getEventListeners(window)['complyr:consent-updated']
// → Array de listeners registrados
📊 Casos de Uso Completos¶
Caso 1: E-commerce com Analytics Condicional¶
// Carregar Google Analytics apenas se consentimento de analytics ativo
window.addEventListener('complyr:consent-updated', function(event) {
const { purposes } = event.detail;
if (purposes.analytics && !window.gtag) {
// Carregar GA4
const script = document.createElement('script');
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX`;
document.head.appendChild(script);
script.onload = () => {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
console.log('✅ Google Analytics carregado');
};
} else if (!purposes.analytics && window.gtag) {
// Desabilitar GA se consentimento revogado
window['ga-disable-G-XXXXXXXXXX'] = true;
console.log('❌ Google Analytics desabilitado');
}
});
Caso 2: SaaS com Identificação Automática¶
// App.js (React)
useEffect(() => {
// Aguardar Complyr carregar
window.addEventListener('complyr:loaded', function() {
// Obter usuário autenticado
const user = getCurrentUser();
if (user?.email) {
// Identificar
window.complyr.identify('email', user.email);
// Confirmar identificação
window.addEventListener('complyr:user-identified', function(event) {
console.log('✅ Usuário identificado:', event.detail.type);
// Enviar evento para analytics interno
analytics.track('user_identified', {
type: event.detail.type,
timestamp: event.detail.timestamp
});
}, { once: true });
}
}, { once: true });
}, []);
Caso 3: Formulário de Cadastro Completo¶
// registration-form.js
const form = document.getElementById('registration-form');
form.addEventListener('submit', async function(event) {
event.preventDefault();
const formData = new FormData(form);
const email = formData.get('email');
const password = formData.get('password');
const acceptedTerms = formData.get('accept-terms') === 'on';
const acceptedPrivacy = formData.get('accept-privacy') === 'on';
try {
// 1. Criar conta
const user = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
}).then(r => r.json());
// 2. Registrar aceites de políticas
const policyPromises = [];
if (acceptedTerms) {
policyPromises.push(
window.complyr.acceptPolicy('terms-of-service', email)
);
}
if (acceptedPrivacy) {
policyPromises.push(
window.complyr.acceptPolicy('privacy-policy', email)
);
}
await Promise.all(policyPromises);
// 3. Escutar confirmações
let policiesAccepted = 0;
const expectedPolicies = policyPromises.length;
window.addEventListener('complyr:policy-accepted', function handler(event) {
policiesAccepted++;
console.log(`✅ Política aceita: ${event.detail.policyType}`);
if (policiesAccepted === expectedPolicies) {
window.removeEventListener('complyr:policy-accepted', handler);
// 4. Identificar usuário
window.complyr.identify('email', email);
// 5. Redirecionar
window.location.href = '/dashboard';
}
});
} catch (error) {
console.error('Erro no cadastro:', error);
alert('Erro ao criar conta. Tente novamente.');
}
});
🌐 Compatibilidade¶
Navegadores Suportados¶
| Navegador | Versão Mínima | CustomEvent |
|---|---|---|
| Chrome | 60+ | ✅ Completo |
| Firefox | 55+ | ✅ Completo |
| Safari | 11+ | ✅ Completo |
| Edge | 79+ (Chromium) | ✅ Completo |
| Opera | 47+ | ✅ Completo |
| IE 11 | - | ⚠️ Polyfill necessário |
Polyfill para IE11¶
// Polyfill para CustomEvent em IE11
(function() {
if (typeof window.CustomEvent === "function") return false;
function CustomEvent(event, params) {
params = params || { bubbles: false, cancelable: false, detail: null };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
window.CustomEvent = CustomEvent;
})();
📚 TypeScript Definitions¶
Interface de Eventos¶
/**
* Detalhes do evento complyr:loaded
*/
interface ComplyrLoadedDetail {
version: string;
}
/**
* Detalhes do evento complyr:consent-updated
*/
interface ComplyrConsentUpdatedDetail {
purposes: {
essential: boolean;
analytics: boolean;
marketing: boolean;
personalization: boolean;
third_party: boolean;
};
status: 'GRANTED' | 'PARTIAL' | 'DENIED';
timestamp: Date;
}
/**
* Detalhes do evento complyr:consent-revoked
*/
interface ComplyrConsentRevokedDetail {
reason?: string;
timestamp: Date;
}
/**
* Detalhes do evento complyr:user-identified
*/
interface ComplyrUserIdentifiedDetail {
type: 'email' | 'phone' | 'name';
timestamp: Date;
}
/**
* Detalhes do evento complyr:policy-accepted
*/
interface ComplyrPolicyAcceptedDetail {
policyType: 'privacy-policy' | 'terms-of-service' | 'cookie-policy' | 'data-processing';
userIdentifier: string;
timestamp: Date;
}
/**
* Mapa de tipos de eventos
*/
interface ComplyrEventMap {
'complyr:loaded': CustomEvent<ComplyrLoadedDetail>;
'complyr:consent-updated': CustomEvent<ComplyrConsentUpdatedDetail>;
'complyr:consent-revoked': CustomEvent<ComplyrConsentRevokedDetail>;
'complyr:user-identified': CustomEvent<ComplyrUserIdentifiedDetail>;
'complyr:policy-accepted': CustomEvent<ComplyrPolicyAcceptedDetail>;
}
/**
* Extensão do Window para addEventListener tipado
*/
declare global {
interface Window {
addEventListener<K extends keyof ComplyrEventMap>(
type: K,
listener: (this: Window, ev: ComplyrEventMap[K]) => any,
options?: boolean | AddEventListenerOptions
): void;
}
}
export {};
Uso com TypeScript¶
// events.ts
import type { ComplyrConsentUpdatedDetail } from './complyr-events';
// Tipagem automática do event.detail
window.addEventListener('complyr:consent-updated', (event: CustomEvent<ComplyrConsentUpdatedDetail>) => {
const { purposes, status, timestamp } = event.detail; // ✅ Tipado
if (purposes.marketing) {
console.log('Marketing ativo');
}
});
// React Hook tipado
import { useEffect } from 'react';
import type { ComplyrUserIdentifiedDetail } from './complyr-events';
export function useComplyrIdentified(callback: (detail: ComplyrUserIdentifiedDetail) => void) {
useEffect(() => {
const handler = (event: CustomEvent<ComplyrUserIdentifiedDetail>) => {
callback(event.detail);
};
window.addEventListener('complyr:user-identified', handler as EventListener);
return () => {
window.removeEventListener('complyr:user-identified', handler as EventListener);
};
}, [callback]);
}
⚠️ Boas Práticas¶
✅ DO: Fazer¶
- Sempre remova listeners em SPAs e componentes React
- Use
{ once: true }para eventos que executam uma vez - Valide
event.detailantes de usar (TypeScript ajuda) - Aguarde
complyr:loadedantes de usarwindow.complyr - Log eventos em desenvolvimento para debug
- Use Promises para fluxos assíncronos complexos
❌ DON'T: Evitar¶
- Não confie que eventos sempre disparam - adicione fallbacks
- Não adicione listeners dentro de loops sem remover
- Não modifique
event.detail- é read-only - Não bloqueie thread em event handlers (use async)
- Não ignore erros em handlers assíncronos
🔗 Recursos Relacionados¶
API: - window.complyr - Objeto global e métodos - identify() - Identificação de usuários - revokeConsent() - Revogar consentimento - acceptPolicy() - Aceitar políticas - openPreferences() - Abrir preferências
Recursos: - Exemplos Práticos - Casos de uso completos - API Overview - Visão geral da API
📞 Suporte¶
Dúvidas sobre eventos JavaScript?
- FAQ - Perguntas frequentes
- Documentação Completa - Índice geral
- Email: contato@complyr.com.br