Dev Life

Creación de flujos de trabajo de emails transaccionales para notificaciones de carritos abandonados con la API de Mailgun

En las aplicaciones de comercio electrónico modernas, los emails transaccionales van más allá de las confirmaciones de pedidos y las actualizaciones de envío. También responden al comportamiento del usuario; por ejemplo, si un usuario añade artículos a su carrito pero no completa la compra, puedes enviar un recordatorio, conocido comúnmente como notificación de «carrito abandonado». […]
Image for Creación de flujos de trabajo de emails transaccionales para notificaciones de carritos abandonados con la API de Mailgun

En las aplicaciones de comercio electrónico modernas, los emails transaccionales van más allá de las confirmaciones de pedidos y las actualizaciones de envío. También responden al comportamiento del usuario; por ejemplo, si un usuario añade artículos a su carrito pero no completa la compra, puedes enviar un recordatorio, conocido comúnmente como notificación de «carrito abandonado». Esto no solo fomenta que se complete la compra, sino que también proporciona un punto de contacto útil en caso de que el usuario tenga algún problema durante el proceso de pago.


En este tutorial, aprenderás a enviar un email de carrito abandonado a los usuarios utilizando las API de Mailgun.

Implementación de flujos de trabajo de emails transaccionales para notificaciones de carritos abandonados

Para implementar flujos de trabajo de emails transaccionales para notificaciones de carritos abandonados, crearás una sencilla interfaz de usuario para simular un carrito de la compra y un Flask backend para hacer un seguimiento de los carritos abandonados y disparar emails transaccionales.


Antes de comenzar, asegúrate de tener lo siguiente:

  • Una Cuenta de Mailgun para enviar emails a través de la API de Mailgun; si no tienes una cuenta, sigue las instrucciones guía de inicio rápido para configurar una de forma gratuita
  • Python 3.8 o superior instalado en tu máquina
  • Cierta familiaridad con HTML y JavaScript para entender el código de la interfaz de usuario

Configurar una cuenta de Mailgun

Primero, inicia sesión en tu cuenta de Mailgun y anota tu dominio de envío en el panel de control de Mailgun. Si estás en un plan gratuito, verás un dominio sandbox, que se utilizará tanto en el punto de conexión de API como en la dirección de email "from" al enviar emails. El dominio sandbox sigue este formato: sandbox.mailgun.org:
Dominio de envío de Mailgun

Nota: Si deseas enviar emails desde tu propio dominio personalizado, necesitarás un plan de pago de Mailgun. El plan gratuito solo admite el dominio sandbox y limita el envío a cinco destinatarios autorizados.

Si deseas enviar emails desde tu propio dominio personalizado, necesitarás un plan de pago de Mailgun. El plan gratuito solo admite el dominio sandbox y limita el envío a cinco destinatarios autorizados.

A continuación, debes generar una clave de API desde la página de seguridad de la API. Puedes encontrar esta opción en el menú desplegable debajo de tu nombre en la esquina superior derecha del panel de control de Mailgun:
Crear una clave de API

Utilizarás esta clave de API en tu aplicación Flask para enviar notificaciones de carritos abandonados a través de la API de Mailgun.

Configurar un nuevo proyecto de Python

Para configurar un nuevo proyecto, abre un terminal dentro del directorio de proyecto que prefieras y ejecuta los siguientes comandos para obtener el código requerido (tanto la interfaz de usuario como el backend) en tu máquina:


git clone https://github.com/manishh/gifts-giveaways.git cd gifts-giveaways/python/mailgun-abandoned-cart-notifications

A continuación, dentro del directorio mailgun-abandoned-cart-notifications, renombra .env.example a .env, y actualízalo con tus credenciales de la API de Mailgun:
# Sustituye por tu clave de API de Mailgun y dominio reales MAILGUN_API_KEY="TU-CLAVE-DE-API" MAILGUN_DOMAIN="TU-DOMINIO-DE-MAILGUN"

