---
title: "Métricas de campanha no WhatsApp: entregue, lido e respondido pela API"
description: "Enviado não é entregue e entregue não é lido. Como capturar cada status pelo webhook, montar o funil da campanha e medir a métrica que importa: resposta."
url: "https://wame.api.br/blog/metricas-campanha-whatsapp-api"
language: "pt-BR"
og:type: "article"
published_time: "2026-09-10"
modified_time: "2026-09-10"
author: "Raphael Serafim"
keywords: "métricas whatsapp api, taxa de entrega whatsapp, relatório disparo whatsapp, status mensagem whatsapp api, webhook status entrega whatsapp, analytics whatsapp api, medir campanha whatsapp"
reading_time: "9 min de leitura"
---

# Métricas de campanha no WhatsApp: entregue, lido e respondido pela API

> Enviado não é entregue e entregue não é lido. Como capturar cada status pelo webhook, montar o funil da campanha e medir a métrica que importa: resposta.

**"A campanha foi bem?" quase nunca tem resposta,** porque quase ninguém captura os eventos que respondem. O envio retorna `200`, alguém conclui que deu certo, e o que aconteceu depois se perde.

Este artigo é sobre medir. A [fila](/blog/fila-rate-limit-retry-disparo-whatsapp) entrega as mensagens; a medição diz se valeu.

## O funil real

| Etapa | O que significa | Onde aparece |
|---|---|---|
| **Enfileirado** | Você decidiu mandar | Seu banco |
| **Enviado** | A plataforma aceitou | Resposta da chamada |
| **Entregue** | Chegou ao aparelho | Webhook `delivered` |
| **Lido** | A pessoa abriu | Webhook `read` |
| **Respondido** | A pessoa escreveu de volta | Webhook `messages` |
| **Saiu** | Pediu descadastro | Seu tratamento de opt-out |

Cada degrau perde gente. Onde perde diz o que consertar — e sem os degraus intermediários você só tem o primeiro e o último.

## Capturar os status

Todo evento de status chega em `value.statuses`, e **não** em `value.messages`:

```js
async function processar(evento) {
  const value = evento?.entry?.[0]?.changes?.[0]?.value;

  for (const s of value?.statuses ?? []) {
    await registrarStatus({
      messageId: s.id,
      status: s.status,        // sent | delivered | read | failed
      em: new Date(Number(s.timestamp) * 1000),
      erro: s.errors?.[0]?.code,
    });
  }

  const msg = value?.messages?.[0];
  if (msg) await registrarResposta(msg);
}
```

Confundir os dois campos é o erro número um de quem escreve o parser pela primeira vez — está entre [as 7 causas de webhook que não funciona](/blog/webhook-whatsapp-nao-chega-como-testar).

## Amarrar status ao envio

Só funciona se você guardou o `messageId` no momento do envio:

```js
const r = await enviarTemplate(to, template, params);
await db.query(
  `UPDATE envios SET status = 'enviado', message_id = $1, enviado_em = NOW()
     WHERE campanha_id = $2 AND numero = $3`,
  [r.messageId, campanhaId, to],
);
```

E, ao receber o status:

```js
await db.query(
  `UPDATE envios
      SET status = $1, ${coluna(status)} = $2
    WHERE message_id = $3`,
  [status, em, messageId],
);
```

Uma coluna de timestamp por etapa (`entregue_em`, `lido_em`, `respondido_em`) rende mais que uma coluna de status só: além do funil, você ganha o **tempo** entre etapas, e é ele que revela problema de ritmo.

## O relatório

```sql
SELECT
  COUNT(*)                                      AS enfileirados,
  COUNT(*) FILTER (WHERE status <> 'pendente')  AS enviados,
  COUNT(*) FILTER (WHERE entregue_em IS NOT NULL)   AS entregues,
  COUNT(*) FILTER (WHERE lido_em     IS NOT NULL)   AS lidos,
  COUNT(*) FILTER (WHERE respondido_em IS NOT NULL) AS respondidos,
  COUNT(*) FILTER (WHERE status = 'falha_definitiva') AS falhas,
  ROUND(100.0 * COUNT(*) FILTER (WHERE entregue_em IS NOT NULL)
              / NULLIF(COUNT(*) FILTER (WHERE status <> 'pendente'), 0), 1) AS taxa_entrega,
  ROUND(100.0 * COUNT(*) FILTER (WHERE respondido_em IS NOT NULL)
              / NULLIF(COUNT(*) FILTER (WHERE entregue_em IS NOT NULL), 0), 1) AS taxa_resposta
FROM envios
WHERE campanha_id = $1;
```

