> ## Documentation Index
> Fetch the complete documentation index at: https://lifters.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Privacidade & LGPD

> Consent flow, denylist, masking PII e como manter o SDK em conformidade com LGPD.

O Atlas Web Analytics SDK foi desenhado para ser **LGPD compliant by default**.
Esta página cobre os 4 níveis de controle: consent, denylist, sanitize e
classes CSS de masking.

## Princípios

<CardGroup cols={2}>
  <Card title="Opt-in pode ser exigido" icon="user-shield">
    Configure `opt_out_capturing_by_default: true` para SDK iniciar em silêncio
    até consentimento explícito.
  </Card>

  <Card title="DNT respeitado" icon="eye-slash">
    Por default (`respect_dnt: true`) o SDK auto opt-out quando o browser tem
    Do-Not-Track ativo.
  </Card>

  <Card title="PII filtrada antes do envio" icon="filter">
    `property_denylist` remove keys sensíveis de **toda** chamada `capture()`.
  </Card>

  <Card title="Masking visual no HTML" icon="mask">
    Classes CSS `ig-no-capture`, `ig-mask`, `ig-ignore-input` controlam captura
    no autocapture e (futuro v2) replay.
  </Card>
</CardGroup>

## 1. Consent flow (banner LGPD)

```javascript Recomendado em produção theme={null}
// 1. Init com opt-out por padrão
window.iGamingSDK.init({
  organizationId: 'org_SEU_ID',
  brandId:        'brand_SEU_ID',
  endpoint:       'https://ingest.atlas.io/v1/sdk-events',
  opt_out_capturing_by_default: true,   // ← SDK silenciado até consentir
  respect_dnt:                  true
});

// 2. Quando usuário aceita o banner:
function onAcceptCookies() {
  window.iGamingSDK.opt_in_capturing();
  // A partir daqui, todos os eventos enfileirados/futuros são enviados.
}

// 3. Quando usuário rejeita ou pede para parar:
function onRejectCookies() {
  window.iGamingSDK.opt_out_capturing();
}

// 4. Para tela de Configurações do usuário (toggle):
function isTrackingEnabled() {
  return window.iGamingSDK.has_opted_in_capturing();
}
```

<Info>
  O estado de consent persiste em `localStorage` (`ig_consent`) entre sessões.
  Usuário responde uma vez, escolha mantém. **Persistência sobrescreve** o
  `respect_dnt` e `opt_out_capturing_by_default` — uma vez que ele opta in/out,
  é a verdade.
</Info>

## 2. Property denylist

Lista de keys que são **sempre removidas** antes do envio, em qualquer `capture()`:

```javascript theme={null}
window.iGamingSDK.init({
  // ...
  property_denylist: [
    'password',
    'password_hash',
    'cvv',
    'cpf',
    'card_number',
    'card_exp',
    'token',
    'auth_token',
    'session_token'
  ]
});

// Mesmo que o operador envie por engano, o SDK remove antes do POST:
iGamingSDK.capture('checkout.intent', {
  amount: 100,
  card_number: '4111-1111-1111-1111',   // ← removido
  cvv: '123'                            // ← removido
});
// Payload final no Kafka: { amount: 100 }
```

## 3. Sanitize properties (avançado)

Função custom executada antes do envio. Útil para redação parcial (ex: deixar
últimos 4 dígitos do cartão para fraude analytics).

```javascript theme={null}
window.iGamingSDK.init({
  // ...
  sanitize_properties: (props, eventName) => {
    // Mascara o cartão deixando últimos 4 dígitos
    if (props.card_number) {
      props.card_last4 = props.card_number.slice(-4);
      delete props.card_number;
    }

    // Mascara CPF preservando estrutura
    if (props.cpf) {
      props.cpf_masked = props.cpf.replace(/\d(?=\d{2})/g, '*');
      delete props.cpf;
    }

    // Truncar emails preservando domínio
    if (props.email) {
      const [local, domain] = props.email.split('@');
      props.email_domain = domain;
      delete props.email;
    }

    return props;
  }
});
```

<Warning>
  O `sanitize_properties` roda **depois** do `property_denylist`. Se você usa
  os dois, a função recebe `props` já filtrado. Erros dentro da função são
  silenciosamente engolidos (props original prevalece) para não quebrar a app.
</Warning>

## 4. Classes CSS de masking

Marque elementos sensíveis diretamente no HTML do app. O SDK respeita estas
classes em **autocapture, heatmap e (futuro v2) replay**.