Antes de continuar, es recomendable que crees y actives un nuevo entorno virtual para aislar tu proyecto y evitar conflictos de dependencias.
Una vez que tu entorno virtual esté activo, instala las dependencias requeridas:
pip install -r requirements.txt
Esto instala todos los paquetes necesarios, incluyendo Flask, el marco web ligero que ejecuta el backend.
Una vez completada la instalación, inicia la aplicación Flask con este comando:
python app.py
La interfaz de usuario de la aplicación estará disponible en http://localhost:5000/.

Creación de la interfaz de carrito abandonado

La captura de pantalla siguiente muestra una sencilla interfaz de usuario de comercio electrónico para simular escenarios de carritos abandonados. En la parte superior, el encabezado muestra el título, junto con un perfil de usuario (mostrando el nombre y el email) y un icono de carrito de la compra que indica el número de artículos en el carrito. Hay cuatro tarjetas de productos que muestran imágenes, nombres, precios y descripciones, y los usuarios pueden seleccionar cantidades antes de añadir artículos con el botón de Añadir al carrito. En la parte inferior izquierda, un panel de ajustes te permite configurar el tiempo de espera del carrito abandonado (en segundos) y restablecer el carrito si es necesario. En la vida real, el tiempo de espera sería en horas, y el backend debería hacer un seguimiento de este.
Puedes utilizar esta interfaz para disparar un evento cuando un usuario deja artículos en su carrito sin completar la compra:
Interfaz de usuario de carrito abandonado

Puedes encontrar el código para esta interfaz de carrito de la compra en templates/shopping_cart.html. Este archivo tiene dos secciones importantes: la configuración de la interfaz de usuario y una función para enviar los datos del carrito abandonado al backend.


Para la configuración de la interfaz de usuario, localiza y edita USER_NAME y USER_EMAIL dentro de la etiqueta  para enviar los datos correctos a tu backend. Estos dos parámetros representan al usuario que ha iniciado sesión en tu aplicación de comercio electrónico:


// Configuración: Sustituye estos por tus propios valores const USER_NAME = "John Smith"; const USER_EMAIL = "john.smith@example.com"; // Email verificado para la cuenta sandbox de Mailgun const BACKEND_URL = 'http://localhost:5000/abandoned-cart'; // Actualiza a tu punto de conexión de API de Flask, si es necesario let ABANDONED_CART_TIMEOUT = 60; // Tiempo de espera predeterminado en segundos

Nota: Si utilizas el plan gratuito de Mailgun, asegúrate de que USER_EMAIL sea una de las direcciones verificadas en tu cuenta de Mailgun. Puedes dejar los dos parámetros restantes sin cambios.


La siguiente función de JavaScript, sendToBackend(data), se encarga del proceso de enviar detalles del carrito abandonado (como la información del usuario, los artículos en el carrito y el valor total) al backend para disparar una notificación:


// Función para enviar datos al backend sendToBackend(data) { console.log('Enviando datos de carrito abandonado al backend...'); fetch(BACKEND_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) }) .then(response => { // Comprueba si el estado de la respuesta es 200 (OK) if (response.status === 200) { return response.json(); } else { // Lanza un error si el estado no es 200 throw new Error(`¡Error HTTP! Estado: ${response.status}`); } }) .then(result => { console.log('Respuesta del backend:', result); alert('¡Notificación de carrito abandonado enviada con éxito!'); resetCart(); }) .catch(error => { console.error('Error al enviar la notificación de carrito abandonado:', error); alert('Error al enviar la notificación de carrito abandonado. Consulta la consola para obtener más detalles.'); }); }


En primer lugar, esta función hace una solicitud HTTP POST a BACKEND_URL utilizando la llamada fetch, para convertir los datos del carrito en una carga útil de JSON.
Si el servidor responde correctamente (HTTP 200), la respuesta se procesa y se guarda en los logs de la consola, y una alerta confirma que la notificación de carrito abandonado se ha enviado. A continuación, se restablece el carrito.


Si la solicitud falla, debido a problemas de red o a un problema del lado del servidor (como errores HTTP 5XX), la función detecta el error, lo guarda en los logs de la consola y alerta al usuario de que algo ha salido mal. De este modo, la función garantiza que tanto los intentos correctos como los fallidos de notificar al backend se gestionan de forma elegante, manteniendo al usuario informado durante todo el proceso.


