Notificaciones Multicanal para E-commerce

Arrastrar para reorganizar las secciones
Editor de contenido enriquecido

 

Introduccion

En el competitivo mundo del e-commerce, la comunicacion efectiva con los clientes puede marcar la diferencia entre una venta exitosa y un carrito abandonado. Las notificaciones multicanal permiten llegar a los clientes por su canal preferido en el momento adecuado.

Por Que Notificaciones Multicanal?

Estadisticas Clave

  • 73% de los clientes prefieren recibir notificaciones por multiples canales
  • 48% de los carritos abandonados pueden recuperarse con recordatorios oportunos
  • 90% espera actualizaciones de envio en tiempo real
  • 3x mas engagement con notificaciones personalizadas

Canales Principales

Canal Mejor Para Tasa de Apertura
SMS Alertas urgentes 98%
WhatsApp Conversaciones 95%
Email Contenido detallado 20-30%
Push Usuarios activos 40-60%

Arquitectura de Notificaciones

Evento (pedido, envio, etc.)
           |
           v
    Motor de Reglas
           |
     ┌─────┴─────┐
     |           |
Seleccion    Personalizacion
de Canal     de Contenido
     |           |
     └─────┬─────┘
           |
           v
    Envio Multicanal
    (SMS + WhatsApp + Email)
           |
           v
    Tracking y Analytics

Implementacion

Servicio de Notificaciones

import Zavudev from '@zavudev/sdk';

class NotificationService {
  constructor() {
    this.client = new Zavudev({
      apiKey: process.env.ZAVUDEV_API_KEY
    });
  }

  // Determinar mejor canal para el cliente
  selectChannel(customer, notificationType) {
    const preferences = customer.notificationPreferences || {};

    // Respetar preferencias del cliente
    if (preferences[notificationType]) {
      return preferences[notificationType];
    }

    // Logica de seleccion por defecto
    const channelPriority = {
      urgent: ['sms', 'whatsapp', 'email'],
      transactional: ['whatsapp', 'sms', 'email'],
      marketing: ['email', 'whatsapp'],
      support: ['whatsapp', 'email', 'sms']
    };

    const channels = channelPriority[notificationType] || ['auto'];

    // Verificar disponibilidad del canal
    for (const channel of channels) {
      if (this.isChannelAvailable(customer, channel)) {
        return channel;
      }
    }

    return 'auto';
  }

  isChannelAvailable(customer, channel) {
    switch (channel) {
      case 'sms':
      case 'whatsapp':
        return !!customer.phone;
      case 'email':
        return !!customer.email;
      default:
        return true;
    }
  }

  async send(customer, notification) {
    const channel = this.selectChannel(customer, notification.type);
    const content = this.formatContent(notification, channel);

    const params = {
      to: channel === 'email' ? customer.email : customer.phone,
      channel,
      ...content
    };

    return await this.zavu.messages.send(params);
  }

  formatContent(notification, channel) {
    const templates = notification.templates || {};

    switch (channel) {
      case 'sms':
        return {
          text: templates.sms || notification.shortMessage
        };

      case 'whatsapp':
        return {
          text: templates.whatsapp || notification.message,
          messageType: notification.interactive ? 'buttons' : 'text',
          content: notification.buttons ? { buttons: notification.buttons } : undefined
        };

      case 'email':
        return {
          subject: notification.subject,
          text: templates.email || notification.message,
          htmlBody: templates.emailHtml
        };

      default:
        return { text: notification.message };
    }
  }
}

Notificaciones de E-commerce

class EcommerceNotifications extends NotificationService {

  // Confirmacion de pedido
  async orderConfirmed(order) {
    return this.send(order.customer, {
      type: 'transactional',
      subject: `Pedido #${order.id} confirmado`,
      shortMessage: `Pedido #${order.id} confirmado. Total: ${order.total}`,
      message: `Hola ${order.customer.name}!\n\nTu pedido #${order.id} ha sido confirmado.\n\nTotal: ${order.total}\nItems: ${order.items.length}\n\nTe avisaremos cuando sea enviado.`,
      templates: {
        whatsapp: `Hola ${order.customer.name}! Tu pedido #${order.id} por ${order.total} esta confirmado. Te avisaremos cuando sea enviado.`
      },
      buttons: [
        { id: 'track', title: 'Ver Pedido' },
        { id: 'help', title: 'Ayuda' }
      ]
    });
  }