A API também expõe números agregados de atendimento, úteis para uma visão geral sem montar tabela — pelo endpoint de estatísticas ou, em conversa, pela ferramenta `get_analytics` do [MCP](/blog/mcp-agente-ia-whatsapp). Para análise por campanha, porém, o registro no seu banco é o que permite cruzar com pedido, cliente e receita.

## Como ler cada número

**Taxa de entrega**

| Faixa | Leitura |
|---|---|
| > 95% | Base saudável |
| 90–95% | Número desatualizado; hora de higienizar |
| < 90% | [Higienização](/blog/lista-contatos-optin-optout-whatsapp) antes da próxima campanha |

Na API oficial isso não é só desperdício: falha repetida prejudica a reputação do número.

**Taxa de leitura.** Sempre subestima — só aparece para quem mantém a confirmação de leitura ativa. Serve para comparar campanhas entre si, não como número absoluto.

**Taxa de resposta.** A que importa. É a única que exige ação deliberada, e no WhatsApp ela ainda **abre a janela de 24 horas** — ou seja, o atendimento seguinte não gera cobrança nova. Uma campanha com boa resposta é mais barata por conversão do que os números brutos sugerem. Vale ler junto com [a janela de 24 horas e os templates](/blog/templates-whatsapp-api-criar-aprovar-enviar).

Leitura alta com resposta zero quase sempre significa mensagem que não pede nada. Template com botão de resposta rápida costuma resolver.

## Os dois números que avisam antes do problema

Taxa de entrega e leitura contam o passado. **Bloqueio e denúncia contam o futuro.**

```sql
SELECT
  c.id, c.nome, c.enviada_em,
  ROUND(100.0 * COUNT(*) FILTER (WHERE e.entregue_em IS NOT NULL)
              / NULLIF(COUNT(*), 0), 1) AS entrega,
  COUNT(*) FILTER (WHERE e.erro = 'contato_bloqueou') AS bloqueios,
  COUNT(*) FILTER (WHERE e.status = 'optout')         AS saidas
FROM campanhas c
JOIN envios e ON e.campanha_id = c.id
GROUP BY c.id
ORDER BY c.enviada_em DESC
LIMIT 10;
```

Olhe a coluna `entrega` de cima para baixo. Se ela cai campanha após campanha **com a mesma base**, a reputação está se deteriorando — e o próximo passo é restrição, não aviso.

Quando esse padrão aparece, a resposta é contraintuitiva: **mandar menos**. Reduzir frequência, revisar o conteúdo, reconfirmar os contatos antigos. Aumentar volume para compensar queda de entrega é o que transforma um problema recuperável em número perdido.

## Comparar de verdade

Para uma comparação valer, mude **uma** variável por vez:

- mesmo público, textos diferentes → o texto;
- mesmo texto, horários diferentes → o horário;
- mesmo texto, com e sem botão → o botão.

Mudar texto, horário e público juntos e concluir que "a nova versão foi melhor" não informa nada sobre o que repetir.

## Conclusão

Medir campanha de WhatsApp é guardar o `messageId`, capturar `value.statuses` e ter uma coluna de timestamp por etapa. Meia hora de trabalho, uma vez.

O retorno é parar de decidir por impressão: você passa a saber se o problema é a lista, o texto, o horário ou o número — e cada um desses tem uma correção diferente.

## Perguntas frequentes

### Como saber se a mensagem foi entregue pela API do WhatsApp?

Pelo webhook de status. Depois do envio, chegam eventos em entry[0].changes[0].value.statuses com o id da mensagem e o estado: sent, delivered, read ou failed. Você amarra esses eventos ao envio original pelo messageId que a chamada de envio retornou.

### Qual a diferença entre enviado, entregue e lido?

Enviado significa que a plataforma aceitou a mensagem. Entregue significa que ela chegou ao aparelho. Lido significa que a pessoa abriu a conversa — e só aparece se ela mantiver a confirmação de leitura ativada, então a taxa de leitura sempre subestima a realidade.

### Qual taxa de entrega é considerada boa?

Acima de 95% é saudável. Entre 90% e 95% indica base com número desatualizado. Abaixo de 90% é sinal de lista precisando de higienização — e, na API oficial, tentativa falha repetida também prejudica a reputação do número.

### Como medir se a campanha deu resultado?

Pela taxa de resposta, não pela de leitura. Resposta é a única métrica que exige uma ação deliberada da pessoa, e no WhatsApp ela ainda abre a janela de 24 horas — o que reduz o custo do atendimento seguinte. Campanha com boa leitura e resposta zero costuma indicar mensagem que não pede nada.

### Como perceber que o número está queimando?

Acompanhe bloqueios e denúncias por campanha e a taxa de entrega ao longo do tempo. Entrega caindo campanha após campanha, com a mesma base, é o sinal mais confiável de que a reputação está se deteriorando. Quando isso aparece, reduza volume e frequência antes de perder o número.
