Un onboarding de SaaS suele dibujarse como una línea muy simple: registro, email de bienvenida, primer uso y activación. En producción, esa línea se rompe cuando el email tarda, el webhook llega dos veces o una persona abre el mensaje desde otro dispositivo.
En mis experimentos de producto intento que el email sea una señal del onboarding, no el dueño de todo el flujo. La diferencia parece pequeña, pero ayuda a separar “el usuario completó el paso” de “nuestro proveedor avisó que envió un mensaje”. Así las métricas son mas honestas y el equipo puede investigar un problema sin adivinar.
El email no es todo el onboarding
Un usuario puede verificar su cuenta desde un enlace, volver a la aplicación y completar su perfil antes de que nuestro sistema procese el evento delivered. Si el producto sólo considera válida la activación cuando recibe ese evento, la métrica queda atrasada o directamente incorrecta.
Conviene tratar cada paso como un estado propio:
-
registered: la cuenta fue creada. -
verification_started: se solicitó la verificación. -
verified: la persona confirmó su dirección. -
profile_completed: terminó el primer dato útil. -
activated: realizó la acción que demuestra valor del producto.
El email conecta estados, pero no los sustituye. Esta idea también sirve para revisar los mensajes comerciales; por ejemplo, puede complementar una guía para auditar los emails de upgrade en un SaaS sin mezclar entrega con conversión.
Define un contrato para cada evento
Antes de cambiar el dashboard, escribe el contrato mínimo que debe cumplir un evento. Para un webhook de correo podría ser:
{
"event_id": "evt_8f12",
"user_id": "usr_42",
"message_type": "welcome",
"status": "delivered",
"occurred_at": "2026-10-20T08:20:00Z"
}
event_id evita contar dos veces el mismo aviso. user_id permite unir el evento con el onboarding sin usar el email como identificador principal. occurred_at ayuda a ordenar una señal atrasada, y message_type evita que un email de recuperación se cuele en la métrica de bienvenida.
También define qué pasa si faltan campos, si el proveedor reintenta o si llega un estado imposible. Un evento desconocido debe quedar en una cola de revisión, no convertirse en una activación silenciosa. Parece trabajo extra, pero despues ahorra bastante conversación ambigua entre producto y backend.
Un flujo pequeño que se puede observar
Una implementación inicial puede guardar el estado del usuario y una tabla de eventos procesados. El pseudocódigo siguiente muestra la regla importante: procesar de forma idempotente.
def handle_email_event(event):
if events.exists(event["event_id"]):
return "already_processed"
events.insert(event["event_id"], event)
if event["message_type"] == "welcome":
onboarding.mark_email_seen(event["user_id"], event["status"])
return "processed"
En una base de datos real, event_id debe tener una restricción única. El patrón “consultar y luego insertar” sin esa protección puede duplicar eventos cuando dos workers reciben el mismo webhook casi al mismo tiempo. La base de datos es la última barrera, aunque el código parezca suficientemente seguro.
Para entender el impacto, registra tres tiempos: cuándo se solicitó el mensaje, cuándo el proveedor informó el estado y cuándo el usuario completó el siguiente paso. Con esos datos puedes distinguir una demora del proveedor de una fricción real del producto. Es una observabilidad modesta, pero muy util.
Pruebas sin depender de una bandeja perfecta
Las pruebas de integración deben comprobar dos cosas separadas: que el sistema solicita el email y que el onboarding responde cuando llega una señal válida. No hace falta que cada test espere una bandeja real durante minutos.
Puedes usar un buzón controlado, un adaptador falso y un caso end-to-end pequeño. Si el equipo necesita un generador de cuentas de correo temporal para aislar registros de prueba, asocia la cuenta temporal al run_id del test y limpia sus datos cuando termine. El buzón es un recurso de test, no la identidad del usuario.
Una prueba útil también envía el mismo webhook dos veces y comprueba que la métrica sólo aumenta una vez. Otra entrega primero delivered y despues verified, y una tercera hace el orden inverso para confirmar que el estado final no depende de la suerte.
En la interfaz, los estados deben ser visibles y comprensibles. Una fila fija para validar el email puede evitar que el usuario pierda el contexto mientras espera, pero el frontend aún necesita manejar pending, expired y verified por separado.
Errores comunes y cómo corregirlos
El primer error es medir el clic del email como activación. Un clic demuestra interés, no necesariamente valor. El segundo es usar el webhook como única fuente de verdad; los proveedores pueden reintentar, cambiar de orden o entregar un estado con retraso.
El tercero es guardar el contenido entero del mensaje para poder depurar. Normalmente basta con conservar el identificador del proveedor, el tipo de mensaje y los tiempos principales. Menos datos hacen el debugging mas seguro.
Y hay un detalle que aparece en búsquedas internas: nombres como tempail mail pueden parecer equivalentes a un correo temporal, pero no deberían convertirse en estados de negocio. Conserva los términos de entrada para entender la consulta, y usa nombres claros dentro del código.
Preguntas rápidas
¿Debo bloquear el onboarding hasta recibir delivered?
No, salvo que el producto dependa realmente de esa entrega. Si la verificación ya ocurrió, permite continuar y registra la señal del proveedor como información adicional.
¿Qué hago con un webhook desconocido?
Guárdalo con estado unhandled, emite una alerta de baja urgencia y evita cambiar la métrica de activación. Así el equipo puede ampliar el contrato sin borrar evidencia.
¿Cuándo conviene separar Marketing y Backend?
Desde el principio en los nombres de eventos y responsables. Marketing puede definir el objetivo del mensaje; Backend debe garantizar que los eventos sean repetibles, trazables y seguros.
Checklist de lanzamiento
- [ ] Cada estado del onboarding tiene una definición observable.
- [ ] Los eventos tienen un identificador único e idempotente.
- [ ] La entrega de email no se confunde con activación.
- [ ] Los reintentos y eventos fuera de orden tienen pruebas.
- [ ]
pending,expiredyverifiedse muestran de forma distinta. - [ ] Los logs guardan tiempos y referencias, no contenido sensible innecesario.
- [ ] El dashboard explica qué fuente alimenta cada métrica.
Un onboarding resistente no necesita ignorar el email. Necesita colocarlo en el lugar correcto: como una señal útil dentro de un contrato de eventos mas amplio. Cuando producto, backend y pruebas comparten esos estados, los fallos son mas faciles de localizar y las decisiones de crecimiento se apoyan en señales reales.
Top comments (0)