Por que a origem se perde (e o número mente)
Os guias por cliente mandam o formulário “ler a UTM do parâmetro da URL”. Isso funciona só se o lead preencher o form na mesma página em que chegou. No mundo real, ele não faz isso.
O lead clica no anúncio → cai em /oferta?utm_source=meta → navega pra /sobre, depois /contato → preenche o form ali. A página /contato não tem os parâmetros na URL → os campos ocultos vêm vazios → o lead entra no CRM como direct / none. A campanha que trouxe some. Você paga por lead e não sabe de qual anúncio veio.
O sintoma no dashboard: um monte de lead “direto/orgânico” que na verdade veio de anúncio. A conta do tráfego pago nunca fecha porque metade das conversões não é atribuída. Deixar a conexão redonda = fechar esse buraco antes de escalar verba.
Os 5 momentos da origem
A origem precisa atravessar 5 momentos. O desenho é o mesmo para todo cliente — só muda a ferramenta no momento 4.
| # | Momento | O que acontece | Quem resolve |
|---|---|---|---|
| 1 | Captura | Lê utm_* + gclid/fbclid/ttclid da URL na primeira chegada. | Script de Captura (bloco 03) |
| 2 | Persistência | Salva a origem em cookie + localStorage (90 dias). Sobrevive à navegação e à volta dias depois. | Script de Captura |
| 3 | Injeção | Preenche os campos ocultos do formulário no momento do envio — mesmo forms embed (iframe). | Script de Captura + campos ocultos no form |
| 4 | Transporte | O form leva a origem pro CRM. | Nativo GHL / Webhook / Make (varia por cliente) |
| 5 | Persistência no CRM | Origem grudada no contato e copiada pro deal, até o Fechado Ganho. | CRM (mapeamento + pipeline) |
Guardamos a origem last-touch persistente: a última campanha marcada que trouxe o lead, mantida por 90 dias mesmo que ele volte depois sem UTM. É o padrão de mercado (o mesmo que o GA4/Ads usam) e o correto pros click IDs (o Google atribui ao último clique). Se um dia você quiser a jornada completa (first-touch), o script guarda os dois — é só ativar.
Script de Captura de Origem 7Tima
Esta é a peça que resolve os momentos 1, 2 e 3 de uma vez, em qualquer cliente. Instala-se uma vez pelo GTM e passa a valer em todas as páginas e formulários.
O que ele faz
- Captura utm_source/medium/campaign/content/term + gclid (Google) + fbclid (Meta) + ttclid (TikTok) + li_fat_id (LinkedIn).
- Guarda por 90 dias em cookie + localStorage. Sobrevive à navegação entre páginas.
- Injeta a origem nos campos ocultos de qualquer formulário — inclusive os embed em iframe do GoHighLevel e do HubSpot (reescreve a URL do iframe).
- Publica a origem no dataLayer (evento sq7_origin_ready), pro GTM/GA4 usarem.
Passo 1 · Instalar pelo GTM (uma vez por cliente)
- GTM → Tags → Novo → 7Tima - Captura de Origem → tipo HTML personalizado → cole o código abaixo.
- Acionamento → All Pages (Todas as páginas). Em “Opções avançadas → Prioridade de acionamento”, coloque um número alto (ex.: 100) pra ele rodar antes das outras tags.
- Salvar → Enviar/Publicar.
<script>
/* Captura de Origem 7Tima — GTM > HTML personalizado > acionador All Pages */
(function () {
var KEY = 'sq7_origin', TTL = 90; // dias
var F = ['utm_source','utm_medium','utm_campaign','utm_content','utm_term','gclid','fbclid','li_fat_id','ttclid'];
function load(){ try { return JSON.parse(localStorage.getItem(KEY)) || {}; } catch(e){ return {}; } }
function save(o){
try { localStorage.setItem(KEY, JSON.stringify(o)); } catch(e){}
var d = new Date(); d.setTime(d.getTime() + TTL*864e5);
document.cookie = KEY + '=' + encodeURIComponent(JSON.stringify(o)) + ';expires=' + d.toUTCString() + ';path=/;SameSite=Lax';
}
var qs = new URLSearchParams(location.search), now = {};
F.forEach(function(f){ var v = qs.get(f); if (v) now[f] = v; });
var saved = load();
// last-touch: se o link veio marcado, atualiza a origem. Se voltar sem marca, mantém a última.
if (now.utm_source || now.gclid || now.fbclid || now.ttclid) {
now._ref = document.referrer || ''; now._land = location.pathname; now._ts = Date.now();
saved = now; save(saved);
}
function fillInputs(){
F.forEach(function(f){ if (!saved[f]) return;
document.querySelectorAll('input[name="' + f + '"]').forEach(function(el){ el.value = saved[f]; });
});
}
function fillIframes(){
var q = F.filter(function(f){ return saved[f]; })
.map(function(f){ return f + '=' + encodeURIComponent(saved[f]); }).join('&');
if (!q) return;
document.querySelectorAll('iframe[src*="leadconnectorhq"],iframe[src*="msgsndr"],iframe[src*="hsforms"]').forEach(function(fr){
if (fr.dataset.sq7) return;
fr.src = fr.src + (fr.src.indexOf('?') > -1 ? '&' : '?') + q; fr.dataset.sq7 = '1';
});
}
function run(){ fillInputs(); fillIframes(); }
run(); document.addEventListener('DOMContentLoaded', run);
[800,2000,4000].forEach(function(t){ setTimeout(run, t); });
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'sq7_origin_ready', sq7_origin: saved });
})();
</script>
Passo 2 · Preparar o formulário (uma vez)
O formulário precisa ter os campos ocultos com o nome exato que o script procura. No Elementor: campos “Oculto” com esses IDs. Numa página HTML feita pelo Claude, cole estes campos dentro do <form>:
<input type="hidden" name="utm_source"> <input type="hidden" name="utm_medium"> <input type="hidden" name="utm_campaign"> <input type="hidden" name="utm_content"> <input type="hidden" name="utm_term"> <input type="hidden" name="gclid"> <input type="hidden" name="fbclid">
Se o form é um embed (iframe), o script já reescreve a URL do iframe com a origem. Do lado do GHL/HubSpot, crie os campos ocultos com “pre-populate = parâmetro da URL” de mesmo nome. Aí a origem entra pelo iframe. Cobre os dois mundos.
Abra a página com ?utm_source=teste&utm_medium=x, navegue pra outra página sem parâmetros, abra o form e inspecione: os campos ocultos têm que estar preenchidos com “teste”. Se sim, o buraco está fechado. ✅
Convenção de UTM (a mesma pra agência inteira)
De nada adianta capturar a origem se cada um escreve utm_source de um jeito. A convenção é única e o Gerador de UTM a força (dropdowns fechados).
| Parâmetro | Valores |
|---|---|
| utm_source | instagram · facebook · youtube · tiktok · linkedin · google · gmn · whatsapp · email · organico |
| utm_medium | cpc · paid_social · organico · post · reel · story · video · bio · status · email · banner |
| utm_campaign | tema/campanha do trimestre (ex.: 2026-agua-invisivel) |
| utm_content | identificador do criativo |
| utm_term | palavra-chave (só Google Ads de Pesquisa) |
Pagos: parâmetros dinâmicos na plataforma (Google sufixo do URL final + auto-tagging; Meta {{campaign.name}}). Manuais/orgânicos: o Gerador. Assim os valores sempre batem com o que o script captura.
Container GTM pronto pra importar
O próximo material plugável: um container GTM que o Vini importa e pronto — sem montar tag por tag.
O que vem dentro
- Tag base do GA4 (com uma variável pro G-XXXX).
- Tag Captura de Origem (o script do bloco 02) em All Pages.
- Eventos generate_lead (página de obrigado) e contact_whatsapp (clique wa.me), com os acionadores prontos.
- Meta Pixel (PageView + Lead) e as variáveis de clique/dataLayer.
O Vini importa em GTM → Administrador → Importar container, troca 2 ou 3 IDs (GA4, Pixel) nas variáveis, e publica. Transforma horas de setup em minutos, idêntico em todo cliente.
É o próximo item que eu monto. Como envolve um arquivo de importação sensível a formato, entrego separado e testável. Diga “pode montar o container” quando quiser.
Checklist de “conexão redonda”
A conexão está redonda quando estas 6 provas passam. Vale pra qualquer cliente.
- Cheguei numa página com ?utm_source=teste, naveguei pra outra sem parâmetro, e os campos ocultos do form ainda vêm preenchidos (persistência OK).
- O evento generate_lead dispara no GA4 (Tempo real / DebugView).
- O contato entra no CRM com a origem preenchida (utm + click ID), não “direct/none”.
- A conversão aparece no Meta (Testar eventos) e no Google Ads (importada do GA4).
- O deal nasce grudado no contato e carrega a origem até o Fechado Ganho.
- No Reportei, o total de leads bate com o CRM e a origem cruza com o gasto por campanha.
Enquanto a prova nº1 e a nº3 não passarem, não escale verba — você estaria pagando por leads sem saber a origem.
Esta camada + os guias por cliente
Este documento é a camada geral (o desenho + o material que serve todos). Os guias por cliente são a aplicação — mudam só o momento 4 (transporte) e os IDs.
| Cliente | Momento 4 (transporte) | Guia |
|---|---|---|
| Guiaderodas | Elementor → Webhook → GoHighLevel | abrir |
| YÁgua | Elementor → Webhook → Make → HubSpot | abrir |
| Dra. Patrícia | Página do Claude → form nativo / webhook GoHighLevel | abrir |
Em todos, o momento 1-2-3 (capturar, persistir, injetar) passa a ser o mesmo script deste documento. É o que deixa a conexão redonda de forma idêntica em toda a carteira.
Ordem pra deixar redondo
- Instalar o Script de Captura de Origem (bloco 02) no GTM do cliente.
- Preparar os campos ocultos no form.
- Garantir o transporte pro CRM (o guia do cliente) e o mapeamento da origem no contato/deal.
- Rodar as 6 provas (bloco 05). Só então escalar verba.