Blog · Métricas
Cómo medir la tasa de clics de tus notificaciones push
Qué diferencia hay entre enviada, entregada y clicada, qué denominador usar, cómo registrar los eventos en el service worker y cómo llevar el clic hasta la conversión.
La tasa de clics de una notificación push se calcula dividiendo los clics entre las notificaciones entregadas, es decir, las que el navegador llegó a mostrar, y no entre las enviadas. Para medirla necesitas que el service worker registre dos eventos por dispositivo (notificación mostrada y clic) con un identificador estable de cada envío, y comparar siempre en la misma ventana de tiempo.
En resumen:
- El embudo tiene cuatro pasos: destinatarios, enviadas, entregadas y clicadas; cada uno pierde dispositivos por motivos distintos.
- Usa clics entre entregadas para juzgar el contenido y entregadas entre enviadas para juzgar la entregabilidad.
- Cuenta como máximo un clic por dispositivo y notificación.
- Añade parámetros UTM a la URL para seguir el camino del clic a la conversión.
- No hay una tasa «buena» universal: compara contra tu propio historial y por tipo de aviso.
Enviada, entregada y clicada no son lo mismo
Entre tu servidor y el dedo del usuario hay varios saltos, y cada uno lo conoce una parte distinta del sistema:
| Paso | Qué significa | Quién lo sabe | Por qué se pierden dispositivos |
|---|---|---|---|
| Destinatarios | Suscripciones activas que encajan con el destino | Tu servidor | — |
| Enviada | El servicio push aceptó el mensaje (201) | La respuesta del servicio push | Suscripciones caducadas (404/410), errores |
| Entregada | El navegador recibió el mensaje y mostró la notificación | El service worker del dispositivo | Dispositivo desconectado hasta que vence el TTL |
| Clicada | La persona tocó la notificación | El service worker, en notificationclick | Decisión del usuario |
La consecuencia práctica es que «enviada» no te dice nada sobre si alguien vio el aviso. Un mensaje con un TTL corto puede ser aceptado por el servicio push y no llegar nunca a un portátil que estuvo cerrado todo el fin de semana; lo explicamos en TTL y urgencia en web push.
Qué denominador usar
Un ejemplo hipotético: envías un aviso a 10 000 dispositivos, se entregan 8000 y 400 personas hacen clic. La tasa sobre entregadas es del 5 %; sobre enviadas, del 4 %. Las dos cifras son correctas, pero responden a preguntas distintas:
- Clics / entregadas: ¿el título, el texto y el momento convencieron a quien vio la notificación? Es la métrica para comparar contenidos.
- Entregadas / enviadas: ¿cuántos dispositivos llegaron a recibirla? Mide la salud de tu audiencia y el efecto del TTL, no la calidad del mensaje.
Mezclarlas en una sola cifra (clics / enviadas) hace que un cambio de TTL o una base con muchos dispositivos inactivos parezca un problema de copy. Dos detalles más: cuenta clics únicos (como máximo uno por dispositivo y notificación, aunque el evento llegue dos veces) y, si recibes un clic de un dispositivo sin entrega registrada, cuéntalo también como entregada. El evento de entrega lo envía el propio dispositivo y puede perderse si se queda sin conexión en ese instante.
Registrar los eventos en el service worker
Si gestionas tú el service worker, registra la entrega solo cuando showNotification() se resuelve (eso es lo que de verdad vio la persona) y el clic dentro de notificationclick, el evento que el navegador lanza al tocar una notificación según la documentación de MDN. Si partes de cero, empieza por tu primer service worker para push.
// sw.js: el payload trae { id, sub, title, body, url }
self.addEventListener('push', (event) => {
const msg = event.data.json();
const data = { id: msg.id, sub: msg.sub, url: msg.url };
event.waitUntil(
self.registration
.showNotification(msg.title, { body: msg.body, data })
.then(() => track('delivered', data))
);
});
self.addEventListener('notificationclick', (event) => {
const data = event.notification.data;
event.notification.close();
event.waitUntil(Promise.all([track('clicked', data), data.url && clients.openWindow(data.url)]));
});
function track(type, { id, sub }) {
return fetch('/api/push-events', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type, notificationId: id, subscriptionId: sub }),
keepalive: true,
}).catch(() => {}); // la analítica nunca debe impedir mostrar ni abrir
}En el servidor, guarda los eventos con una clave única por notificación y suscripción para que los duplicados no inflen la cifra. Cerrar la notificación lanza otro evento, notificationclose, que no debe contar como clic.
Si usas castly, su service worker ya hace este trabajo: cada dispositivo pasa por sent, delivered y clicked en el registro de la notificación, y los clics se cuentan una sola vez por dispositivo.
Calcularla a partir de los totales
Con los totales de una notificación, la cuenta es directa. Este ejemplo usa GET /v1/notifications/:id, que devuelve sent, delivered y clicked entre sus totales:
const res = await fetch(`https://castly.sh/v1/notifications/${id}`, {
headers: { Authorization: `Bearer ${process.env.PUSH_SECRET_KEY}` },
});
const { totals } = await res.json();
const ctr = totals.delivered ? totals.clicked / totals.delivered : 0;
const delivery = totals.sent ? totals.delivered / totals.sent : 0;
console.log(`CTR ${(ctr * 100).toFixed(1)} % · entrega ${(delivery * 100).toFixed(1)} %`);Fija una ventana de lectura. Los clics siguen llegando mientras la notificación está en pantalla y mientras el TTL permite entregas tardías, así que comparar un envío de hace una hora con otro de hace una semana no es justo. Una regla práctica: lee todas las métricas a las 24 o 48 horas del envío y guárdalas en tu propio almacén, porque los registros detallados no se conservan para siempre (castly los guarda 30 días).
Del clic a la conversión
El clic es un medio, no el objetivo. Para saber qué pasó después, añade parámetros UTM a la URL de la notificación, por ejemplo ?utm_source=push&utm_medium=web-push&utm_campaign=bajada-precio-nov, y tu herramienta de analítica atribuirá la sesión al aviso. Haz que esa URL lleve a la página exacta de la que habla la notificación (el pedido, el hilo, el producto) y nunca a la portada: un clic que aterriza en una página genérica obliga a buscar otra vez, mucha gente abandona y un buen aviso parece malo.
Para conversiones que ocurren en tu backend (una compra, una reserva), el webhook notification.clicked incluye la notificación, el suscriptor y tu externalUserId, así que puedes unir el clic con lo que esa persona hizo después en tu base de datos. Los parámetros del evento están en la documentación de webhooks.
Y analiza la métrica por partes antes de sacar conclusiones: por tipo de aviso (transaccional o promocional), por navegador y sistema (en móvil y en escritorio la notificación se ve distinta), por hora de envío y por segmento. Si quieres probar dos textos, reparte la audiencia con una etiqueta asignada al azar al suscribir y envía cada variante a su mitad; lo contamos en segmentar con etiquetas.
Preguntas frecuentes
¿Qué es una buena tasa de clics para notificaciones push?
No hay una cifra universal fiable: depende del tipo de aviso, de la audiencia y de cómo se mida. Un aviso transaccional esperado («tu pedido ha llegado») y una promoción no son comparables. Usa tu propio historial como referencia y busca mejoras respecto a él.
¿Por qué a veces tengo más clics que entregas?
Porque la entrega la comunica el dispositivo y ese aviso puede perderse si la conexión cae justo entonces. Por eso conviene contar cada clic sin entrega registrada como entregada.
¿Cerrar la notificación cuenta como interacción?
No como clic. Al descartarla se lanza notificationclose, que puedes registrar aparte si te interesa medir rechazos, pero no debe sumar en la tasa de clics.
¿Los clics en botones de acción cuentan como clics?
Si añades botones con la opción actions, el mismo notificationclick se lanza con event.action indicando cuál se pulsó. Decide si cuentan y regístralo de forma separada para poder comparar.
¿Cuánto tiempo debo esperar para medir un envío?
Lo suficiente para que pase la mayor parte de la actividad y siempre la misma ventana para todos los envíos. Leer a las 24 o 48 horas es una regla práctica razonable para la mayoría de avisos.