El código restante en shopping_cart.html se encarga del estilo CSS para conseguir un diseño limpio y visualmente atractivo, de la lógica de JavaScript para calcular el valor total del carrito y de la gestión del temporizador para simular el abandono del carrito.

Procesamiento de notificaciones de carritos abandonados en el backend


Cuando la interfaz de usuario envía datos de carrito abandonado a BACKEND_URL, la aplicación Flask (app.py) los procesa utilizando la siguiente función:
@app.route('/abandoned-cart', methods=['POST']) def abandoned_cart(): """ Punto de conexión para recibir datos de carrito abandonado, incluyendo información del usuario. Envía una notificación por email al usuario en cuestión. """ try: # Obtiene los datos del carrito a partir de la solicitud cart_data = request.json # Extrae la información del usuario user_info = cart_data.get('user', {}) user_email = user_info.get('email', 'unknown') # Guarda los datos recibidos en los logs logger.info(f"Carrito abandonado recibido de {user_email} a las {datetime.datetime.now()}, Total de artículos: {len(cart_data.get('items', []))}") # Envía un email sobre el carrito abandonado html_message = _generate_abandoned_cart_email(cart_data) _send_email(f"{user_info.get('name', user_email)} ", "Tu carrito te está esperando...", html_message) # Devuelve la respuesta de éxito return jsonify({ "status": "success", "message": f"Notificación de carrito abandonado enviada a: {user_info.get('email')}", "timestamp": datetime.datetime.now().isoformat(), }), 200 except Exception as e: logger.error(f"Error al procesar el carrito abandonado: {str(e)}") return jsonify({"status": "error", "message": str(e)}), 500


Este punto de conexión de API (/abandoned-cart) escucha solicitudes POST cuando un usuario abandona su carrito. Extrae los detalles del carrito de la carga útil JSON de la solicitud, recupera el email y el nombre del usuario, y registra el evento en los logs junto con la marca de tiempo y el número de artículos.


A continuación, genera un email utilizando _generate_abandoned_cart_email(cart_data), que convierte los detalles del carrito en una ordenada plantilla de email HTML. A continuación, el email se envía a user_email a través de _send_email(), utilizando el asunto «Tu carrito te está esperando…» para recordar al usuario su compra pendiente.
Si tiene éxito, la función devuelve una respuesta JSON para confirmar que el email ha sido enviado. Si se produce un error, como un problema con la solicitud o con el servicio de envío de emails, guarda el error en los logs y devuelve una respuesta HTTP 500 Internal Server Error, que la interfaz de usuario puede usar para informar al usuario sobre el estado de la notificación.

Diseño de la plantilla de email

Los emails de recordatorio de carrito abandonado no solo deben ser informativos, sino también visualmente atractivos. Un email HTML bien diseñado con imágenes presenta los detalles del carrito de forma clara y aumenta las posibilidades de que el usuario regrese para completar su compra. La función _generate_abandoned_cart_email(...) se encarga de esto:


def _generate_abandoned_cart_email(cart_data: Dict[str, Any]) -> str: """ Genera un email HTML para un carrito abandonado utilizando los datos proporcionados del carrito. Args: cart_data: Diccionario que contiene la información del carrito, incluyendo los detalles del usuario y los artículos Returns: Cadena HTML para el email """ try: # Extrae datos con gestión de errores user_name = cart_data.get('user', {}).get('name', 'Estimado cliente') first_name = user_name.split()[0] if ' ' in user_name else user_name items = cart_data.get('items', []) total_value = cart_data.get('totalValue', 0) # Formatea la marca de tiempo si está disponible timestamp_str = cart_data.get('timestamp', '') timezone_offset = cart_data.get('timezoneOffset', 0) # Representa la zona horaria del usuario if timestamp_str: try: timestamp = datetime.datetime.fromisoformat(timestamp_str.replace('Z', '+00:00')) - datetime.timedelta(minutes=timezone_offset) abandonment_time = f"el {timestamp.strftime('%d de %B a las %H:%M')}" except (ValueError, TypeError): abandonment_time = 'recientemente' else: abandonment_time = 'recientemente' # Genera el contenido HTML con un CSS mínimo combinado html = f""" /* El estilo CSS va aquí */

