Emails de convite de equipe são cruciais para o crescimento de SaaS. Um convite bem projetado converte destinatários em usuários ativos. Veja como otimizar seu fluxo de convites.
Anatomia do email de convite
Elementos essenciais
interface TeamInvitation {
inviter: {
name: string;
email: string;
avatarUrl?: string;
};
organization: {
name: string;
logoUrl?: string;
};
invitee: {
email: string;
role: string;
};
invitation: {
id: string;
expiresAt: Date;
message?: string;
};
}
Template de alta conversão
await sendEmail({
to: invitee.email,
subject: `${inviter.name} invited you to join ${org.name}`,
template: 'team-invitation',
data: {
inviter,
organization: org,
role: invitee.role,
personalMessage: invitation.message,
acceptUrl: `${baseUrl}/invitations/${invitation.id}/accept`,
expiresAt: invitation.expiresAt,
previewText: `Join ${org.name} on YourApp`
}
});
Otimização de conversão
Prova social
// Include team context
const teamContext = {
teamSize: org.memberCount,
recentActivity: `${org.activeMembers} team members active this week`,
popularFeatures: await getOrgTopFeatures(org.id)
};
Urgência sem pressão
// Soft expiration
const expirationCopy = {
'7days': 'This invitation expires in 7 days',
'3days': 'Expires in 3 days',
'1day': 'Expires tomorrow',
'expired': 'This invitation has expired'
};
Sequência de lembretes
const invitationReminders = [
{
daysAfter: 3,
subject: `Reminder: ${inviter.name} invited you to ${org.name}`,
template: 'invitation-reminder-1'
},
{
daysAfter: 6,
subject: `Your invitation to ${org.name} expires soon`,
template: 'invitation-reminder-2'
}
];
async function scheduleReminders(invitation: Invitation) {
for (const reminder of invitationReminders) {
await scheduleEmail({
sendAt: addDays(invitation.createdAt, reminder.daysAfter),
to: invitation.email,
subject: reminder.subject,
template: reminder.template,
data: { invitation },
cancelIf: [
{ condition: 'invitation_accepted' },
{ condition: 'invitation_cancelled' }
]
});
}
}
Convites específicos por função
Convite para Admin
await sendEmail({
to: invitee.email,
subject: `You've been invited as an admin of ${org.name}`,
template: 'admin-invitation',
data: {
inviter,
organization: org,
role: 'Admin',
permissions: [
'Manage team members',
'Access billing',
'Configure integrations',
'View all projects'
],
acceptUrl: `${baseUrl}/invitations/${invitation.id}/accept`
}
});
Convite para função limitada
await sendEmail({
to: invitee.email,
subject: `${inviter.name} invited you to collaborate on ${org.name}`,
template: 'member-invitation',
data: {
inviter,
organization: org,
role: 'Member',
accessScope: 'You\'ll have access to projects you\'re added to',
acceptUrl: `${baseUrl}/invitations/${invitation.id}/accept`
}
});
Fluxo pós-aceitação
Bem-vindo à equipe
// After invitation accepted
await sendEmail({
to: newMember.email,
subject: `Welcome to ${org.name}!`,
template: 'team-welcome',
data: {
member: newMember,
organization: org,
invitedBy: inviter,
gettingStarted: [
{ step: 'Complete your profile', url: `${baseUrl}/settings/profile` },
{ step: 'Explore your projects', url: `${baseUrl}/projects` },
{ step: 'Meet your team', url: `${baseUrl}/team` }
],
helpResources: {
docs: `${baseUrl}/docs`,
support: `${baseUrl}/support`
}
}
});
Notificar quem convidou
await sendEmail({
to: inviter.email,
subject: `${invitee.name} joined ${org.name}`,
template: 'invitation-accepted',
data: {
inviter,
newMember: {
name: invitee.name,
email: invitee.email,
role: invitee.role
},
teamUrl: `${baseUrl}/team`
}
});
Tratando casos de borda
Convite para usuário existente
if (await userExists(invitee.email)) {
await sendEmail({
to: invitee.email,
subject: `${inviter.name} invited you to join ${org.name}`,
template: 'existing-user-invitation',
data: {
inviter,
organization: org,
// Different CTA - just accept, no signup
acceptUrl: `${baseUrl}/invitations/${invitation.id}/accept`,
note: 'You already have an account. Just click to join.'
}
});
}
Convite para email errado
// Allow forwarding to correct email
await sendEmail({
to: invitee.email,
template: 'invitation',
data: {
// ...
wrongEmailUrl: `${baseUrl}/invitations/${invitation.id}/wrong-email`,
wrongEmailNote: 'Not the right email? Let us know.'
}
});
Boas práticas
- —Contexto claro do remetente - Quem os convidou e por quê
- —Mostre a equipe - Prova social aumenta as taxas de aceitação
- —Explique a função - Que acesso terão
- —CTA simples - Um botão para aceitar
- —Lembre com delicadeza - No máximo 2-3 lembretes
- —Recusa fácil - Permita que optem por não participar com elegância
- —Receba calorosamente - Ótima primeira impressão após a aceitação
Convites de equipe costumam ser a primeira interação de alguém com seu produto. Faça valer a pena.