# Gerar link wa.me com tracking invisivel

`POST /chat/lead/stego`

Pasta: **CRM**

## Autenticação

```http
token: {{token}}
```

## Descrição

# Gerar link wa.me com tracking invisível

Gera um texto de mensagem com trailer esteganográfico assinado (HMAC) usando caracteres invisíveis (`U+00AD` soft hyphen = bit 0, `U+3164` Hangul filler = bit 1). Use no botão WhatsApp do site sem expor UTM. No inbound, a API decodifica e grava first-touch em `lead` (`ref`/`source`/`medium`/`campaign` + `custom_attrs.stego`).

## Endpoint

`POST {{baseUrl}}/chat/lead/stego`

## Autenticação

Envie o token da instância no header `token: {{token}}`.

## Corpo da requisição

| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `text` | string | Não | Texto visível (padrão `Oi!`). O trailer invisível é anexado ao final. |
| `tracking_id` | string | Sim | ID opaco da campanha/sessão (vira `lead_ref`). Máx. 48 chars. |
| `source` | string | Não | Origem assinada (ex.: `website`). Máx. 24 chars. |
| `medium` | string | Não | Meio (ex.: `cta`). Máx. 24 chars. |
| `campaign` | string | Não | Campanha. Máx. 24 chars. |
| `number` | string | Não | DDI+número para montar `wa_me_url` (só dígitos são usados). |

## Exemplo de Requisição

```bash
curl --request POST '{{baseUrl}}/chat/lead/stego' \
  --header 'token: {{token}}' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "text": "Oi!",
  "tracking_id": "home-q3",
  "source": "website",
  "medium": "cta",
  "campaign": "home",
  "number": "5511999999999"
}'
```

## Resposta de Sucesso

```json
{
  "success": true,
  "text": "Oi!<trailer-invisível>",
  "visible_text": "Oi!",
  "wa_me_url": "https://wa.me/5511999999999?text=Oi%21%C2%AD...",
  "tracking_id": "home-q3"
}
```

## Erros comuns

- `401 Unauthorized`: header `token` ausente ou inválido.
- `400 Bad Request`: `tracking_id` ausente ou campos longos demais.
- `503 Service Unavailable`: secret stego não configurado — use `POST /admin/lead/stego` com `admintoken`.

## Observações

Configure o HMAC com `POST /admin/lead/stego` (`admintoken`, body `{ "secret": "..." }`). Consulte status em `GET /admin/lead/stego` (`configured: true/false`; o secret nunca é retornado).
O `wa_me_url` já usa `encodeURIComponent` no `text` completo — não recorte o trailer.
Teste no webhook: a mensagem visual é `Oi!`; `data.lead` deve trazer `ref`/`source` e `custom_attrs.stego=1`.
Hangul filler pode ocupar largura em alguns clientes; valide no app real. Soft hyphen costuma ser invisível.

### Rastreamento de origem (site, Ads, parceiros)

A atribuição é **first-touch** em mensagens inbound (DM): a API só preenche campos vazios. Grupos são ignorados.

| Origem | Como rastrear |
|---|---|
| **Ads Meta (CTWA)** | Automático: `ctwaClid`, título/corpo do anúncio e `ExternalAdReply` na primeira mensagem. |
| **Seu site / landing** | Link `wa.me` com UTM/`ref` na mensagem pré-preenchida, **ou** `POST /chat/editLead` / `/chat/lead/attrs` quando o backend já sabe a origem. |
| **Parceiro / QR / bio** | Mesma ideia: `ref=parceiro-x` (ou UTM) no texto do link. |
| **Tracking invisível (stego)** | `POST /chat/lead/stego` gera `text` + `wa_me_url` com trailer HMAC. Secret via `POST /admin/lead/stego` (admintoken). |

**Exemplo de botão no site (captura automática):**

Encode **todo** o texto do `text=` (incluindo `&` e `=`). Se deixar `&utm_medium=...` fora do encode, o navegador trata como query do `wa.me` e o WhatsApp só recebe até o primeiro `&`.

```
https://wa.me/5511999999999?text=Oi!%20utm_source%3Dsite%26utm_medium%3Dcta%26utm_campaign%3Dhome%26ref%3Dlanding-home
```

Mensagem que chega no chat: `Oi! utm_source=site&utm_medium=cta&utm_campaign=home&ref=landing-home`.

Isso grava `lead_source=site`, `lead_medium=cta`, `lead_campaign=home`, `lead_ref=landing-home`.

Em JavaScript: `https://wa.me/55...?text=${encodeURIComponent("Oi! utm_source=site&utm_medium=cta&utm_campaign=home&ref=landing-home")}`.

**Webhook / SSE:** eventos `messages` inbound incluem o objeto `data.lead` (CRM + atribuição + `fields` + `custom_attrs`) quando houver dados no chat.

**Consulta:** `POST /chat/details` devolve o chat completo com as colunas `lead_*`.

- `custom_attrs`: merge por padrão; use `replace_custom_attrs: true` para substituir o mapa inteiro.
- `lead_fields`: chaves `01`…`20`, `field01` ou `lead_field01` → `lead_field01`…`lead_field20`.
- Atribuição via API sobrescreve campos enviados (não-vazios); captura inbound não sobrescreve first-touch.

## Corpo (exemplo)

```json
{
  "text": "Oi!",
  "tracking_id": "home-q3",
  "source": "website",
  "medium": "cta",
  "campaign": "home",
  "number": "5511999999999"
}
```

## cURL

```bash
curl -X POST "{{baseUrl}}/chat/lead/stego" \
  -H "token: {{token}}" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "Oi!",
  "tracking_id": "home-q3",
  "source": "website",
  "medium": "cta",
  "campaign": "home",
  "number": "5511999999999"
}'
```

---

[Índice da pasta](./index.md) · [Índice geral](../index.md) · [UI](https://gozap.dev/docs?op=crm/gerar-link-wa-me-com-tracking-invisivel)