¡Tu carrito te está esperando!

Esta función elabora un email HTML que recuerda a un usuario su carrito abandonado. En primer lugar, extrae detalles clave de los datos proporcionados, incluyendo el nombre del usuario, los artículos del carrito y el precio total. Si hay una marca de tiempo disponible, la convierte a la zona horaria del usuario (ya que las zonas horarias del servidor y del cliente serían diferentes) y la formatea en una cadena de fecha y hora fácil de leer (como "el 25 de marzo a las 15:49"). En caso contrario, el valor predeterminado es "recientemente".


El email informa al usuario de que se ha guardado su carrito y enumera los artículos que dejó, incluyendo el nombre del producto, la cantidad, el precio, la descripción y una imagen. El valor total del carrito se muestra de forma destacada, seguido de un botón de Completa tu compra para animar al usuario a regresar y terminar el proceso de pago.
Si se produce un error, como la falta de datos o problemas de formato, la función recurre a un email sencillo con un mensaje básico y un enlace de compra. De este modo se garantiza que, aunque la versión detallada falle, los usuarios sigan recibiendo un recordatorio para completar su transacción.

Consejo profesional: Mailgun ofrece plantillas de email prediseñadas y un editor visual intuitivo para crear emails atractivos y adaptativos sin escribir ni una sola línea de código.

Navega a Send > Envíos > Plantillas en tu cuenta de Mailgun para diseñar tus propias plantillas de email:
Plantillas de emails

Implementación de la funcionalidad de envío de emails con la API de Mailgun


Una vez generado el contenido del email, debe entregarse de forma fiable. La función _send_email(...) se encarga de realizar los envíos de notificaciones de carritos abandonados utilizando la API de Mailgun:


def _send_email(to_address: str, subject: str, html_message: str): """ Envía un solo email a la dirección de email especificada utilizando la API de Mailgun. :param to_address: :param subject: :param message: """ api_key = os.getenv("MAILGUN_API_KEY") # Obtiene la clave de API del archivo `.env` resp = requests.post(MAILGUN_API_URL, auth=("api", api_key), data={"from": FROM_EMAIL_ADDRESS, "to": to_address, "subject": subject, "html": html_message}) if resp.status_code == 200: # Éxito logging.info(f"Se ha enviado correctamente un email a '{to_address}' a través de la API de Mailgun.") else: # Error raise RuntimeError(f"No se pudo enviar el email, motivo: {resp.text}")


Esta función lee MAILGUN_API_KEY y a continuación envía un email a través de la API de Mailgun mediante una solicitud HTTP POST. La solicitud incluye los detalles básicos del email, como la dirección del remitente, la dirección del destinatario, el asunto y el contenido HTML generado por la función _generate_abandoned_cart_email(...).
Si la solicitud tiene éxito (resp.status_code == 200), guarda un mensaje de éxito en los logs. En caso contrario, genera una excepción con los detalles de la respuesta.
Es importante entender que _send_email(...) deliberadamente no gestiona los errores, dejándolo a cargo de la función de llamada (abandoned_cart(), que sirve al punto de conexión /abandoned-cart), para que pueda detectar las excepciones y devolver una respuesta HTTP adecuada. Si el email se envía correctamente, abandoned_cart() devuelve una respuesta HTTP 200 para confirmar que la notificación ha sido enviada. Si se produce un error, como una clave de API inválida o un fallo en la red, devuelve una respuesta HTTP 500, asegurando que la interfaz de usuario esté informada del problema.

Probar el flujo de trabajo

Ahora que has explorado todos los componentes clave, es hora de probar el flujo de trabajo del email de carrito abandonado de principio a fin.
Primero, asegúrate de que tu servidor Flask se esté ejecutando y de que se pueda acceder a la interfaz de usuario en tu navegador en http://localhost:5000/. Puedes ajustar el tiempo de espera del carrito abandonado en el panel de ajustes en la parte inferior izquierda de la página según sea necesario.