  // Pedido enviado
  async orderShipped(order) {
    return this.send(order.customer, {
      type: 'transactional',
      subject: `Tu pedido #${order.id} ha sido enviado`,
      shortMessage: `Pedido #${order.id} enviado! Seguimiento: ${order.tracking}`,
      message: `Tu pedido #${order.id} va en camino!\n\nNumero de seguimiento: ${order.tracking}\nEntrega estimada: ${order.deliveryDate}`,
      templates: {
        whatsapp: `Tu pedido #${order.id} va en camino! Seguimiento: ${order.tracking}. Entrega: ${order.deliveryDate}`
      },
      buttons: [
        { id: 'track', title: 'Rastrear' }
      ]
    });
  }

  // Pedido entregado
  async orderDelivered(order) {
    return this.send(order.customer, {
      type: 'transactional',
      subject: `Pedido #${order.id} entregado`,
      shortMessage: `Pedido #${order.id} entregado. Gracias por tu compra!`,
      message: `Tu pedido #${order.id} ha sido entregado.\n\nGracias por comprar con nosotros!\n\nNos encantaria conocer tu opinion.`,
      buttons: [
        { id: 'review', title: 'Dejar Opinion' },
        { id: 'problem', title: 'Reportar Problema' }
      ]
    });
  }

  // Carrito abandonado
  async abandonedCart(cart) {
    // Esperar tiempo configurable
    return this.send(cart.customer, {
      type: 'marketing',
      subject: 'Olvidaste algo en tu carrito',
      shortMessage: `Tienes ${cart.items.length} productos esperando. Completa tu compra!`,
      message: `Hola ${cart.customer.name}!\n\nNotamos que dejaste algunos productos en tu carrito:\n\n${this.formatCartItems(cart.items)}\n\nTotal: ${cart.total}\n\nCompleta tu compra antes de que se agoten!`,
      buttons: [
        { id: 'complete', title: 'Completar Compra' },
        { id: 'later', title: 'Recordar Despues' }
      ]
    });
  }

  // Producto de nuevo en stock
  async backInStock(product, customers) {
    for (const customer of customers) {
      await this.send(customer, {
        type: 'marketing',
        subject: `${product.name} esta de vuelta!`,
        shortMessage: `${product.name} volvio a stock. Compralo ahora!`,
        message: `Buenas noticias! ${product.name} que estabas esperando ya esta disponible.\n\nPrecio: ${product.price}\n\nApurate, el stock es limitado!`,
        buttons: [
          { id: 'buy', title: 'Comprar Ahora' }
        ]
      });
    }
  }

  formatCartItems(items) {
    return items
      .map(item => `- ${item.name} (x${item.quantity}): ${item.price}`)
      .join('\n');
  }
}

Motor de Reglas

class NotificationRules {
  constructor(notificationService) {
    this.notifications = notificationService;
    this.rules = [];
  }

  addRule(rule) {
    this.rules.push(rule);
  }

  async processEvent(event) {
    for (const rule of this.rules) {
      if (rule.condition(event)) {
        await rule.action(event, this.notifications);
      }
    }
  }
}

// Configurar reglas
const rules = new NotificationRules(new EcommerceNotifications());

// Regla: Confirmar pedido inmediatamente
rules.addRule({
  condition: (event) => event.type === 'order.created',
  action: async (event, notif) => {
    await notif.orderConfirmed(event.order);
  }
});

// Regla: Notificar envio
rules.addRule({
  condition: (event) => event.type === 'order.shipped',
  action: async (event, notif) => {
    await notif.orderShipped(event.order);
  }
});

// Regla: Carrito abandonado (despues de 1 hora)
rules.addRule({
  condition: (event) =>
    event.type === 'cart.abandoned' &&
    event.cart.age > 60 * 60 * 1000 && // 1 hora
    event.cart.total > 0,
  action: async (event, notif) => {
    await notif.abandonedCart(event.cart);
  }
});

