image

Investimento único e acesso para sempre

84
%OFF
Article image
Walakys Providello
Walakys Providello05/10/2026 10:21
Compartir

Como criei rastreabilidade de disparos WhatsApp no Salesforce Data Cloud com SQL

    Do envio ao read: relacionando Marketing Cloud, templates, contatos e eventos de tracking

    Quando trabalhamos com campanhas de WhatsApp em escala, saber apenas que uma mensagem foi disparada não é suficiente.

    Em uma operação real, rapidamente surgem perguntas como:

    Qual template foi utilizado? Para qual cliente a mensagem foi enviada? Qual linha oficial realizou o disparo?

    Foi a partir dessa necessidade que comecei a estruturar uma visão de rastreabilidade dos disparos de WhatsApp utilizando Salesforce Data Cloud e SQL. O resultado foi uma consulta capaz de relacionar informações do envio realizado pelo Marketing Cloud com os eventos posteriores de tracking.

    O problema

    Os dados necessários existiam, porém não estavam todos no mesmo registro.

    De um lado, temos informações relacionadas ao envio:

    cliente;
    contato;
    telefone;
    CPF/CNPJ;
    operação;
    template;
    Journey Activity;
    data do disparo.
    

    Do outro lado, temos os eventos gerados pelo WhatsApp:

    sent
    delivered
    read
    failed
    error
    

    Além deles, também podemos ter informações como:


    Message ID;
    número destinatário;
    Sender ID;
    código de erro;
    descrição do erro;
    data de cada evento.
    

    Visão da solução

    A lógica criada ficou aproximadamente assim:

    Marketing Cloud
        ↓
    Message Engagement
        ↓
    Dados do envio
        ↓
    Normalização do telefone
        ↓
    Localização do evento SENT mais próximo
        ↓
    Message ID
        ↓
    Eventos de Tracking
        ↓
    SENT → DELIVERED → READ → FAILED
    

    O ponto mais importante dessa estratégia foi encontrar um identificador capaz de conectar toda a jornada da mensagem.

    Nesse caso, chegamos ao:

    message_id
    

    Porém, antes de obter esse ID, havia outro desafio.

    Precisávamos descobrir qual evento sent pertencia a determinado disparo.

    1. Identificando os disparos

    A primeira CTE da consulta foi chamada de:

    WITH envios AS (...)
    

    Ela busca os dados relacionados aos disparos.

    Entre as informações recuperadas estão:

    s.ssot__Id__c AS envio_id,
    s.ssot__EngagementDateTm__c AS data_envio,
    s.ssot__IndividualId__c AS contact_id,
    c.Name__c AS nome_cliente,
    c.MobilePhone__c AS telefone_contact,
    c.CPF_CNPJ_c__c AS cpf_cnpj,
    c.Operacao_c__c AS operacao
    

    Também relacionamos o disparo ao template:

    s.ssot__EngagementAssetId__c AS template_id,
    t.ssot__Name__c AS template_nome,
    t.ssot__EngagementAssetTypeId__c AS tipo_template
    

    Isso já permite responder uma pergunta importante:

    Qual cliente recebeu qual template?

    Também conseguimos obter a atividade da jornada:

    s.ssot__MarketJourneyActivityId__c AS journey_activity_id
    

    Criando a base para futuramente expandir a rastreabilidade até Journey Builder e campanhas.

    2. Um problema clássico: telefone

    Essa foi uma das partes mais interessantes do desenvolvimento.

    O telefone do contato poderia aparecer em formatos diferentes.

    Por exemplo:

    5514999999999
    14999999999
    1499999999
    +55 (14) 99999-9999
    

    Para relacionar corretamente envio e tracking, foi necessário normalizar esses números.

    A consulta remove primeiro todos os caracteres que não sejam números:

    REGEXP_REPLACE(
      c.MobilePhone__c,
      '[^0-9]',
      '',
      'g'
    )
    

    Depois avaliamos o tamanho do telefone.

    Por exemplo, caso recebamos:

    551499999999
    

    e seja identificado que está faltando o nono dígito, realizamos o tratamento:

    SUBSTRING(
      REGEXP_REPLACE(c.MobilePhone__c, '[^0-9]', '', 'g'),
      3,
      2
    )
    || '9' ||
    RIGHT(
      REGEXP_REPLACE(c.MobilePhone__c, '[^0-9]', '', 'g'),
      8
    )
    

    Assim conseguimos criar:

    telefone_normalizado
    

    Essa coluna passa a funcionar como uma chave auxiliar para relacionar diferentes fontes.

    3. Capturando os eventos do WhatsApp

    Depois criamos outra CTE:

    tracking AS (...)
    

    Ela representa os eventos retornados pela camada de tracking.

    Entre os campos recuperados:

    x.ssot__EngagementDateTm__c AS data_evento,
    x.ssot__EngagementChannelActionId__c AS evento,
    x.Mobile_Number__c AS telefone_cliente,
    x.Sender_ID__c AS linha_oficial,
    x.ssot__EngagementAssetId__c AS message_id
    

    Aqui começam a aparecer eventos como:

    sent
    delivered
    read
    failed
    error
    

    Também capturamos informações importantes para troubleshooting:

    x.ssot__MessagingErrorCode__c AS codigo_erro,
    x.ssot__ErrorMessageText__c AS descricao_erro
    

    Isso significa que a mesma estrutura utilizada para acompanhamento de campanhas pode ajudar também na investigação de falhas.

    4. Como descobrir qual sent pertence ao envio?

    Esse foi um dos pontos centrais da solução.

    Apenas relacionar pelo telefone não seria suficiente.

    Um mesmo cliente poderia receber diversas mensagens ao longo do dia.

    Por isso, além do telefone normalizado, utilizamos uma janela temporal.

    AND tr.data_evento >=
      e.data_envio - INTERVAL '5 minutes'
    
    AND tr.data_evento <=
      e.data_envio + INTERVAL '5 minutes'
    

    Ou seja:

    5 minutos antes do envio
          ↓
       DISPARO
          ↓
    5 minutos depois do envio
    

    Dentro desses candidatos, selecionamos o evento sent cuja data está mais próxima da data original do disparo.

    Para isso utilizamos:

    ROW_NUMBER() OVER (
      PARTITION BY e.envio_id
      ORDER BY
          ABS(
              EXTRACT(
                  EPOCH FROM (
                      tr.data_evento - e.data_envio
                  )
              )
          )
    ) AS ordem
    

    Depois:

    WHERE ordem = 1
    

    Dessa maneira, cada envio fica relacionado ao evento sent temporalmente mais próximo.

    5. Encontrando o Message ID

    Depois dessa associação, obtemos uma informação extremamente importante:

    message_id
    

    A partir dele, não precisamos mais depender do telefone ou da proximidade de horário.

    Podemos relacionar diretamente todos os eventos daquela mensagem:

    INNER JOIN tracking tr
      ON e.message_id = tr.message_id
    

    Agora conseguimos reconstruir algo parecido com:

    Cliente: João
    
    Template:
    cobranca_whatsapp_01
    
    Disparo:
    10:01:03
    
    SENT:
    10:01:05
    
    DELIVERED:
    10:01:07
    
    READ:
    10:03:21
    

    Ou, em um cenário de erro:

    SENT
    ↓
    FAILED
    ↓
    Código do erro
    ↓
    Descrição do erro
    

    Essa é a parte que transforma os dados técnicos em rastreabilidade operacional.

    Resultado final

    A consulta consegue retornar informações como:

    data_envio
    data_evento
    evento
    telefone_cliente
    linha_oficial
    template_nome
    nome_cliente
    cpf_cnpj
    operacao
    template_id
    contact_id
    tipo_template
    journey_activity_id
    message_id
    codigo_erro
    descricao_erro
    origem_envio
    origem_tracking
    

    Próximo passo

    Hoje essa visão já permite consultar essas informações dentro do ecossistema Salesforce.

    O próximo objetivo é levar essa rastreabilidade para nossa estrutura interna de dados.

    A arquitetura começa a evoluir para algo como:

    Salesforce Marketing Cloud
            ↓
    Salesforce Data Cloud
            ↓
    SQL / Tracking
            ↓
    Integração
            ↓
    Banco de Dados interno
            ↓
    Dashboard / Indicadores / Auditoria
    

    A ideia é reduzir a necessidade de acessar diferentes ferramentas para investigar um disparo.

    Em uma única fonte poderemos acompanhar toda a jornada da mensagem.

    O que aprendi

    Essa implementação me mostrou que um dos maiores desafios de dados nem sempre é simplesmente consultar uma tabela.

    Muitas vezes o trabalho está em descobrir como diferentes eventos se relacionam.

    Nesse projeto utilizamos:

    CTEs → organização da consulta.

    REGEXP_REPLACE → tratamento dos telefones.

    CASE → normalização.

    ROW_NUMBER() → seleção do melhor candidato.

    EXTRACT(EPOCH) → comparação temporal.

    JOIN → relacionamento entre diferentes informações.

    Message ID → reconstrução do ciclo completo da mensagem.

    E o resultado deixou de ser somente uma consulta SQL.

    Passou a ser uma forma de acompanhar o ciclo de vida de uma comunicação enviada ao cliente.

    Conclusão

    Criar rastreabilidade para WhatsApp dentro do Salesforce Data Cloud abriu novas possibilidades para nossa operação.

    Saímos de:

    “A campanha disparou.”

    para:

    “Esse cliente recebeu esse template, por essa linha, nesse horário, a mensagem foi entregue, posteriormente lida e esse é o identificador que acompanha todo o processo.”

    É uma mudança relativamente simples de explicar, mas extremamente relevante quando pensamos em dados, governança, atendimento, campanhas e tomada de decisão.

    E esse projeto ainda está evoluindo. 🚀

    Tecnologias utilizadas: Salesforce Data Cloud • Marketing Cloud • WhatsApp • SQL • Data Model Objects • Journey Builder • Integração de Dados

    Compartir
    Recomendado para ti
    Reclame AQUI - Dados e IA na Prática
    CI&T - Java AI Copilot
    Itaú - Java com Inteligência Artificial
    Comentarios (0)