Las notificaciones de envío reducen los tickets de soporte y generan confianza en los clientes. Así es como diseñar emails de envío eficaces a lo largo de todo el recorrido de entrega.
Secuencia de emails de envío
Pedido enviado
interface ShippingNotification {
order: {
id: string;
items: OrderItem[];
};
shipping: {
carrier: string;
trackingNumber: string;
trackingUrl: string;
estimatedDelivery: Date;
shippedAt: Date;
};
customer: {
name: string;
email: string;
};
address: ShippingAddress;
}
await sendEmail({
to: customer.email,
subject: `Your order has shipped! 📦`,
template: 'order-shipped',
data: {
customer,
order,
shipping,
trackingUrl: shipping.trackingUrl,
estimatedDelivery: formatDate(shipping.estimatedDelivery)
}
});
En reparto
await sendEmail({
to: customer.email,
subject: 'Your order is out for delivery! 🚚',
template: 'out-for-delivery',
data: {
customer,
order,
estimatedWindow: '2:00 PM - 6:00 PM',
trackingUrl: shipping.trackingUrl
}
});
Confirmación de entrega
await sendEmail({
to: customer.email,
subject: 'Your order has been delivered ✓',
template: 'order-delivered',
data: {
customer,
order,
deliveredAt: shipping.deliveredAt,
deliveryPhoto: shipping.proofOfDelivery,
reviewUrl: `${baseUrl}/orders/${order.id}/review`,
supportUrl: `${baseUrl}/support`
}
});
Gestión de excepciones
Excepción de entrega
const exceptionTemplates = {
'address_issue': {
subject: 'Delivery issue - address update needed',
template: 'delivery-exception-address'
},
'recipient_unavailable': {
subject: 'Delivery attempted - no one home',
template: 'delivery-exception-unavailable'
},
'weather_delay': {
subject: 'Shipping delay due to weather',
template: 'delivery-exception-weather'
}
};
async function sendExceptionNotification(order: Order, exception: DeliveryException) {
const config = exceptionTemplates[exception.type];
await sendEmail({
to: order.customer.email,
subject: config.subject,
template: config.template,
data: {
order,
exception,
newEstimate: exception.newEstimatedDelivery,
actionRequired: exception.requiresAction,
updateUrl: `${baseUrl}/orders/${order.id}/update-address`
}
});
}
Entrega fallida
await sendEmail({
to: customer.email,
subject: 'Delivery unsuccessful - action required',
template: 'delivery-failed',
data: {
customer,
order,
reason: exception.reason,
options: [
{ label: 'Reschedule delivery', url: rescheduleUrl },
{ label: 'Update address', url: updateAddressUrl },
{ label: 'Hold at facility', url: holdUrl }
],
deadline: 'Package will be returned after 5 days'
}
});
Pedidos con varios paquetes
interface MultiPackageShipment {
order: Order;
packages: Array<{
packageNumber: number;
totalPackages: number;
trackingNumber: string;
items: OrderItem[];
status: string;
}>;
}
await sendEmail({
to: customer.email,
subject: `Package 1 of 3 shipped - Order #${order.number}`,
template: 'multi-package-shipped',
data: {
customer,
order,
package: packages[0],
remainingPackages: packages.slice(1),
allTrackingUrl: `${baseUrl}/orders/${order.id}/tracking`
}
});
Integración con el transportista
Gestión de webhooks
async function handleCarrierWebhook(event: CarrierEvent) {
const order = await getOrderByTracking(event.trackingNumber);
const eventMap = {
'shipped': sendShippedNotification,
'in_transit': sendTransitUpdate,
'out_for_delivery': sendOutForDeliveryNotification,
'delivered': sendDeliveredNotification,
'exception': sendExceptionNotification
};
const handler = eventMap[event.status];
if (handler) {
await handler(order, event);
}
}
Mejores prácticas
- —Actualizaciones en tiempo real - Envía en cuanto cambie el estado
- —Enlaces de seguimiento claros - Un clic al seguimiento del transportista
- —Establece expectativas - Ventanas de entrega estimadas
- —Gestiona las excepciones - Comunicación proactiva ante retrasos
- —Incluye detalles del pedido - Recuérdales qué viene
- —Optimizado para móviles - La mayoría consulta el envío desde el teléfono
Unos buenos emails de envío reducen los tickets de soporte de "¿dónde está mi pedido?" y generan confianza en los clientes.