A continuación, añade algunos artículos a tu carrito. Cada vez que añades un artículo, el temporizador de cuenta atrás del carrito se restablece y vuelve a empezar. Cuando hayas terminado, haz clic en el icono del carrito para ver el panel deslizable, que muestra los productos seleccionados, sus precios y el botón de Continuar con el pago:


Triggering an abandoned cart

En lugar de continuar con el pago, deja que el temporizador termine su cuenta atrás. Una vez que la cuenta atrás llegue a cero, debería aparecer una alerta en la interfaz de usuario para confirmar que la notificación de carrito abandonado se ha enviado. El mensaje de alerta debería decir:
¡Notificación de carrito abandonado enviada con éxito!


Al mismo tiempo, el terminal de tu aplicación Flask debería registrar mensajes en los logs como este:
INFO:__main__:Carrito abandonado recibido de a las 2025-03-24 14:02:00.077949, Total de artículos: 3 INFO:root:Se ha enviado correctamente un email a 'Nombre ' a través de la API de Mailgun.


Por último, revisa tu bandeja de entrada en busca del email de carrito abandonado. Si todo ha funcionado correctamente, deberías recibir este mensaje:


Abandoned cart notification email


Nota: Si utilizas el plan gratuito de Mailgun, el email puede acabar en la carpeta de spam.


¡Enhorabuena! Has implementado y probado con éxito el flujo de trabajo de notificaciones por email de carritos abandonados utilizando la API de Mailgun.

Seguimiento y gestión de emails

Una vez que se realizan los envíos de los emails de carritos abandonados, es importante hacer un seguimiento de su entrega, seguir la interacción y gestionar los fallos de forma eficaz. Mailgun proporciona herramientas de panel de informes integradas para hacer un seguimiento de los emails enviados, las tasas de aperturas y los fallos.


Para acceder a esta información estratégica, navega a Send > Panel de informes > Métricas en el panel de control de Mailgun:


Mailgun email monitoring

Aquí encontrarás un desglose gráfico de las estadísticas de email clave, como:
Recuento de enviados: Número total de emails intentados
Recuento de entregados: Emails recibidos con éxito por los destinatarios
Recuento de abiertos: Número de aperturas de emails por los destinatarios (si se ha activado el seguimiento de aperturas)
Recuento de fallidos: Emails que han fallado debido a problemas como direcciones inválidas o filtros de correo no deseado


Para un análisis más profundo, la pestaña Logs proporciona registros detallados del estado de cada email, mientras que la pestaña de clasificación de rebotes ayuda a diagnosticar los fallos.
Una alta tasa de rebotes puede afectar de forma negativa a la entregabilidad de tu email. Para reducir los rebotes, revisa periódicamente la pestaña de clasificación de rebotes en Mailgun, elimina los emails inválidos y utiliza listas de supresión para evitar reenvíos a las direcciones de los rebotes.

En resumen

En este tutorial, has aprendido cómo implementar un flujo de trabajo de emails de carritos abandonados utilizando Mailgun. El proceso abarcó la creación de una interfaz de usuario sencilla para simular un sitio de comercio electrónico, los envíos de datos del carrito al backend, su procesamiento con Flask, la generación de plantillas de email, los envíos de notificaciones a través de la API de Mailgun y el seguimiento de las métricas de entrega. Los emails transaccionales como estos son una gran ayuda para recuperar ventas perdidas y mejorar la interacción del cliente.


Puedes encontrar el código completo de este tutorial en este repositorio de GitHub.


Ahora puedes poner estos conocimientos en práctica: integra Mailgun en tus proyectos y comienza a usar emails transaccionales para mejorar la experiencia de usuario. Explorar Plantillas para correos transaccionales y prueba la API de Mailgun gratis hoy mismo!

¡Mantenme al día! Recibe excelentes recursos en tu bandeja de entrada cada semana.
Envíame la newsletter de Mailgun. Acepto expresamente recibir la newsletter y sé que puedo darme de baja fácilmente en cualquier momento.

¡Revisa tu bandeja de entrada cada mes para ver tu newsletter de Mailgun!