emailr_
Todos os artigos
usecase·8 min

Emails de convite de equipe: otimização de conversão

saasinvitationsconversion

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

  1. Contexto claro do remetente - Quem os convidou e por quê
  2. Mostre a equipe - Prova social aumenta as taxas de aceitação
  3. Explique a função - Que acesso terão
  4. CTA simples - Um botão para aceitar
  5. Lembre com delicadeza - No máximo 2-3 lembretes
  6. Recusa fácil - Permita que optem por não participar com elegância
  7. 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.

e_

Escrito pela equipe emailr

Construindo infraestrutura de email para desenvolvedores

Pronto para começar a enviar?

Obtenha sua chave API e envie seu primeiro email em menos de 5 minutos. Não é necessário cartão de crédito.