UTM persistence script e arquitetura martech em 3 BUs
Governança única de UTM, persistência via sessionStorage e propagação automática em links internos. Atribuição 100% coberta ponta a ponta.
Contexto
O que é: governança unificada de UTM e arquitetura martech cross-BU num grupo de educação com 3 unidades de negócio. Script de persistência via sessionStorage + propagação automática em links internos + push no dataLayer para HubSpot e GA4 consumirem. Resultado: 100% de cobertura de atribuição ponta a ponta.
Contexto: 3 BUs com nomenclaturas de UTM distintas, implementações parciais de HubSpot e atribuição fragmentada. Era impossível responder "essa lead veio de onde" com confiança.
Problema
UTMs se perdiam em navegações internas entre sites das 3 BUs. Formulários capturavam apenas o último referrer. Atribuição ficava incompleta no HubSpot.
Abordagem
Governança unificada de UTM nomenclature + script de persistência via sessionStorage + injeção automática em links internos + push para dataLayer para HubSpot e GA4 consumirem.
Execução
Script único carregado em todas as 3 BUs via GTM. Captura entry point, persiste na sessão, propaga em navegação interna, expõe no dataLayer.
const SESSION_KEY = 'sp_session_attribution';
const UTM_KEYS = ['utm_source', 'utm_medium', 'utm_campaign',
'utm_content', 'utm_term'];
function captureEntryPoint() {
const stored = sessionStorage.getItem(SESSION_KEY);
if (stored) return JSON.parse(stored);
const params = new URLSearchParams(window.location.search);
const captured = {};
UTM_KEYS.forEach((k) => {
if (params.has(k)) captured[k] = params.get(k);
});
if (Object.keys(captured).length) {
captured.captured_at = new Date().toISOString();
captured.landing_page = window.location.pathname;
sessionStorage.setItem(SESSION_KEY, JSON.stringify(captured));
}
return captured;
}
function appendToInternalLinks(attribution) {
if (!Object.keys(attribution).length) return;
const selector = `a[href^="/"], a[href*="${window.location.hostname}"]`;
document.querySelectorAll(selector).forEach((a) => {
const url = new URL(a.href, window.location.origin);
UTM_KEYS.forEach((k) => {
if (attribution[k] && !url.searchParams.has(k)) {
url.searchParams.set(k, attribution[k]);
}
});
a.href = url.toString();
});
}
const attribution = captureEntryPoint();
appendToInternalLinks(attribution);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'sp_attribution_ready', attribution });Resultados
Output reutilizável
Convenção UTM governada em documento, script versionado, plano de teste pré-produção, playbook para replicar em novas BUs.