acceptPolicy()¶
Visão Geral¶
O método acceptPolicy() permite registrar programaticamente a aceitação de uma política (Termos de Uso, Política de Privacidade, etc.) por parte de um usuário identificado. Este método é essencial para conformidade com LGPD, que exige consentimento explícito e rastreável.
Para Que Serve?¶
O acceptPolicy() é utilizado em fluxos onde o usuário precisa aceitar políticas específicas:
- Registro de Usuários: Aceitar Termos de Uso e Política de Privacidade durante cadastro
- Checkout de E-commerce: Aceitar políticas antes de finalizar compra
- Acesso a Recursos: Aceitar políticas específicas antes de usar funcionalidades
- Conformidade LGPD: Registrar aceitação explícita com auditoria completa
- Integrações via API: Registrar aceitação de políticas em sistemas backend
Assinatura TypeScript¶
interface ComplyrAPI {
/**
* Registra a aceitação de uma política específica por um usuário identificado
*
* @param policyType - Tipo da política ('privacy-policy', 'terms-of-service', etc.)
* @param userIdentifier - Identificador único do usuário (email recomendado)
* @returns Promise que resolve quando a aceitação for registrada
* @throws Error se o script Complyr não estiver carregado ou se houver falha na requisição
*/
acceptPolicy(policyType: string, userIdentifier: string): Promise<void>;
}
// Acesso via window
declare global {
interface Window {
complyr?: ComplyrAPI;
}
}
Parâmetros¶
policyType (string, obrigatório)¶
Tipo da política a ser aceita. Valores suportados:
| Valor | Descrição | Uso Comum |
|---|---|---|
privacy-policy | Política de Privacidade | Registro, newsletters |
terms-of-service | Termos de Uso | Registro, acesso à plataforma |
cookie-policy | Política de Cookies | Banner de cookies |
data-processing | Acordo de Processamento de Dados | Compartilhamento de dados |
Importante: O policyType deve corresponder a uma política publicada no workspace Complyr.
userIdentifier (string, obrigatório)¶
Identificador único do usuário que está aceitando a política.
Recomendado: Email do usuário
Requisitos: - Deve ser um identificador único e persistente - Será hasheado (SHA-256) antes de ser enviado ao servidor - Não pode ser vazio ou apenas espaços em branco
Exemplos válidos:
'usuario@example.com' // ✅ Email (recomendado)
'user-uuid-12345' // ✅ UUID do sistema
'CPF-12345678900' // ✅ CPF (será hasheado)
Exemplos inválidos:
Valor de Retorno¶
Tipo: Promise<void>
Resolução: - Promise resolve quando a aceitação for registrada com sucesso no backend - Não retorna nenhum valor (void)
Rejeição: - Promise rejeita se houver erro na requisição - Mensagem de erro disponível em error.message
Exemplo de uso com async/await:
try {
await window.complyr.acceptPolicy('privacy-policy', 'usuario@example.com');
console.log('✅ Política aceita com sucesso');
} catch (error) {
console.error('❌ Erro ao aceitar política:', error.message);
}
Exemplos Práticos¶
1. Formulário de Registro HTML¶
Aceitar Termos de Uso e Política de Privacidade durante cadastro:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Registro - Minha Empresa</title>
<!-- Carregar script Complyr -->
<script
src="https://app.complyr.com.br/tag/js"
data-workspace-id="seu-workspace-id"
data-complyr-script
async
defer>
</script>
</head>
<body>
<form id="registration-form">
<h1>Criar Conta</h1>
<label for="name">Nome Completo</label>
<input type="text" id="name" name="name" required>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="password">Senha</label>
<input type="password" id="password" name="password" required>
<!-- Checkbox de aceitação -->
<label>
<input type="checkbox" id="accept-terms" required>
Li e aceito os
<a href="#" onclick="window.complyr.loadPolicy('terms-of-service', '#policy-modal'); return false;">
Termos de Uso
</a>
e a
<a href="#" onclick="window.complyr.loadPolicy('privacy-policy', '#policy-modal'); return false;">
Política de Privacidade
</a>
</label>
<button type="submit">Criar Conta</button>
</form>
<!-- Container para exibir políticas -->
<div id="policy-modal"></div>
<script>
document.getElementById('registration-form').addEventListener('submit', async function(e) {
e.preventDefault();
const email = document.getElementById('email').value;
const acceptTerms = document.getElementById('accept-terms').checked;
if (!acceptTerms) {
alert('Você precisa aceitar os Termos de Uso e a Política de Privacidade');
return;
}
try {
// Aguardar carregamento do Complyr
if (!window.complyr) {
console.error('Script Complyr não carregado');
return;
}
// Registrar aceitação das políticas
await window.complyr.acceptPolicy('terms-of-service', email);
await window.complyr.acceptPolicy('privacy-policy', email);
console.log('✅ Políticas aceitas com sucesso');
// Enviar formulário para seu backend
const formData = new FormData(this);
const response = await fetch('/api/register', {
method: 'POST',
body: formData
});
if (response.ok) {
alert('Conta criada com sucesso! Verifique seu email.');
window.location.href = '/login';
} else {
alert('Erro ao criar conta. Tente novamente.');
}
} catch (error) {
console.error('Erro ao processar registro:', error);
alert('Erro ao registrar políticas. Tente novamente.');
}
});
// Aguardar carregamento do Complyr
document.addEventListener('complyr:loaded', function() {
console.log('✅ Complyr carregado e pronto');
});
</script>
</body>
</html>
2. Componente React de Registro¶
Integração com React para formulário de cadastro:
import React, { useState } from 'react';
interface RegistrationFormProps {
onSuccess?: () => void;
}
export const RegistrationForm: React.FC<RegistrationFormProps> = ({ onSuccess }) => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
acceptTerms: false,
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError(null);
// Validar aceitação de termos
if (!formData.acceptTerms) {
setError('Você precisa aceitar os Termos de Uso e a Política de Privacidade');
return;
}
setLoading(true);
try {
// Verificar se Complyr está carregado
if (!window.complyr) {
throw new Error('Sistema de conformidade não disponível. Recarregue a página.');
}
// Registrar aceitação das políticas
await window.complyr.acceptPolicy('terms-of-service', formData.email);
await window.complyr.acceptPolicy('privacy-policy', formData.email);
console.log('✅ Políticas aceitas:', {
email: formData.email,
policies: ['terms-of-service', 'privacy-policy'],
timestamp: new Date().toISOString(),
});
// Enviar dados do usuário para backend
const response = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: formData.name,
email: formData.email,
password: formData.password,
}),
});
if (!response.ok) {
throw new Error('Erro ao criar conta');
}
// Sucesso
alert('Conta criada com sucesso! Verifique seu email.');
onSuccess?.();
} catch (err) {
console.error('Erro no registro:', err);
setError(err instanceof Error ? err.message : 'Erro ao processar registro');
} finally {
setLoading(false);
}
};
const handleViewPolicy = (policyType: string) => {
if (window.complyr) {
window.complyr.loadPolicy(policyType, '#policy-modal');
}
};
return (
<div className="registration-form">
<h1>Criar Conta</h1>
{error && (
<div className="alert alert-error">
{error}
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="name">Nome Completo</label>
<input
type="text"
id="name"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
required
/>
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
type="email"
id="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
required
/>
</div>
<div className="form-group">
<label htmlFor="password">Senha</label>
<input
type="password"
id="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
required
minLength={8}
/>
</div>
<div className="form-group checkbox">
<label>
<input
type="checkbox"
checked={formData.acceptTerms}
onChange={(e) => setFormData({ ...formData, acceptTerms: e.target.checked })}
required
/>
Li e aceito os{' '}
<button
type="button"
onClick={() => handleViewPolicy('terms-of-service')}
className="link-button"
>
Termos de Uso
</button>
{' '}e a{' '}
<button
type="button"
onClick={() => handleViewPolicy('privacy-policy')}
className="link-button"
>
Política de Privacidade
</button>
</label>
</div>
<button
type="submit"
disabled={loading}
className="btn btn-primary"
>
{loading ? 'Criando conta...' : 'Criar Conta'}
</button>
</form>
{/* Container para exibir políticas */}
<div id="policy-modal"></div>
</div>
);
};
// TypeScript declaration
declare global {
interface Window {
complyr?: {
acceptPolicy(policyType: string, userIdentifier: string): Promise<void>;
loadPolicy(policyType: string, selector: string): void;
};
}
}
3. Hook React Personalizado¶
Custom hook para facilitar aceitação de políticas em qualquer componente:
import { useState, useCallback } from 'react';
interface UsePolicyAcceptanceOptions {
onSuccess?: () => void;
onError?: (error: Error) => void;
}
interface UsePolicyAcceptanceResult {
acceptPolicy: (policyType: string, userIdentifier: string) => Promise<void>;
acceptMultiplePolicies: (policyTypes: string[], userIdentifier: string) => Promise<void>;
loading: boolean;
error: Error | null;
}
export const usePolicyAcceptance = (
options: UsePolicyAcceptanceOptions = {}
): UsePolicyAcceptanceResult => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const acceptPolicy = useCallback(async (
policyType: string,
userIdentifier: string
) => {
setLoading(true);
setError(null);
try {
if (!window.complyr) {
throw new Error('Complyr não está disponível');
}
await window.complyr.acceptPolicy(policyType, userIdentifier);
console.log(`✅ Política aceita: ${policyType}`, {
user: userIdentifier,
timestamp: new Date().toISOString(),
});
options.onSuccess?.();
} catch (err) {
const error = err instanceof Error ? err : new Error('Erro desconhecido');
setError(error);
options.onError?.(error);
throw error;
} finally {
setLoading(false);
}
}, [options]);
const acceptMultiplePolicies = useCallback(async (
policyTypes: string[],
userIdentifier: string
) => {
setLoading(true);
setError(null);
try {
if (!window.complyr) {
throw new Error('Complyr não está disponível');
}
// Aceitar todas as políticas em paralelo
await Promise.all(
policyTypes.map(type => window.complyr!.acceptPolicy(type, userIdentifier))
);
console.log(`✅ ${policyTypes.length} políticas aceitas`, {
policies: policyTypes,
user: userIdentifier,
timestamp: new Date().toISOString(),
});
options.onSuccess?.();
} catch (err) {
const error = err instanceof Error ? err : new Error('Erro desconhecido');
setError(error);
options.onError?.(error);
throw error;
} finally {
setLoading(false);
}
}, [options]);
return {
acceptPolicy,
acceptMultiplePolicies,
loading,
error,
};
};
// Exemplo de uso do hook
export const RegistrationFormWithHook: React.FC = () => {
const [email, setEmail] = useState('');
const [acceptTerms, setAcceptTerms] = useState(false);
const { acceptMultiplePolicies, loading, error } = usePolicyAcceptance({
onSuccess: () => {
alert('Políticas aceitas! Conta criada com sucesso.');
window.location.href = '/dashboard';
},
onError: (error) => {
console.error('Erro ao aceitar políticas:', error);
},
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!acceptTerms) {
alert('Você precisa aceitar as políticas');
return;
}
try {
await acceptMultiplePolicies(
['terms-of-service', 'privacy-policy'],
email
);
} catch (err) {
// Erro já tratado pelo hook
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<label>
<input
type="checkbox"
checked={acceptTerms}
onChange={(e) => setAcceptTerms(e.target.checked)}
/>
Aceito as políticas
</label>
{error && <p className="error">{error.message}</p>}
<button type="submit" disabled={loading}>
{loading ? 'Processando...' : 'Criar Conta'}
</button>
</form>
);
};
4. Vue.js Composable¶
Composable para Vue 3 com Composition API:
import { ref } from 'vue';
interface PolicyAcceptanceOptions {
onSuccess?: () => void;
onError?: (error: Error) => void;
}
export function usePolicyAcceptance(options: PolicyAcceptanceOptions = {}) {
const loading = ref(false);
const error = ref<Error | null>(null);
const acceptPolicy = async (policyType: string, userIdentifier: string) => {
loading.value = true;
error.value = null;
try {
if (!window.complyr) {
throw new Error('Complyr não está disponível');
}
await window.complyr.acceptPolicy(policyType, userIdentifier);
console.log(`✅ Política aceita: ${policyType}`, {
user: userIdentifier,
timestamp: new Date().toISOString(),
});
options.onSuccess?.();
} catch (err) {
const errorObj = err instanceof Error ? err : new Error('Erro desconhecido');
error.value = errorObj;
options.onError?.(errorObj);
throw errorObj;
} finally {
loading.value = false;
}
};
const acceptMultiplePolicies = async (
policyTypes: string[],
userIdentifier: string
) => {
loading.value = true;
error.value = null;
try {
if (!window.complyr) {
throw new Error('Complyr não está disponível');
}
await Promise.all(
policyTypes.map(type => window.complyr!.acceptPolicy(type, userIdentifier))
);
console.log(`✅ ${policyTypes.length} políticas aceitas`);
options.onSuccess?.();
} catch (err) {
const errorObj = err instanceof Error ? err : new Error('Erro desconhecido');
error.value = errorObj;
options.onError?.(errorObj);
throw errorObj;
} finally {
loading.value = false;
}
};
return {
acceptPolicy,
acceptMultiplePolicies,
loading,
error,
};
}
Exemplo de uso no componente Vue:
<template>
<form @submit.prevent="handleSubmit">
<h1>Criar Conta</h1>
<div v-if="error" class="alert alert-error">
{{ error.message }}
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
id="email"
v-model="formData.email"
required
/>
</div>
<div class="form-group">
<label>
<input
type="checkbox"
v-model="formData.acceptTerms"
required
/>
Li e aceito as políticas
</label>
</div>
<button type="submit" :disabled="loading">
{{ loading ? 'Processando...' : 'Criar Conta' }}
</button>
</form>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import { usePolicyAcceptance } from '@/composables/usePolicyAcceptance';
const formData = reactive({
email: '',
acceptTerms: false,
});
const { acceptMultiplePolicies, loading, error } = usePolicyAcceptance({
onSuccess: () => {
alert('Conta criada com sucesso!');
window.location.href = '/dashboard';
},
});
const handleSubmit = async () => {
if (!formData.acceptTerms) {
alert('Você precisa aceitar as políticas');
return;
}
try {
await acceptMultiplePolicies(
['terms-of-service', 'privacy-policy'],
formData.email
);
} catch (err) {
console.error('Erro:', err);
}
};
</script>
5. E-commerce: Checkout com Aceitação de Políticas¶
Aceitar políticas durante finalização de compra:
// Checkout page
document.addEventListener('DOMContentLoaded', function() {
const checkoutForm = document.getElementById('checkout-form');
checkoutForm.addEventListener('submit', async function(e) {
e.preventDefault();
const customerEmail = document.getElementById('customer-email').value;
const acceptDataProcessing = document.getElementById('accept-data-processing').checked;
if (!acceptDataProcessing) {
alert('Você precisa aceitar o Acordo de Processamento de Dados para continuar');
return;
}
try {
// Registrar aceitação do acordo de processamento de dados
if (window.complyr) {
await window.complyr.acceptPolicy('data-processing', customerEmail);
console.log('✅ Acordo de processamento aceito');
}
// Processar pagamento
const paymentData = {
email: customerEmail,
amount: calculateTotal(),
items: getCartItems(),
};
const response = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(paymentData),
});
if (response.ok) {
window.location.href = '/order-confirmation';
} else {
alert('Erro ao processar pedido');
}
} catch (error) {
console.error('Erro no checkout:', error);
alert('Erro ao processar pedido. Tente novamente.');
}
});
});
6. WordPress: Plugin de Registro¶
Integração com WordPress para aceitar políticas no registro:
<?php
/**
* Plugin Name: Complyr Policy Acceptance
* Description: Integra aceitação de políticas Complyr no registro do WordPress
* Version: 1.0.0
*/
// Adicionar campos ao formulário de registro
add_action('register_form', 'complyr_add_registration_fields');
function complyr_add_registration_fields() {
?>
<p>
<label>
<input type="checkbox" name="accept_policies" required />
<?php _e('Li e aceito os'); ?>
<a href="#" onclick="event.preventDefault(); window.complyr.loadPolicy('terms-of-service', '#policy-container');">
<?php _e('Termos de Uso'); ?>
</a>
<?php _e('e a'); ?>
<a href="#" onclick="event.preventDefault(); window.complyr.loadPolicy('privacy-policy', '#policy-container');">
<?php _e('Política de Privacidade'); ?>
</a>
</label>
</p>
<div id="policy-container"></div>
<?php
}
// Validar aceitação antes de criar usuário
add_filter('registration_errors', 'complyr_validate_registration', 10, 3);
function complyr_validate_registration($errors, $sanitized_user_login, $user_email) {
if (!isset($_POST['accept_policies'])) {
$errors->add('policy_error', __('Você precisa aceitar as políticas para continuar'));
}
return $errors;
}
// Registrar aceitação após criar usuário
add_action('user_register', 'complyr_register_policy_acceptance');
function complyr_register_policy_acceptance($user_id) {
$user = get_userdata($user_id);
$workspace_id = get_option('complyr_workspace_id');
if (!$workspace_id || !$user) {
return;
}
// Enfileirar JavaScript para registrar aceitação
add_action('wp_footer', function() use ($user) {
?>
<script>
document.addEventListener('complyr:loaded', async function() {
try {
await window.complyr.acceptPolicy('terms-of-service', '<?php echo esc_js($user->user_email); ?>');
await window.complyr.acceptPolicy('privacy-policy', '<?php echo esc_js($user->user_email); ?>');
console.log('✅ Políticas registradas para novo usuário');
} catch (error) {
console.error('Erro ao registrar políticas:', error);
}
});
</script>
<?php
});
}
// Adicionar script Complyr ao header
add_action('wp_head', 'complyr_add_script');
function complyr_add_script() {
$workspace_id = get_option('complyr_workspace_id');
if (!$workspace_id) {
return;
}
?>
<script
src="https://app.complyr.com.br/tag/js"
data-workspace-id="<?php echo esc_attr($workspace_id); ?>"
data-complyr-script
async
defer>
</script>
<?php
}
7. Next.js API Route¶
Aceitar políticas via rota de API server-side:
// pages/api/register.ts
import type { NextApiRequest, NextApiResponse } from 'next';
interface RegisterRequest {
name: string;
email: string;
password: string;
acceptPolicies: boolean;
}
interface RegisterResponse {
success: boolean;
message: string;
userId?: string;
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<RegisterResponse>
) {
if (req.method !== 'POST') {
return res.status(405).json({ success: false, message: 'Method not allowed' });
}
const { name, email, password, acceptPolicies }: RegisterRequest = req.body;
// Validar dados
if (!acceptPolicies) {
return res.status(400).json({
success: false,
message: 'Você precisa aceitar as políticas',
});
}
try {
// 1. Criar usuário no banco de dados
const user = await createUser({ name, email, password });
// 2. Registrar aceitação de políticas via Complyr API
const workspaceId = process.env.COMPLYR_WORKSPACE_ID!;
const apiUrl = process.env.COMPLYR_API_URL || 'https://app.complyr.com.br/api';
// Aceitar múltiplas políticas em paralelo
await Promise.all([
fetch(`${apiUrl}/policy-acceptances`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Workspace-ID': workspaceId,
},
body: JSON.stringify({
policyType: 'terms-of-service',
userEmail: email,
}),
}),
fetch(`${apiUrl}/policy-acceptances`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Workspace-ID': workspaceId,
},
body: JSON.stringify({
policyType: 'privacy-policy',
userEmail: email,
}),
}),
]);
console.log(`✅ Políticas registradas para ${email}`);
// 3. Enviar email de boas-vindas
await sendWelcomeEmail(email, name);
return res.status(201).json({
success: true,
message: 'Conta criada com sucesso',
userId: user.id,
});
} catch (error) {
console.error('Erro no registro:', error);
return res.status(500).json({
success: false,
message: 'Erro ao criar conta',
});
}
}
// Funções auxiliares
async function createUser(data: { name: string; email: string; password: string }) {
// Implementação de criação de usuário
// ...
return { id: 'user-123' };
}
async function sendWelcomeEmail(email: string, name: string) {
// Implementação de envio de email
// ...
}
Componente Next.js correspondente:
// components/RegistrationForm.tsx
'use client';
import { useState } from 'react';
export default function RegistrationForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
acceptPolicies: false,
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
// Validar frontend
if (!formData.acceptPolicies) {
alert('Você precisa aceitar as políticas');
return;
}
// Enviar para API route
const response = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});
const data = await response.json();
if (data.success) {
alert('Conta criada com sucesso!');
window.location.href = '/login';
} else {
alert(data.message);
}
} catch (error) {
console.error('Erro:', error);
alert('Erro ao criar conta');
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
{/* Campos do formulário */}
<input
type="text"
placeholder="Nome"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
required
/>
<input
type="email"
placeholder="Email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
required
/>
<input
type="password"
placeholder="Senha"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
required
/>
<label>
<input
type="checkbox"
checked={formData.acceptPolicies}
onChange={(e) => setFormData({ ...formData, acceptPolicies: e.target.checked })}
required
/>
Aceito as políticas
</label>
<button type="submit" disabled={loading}>
{loading ? 'Criando...' : 'Criar Conta'}
</button>
</form>
);
}
Fluxo de Execução¶
sequenceDiagram
participant User as Usuário
participant App as Aplicação
participant Complyr as window.complyr
participant API as Complyr API
participant DB as Banco de Dados
User->>App: Clica em "Criar Conta"
App->>App: Valida campos do formulário
App->>App: Verifica acceptTerms === true
App->>Complyr: acceptPolicy('terms-of-service', email)
Complyr->>Complyr: Valida parâmetros
Complyr->>Complyr: Hasheia email (SHA-256)
Complyr->>API: POST /policy-acceptances
Note over API: { policyType, userEmail (hashed), workspaceId }
API->>DB: Registra aceitação
DB-->>API: Aceitação salva
API-->>Complyr: 200 OK
Complyr-->>App: Promise resolved
App->>Complyr: acceptPolicy('privacy-policy', email)
Complyr->>API: POST /policy-acceptances
API->>DB: Registra aceitação
DB-->>API: Aceitação salva
API-->>Complyr: 200 OK
Complyr-->>App: Promise resolved
App->>App: Cria usuário no sistema
App->>User: Exibe "Conta criada com sucesso"
App->>App: Redireciona para /dashboard Conformidade LGPD¶
Consentimento Explícito (Art. 7º, I)¶
O método acceptPolicy() implementa conformidade com o artigo 7º, inciso I da LGPD, que exige consentimento explícito do titular dos dados:
Art. 7º O tratamento de dados pessoais somente poderá ser realizado nas seguintes hipóteses:
I - mediante o fornecimento de consentimento pelo titular;
Como o Complyr implementa:
- Aceitação Ativa: Usuário deve marcar checkbox explicitamente (não pode ser pré-marcada)
- Rastreabilidade: Registro inclui timestamp, IP, user-agent e identificador do usuário
- Granularidade: Cada política é aceita individualmente, permitindo controle por finalidade
- Revogabilidade: Usuário pode revogar consentimento a qualquer momento via
revokeConsent()
Registro de Aceitação (Auditoria)¶
Toda chamada a acceptPolicy() gera registro de auditoria no backend:
{
"id": "uuid-123",
"workspaceId": "workspace-456",
"policyType": "privacy-policy",
"userEmail": "hash-sha256-do-email",
"acceptedAt": "2025-10-22T14:30:00Z",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0...",
"consentVersion": "1.0.0"
}
Informações rastreadas: - ✅ Quem aceitou (identificador hasheado) - ✅ O que aceitou (tipo de política) - ✅ Quando aceitou (timestamp UTC) - ✅ De onde aceitou (endereço IP) - ✅ Como aceitou (navegador, dispositivo) - ✅ Versão da política aceita
Finalidade Específica¶
Cada política aceita deve ter finalidade clara e específica:
| Política | Finalidade | Exemplo de Uso |
|---|---|---|
terms-of-service | Uso da plataforma | Acesso aos recursos do sistema |
privacy-policy | Tratamento de dados pessoais | Coleta, armazenamento, processamento |
cookie-policy | Cookies e rastreamento | Analytics, personalização, publicidade |
data-processing | Compartilhamento com terceiros | Processadores de pagamento, email |
Tempo de Retenção¶
As aceitações de políticas são mantidas pelo tempo necessário para comprovar conformidade com LGPD:
- Durante relacionamento ativo: Enquanto usuário usar o serviço
- Após encerramento: 5 anos para fins de defesa legal (Art. 16, I)
- Exclusão a pedido: Usuário pode solicitar exclusão via DSAR (Art. 18, VI)
Tratamento de Erros¶
Erros Comuns¶
1. Script Complyr não carregado:
try {
if (!window.complyr) {
throw new Error('Sistema de conformidade não disponível');
}
await window.complyr.acceptPolicy('privacy-policy', email);
} catch (error) {
console.error('Erro:', error.message);
// Fallback: salvar aceitação localmente e sincronizar depois
localStorage.setItem('pending_policy_acceptance', JSON.stringify({
policyType: 'privacy-policy',
email: email,
timestamp: new Date().toISOString(),
}));
}
2. Política não encontrada:
try {
await window.complyr.acceptPolicy('invalid-policy', email);
} catch (error) {
if (error.message.includes('not found')) {
console.error('Política não existe no workspace');
alert('Erro de configuração. Contate o suporte.');
}
}
3. Erro de rede:
try {
await window.complyr.acceptPolicy('privacy-policy', email);
} catch (error) {
if (error.message.includes('network') || error.message.includes('timeout')) {
console.error('Erro de conexão:', error);
// Tentar novamente após 3 segundos
setTimeout(async () => {
try {
await window.complyr.acceptPolicy('privacy-policy', email);
console.log('✅ Política aceita na segunda tentativa');
} catch (retryError) {
console.error('Falha na segunda tentativa:', retryError);
}
}, 3000);
}
}
4. Email inválido:
const email = userInput.trim();
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
alert('Email inválido');
return;
}
try {
await window.complyr.acceptPolicy('privacy-policy', email);
} catch (error) {
console.error('Erro ao aceitar política:', error);
}
Estratégia de Retry com Exponential Backoff¶
Para aplicações críticas, implemente retry automático:
async function acceptPolicyWithRetry(policyType, email, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
await window.complyr.acceptPolicy(policyType, email);
console.log(`✅ Política aceita (tentativa ${attempt})`);
return; // Sucesso
} catch (error) {
lastError = error;
console.warn(`⚠️ Tentativa ${attempt} falhou:`, error.message);
if (attempt < maxRetries) {
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt - 1) * 1000;
console.log(`Aguardando ${delay}ms antes de tentar novamente...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Todas as tentativas falharam
throw new Error(`Falha após ${maxRetries} tentativas: ${lastError.message}`);
}
// Uso
try {
await acceptPolicyWithRetry('privacy-policy', 'usuario@example.com');
} catch (error) {
console.error('❌ Não foi possível registrar aceitação:', error);
// Notificar usuário e/ou salvar localmente
}
Verificação de Debug¶
1. Verificar se política foi aceita¶
Consulte o localStorage para verificar aceitações locais:
// Verificar consentimento armazenado
const consent = localStorage.getItem('complyr_consent');
if (consent) {
const consentData = JSON.parse(consent);
console.log('Consentimento armazenado:', consentData);
}
// Verificar via API (requer autenticação)
const response = await fetch(`https://app.complyr.com.br/api/policy-acceptances?email=${email}`);
const acceptances = await response.json();
console.log('Políticas aceitas:', acceptances);
2. Verificar chamadas de rede¶
Abra DevTools → Network → XHR/Fetch e procure por:
- Endpoint:
POST https://app.complyr.com.br/api/policy-acceptances - Status:
200 OK(sucesso) - Payload:
3. Console Logs¶
Ative logs detalhados:
// Antes de chamar acceptPolicy
console.log('🔵 Iniciando aceitação de política', {
policyType: 'privacy-policy',
email: email,
timestamp: new Date().toISOString(),
});
await window.complyr.acceptPolicy('privacy-policy', email);
console.log('✅ Política aceita com sucesso');
4. Auditoria Backend¶
Consulte o painel Complyr para ver auditoria completa:
- Acesse https://app.complyr.com.br/dashboard
- Vá em Auditoria → Policy Acceptances
- Filtre por email do usuário
- Verifique timestamp, IP, user-agent
Melhores Práticas¶
✅ DOs (Faça)¶
-
Sempre validar checkbox antes de chamar
acceptPolicy() -
Usar try/catch para tratamento de erros
-
Aceitar políticas ANTES de criar o usuário no backend
-
Usar email como identificador (recomendado)
-
Aceitar múltiplas políticas em paralelo
-
Fornecer feedback visual ao usuário
-
Logs para debug e auditoria
-
Exibir políticas antes da aceitação
❌ DON'Ts (Não Faça)¶
-
Não aceitar políticas sem consentimento explícito
-
Não usar identificadores genéricos
-
Não ignorar erros silenciosamente
-
Não aceitar políticas inexistentes
-
Não chamar sem verificar se Complyr está carregado
-
Não usar checkboxes pré-marcadas
-
Não aceitar políticas após erro no registro
Perguntas Frequentes (FAQ)¶
1. Quando devo usar acceptPolicy() vs loadPolicy()?¶
Use acceptPolicy() quando: - Usuário já aceitou a política (marcou checkbox) - Você quer registrar a aceitação no backend - É parte de um fluxo de cadastro ou checkout
Use loadPolicy() quando: - Usuário quer ler a política antes de decidir - Você quer exibir o conteúdo da política em uma modal ou página
Exemplo combinado:
// 1. Usuário clica "Ler Política"
btnReadPolicy.onclick = () => {
window.complyr.loadPolicy('privacy-policy', '#modal');
};
// 2. Usuário marca checkbox e submete formulário
form.onsubmit = async (e) => {
e.preventDefault();
if (checkbox.checked) {
await window.complyr.acceptPolicy('privacy-policy', email);
// Prosseguir com registro
}
};
2. Posso aceitar múltiplas políticas de uma vez?¶
Sim! Use Promise.all() para aceitar múltiplas políticas em paralelo:
await Promise.all([
window.complyr.acceptPolicy('terms-of-service', email),
window.complyr.acceptPolicy('privacy-policy', email),
window.complyr.acceptPolicy('cookie-policy', email),
]);
console.log('✅ Todas as 3 políticas aceitas');
Benefícios: - Mais rápido (execução paralela) - Atomicidade: se uma falhar, todas falham - Código mais limpo
3. O que acontece se chamar acceptPolicy() duas vezes para a mesma política?¶
O sistema registrará duas aceitações separadas. Não há problema, mas é redundante.
Comportamento: - Primeira chamada: Cria registro de aceitação - Segunda chamada: Cria novo registro de aceitação
Recomendação: Evite chamadas duplicadas usando flags:
let policiesAccepted = false;
async function acceptPoliciesOnce(email) {
if (policiesAccepted) {
console.log('Políticas já foram aceitas');
return;
}
await window.complyr.acceptPolicy('privacy-policy', email);
policiesAccepted = true;
}
4. Preciso identificar o usuário com identify() antes de acceptPolicy()?¶
Não é obrigatório, mas é altamente recomendado para rastreamento mais preciso:
// ✅ Recomendado: Identificar antes de aceitar
window.complyr.identify('email', 'usuario@example.com');
await window.complyr.acceptPolicy('privacy-policy', 'usuario@example.com');
// ✅ Também funciona sem identify()
await window.complyr.acceptPolicy('privacy-policy', 'usuario@example.com');
Benefícios de usar identify() antes: - Melhor rastreamento cross-device - Analytics mais precisos (GTM, Facebook Pixel) - Consentimento vinculado corretamente ao usuário
5. Posso usar acceptPolicy() para aceitar consentimento de cookies?¶
Não. Para consentimento de cookies (Analytics, Marketing, etc.), use o banner nativo do Complyr ou chame métodos específicos de consentimento.
acceptPolicy() é para: - ✅ Termos de Uso - ✅ Política de Privacidade - ✅ Política de Cookies (documento) - ✅ Acordo de Processamento de Dados
Para consentimento de cookies e finalidades, use:
// Banner nativo (recomendado)
// O usuário aceita via interface gráfica
// Ou aceitar programaticamente via API
await fetch('https://app.complyr.com.br/api/consents', {
method: 'POST',
body: JSON.stringify({
workspaceId: 'workspace-id',
purposes: [
{ purposeId: 'analytics', granted: true },
{ purposeId: 'marketing', granted: true },
],
}),
});
6. Como verificar se uma política já foi aceita por um usuário?¶
Consulte a API de aceitações de políticas:
async function checkPolicyAcceptance(email, policyType) {
try {
const response = await fetch(
`https://app.complyr.com.br/api/policy-acceptances?` +
`email=${encodeURIComponent(email)}&` +
`policyType=${encodeURIComponent(policyType)}`
);
if (!response.ok) {
throw new Error('Erro ao verificar aceitação');
}
const acceptances = await response.json();
if (acceptances.length > 0) {
console.log(`✅ Política "${policyType}" já foi aceita em:`, acceptances[0].acceptedAt);
return true;
} else {
console.log(`❌ Política "${policyType}" ainda não foi aceita`);
return false;
}
} catch (error) {
console.error('Erro ao verificar:', error);
return false;
}
}
// Uso
const hasAccepted = await checkPolicyAcceptance('user@example.com', 'privacy-policy');
if (!hasAccepted) {
// Mostrar formulário de aceitação
}
7. O email é hasheado antes de ser enviado ao servidor?¶
Sim! Por segurança e conformidade com LGPD, o email (ou qualquer identificador) é automaticamente hasheado com SHA-256 antes de ser enviado ao servidor.
Processo: 1. Você chama: acceptPolicy('privacy-policy', 'usuario@example.com') 2. Complyr hasheia: SHA-256('usuario@example.com') → '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8' 3. Envia ao servidor: { userEmail: '5e884898...' }
Benefícios: - Proteção de dados pessoais em trânsito - Conformidade com Art. 46 da LGPD (segurança) - Impossibilidade de engenharia reversa
8. Posso usar acceptPolicy() em aplicações mobile (React Native, Flutter)?¶
Não diretamente. O método acceptPolicy() é parte da API JavaScript do navegador (window.complyr).
Para aplicações mobile, use a API REST:
// React Native / Flutter
async function acceptPolicy(policyType, userEmail) {
const response = await fetch('https://app.complyr.com.br/api/policy-acceptances', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Workspace-ID': 'seu-workspace-id',
},
body: JSON.stringify({
policyType: policyType,
userEmail: userEmail, // Será hasheado pelo servidor
}),
});
if (!response.ok) {
throw new Error('Erro ao aceitar política');
}
return await response.json();
}
// Uso
await acceptPolicy('privacy-policy', 'usuario@example.com');
9. Qual a diferença entre aceitar uma política e dar consentimento de cookies?¶
| Aspecto | Aceitar Política | Consentimento de Cookies |
|---|---|---|
| Método | acceptPolicy() | Banner nativo Complyr |
| O que registra | Aceitação de documento legal (Termos, Privacidade) | Permissão para finalidades (Analytics, Marketing) |
| Quando usar | Cadastro, login, checkout | Primeira visita ao site |
| Granularidade | Por política | Por finalidade (5 categorias) |
| Obrigatório? | Depende do serviço | Sim (LGPD Art. 7º, I) |
| Revogável? | Via DSAR | Via revokeConsent() ou banner |
Exemplo de fluxo completo:
// 1. Primeira visita: Consentimento de cookies (banner)
// → Usuário aceita Analytics e Marketing
// 2. Registro: Aceitar políticas
document.getElementById('signup-form').onsubmit = async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
// Aceitar Termos e Privacidade
await window.complyr.acceptPolicy('terms-of-service', email);
await window.complyr.acceptPolicy('privacy-policy', email);
// Criar conta
await createUser(email);
};
10. Há limite de chamadas para acceptPolicy()?¶
Sim, existe rate limiting para prevenir abuso:
- Limite padrão: 20 requisições por minuto por workspace
- Limite por IP: 100 requisições por minuto
Se exceder o limite: - HTTP Status: 429 Too Many Requests - Mensagem: "Rate limit exceeded. Try again later." - Headers:
Recomendações: - Não chame acceptPolicy() em loops ou intervalos - Aceite políticas apenas quando usuário explicitamente aceitar - Use cache para evitar chamadas duplicadas
Suporte¶
Recursos Adicionais¶
- Documentação Completa: https://docs.complyr.com.br
- API Reference: https://docs.complyr.com.br/reference/api-endpoints
- Exemplos Práticos: https://docs.complyr.com.br/examples
Contato¶
- Email: contato@complyr.com.br
- GitHub Issues: https://github.com/complyr/complyr/issues
- LinkedIn: https://www.linkedin.com/company/complyr
Métodos Relacionados¶
loadPolicy()- Carregar e exibir políticasidentify()- Identificar usuário para rastreamentorevokeConsent()- Revogar consentimento (LGPD Art. 18, VI)openPreferences()- Abrir central de preferências