// Regla: Recordatorio de pago pendiente
rules.addRule({
  condition: (event) =>
    event.type === 'order.payment_pending' &&
    event.order.age > 24 * 60 * 60 * 1000, // 24 horas
  action: async (event, notif) => {
    await notif.paymentReminder(event.order);
  }
});

Integracion con Plataformas

Shopify

const Shopify = require('shopify-api-node');

async function setupShopifyWebhooks(shop) {
  const shopify = new Shopify({
    shopName: shop.name,
    apiKey: shop.apiKey,
    password: shop.password
  });

  // Webhook para pedidos creados
  await shopify.webhook.create({
    topic: 'orders/create',
    address: 'https://tuapi.com/webhooks/shopify/orders',
    format: 'json'
  });

  // Webhook para fulfillments
  await shopify.webhook.create({
    topic: 'fulfillments/create',
    address: 'https://tuapi.com/webhooks/shopify/fulfillments',
    format: 'json'
  });
}

// Procesar webhook de Shopify
app.post('/webhooks/shopify/orders', async (req, res) => {
  const order = transformShopifyOrder(req.body);
  await rules.processEvent({ type: 'order.created', order });
  res.sendStatus(200);
});

WooCommerce

// Procesar webhook de WooCommerce
app.post('/webhooks/woocommerce', async (req, res) => {
  const { topic } = req.headers['x-wc-webhook-topic'];
  const data = req.body;

  switch (topic) {
    case 'order.created':
      const order = transformWooOrder(data);
      await rules.processEvent({ type: 'order.created', order });
      break;

    case 'order.updated':
      if (data.status === 'completed') {
        await rules.processEvent({ type: 'order.shipped', order: transformWooOrder(data) });
      }
      break;
  }

  res.sendStatus(200);
});

Personalizacion Avanzada

Segmentacion de Clientes

function segmentCustomer(customer, purchaseHistory) {
  if (purchaseHistory.totalSpent > 1000) {
    return 'vip';
  }
  if (purchaseHistory.orderCount > 5) {
    return 'loyal';
  }
  if (purchaseHistory.orderCount === 0) {
    return 'new';
  }
  return 'regular';
}

async function sendSegmentedNotification(customer, notification) {
  const segment = segmentCustomer(customer, customer.purchaseHistory);

  // Personalizar mensaje segun segmento
  const templates = {
    vip: {
      prefix: `Estimado cliente VIP ${customer.name},`,
      suffix: 'Como siempre, tu envio es prioritario y gratuito.'
    },
    loyal: {
      prefix: `Hola ${customer.name}!`,
      suffix: 'Gracias por seguir confiando en nosotros.'
    },
    new: {
      prefix: `Bienvenido ${customer.name}!`,
      suffix: 'Esperamos que esta sea la primera de muchas compras.'
    },
    regular: {
      prefix: `Hola ${customer.name},`,
      suffix: ''
    }
  };

  const template = templates[segment];
  notification.message = `${template.prefix}\n\n${notification.message}\n\n${template.suffix}`;

  await notificationService.send(customer, notification);
}

Analytics y Optimizacion

async function trackNotificationMetrics(notification, result) {
  await analytics.track({
    event: 'notification_sent',
    properties: {
      channel: result.channel,
      type: notification.type,
      customerId: notification.customerId,
      messageId: result.id,
      timestamp: new Date().toISOString()
    }
  });
}

async function getNotificationReport(dateRange) {
  return {
    byChannel: await getMetricsByChannel(dateRange),
    byType: await getMetricsByType(dateRange),
    conversionRate: await getConversionRate(dateRange),
    optOutRate: await getOptOutRate(dateRange)
  };
}

Conclusion

Las notificaciones multicanal son esenciales para cualquier e-commerce moderno. Permiten comunicarse con los clientes en el momento adecuado, por el canal que prefieren, aumentando la satisfaccion y las conversiones.

La clave esta en respetar las preferencias del cliente, personalizar los mensajes y medir constantemente para optimizar.

Recursos

rich_text    
Arrastrar para reorganizar las secciones
Editor de contenido enriquecido
rich_text    

Comentarios de la página