Martech
Por que o Google Ads perde atribuição quando você instala o Pixel do X (e como auditar em 5 minutos)
O pixel do X reescreve a URL via history.replaceState, engole UTM e gclid, e o Google Ads perde o rastro no checkout. Três passos pra detectar isso sem abrir DevTools.
· 6 min de leitura
Toda vez que um cliente me chama dizendo "o Google Ads parou de atribuir conversão sem a gente mudar nada nas campanhas", a primeira coisa que eu pergunto é se alguém instalou um pixel novo nos últimos 30 dias. A resposta quase sempre é sim, e a suspeita número um é o pixel do X (antigo Twitter).
O problema não é o pixel em si. É o que ele faz com a URL quando ele aterrissa na página.
O mecanismo do bug
O pixel do X injeta parâmetros próprios (tw_source, tw_adid e similares) via history.replaceState(). Essa chamada substitui a URL do browser sem recarregar, e é aí que mora o drama: se o pixel não for cuidadoso em preservar a query string existente, ele reescreve tudo, incluindo utm_* e gclid.
A maioria das tags de analytics (Google Ads, GA4, HubSpot) lê esses parâmetros na hora do submit de formulário ou do checkout, não no pageload. Se o pixel do X disparou antes, quando o Google Ads for ler, gclid já era. A atribuição cai pra "direct" ou pra "other", e o dashboard do anunciante começa a mostrar uma narrativa errada.
Como auditar em 5 minutos
Sem precisar mexer em código:
- Acesse seu site com um UTM + gclid manualmente. Algo como
?utm_source=test&gclid=debug123na barra de endereço. - Espere 3 segundos. Todos os pixels já dispararam.
- Copie a URL da barra de endereço. Se o
gclid=debug123ainda estiver lá, você passou. Se sumiu ou foi trocado portw_*, o pixel do X sobrescreveu.
Esse teste leva mais tempo pra abrir a janela anônima do que pra rodar. Funciona em qualquer stack (Shopify, WordPress, Next.js, Webflow) porque o bug é na camada de browser, não no backend.
A correção em uma linha
A correção longa está num case que publiquei sobre uma loja DTC de vestuário onde apliquei esse fix, mas o princípio é simples: um guard script carregado antes de qualquer pixel, via GTM no início do <head>, que persiste os parâmetros críticos em sessionStorage e intercepta chamadas a history.pushState/replaceState pra reaplicar.
const CRITICAL = ['utm_source', 'utm_medium', 'utm_campaign',
'utm_content', 'utm_term', 'gclid', 'fbclid'];
// ...captura, persiste, e restaura após cada replaceState de terceiros
No caso da loja que audito, isso recuperou 100% da atribuição do Google Ads. O Meta, o X e o Google passaram a coexistir sem conflito.
Por que isso não aparece no lighthouse ou no tag assistant
O Tag Assistant valida se a tag disparou, não se ela deixou a página num estado saudável pra próxima tag. O Lighthouse mede performance, não atribuição. Esse tipo de colisão só aparece quando você compara o dashboard antes e depois, e nessa altura o estrago já rodou por semanas.
Auditoria cross-pixel precisa entrar no checklist de QA sempre que uma tag nova sobe. Não é paranoia; é higiene.
Projeto relacionado: Fix de colisão de pixel Twitter/X vs Google Ads em Shopify.