Métricas de campaña en WhatsApp: entregado, leído y respondido por la API
Enviado no es entregado y entregado no es leído. Cómo capturar cada estado por el webhook, armar el embudo real de la campaña, medir la métrica que de verdad importa — la respuesta — y reconocer cuándo el número se está quemando.
"¿Cómo fue la campaña?" casi nunca tiene respuesta, porque casi nadie captura los eventos que la responden. El envío devuelve 200, alguien concluye que salió bien, y lo que pasó después se pierde.
Este artículo es sobre medir. La cola entrega los mensajes; la medición dice si valió la pena.
El embudo real
| Etapa | Qué significa | Dónde aparece |
|---|---|---|
| Encolado | Decidiste enviarlo | Tu base de datos |
| Enviado | La plataforma lo aceptó | Respuesta de la llamada |
| Entregado | Llegó al aparato | Webhook delivered |
| Leído | La persona lo abrió | Webhook read |
| Respondido | La persona escribió de vuelta | Webhook messages |
| Se dio de baja | Pidió no recibir más | Tu manejo de opt-out |
Cada escalón pierde gente. Dónde pierde dice qué arreglar — y sin los escalones intermedios solo tienes el primero y el último.
Capturar los estados
Todo evento de estado llega en value.statuses, y no en value.messages:
async function procesar(evento) {
const value = evento?.entry?.[0]?.changes?.[0]?.value;
for (const s of value?.statuses ?? []) {
await registrarEstado({
messageId: s.id,
estado: s.status, // sent | delivered | read | failed
en: new Date(Number(s.timestamp) * 1000),
error: s.errors?.[0]?.code,
});
}
const msg = value?.messages?.[0];
if (msg) await registrarRespuesta(msg);
}Confundir los dos campos es el error número uno de quien escribe el parser por primera vez — está entre las 7 causas de webhook que no funciona.
Unir el estado al envío
Solo funciona si guardaste el messageId al momento de enviar:
const r = await enviarPlantilla(to, plantilla, params);
await db.query(
`UPDATE envios SET estado = 'enviado', message_id = $1, enviado_en = NOW()
WHERE campana_id = $2 AND numero = $3`,
[r.messageId, campanaId, to],
);Y al recibir el estado:
await db.query(
`UPDATE envios
SET estado = $1, ${columna(estado)} = $2
WHERE message_id = $3`,
[estado, en, messageId],
);Una columna de timestamp por etapa (entregado_en, leido_en, respondido_en) rinde más que una sola columna de estado: además del embudo, ganas el tiempo entre etapas, y es ahí donde se ve un problema de ritmo.
El reporte
SELECT
COUNT(*) AS encolados,
COUNT(*) FILTER (WHERE estado <> 'pendiente') AS enviados,
COUNT(*) FILTER (WHERE entregado_en IS NOT NULL) AS entregados,
COUNT(*) FILTER (WHERE leido_en IS NOT NULL) AS leidos,
COUNT(*) FILTER (WHERE respondido_en IS NOT NULL) AS respondidos,
COUNT(*) FILTER (WHERE estado = 'fallo_definitivo') AS fallos,
ROUND(100.0 * COUNT(*) FILTER (WHERE entregado_en IS NOT NULL)
/ NULLIF(COUNT(*) FILTER (WHERE estado <> 'pendiente'), 0), 1) AS tasa_entrega,
ROUND(100.0 * COUNT(*) FILTER (WHERE respondido_en IS NOT NULL)
/ NULLIF(COUNT(*) FILTER (WHERE entregado_en IS NOT NULL), 0), 1) AS tasa_respuesta
FROM envios
WHERE campana_id = $1;La API también expone números agregados de atención, útiles para una vista general sin armar tablas — por el endpoint de estadísticas o, conversando, con la herramienta get_analytics del MCP. Para análisis por campaña, en cambio, el registro en tu base es lo que permite cruzar con pedido, cliente e ingresos.
Cómo leer cada número
Tasa de entrega
| Rango | Lectura |
|---|---|
| > 95% | Base saludable |
| 90–95% | Números desactualizados; toca limpiar |
| < 90% | Limpieza antes de la próxima campaña |
En la API oficial esto no es solo desperdicio: un fallo repetido perjudica la reputación del número.
Tasa de lectura. Siempre subestima — solo aparece para quien tiene activa la confirmación de lectura. Sirve para comparar campañas entre sí, no como número absoluto.
Tasa de respuesta. La que importa. Es la única que exige una acción deliberada, y en WhatsApp además abre la ventana de 24 horas — o sea, la atención siguiente no genera cobro nuevo. Una campaña con buena respuesta es más barata por conversión de lo que sugieren los números brutos. Vale leerlo junto con la ventana de 24 horas y las plantillas.
Lectura alta con respuesta cero casi siempre significa un mensaje que no pide nada. Una plantilla con botón de respuesta rápida suele resolverlo.
Los dos números que avisan antes
La entrega y la lectura cuentan el pasado. El bloqueo y la denuncia cuentan el futuro.
SELECT
c.id, c.nombre, c.enviada_en,
ROUND(100.0 * COUNT(*) FILTER (WHERE e.entregado_en IS NOT NULL)
/ NULLIF(COUNT(*), 0), 1) AS entrega,
COUNT(*) FILTER (WHERE e.error = 'contacto_bloqueo') AS bloqueos,
COUNT(*) FILTER (WHERE e.estado = 'optout') AS bajas
FROM campanas c
JOIN envios e ON e.campana_id = c.id
GROUP BY c.id
ORDER BY c.enviada_en DESC
LIMIT 10;Mira la columna entrega de arriba hacia abajo. Si cae campaña tras campaña con la misma base, la reputación se está deteriorando — y el paso siguiente es una restricción, no un aviso.
Cuando aparece ese patrón, la respuesta es contraintuitiva: enviar menos. Bajar la frecuencia, revisar el contenido, reconfirmar a los contactos antiguos. Subir el volumen para compensar la caída de entrega es lo que convierte un problema recuperable en un número perdido.
Comparar de verdad
Para que una comparación valga, cambia una variable por vez:
- mismo público, textos distintos → el texto;
- mismo texto, horarios distintos → el horario;
- mismo texto, con y sin botón → el botón.
Cambiar texto, horario y público a la vez y concluir que "la versión nueva anduvo mejor" no informa nada sobre qué repetir.
Conclusión
Medir una campaña de WhatsApp es guardar el messageId, capturar value.statuses y tener una columna de timestamp por etapa. Media hora de trabajo, una sola vez.
El retorno es dejar de decidir por impresión: pasas a saber si el problema es la lista, el texto, el horario o el número — y cada uno tiene una corrección distinta.
¿Listo para automatizar tu WhatsApp?
Crea tu cuenta gratis y empieza a enviar mensajes por la API en minutos.
Empezar gratisPreguntas frecuentes
¿Cómo sé si el mensaje fue entregado por la API de WhatsApp?+
Por el webhook de estado. Después del envío llegan eventos en entry[0].changes[0].value.statuses con el id del mensaje y el estado: sent, delivered, read o failed. Los unes al envío original por el messageId que devolvió la llamada de envío.
¿Cuál es la diferencia entre enviado, entregado y leído?+
Enviado significa que la plataforma aceptó el mensaje. Entregado significa que llegó al aparato. Leído significa que la persona abrió la conversación, y solo aparece si mantiene activada la confirmación de lectura, así que la tasa de lectura siempre subestima la realidad.
¿Qué tasa de entrega se considera buena?+
Por encima del 95% es saludable. Entre 90% y 95% indica una base con números desactualizados. Por debajo del 90% es señal de que la lista necesita limpieza — y en la API oficial, un intento fallido repetido también perjudica la reputación del número.
¿Cómo mido si la campaña dio resultado?+
Por la tasa de respuesta, no por la de lectura. La respuesta es la única métrica que exige una acción deliberada de la persona, y en WhatsApp además abre la ventana de 24 horas, lo que reduce el costo de la atención siguiente.
¿Cómo me doy cuenta de que el número se está quemando?+
Sigue los bloqueos y las denuncias por campaña y la tasa de entrega a lo largo del tiempo. Una entrega que cae campaña tras campaña, con la misma base, es la señal más confiable de que la reputación se está deteriorando. Cuando eso aparece, baja el volumen antes de perder el número.
Sigue leyendo
API de Instagram y Messenger en la misma API de WhatsApp: una instancia, un estándar
Tres canales oficiales de Meta casi siempre significan tres integraciones. Con una sola instancia, el mismo envío y el mismo sobre de webhook, solo cambia un campo: provider. Cómo funciona y qué te ahorra.
API no oficial de WhatsApp: qué es, si es segura y cómo usarla (2026)
Entiende qué es una API no oficial de WhatsApp, cómo funciona la conexión por código QR, si es segura y legal, cuál es el riesgo real de bloqueo y cuándo conviene usarla en lugar de la API oficial.
API de WhatsApp gratis: cómo probarla y empezar sin costo (2026)
¿Existe una API de WhatsApp gratis? Qué se puede hacer sin pagar, cómo probar la integración sin costo, las limitaciones reales de lo gratuito y cómo hacer el primer envío en minutos.