Pular para o conteúdo
10 min de leitura

Webhooks na conversão real: por que o evento deve disparar só quando a venda acontece

Por Equipe Owiew ·

Disparar conversão na intenção envenena a otimização. O evento certo dispara no pedido pago, com dedupe, retry e assinatura. Veja como.

Existe uma diferença enorme entre "alguém demonstrou interesse" e "alguém comprou". Boa parte dos setups de rastreamento não respeita essa diferença: eles disparam o evento de conversão no clique, na visualização, no add to cart ou no envio do formulário — e depois se surpreendem quando o algoritmo de anúncios otimiza para o público errado e o custo por aquisição não fecha com o financeiro. O princípio que corrige isso é simples de enunciar e exigente de implementar: o evento de conversão só dispara quando a conversão realmente ocorre. Este artigo destrincha o que é um webhook, por que disparar na intenção envenena a otimização e como montar um pipeline confiável que entrega o sinal certo, sem duplicar e sem perder.

O que é um webhook, de fato

Um webhook é um HTTP POST que um sistema envia para uma URL sua no instante em que algo acontece. Em vez de você ficar perguntando "e agora, houve um pedido?" a cada minuto (polling), o sistema de origem te avisa: assim que o evento ocorre, ele monta um payload — normalmente JSON — e o entrega no seu endpoint. É o modelo push, e é o que torna o rastreamento em tempo quase real possível.

O Shopify manda orders/paid quando um pedido é pago. Um CRM como Kommo ou Pipe.run manda um evento quando um negócio muda de estágio. Um gateway de pagamento manda um evento quando a cobrança é aprovada. Todos falam a mesma língua: um POST no seu servidor, carregando o que aconteceu.

A força do webhook — reagir a um evento real do lado do servidor — é também onde estão suas armadilhas. Rede falha, o mesmo evento chega duas vezes, eventos chegam fora de ordem, e qualquer um pode mandar um POST para a sua URL se você não verificar quem enviou. Um pipeline de conversão que não trata esses quatro pontos não é confiável, é sorte.

O erro de origem: disparar na intenção

O pecado capital do rastreamento é confundir sinal de intenção com conversão. Page view, add to cart, initiate checkout, form submit são todos eventos de intenção. Eles indicam que alguém está no caminho — não que chegou ao fim dele.

O problema é que uma fração grande dessas intenções nunca vira venda. Carrinhos são abandonados. Checkouts iniciados ficam com o Pix pendente e expiram. Formulários são preenchidos por curiosos, bots e leads que nunca vão comprar. Se você dispara o evento de "conversão" nesses momentos, está reportando à plataforma de anúncios uma venda que não existiu.

Por que o falso positivo envenena a otimização

As plataformas de anúncios modernas otimizam por aprendizado de máquina em cima dos eventos de conversão que você reporta. Elas constroem um modelo de "quem se parece com quem converte" e realocam orçamento para achar mais gente parecida. Se metade dos seus eventos de conversão são, na verdade, carrinhos abandonados e formulários vazios, o modelo aprende o perfil errado. Ele passa a caçar quem clica em "comprar" e vai embora, porque foi isso que você chamou de conversão.

O efeito é insidioso porque os números sobem. Você vê muitas "conversões" no painel, o custo por conversão parece ótimo, e só semanas depois — quando bate com o faturamento real — percebe que estava otimizando para ruído. Sinal sujo não é neutro; ele ativamente piora a campanha. Por isso o marco tem de ser o pedido pago e o negócio ganho, nunca a intenção.

O evento certo: pedido pago, negócio ganho

A conversão real tem uma assinatura inconfundível: dinheiro confirmado. No e-commerce, é o orders/paid do Shopify — pagamento aprovado, não pedido criado. Na venda assistida, é o deal won do CRM — o negócio efetivamente fechado. Esse é o momento em que o webhook deve resultar em um evento de conversão enviado ao destino.

Tratar pedido criado como conversão é um erro sutil: um pedido com boleto ou Pix pendente foi criado, mas não é receita. Ele só vira conversão quando o pagamento confirma. Da mesma forma, um refunds/create posterior precisa reverter a conversão, senão você contabiliza uma venda que voltou. O pipeline não escuta "algo começou"; ele escuta "algo se concretizou".

Idempotência: o mesmo evento não pode contar duas vezes

Webhooks operam sob entrega at-least-once: o remetente garante que tenta entregar pelo menos uma vez, o que significa que, na prática, o mesmo evento pode chegar duas ou mais vezes. Isso acontece quando sua resposta demora, quando a rede engole o ACK, ou quando o remetente reenvia por precaução.

Se cada chegada disparar uma conversão, você conta a mesma venda várias vezes. A defesa é a idempotência: cada evento carrega um identificador único (um event id ou uma chave derivada do order id), e você registra os identificadores já processados. Ao receber um evento, verifica: já vi esse id? Se sim, respondo 200 OK e não faço nada. Se não, processo e gravo o id.

Essa deduplicação tem duas frentes. A primeira é interna, contra o reenvio do webhook. A segunda é externa: as APIs de conversão das plataformas de anúncios aceitam um event id justamente para deduplicar o evento server-side contra o evento do pixel do navegador. O mesmo identificador estável serve aos dois propósitos — desde que ele seja determinístico, derivado do fato (o pedido), e não um UUID novo gerado a cada tentativa.

Retry e confiabilidade: entregar sem perder

