Los emails de renovación de suscripción impactan directamente en la retención y los ingresos. Comunicaciones claras y bien programadas reducen el abandono y los pagos fallidos. Aquí tienes cómo diseñar un flujo de renovación efectivo.
Secuencia de emails de renovación
Cronograma
const renewalSequence = [
{ daysBefore: 14, template: 'renewal-reminder-14d' },
{ daysBefore: 7, template: 'renewal-reminder-7d' },
{ daysBefore: 3, template: 'renewal-reminder-3d' },
{ daysBefore: 0, template: 'renewal-processed' },
{ daysAfter: 1, template: 'renewal-failed', condition: 'payment_failed' }
];
Email de recordatorio
interface RenewalReminder {
user: User;
subscription: {
plan: string;
amount: number;
currency: string;
renewsAt: Date;
paymentMethod: string;
};
}
await sendEmail({
to: user.email,
subject: `Your ${subscription.plan} plan renews in ${daysUntil} days`,
template: 'renewal-reminder',
data: {
user,
subscription,
updatePaymentUrl: `${baseUrl}/billing/payment-method`,
changePlanUrl: `${baseUrl}/billing/plans`,
cancelUrl: `${baseUrl}/billing/cancel`
}
});
Confirmación de renovación
await sendEmail({
to: user.email,
subject: `Your ${subscription.plan} plan has renewed`,
template: 'renewal-confirmation',
data: {
user,
subscription,
invoice: {
id: invoice.id,
amount: invoice.amount,
pdfUrl: invoice.pdfUrl
},
nextRenewal: subscription.nextRenewalDate,
usageSummary: await getUsageSummary(user.id)
}
});
Recuperación de pagos fallidos
Secuencia de dunning
const dunningSequence = [
{
attempt: 1,
delay: 0,
template: 'payment-failed-1',
subject: 'Payment failed - please update your card'
},
{
attempt: 2,
delay: 3, // days
template: 'payment-failed-2',
subject: 'Second attempt failed - action required'
},
{
attempt: 3,
delay: 7,
template: 'payment-failed-3',
subject: 'Final notice - your account will be suspended'
},
{
attempt: 4,
delay: 10,
template: 'account-suspended',
subject: 'Your account has been suspended'
}
];
Email de pago fallido
await sendEmail({
to: user.email,
subject: 'Payment failed - please update your card',
template: 'payment-failed',
data: {
user,
subscription,
failureReason: getReadableFailureReason(payment.failureCode),
retryDate: payment.nextRetryAt,
updateCardUrl: `${baseUrl}/billing/payment-method`,
gracePeriodEnds: subscription.gracePeriodEnds
},
priority: 'high'
});
function getReadableFailureReason(code: string): string {
const reasons = {
'card_declined': 'Your card was declined',
'insufficient_funds': 'Insufficient funds',
'expired_card': 'Your card has expired',
'incorrect_cvc': 'Incorrect security code',
'processing_error': 'Processing error - we\'ll retry'
};
return reasons[code] || 'Payment could not be processed';
}
Notificaciones de cambio de plan
Confirmación de mejora
await sendEmail({
to: user.email,
subject: `Welcome to ${newPlan.name}!`,
template: 'plan-upgraded',
data: {
user,
previousPlan: oldPlan.name,
newPlan: {
name: newPlan.name,
features: getNewFeatures(oldPlan, newPlan),
price: newPlan.price
},
prorated: {
credit: proratedCredit,
charged: proratedCharge
},
gettingStartedUrl: `${baseUrl}/getting-started/${newPlan.slug}`
}
});
Confirmación de downgrade
await sendEmail({
to: user.email,
subject: `Your plan change to ${newPlan.name}`,
template: 'plan-downgraded',
data: {
user,
currentPlan: oldPlan.name,
newPlan: newPlan.name,
effectiveDate: downgrade.effectiveDate,
lostFeatures: getLostFeatures(oldPlan, newPlan),
dataRetention: 'Your data will be preserved',
upgradeUrl: `${baseUrl}/billing/plans`
}
});
Flujo de cancelación
Confirmación de cancelación
await sendEmail({
to: user.email,
subject: 'Your subscription has been cancelled',
template: 'subscription-cancelled',
data: {
user,
subscription: {
plan: subscription.plan,
endsAt: subscription.currentPeriodEnd,
// Access continues until period end
accessUntil: subscription.currentPeriodEnd
},
dataExport: {
available: true,
exportUrl: `${baseUrl}/settings/export`
},
feedback: {
url: `${baseUrl}/feedback/cancellation`,
incentive: 'Help us improve and get 1 month free if you return'
},
reactivateUrl: `${baseUrl}/billing/reactivate`
}
});
Win-back tras la cancelación
// Send 7 days before access ends
await sendEmail({
to: user.email,
subject: 'Your access ends in 7 days',
template: 'access-ending-soon',
data: {
user,
endsAt: subscription.currentPeriodEnd,
whatYouLose: [
`${usage.projectCount} projects`,
`${usage.teamMembers} team members`,
'All integrations'
],
specialOffer: {
discount: '30% off for 3 months',
code: 'COMEBACK30',
expiresAt: subscription.currentPeriodEnd
},
reactivateUrl: `${baseUrl}/billing/reactivate?offer=COMEBACK30`
}
});
Gestión de la renovación anual
Recordatorio de renovación anual
// 30 days before annual renewal
await sendEmail({
to: user.email,
subject: 'Your annual subscription renews soon',
template: 'annual-renewal-reminder',
data: {
user,
subscription: {
plan: subscription.plan,
amount: subscription.annualPrice,
renewsAt: subscription.renewsAt,
savings: calculateAnnualSavings(subscription)
},
yearInReview: {
// Show value received
emailsSent: usage.totalEmails,
uptime: '99.99%',
supportTickets: usage.supportTickets
},
options: {
continueAnnual: 'Continue annual billing',
switchMonthly: 'Switch to monthly',
cancel: 'Cancel subscription'
},
manageUrl: `${baseUrl}/billing`
}
});
Mejores prácticas
- —Recuerda con antelación - Da tiempo a los usuarios para actualizar los métodos de pago
- —Sé específico - Incluye importes y fechas exactos
- —Explica los fallos - Indica por qué falló el pago
- —Ofrece soluciones fáciles - Actualización de pago en un solo clic
- —Muestra el valor - Recuerda a los usuarios por qué están pagando
- —Períodos de gracia - No cortes el acceso inmediatamente
- —Múltiples canales - Considera SMS para pagos fallidos
Los emails de renovación tratan de reducir la fricción y prevenir el churn involuntario. Facilita que los usuarios sigan suscritos.