Rastreamento server-side no WooCommerce: do hook ao evento de conversão
WooCommerce é PHP rodando sobre o WordPress, e isso muda como você captura a conversão. Veja onde enganchar o pedido, o que enviar por CAPI e como não contar duas vezes.
Neste artigo
O WooCommerce ocupa uma fatia enorme das lojas online justamente porque não é um SaaS fechado: é um plugin PHP rodando dentro do WordPress, com acesso total ao banco, aos hooks do pedido e ao servidor onde tudo mora. Para quem quer rastreamento server-side de verdade, isso é uma vantagem que poucas plataformas oferecem — você não depende de um app de terceiro nem de um webhook opaco. O preço dessa liberdade é que ninguém entrega a mensuração pronta: a arquitetura é sua para desenhar. Este texto percorre onde capturar a conversão no ciclo de vida do pedido, o que mandar para as APIs de conversão da Meta e do Google, e como manter a contagem íntegra sem contar o mesmo pedido duas vezes.
Por que server-side muda o jogo no WooCommerce#
O rastreamento tradicional do WooCommerce vive no navegador: um pixel dispara na página de "obrigado" (a order-received) quando o comprador chega lá. O problema é que essa página nem sempre é vista. Bloqueadores de anúncio derrubam o script, o comprador fecha a aba antes do carregamento, o navegador restringe cookies de terceiros, e pagamentos que redirecionam para um gateway externo às vezes não trazem o cliente de volta à página final. Cada uma dessas situações é uma conversão real que aconteceu no banco de dados mas nunca chegou à plataforma de anúncios.
O server-side resolve isso porque a fonte da verdade deixa de ser o navegador e passa a ser o próprio WooCommerce. Quando um pedido muda de status para pago ou concluído, isso é um fato registrado no banco. Enganchar a captura nesse fato — e não no carregamento de uma página — significa que a conversão é enviada mesmo que o comprador nunca tenha visto a tela de agradecimento. A precisão sobe, e você passa a alimentar os algoritmos de otimização de campanha com dados que antes se perdiam.
Onde enganchar: o ciclo de vida do pedido#
O WooCommerce expõe o pedido através de uma série de hooks (ganchos de ação) que disparam em momentos específicos. Escolher o gancho certo é a decisão de arquitetura mais importante, porque cada um representa um significado diferente de "conversão".
woocommerce_thankyoudispara no carregamento da página de obrigado. É o mais fácil de usar, mas herda todos os problemas do lado do cliente porque depende do comprador chegar à página.woocommerce_payment_completedispara quando o gateway confirma o pagamento. É um bom ponto para lojas que só consideram conversão o pedido efetivamente pago.woocommerce_order_status_changeddispara em qualquer transição de status e recebe o status antigo e o novo. É o mais flexível: você decide qual transição conta como conversão.woocommerce_new_orderdispara na criação do pedido, antes do pagamento. Serve para eventos de "início de checkout" ou "pedido criado", não para a conversão final.
A recomendação para a maioria das lojas é tratar a transição para "processing" (processando) ou "completed" (concluído) como o evento de compra, usando woocommerce_order_status_changed. Isso captura o pagamento aprovado independentemente do gateway e ignora pedidos que ficaram presos em "pending" ou "failed", que não são receita.
Um detalhe fácil de errar: idempotência do hook#
Hooks de status podem disparar mais de uma vez para o mesmo pedido. Um pedido pode ir de "pending" para "processing" e depois para "completed", e se você contar as duas transições como compra, o mesmo pedido vira duas conversões. A defesa é gravar uma marca no próprio pedido — um metadado do tipo _conversion_sent — na primeira vez que o evento é enviado, e checar essa marca antes de enviar de novo. O WooCommerce guarda metadados de pedido com facilidade, e essa marca é a sua trava de idempotência. Sem ela, o double counting é questão de tempo.
O que enviar: montando o payload de conversão#
Com o gancho escolhido e a trava de idempotência no lugar, você tem em mãos o objeto do pedido e pode extrair tudo o que a API de conversão precisa. Para a Conversions API da Meta e para o Measurement Protocol do Google, o payload gira em torno de três blocos: o evento, os dados de valor e os dados de correspondência do usuário.
O bloco de evento identifica a ação. Para uma compra, você envia o nome do evento (Purchase na Meta, purchase no GA4), o horário do evento e um identificador único do evento — geralmente o próprio número do pedido, que é perfeito porque já é único no WooCommerce e serve tanto de chave de deduplicação quanto de referência para auditoria depois.
O bloco de valor carrega o dinheiro. Aqui é essencial enviar o valor total do pedido e a moeda, e decidir com clareza se o valor inclui frete e impostos. O WooCommerce dá acesso ao subtotal, ao total, ao frete e aos impostos separadamente, então a escolha é sua — mas ela precisa ser consistente com o que a plataforma espera e com o que o financeiro reconhece como receita. Enviar o total com frete para a Meta e reconciliar contra o subtotal sem frete no financeiro é uma fonte clássica de divergência que ninguém consegue explicar meses depois.
O bloco de itens detalha o carrinho. Cada linha do pedido vira um item com identificador do produto, quantidade e preço. O identificador precisa casar com o que está no seu feed de produtos, senão os anúncios dinâmicos não conseguem cruzar a compra com o catálogo. No WooCommerce o SKU costuma ser o candidato natural, mas confirme qual campo o seu feed usa.
Dados de correspondência: o coração da qualidade#
De nada adianta enviar a compra se a plataforma não consegue atribuir aquela conversão a um clique de anúncio. É por isso que os dados de correspondência do usuário são o que separa uma integração que funciona de uma que só engorda relatório. O WooCommerce tem, no objeto do pedido, praticamente tudo o que você precisa: e-mail, telefone, nome, sobrenome, cidade, estado, CEP e país de cobrança.
Esses dados são informação pessoal e não podem sair em texto puro. A regra é hashear cada campo com SHA-256 depois de normalizar — colocar em minúsculas, remover espaços nas pontas, tirar a formatação do telefone e deixar só os dígitos com o código do país. E-mail e telefone hasheados são os campos de maior peso na correspondência; nome, cidade e CEP ajudam a refinar. Quanto mais campos válidos você enviar, maior a métrica de qualidade da correspondência, e maior a fração de conversões que a plataforma consegue de fato atribuir.
Além dos dados pessoais, capture os parâmetros de clique. O fbclid e o gclid chegam na URL quando o comprador vem de um anúncio, e o ideal é gravá-los numa sessão ou num cookie de primeira parte no momento da entrada, para depois anexá-los ao pedido. No WooCommerce isso costuma exigir capturar o parâmetro no início da visita e persistir junto ao carrinho ou à sessão, recuperando-o no hook de conversão. O IP do servidor e o user agent do comprador também entram no payload e ajudam na correspondência.
Deduplicação: pixel e CAPI convivendo#
A maioria das lojas WooCommerce não abandona o pixel do navegador — ela roda pixel e server-side em paralelo, porque o navegador captura sinais que o servidor não vê (comportamento na página, eventos de visualização) e o servidor captura conversões que o navegador perde. O risco óbvio é que os dois enviem a mesma compra e a plataforma conte duas vezes.
A solução é a deduplicação por identificador de evento. Tanto o pixel quanto o envio server-side precisam mandar o mesmo event_id para a mesma compra — e aqui o número do pedido do WooCommerce volta a ser o herói, porque é o mesmo dos dois lados. A Meta, ao receber dois eventos Purchase com o mesmo event_id numa janela curta, entende que são o mesmo fato e mantém apenas um. O segredo é garantir que o pixel no navegador e o código PHP no servidor derivem o event_id da mesma fonte: o pedido. Se o pixel usa um identificador aleatório e o servidor usa o número do pedido, a deduplicação não acontece e você conta em dobro justamente onde queria contar uma vez só.
Entrega confiável: não perca o evento se a API cair#
Enviar a conversão dentro do hook do WooCommerce tem uma armadilha: se você fizer a chamada HTTP para a Meta ou o Google de forma síncrona, o processamento do pedido fica esperando a resposta da API. Se a API estiver lenta, o comprador espera; se cair, você pode perder o evento ou, pior, travar a finalização do pedido.
O padrão robusto é desacoplar. Grave o evento numa fila — pode ser uma tabela própria, o sistema de ações agendadas do WooCommerce (Action Scheduler) ou uma fila externa — e processe o envio em segundo plano. Assim o pedido finaliza na hora, e um worker separado pega os eventos pendentes, chama a API, e só marca como enviado quando recebe confirmação. Se a chamada falhar, o evento continua na fila e é retentado com espera crescente. Essa arquitetura de outbox garante que nenhuma conversão se perde só porque a API teve um soluço de rede, e é a diferença entre um rastreamento que você confia e um que "quase sempre" funciona.
Testando sem sujar a produção#
Antes de acreditar em qualquer número, valide o fluxo. A Meta oferece a aba de eventos de teste no gerenciador de eventos, onde você envia um código de teste no payload e vê o evento chegar em tempo real, com os campos de correspondência que passaram. O GA4 tem o modo de depuração equivalente. Faça um pedido de ponta a ponta num ambiente de teste, confirme que o evento chega com valor, moeda, itens e dados de correspondência corretos, e só então ligue em produção. Um cuidado extra: pedidos de teste e reembolsos precisam de tratamento. Um pedido cancelado ou estornado idealmente dispara um evento de reembolso ou simplesmente não conta, para o valor reconhecido bater com o financeiro.
Fechando o ciclo#
O WooCommerce recompensa quem trata a mensuração como engenharia e não como plugin mágico. Escolha o hook que representa a sua definição de conversão, trave a idempotência com um metadado no pedido, monte um payload completo com valor, itens e dados de correspondência hasheados, unifique o event_id entre pixel e servidor para deduplicar, e desacople o envio numa fila para não perder evento nem travar o checkout. Com essas peças no lugar, você tem um rastreamento server-side que reflete a receita real da loja — e não a fração dela que sobreviveu ao navegador.