Pular para conteúdo

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:

interface ComplyrLoadedDetail {
  version: string;        // Versão do script (ex: "1.2.3")
}

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

  1. Abrir DevTools (F12)
  2. Ir em SourcesEvent Listener Breakpoints
  3. Expandir Control
  4. Marcar load (para complyr:loaded)
  5. Expandir Custom
  6. 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

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

  1. Sempre remova listeners em SPAs e componentes React
  2. Use { once: true } para eventos que executam uma vez
  3. Valide event.detail antes de usar (TypeScript ajuda)
  4. Aguarde complyr:loaded antes de usar window.complyr
  5. Log eventos em desenvolvimento para debug
  6. Use Promises para fluxos assíncronos complexos

❌ DON'T: Evitar

  1. Não confie que eventos sempre disparam - adicione fallbacks
  2. Não adicione listeners dentro de loops sem remover
  3. Não modifique event.detail - é read-only
  4. Não bloqueie thread em event handlers (use async)
  5. 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?