```html theme={null}
<!-- Bloqueia captura do elemento + subárvore inteira -->
<img src="/avatar.png" class="ig-no-capture" />
<div class="ig-no-capture">
  CPF: 123.456.789-00
  Endereço: Rua das Flores, 123
</div>

<!-- Mascara texto: não aparece em $el_text do autocapture -->
<span class="ig-mask">R$ 1.234,56</span>

<!-- Input cujo valor é ignorado mas elemento é capturado -->
<input type="text" class="ig-ignore-input" placeholder="CPF" />

<!-- Excluir do detector de rage click (botões +/- de aposta múltipla) -->
<button class="ig-no-rageclick">+</button>
<button class="ig-no-rageclick">-</button>
```

| Classe            | Comportamento                                                             |
| ----------------- | ------------------------------------------------------------------------- |
| `ig-no-capture`   | Elemento + filhos completamente bloqueados (autocapture, heatmap, replay) |
| `ig-mask`         | Texto mascarado no `$el_text` do autocapture e no replay (v2)             |
| `ig-ignore-input` | Valor do input não é capturado                                            |
| `ig-no-rageclick` | Excluído do detector de rage clicks                                       |

## Hard-coded (sempre mascarado)

Mesmo sem classe CSS, o SDK **nunca** captura:

* `<input type="password">` (valor)
* `<input autocomplete="cc-number">`, `cc-csc`, `cc-exp` (cartão de crédito)
* Atributos: `data-ig-sensitive`, `data-ph-sensitive`
* Headers HTTP `Authorization`, `Cookie` (no futuro replay v2 — network capture)

## Direito ao esquecimento (LGPD)

Quando um usuário solicita exclusão de dados (Art. 18 LGPD), exclua os
registros via Atlas Admin API:

```bash theme={null}
curl -X DELETE \
  https://api.atlas.io/v1/admin/users/{user_ext_id}/data \
  -H "Authorization: Bearer ${ADMIN_TOKEN}"
```

Isso remove:

* Todos os eventos em `atlas.tbt_sdk_events` com `user_ext_id` informado
* Cross-referência com `tbt_raw_events_*` (transacionais) opcional via flag

A operação é assíncrona e leva até 24h para propagar em todas as agregações.

## Checklist LGPD para operadores

<CardGroup cols={1}>
  <Card title="Antes de instalar o SDK">
    * [ ] Banner de cookies/consent implementado no app
    * [ ] Política de privacidade menciona analytics behavioral
    * [ ] DPO ciente do escopo de coleta
  </Card>

  <Card title="No código do app">
    * [ ] `opt_out_capturing_by_default: true` no `init()`
    * [ ] `iGamingSDK.opt_in_capturing()` só após aceite explícito
    * [ ] `property_denylist` cobre PII conhecido do seu domínio
    * [ ] Classes `ig-no-capture` aplicadas em elementos PII visíveis (CPF, endereço, etc)
    * [ ] `iGamingSDK.reset()` chamado no logout
  </Card>

  <Card title="Processos">
    * [ ] Endpoint admin de exclusão LGPD documentado para o time de DPO
    * [ ] Retenção de dados configurada (default 90 dias)
    * [ ] Logs de acesso ao dashboard para fins de compliance
  </Card>
</CardGroup>

## Verificar consent

```javascript Cole no DevTools Console theme={null}
console.log({
  optedIn:  iGamingSDK.has_opted_in_capturing(),
  optedOut: iGamingSDK.has_opted_out_capturing(),
  storage:  localStorage.getItem('ig_consent')
});
```

Valores possíveis de `storage`:

| Valor  | Significado                                                            |
| ------ | ---------------------------------------------------------------------- |
| `'1'`  | Usuário explicitamente opt-in                                          |
| `'0'`  | Usuário explicitamente opt-out                                         |
| `null` | Não respondeu — SDK usa `respect_dnt` + `opt_out_capturing_by_default` |

## Reset completo (debug)

Para limpar todo o estado de consent + identidade (útil em testes):

```javascript theme={null}
Object.keys(localStorage)
  .filter(k => k.startsWith('ig_'))
  .forEach(k => localStorage.removeItem(k));

document.cookie.split(';').forEach(c => {
  const n = c.split('=')[0].trim();
  if (n.startsWith('ig_')) {
    document.cookie = `${n}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
  }
});

location.reload();
```

## Próximos passos

* [Catálogo de eventos](/sdk/web-analytics/events) — quais eventos são capturados
* [Configuração](/sdk/web-analytics/configuration) — todas as opções de privacy
* [Identificar usuário](/sdk/web-analytics/identify) — traits seguros vs perigosos