O outro lado da moeda da entrega at-least-once é o que acontece quando você falha. Se o seu endpoint está fora do ar ou responde com erro quando o webhook chega, o evento não pode simplesmente evaporar.

Do lado de quem recebe, a regra é responder rápido e processar depois. O handler do webhook deve validar, persistir o evento cru e responder 2xx imediatamente — e só então processar em background. Se você tentar fazer todo o trabalho pesado dentro do handler e estourar o timeout, o remetente vai considerar falha e reenviar, multiplicando carga justamente quando você está lento.

Do lado de quem envia para o destino, entra o retry com backoff exponencial. Se o POST para a Conversions API falhar, você tenta de novo — mas não em rajada. Espera 1s, depois 2s, 4s, 8s, com um teto e um limite de tentativas, idealmente com jitter para não sincronizar todas as retentativas. Falhas transitórias (5xx, timeout) merecem retry; falhas permanentes (4xx de payload inválido) não — elas vão para uma fila de erro para inspeção, não para retry infinito.

Assinatura e ordem: confiança e sequência

Se qualquer POST na sua URL vira uma conversão, qualquer um pode forjar vendas. Por isso os webhooks sérios vêm assinados. O Shopify, por exemplo, envia um header com um HMAC-SHA256 do corpo da requisição, computado com um segredo compartilhado. Você recomputa o HMAC do payload recebido com o mesmo segredo e compara — usando comparação de tempo constante para não vazar informação por timing. Se não bater, o evento é descartado. Sem verificação de assinatura, o pipeline aceita qualquer coisa e o rastreamento vira ficção.

Há ainda a questão da ordem. Webhooks não garantem entrega em sequência: um orders/paid pode chegar antes ou depois de um orders/updated, e um refunds/create pode disputar com o próprio pedido. Em vez de confiar na ordem de chegada, use o timestamp do evento e a versão do recurso para reconciliar o estado final. O que importa é o estado consistente, não qual pacote chegou primeiro.

O padrão outbox: um pipeline que não perde eventos

Amarrando tudo, o desenho confiável separa "receber" de "entregar". Quando um evento de conversão real chega e é validado, você o grava numa tabela de outbox dentro da mesma transação em que registra o fato de negócio. Um processador lê essa outbox e faz a entrega ao destino, com retry e backoff, marcando cada linha como entregue só depois do ACK do destino.

Por que isso importa: se você gravar o pedido e tentar notificar o destino em duas operações separadas, uma falha no meio deixa o pedido salvo e a conversão nunca enviada — receita fantasma. Com o outbox, ou os dois acontecem, ou nenhum; e a entrega ao destino é retomável porque o evento está persistido, esperando ser drenado. É a garantia de que nenhuma conversão real se perde por causa de uma falha de rede momentânea.

O outbox também dá algo que o disparo direto não dá: observabilidade. Cada linha registra quando o evento entrou, quantas tentativas de entrega houve, qual foi a última resposta do destino e se já foi confirmado. Isso transforma o pipeline de uma caixa-preta em algo auditável — você consegue responder "esta venda foi reportada ao Meta? quando? deu certo?" olhando uma tabela, não vasculhando logs. Uma fila de eventos presos com falha permanente vira um alerta acionável, não uma perda silenciosa que só aparece semanas depois na reconciliação.

Cada serviço aguenta a queda do vizinho

Um pipeline de conversão toca vários sistemas: a origem que manda o webhook, a camada que recebe, o destino que precisa ser notificado. A regra de ouro é que a indisponibilidade de um não pode derrubar os outros nem perder dados. Se a Conversions API do destino está fora do ar, o seu recebimento de webhooks continua funcionando — o evento é validado, persistido na outbox e drenado quando o destino voltar. Se o seu processador de entrega cai, os webhooks já recebidos estão salvos, esperando.

O antipadrão é o oposto: o handler do webhook chama o destino de forma síncrona e, quando o destino falha ou demora, o handler estoura o timeout, o remetente considera falha e reenvia, e a carga se multiplica no pior momento. Desacoplar recebimento de entrega — com a outbox no meio — é o que dá degradação graciosa em vez de falha em cascata. Cada peça faz o seu trabalho mesmo com a vizinha caída, e nada se perde no caminho.

Do webhook ao evento de destino

O último passo é o mapeamento: transformar o orders/paid ou o deal won no formato que cada destino entende — Conversions API do Meta, enhanced conversions do Google. Isso significa carregar valor e moeda do pedido real, os dados de identidade normalizados e com hash, o identificador de clique capturado na entrada, e o event id estável para deduplicar. Esse mapeamento — e a costura da identidade entre loja, CRM e anúncio — é um tema por si só, que exploramos na integração de Shopify com CRM para rastrear a conversão do carrinho ao fechamento.

O princípio, em uma frase

Todos esses mecanismos — idempotência, retry com backoff, verificação de assinatura, reconciliação de ordem, outbox — servem a um único princípio: o evento de conversão dispara só quando a conversão realmente aconteceu, e chega ao destino exatamente uma vez, comprovadamente daquela origem. Disparar na intenção é rápido e fácil, e é justamente por isso que tanta gente faz — e paga o preço em otimização envenenada. O caminho confiável escuta o pedido pago, verifica quem mandou, deduplica, tenta de novo quando falha, e nunca conta duas vezes. É mais trabalho, e é o único jeito de o número no painel bater com o dinheiro na conta.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly