🔧 Guia técnico

Configurando Réguas de Followup

Guia para administradores de tenant. Como criar régua, configurar gatilho, montar a sequência de passos, escrever templates com variáveis e evitar as armadilhas conhecidas do motor de execução.

Antes de ler isso aqui, recomendo ler o guia de conceitos se o modelo mental ainda não está claro.

Estrutura da régua

Uma régua vive na tabela regras_followup. Os campos principais:

CampoPara que serve
nome Identificador único dentro do tenant. Ex.: “Pós-Proposta Trade”.
ativo Liga/desliga a régua. Desligada = não inscreve novos leads, mas sessões já ativas continuam até o fim.
gatilho_tipo + gatilho_config Define o que inicia a régua. Detalhes na próxima seção.
saida_tipo + saida_config Define o que encerra a régua antes da sequência terminar. Usa as mesmas opções do gatilho.
prioridade Quando o mesmo lead bate gatilho de mais de uma régua ao mesmo tempo, a de maior prioridade vence.
max_ativos Quantas inscrições simultâneas a régua aceita. Usado pra rampar devagar.

Gatilhos disponíveis

O gatilho_tipo aceita cinco valores. Cada um usa um gatilho_config diferente (JSON):

TipoQuando disparaExemplo de gatilho_config
lead_estagio Lead entrou em uma etapa específica do funil. {"estagio": "proposta_enviada"}
contrato_status Contrato mudou pra um status específico (ex.: assinado, suspenso). {"status": "assinado"}
dias_sem_interacao X dias sem nenhuma atividade registrada. Aceita 2 escopos: comercial (varre leads) ou gestao (varre contratos). Veja detalhe abaixo. {"dias": 60, "escopo": "comercial"}
data_contrato Data específica do contrato (vencimento, aniversário, renovação). {"campo": "renovacao_em", "dias_antes": 15}
manual Inscrição feita à mão pelo operador (botão na tela do lead). {}

Etapas atuais do funil (valores aceitos em gatilho_config.estagio):

novo | contato_feito | proposta_enviada | negociacao | ganho | perdido

Detalhe — dias_sem_interacao

Esse é o gatilho mais sutil. Importante entender o que ele faz e o que NÃO faz.

💡 O gatilho só ATIVA — quem envia são os passos

Quando o filtro bate (X dias sem atividade), o lead/contrato é inscrito na régua. A partir daí, cada passo da régua decide o que mandar (e-mail, WhatsApp, tarefa, notificação) e pra quem (contato do lead, vendedor responsável). Mudar o gatilho não muda a mensagem.

EscopoQuem entra na réguaCritério "sem atividade"
comercial Leads do tenant que ainda estão vivos — etapa diferente de ganho ou perdido — e que ainda não viraram contrato (contrato_id IS NULL). Sem nenhum registro em lead_atividades com aquele lead_id nos últimos X dias.
gestao Contratos com status = 'assinado'. Sem registro em lead_atividades nem no contrato, nem nos leads vinculados a ele, nos últimos X dias.

📝 O que conta como "atividade"

Qualquer linha em lead_atividades — a tabela é a fonte única de verdade. Entram automaticamente:

  • Atividades manuais cadastradas pelo vendedor (ligação, visita, nota, reunião)
  • Mensagens WhatsApp recebidas — o webhook do ZAAPS registra uma linha leve (apenas metadado, sem o corpo da mensagem) ao receber. Dedupe por lead + dia.
  • E-mails recebidos no webmail — o worker IMAP registra uma linha leve ao sincronizar mensagem nova (filtra Sent/Drafts/Trash/Spam). Dedupe por lead + dia.

O conteúdo da mensagem fica no ZAAPS / webmail — é auditável lá. O CRM só guarda o "carimbo de quando conversaram" pra alimentar esse gatilho.

⚠ O que não conta hoje

  • Mensagem WhatsApp enviada pelo vendedor pelo CRM — só inbound do cliente entra. Isso é proposital: vendedor mandando msg não significa que o lead está vivo.
  • Mudança de etapa do funil — se você só arrasta o card e não registra nada, o gatilho considera "sem atividade".
  • Login do cliente em portal/app — não está conectado ainda.

A saída (saida_tipo / saida_config) usa os mesmos cinco tipos. Exemplo de saída comum:

saida_tipo: lead_estagio
saida_config: {"estagio": "ganho"}

Saída por “ganho” e “perdido” geralmente é configurada em ambas — a régua tem que parar nos dois cenários.

Passos — a sequência de ações

Cada régua tem N passos na tabela regra_followup_passos. Os campos:

CampoPara que serve
ordem Sequência: 1, 2, 3... Os passos são executados nessa ordem.
dias_apos_anterior Atraso em dias depois do passo anterior ser executado. 0 = imediato.
horario_preferencial Hora do dia sugerida para o envio (ex.: 09:00). Veja armadilha abaixo.
acao_tipo Canal/ação: email, whatsapp, tarefa ou notificacao.
acao_config Configuração da ação. Pra e-mail e WhatsApp: {"template_id": "..."}. Pra tarefa: descrição e prazo.
condicao JSON de branching opcional (ex.: só executar se lead respondeu o passo anterior).

Tipos de ação

Templates — o texto da mensagem

Templates vivem em followup_templates. Cada um é amarrado a um canal (e-mail ou WhatsApp) e pertence a um tenant.

CampoDescrição
nome Identificador único dentro do tenant. Não aparece pro cliente.
canal email ou whatsapp.
assunto Só usado em e-mail. NULL pra WhatsApp.
corpo Texto da mensagem. Aceita variáveis entre chaves.

💡 Sem layout HTML fixo

Hoje cada template é texto livre — sem wrapper visual padrão, sem logo da empresa embutida automaticamente, sem header/footer customizado por tenant. O texto vai como você escreveu.

Exceção: em e-mails, o sistema injeta automaticamente um footer de unsubscribe com um link pra cliente cancelar a régua. Você não precisa colocar isso no template.

Variáveis disponíveis

Você usa as variáveis entre chaves no assunto ou no corpo. O sistema substitui na hora do envio:

VariávelDe onde vem
{contato_nome} Nome do contato do lead (ou nome do cliente do contrato).
{lead_empresa} Empresa do lead.
{nome_empresa} Alias de {lead_empresa}.
{vendedor_nome} Nome do vendedor responsável pelo lead.
{link_agendar} URL pública pro cliente agendar reunião (usa o slug da agenda do vendedor).
{status_contrato} Status atual do contrato (apenas em réguas de contrato).
{valor_contrato} Valor do contrato.
{email_cliente} E-mail principal do cliente.
{telefone_cliente} Telefone principal do cliente.

⚠ Variável não encontrada vira texto literal

Se você escrever {nome_cliente} num template e essa variável não existir (o nome certo é {contato_nome}), o e-mail vai sair com o texto literal {nome_cliente} no lugar — sem nenhum aviso. Sempre faça um envio de teste antes de ativar.

Armadilhas conhecidas

Coisas que o motor de execução faz que talvez você não esperasse. Ler antes de planejar a régua evita surpresa.

⚠ Atraso é em dias corridos

dias_apos_anterior: 2 soma dois dias do calendário, não dois dias úteis. Se o passo anterior caiu na sexta, o próximo cai no domingo.

Solução prática: pra evitar envio no fim de semana, use 3 dias em vez de 2 quando o passo anterior costuma cair na sexta — ou aceite que algum cliente vai receber WhatsApp no domingo.

horario_preferencial não é garantido

O cron de followup roda a cada 5 minutos e dispara qualquer passo vencido. O horario_preferencial hoje é uma sugestão — o cron não atrasa o envio só pra cair exatamente no horário pedido. Se o passo venceu às 03:00 da manhã, o cron das 03:05 já manda.

⚠ Régua desativada não cancela inscrições ativas

Setar ativo: false impede novas inscrições, mas as inscrições já em andamento continuam até concluir a sequência ou bater a saída.

Pra interromper geral: use o botão “Pausar” na tela de Réguas — ele cancela as inscrições ativas também.

⚠ Sem dedupe automático entre réguas

Se um lead bater gatilho de duas réguas, ele entra nas duas. Use o campo prioridade e saida_config bem amarrada pra evitar cliente recebendo mensagem dobrada.

Onde acompanho

Toda a operação de followup fica em CRM → Followup. Lá você tem:

💡 Recomendação operacional

Quando criar uma régua nova:

  1. Cadastre os templates primeiro.
  2. Crie a régua com ativo: false.
  3. Inscreva manualmente um lead de teste (você mesmo, com seu WhatsApp/e-mail).
  4. Confira cada passo chegando na ordem certa.
  5. Só então ative a régua pra disparar com gatilho automático.