Painéis de mídia paga frequentemente relatam retornos excelentes. O Google Ads aponta um ROAS de 600%, o Meta Ads exibe um CPA muito abaixo do teto contratual e as plataformas de atribuição multitoque distribuem créditos entre todos os pontos de contato. Quando a diretoria financeira confronta esses números com a receita líquida que entrou na conta bancária da empresa, a conta não fecha. Aumentar o investimento em 40% muitas vezes gera um crescimento quase imperceptível nas vendas globais.
Essa discrepância decorre de um erro metodológico comum: confundir correlação com causalidade. Modelos de atribuição convencionais (last-click, first-click ou data-driven das próprias plataformas de anúncios) monitoram usuários que clicaram em anúncios e posteriormente converteram. Esses modelos são incapazes de responder à pergunta central de negócios: quantas dessas conversões teriam acontecido mesmo se nenhum anúncio tivesse sido veiculado?
Com o bloqueio progressivo de cookies de terceiros, a consolidação do App Tracking Transparency (ATT) da Apple e restrições regulatórias de privacidade, o rastreamento individualizado perdeu a confiabilidade técnica. A inferência causal baseada em testes geográficos (geo-experiments) consolidou-se como o padrão metodológico para auditar a eficácia da mídia paga. Neste guia, você aprenderá a estruturar, executar e analisar testes de incrementalidade utilizando o método de Controle Sintético Aumentado (Augmented Synthetic Control Method) por meio do GeoLift integrado a pipelines de dados em Python.
A falácia da atribuição e o conceito de lift causal
A maior parte dos investimentos em publicidade digital sofre com o problema da seleção endógena. Plataformas de leilão otimizam algoritmos para encontrar os usuários com maior propensão prévia de conversão. Se um consumidor já conhece a marca, visita o site com frequência e pretende comprar nos próximos dois dias, a plataforma de mídia posiciona um anúncio de retargeting ou busca de marca exatamente no caminho desse usuário. O clique acontece, a plataforma registra a conversão no painel, mas o valor econômico gerado por aquele investimento foi nulo. O anúncio apenas tributou uma venda que já ocorreria organicamente.
Na econometria e na inferência causal, definimos o efeito causal de uma intervenção através do framework de resultados potenciais de Rubin. Para cada unidade geográfica $i$ em um período de tempo $t$:
$$Y_{it}(1) \quad \text{é o resultado com a intervenção (com campanha de mídia)}$$ $$Y_{it}(0) \quad \text{é o resultado potencial sem a intervenção (contrafactual sem mídia)}$$
O efeito de tratamento individual ou causal lift ($\tau_{it}$) é dado por:
$$\tau_{it} = Y_{it}(1) - Y_{it}(0)$$
O desafio fundamental da inferência causal reside no fato de que nunca podemos observar $Y_{it}(1)$ e $Y_{it}(0)$ simultaneamente para a mesma unidade no mesmo instante. Se ativamos uma campanha em São Paulo durante o mês de outubro, observamos apenas $Y_{\text{SP}, t}(1)$. O valor de $Y_{\text{SP}, t}(0)$, isto é, o que teria acontecido em São Paulo se a verba não tivesse sido investida, é estritamente não observável. É uma hipótese contrafactual que precisa ser estimada com rigor estatístico.
Testes A/B convencionais baseados em divisão de usuários (user-split) tentam resolver isso randomizando cookies ou IDs de usuários. No ecossistema atual, esse método apresenta falhas graves: contaminação entre grupos por múltiplos dispositivos, navegadores que bloqueiam identificadores e vazamento de público em campanhas de topo de funil.
Os testes geográficos contornam essas limitações operando em nível agregado. Em vez de tentar rastrear indivíduos, dividimos regiões geográficas (estados, cidades ou regiões metropolitanas) entre mercados de teste e mercados de controle, medindo as variações agregadas na receita ou no volume de conversões.
Fundamentos matemáticos: de Synthetic Control a Augmented Synthetic Control
Para estimar o contrafactual geográfico, a técnica mais intuitiva seria escolher uma cidade similar para servir de controle. Comparar diretamente o desempenho de Belo Horizonte com Curitiba costuma introduzir viés de escala, sazonalidade local e dinâmicas econômicas distintas.
Em 2010, Alberto Abadie, Alexis Diamond e Jens Hainmueller formalizaram o Synthetic Control Method (SCM). Em vez de selecionar uma única cidade de controle, o SCM constrói uma combinação convexa ponderada de múltiplas regiões não tratadas (o pool de doadores).
Sejam $J$ unidades de controle disponíveis. O SCM encontra um vetor de pesos $W = (w_1, w_2, \dots, w_J)^T$ que minimiza a distância entre a trajetória histórica pré-intervenção da região tratada e a média ponderada das regiões de controle:
$$\min_W || X_1 - X_0 W ||_V$$
Sob as restrições:
$$w_j \ge 0 \quad \text{para todo } j$$ $$\sum_{j=1}^J w_j = 1$$
Onde $X_1$ representa os dados pré-tratamento da região tratada e $X_0$ a matriz de características das unidades de controle.
A limitação do SCM clássico e a solução do ASCM
O SCM clássico exige que a unidade tratada esteja contida no fecho convexo (convex hull) das unidades de controle. Se a sua empresa opera em um mercado concentrado onde o estado de São Paulo representa 45% do faturamento total, nenhum conjunto de outros estados ponderados entre 0 e 1 conseguirá reproduzir a escala de São Paulo sem gerar viés de interpolação severo.
Para superar essa barreira, pesquisadores de Stanford e Meta (Eli Ben-Michael, Avi Feller e Jesse Rothstein, 2021) desenvolveram o Augmented Synthetic Control Method (ASCM), que é o núcleo algorítmico do GeoLift.
O ASCM combina o controle sintético clássico com um modelo de desenviesamento (outcome model), tipicamente uma regressão ridge regularizada. O estimador contrafactual do ASCM para o período pós-tratamento $t$ assume a seguinte forma:
$$\hat{Y}{1t}(0) = \sum{j=1}^J w_j Y_{jt} + \left( \hat{m}(X_1) - \sum_{j=1}^J w_j \hat{m}(X_j) \right)$$
Onde $\hat{m}(\cdot)$ é a função ajustada pelo modelo de regressão sobre as covariáveis ou períodos pré-intervenção.
Essa formulação relaxa a exigência estrita de que os pesos pertençam puramente ao fecho convexo. O parâmetro de penalização $\lambda$ da regressão ridge permite extrapolamento controlado quando a unidade tratada for maior ou apresentar dinâmicas não perfeitamente sintetizáveis pelos controles, mantendo o erro quadrático médio (RMSE) pré-tratamento significativamente menor do que no SCM tradicional.
Assim como exploramos na análise de intervenções em SEO split testing com Python e CausalImpact, onde séries temporais bayesianas estimam contrafactuais para grupos de páginas, o GeoLift aplica a matemática do controle sintético aumentado diretamente aos dados em painel geográficos.
Estrutura da base de dados e extração via BigQuery
Para executar um teste com GeoLift, a base de dados precisa ser organizada em formato de painel balanceado. Isso significa que para cada localização geográfica selecionada, devemos possuir uma série temporal ininterrupta da métrica analisada (receita, leads qualificados ou novas assinaturas).
A tabela requer três colunas obrigatórias:
date: data no formato YYYY-MM-DD.location: identificador estável da região (UF, código IBGE, DDD ou sigla de cidade).Y: a métrica de negócio a ser avaliada.
Os dados podem ser extraídos de bancos transacionais internos ou do pipeline analítico do Google Analytics. Se você utiliza o GA4 BigQuery export, pode extrair transações diárias agregadas por estado brasileiro com a seguinte consulta:
WITH daily_geo_transactions AS (
SELECT
PARSE_DATE('%Y%m%d', event_date) AS date,
geo.region AS location,
SUM(event_value_in_usd) AS Y
FROM
`seu-projeto-gcp.analytics_123456789.events_*`
WHERE
event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN '20260101' AND '20260831'
AND geo.region IS NOT NULL
AND geo.region != ''
GROUP BY
1, 2
)
SELECT
date,
location,
COALESCE(Y, 0.0) AS Y
FROM
daily_geo_transactions
ORDER BY
location, date ASC;
Recomenda-se manter um histórico pré-teste de no mínimo 90 a 180 dias diários. Séries curtas impedem que o algoritmo capture ciclos semanais e sazonalidades mensais, prejudicando o cálculo dos pesos sintéticos.
Arquitetura de integração entre Python e GeoLift via rpy2
O GeoLift foi originalmente concebido e mantido pela equipe de Marketing Science da Meta em R. Para engenheiros de dados e cientistas de dados que operam pipelines analíticos inteiramente em Python, a biblioteca rpy2 oferece a ponte para executar chamadas de baixo nível diretamente nos objetos do R, mantendo a ingestão, limpeza e pós-processamento no ecossistema Pandas e Polars.
Instale os pacotes necessários no seu ambiente virtual:
pip install pandas numpy rpy2
No ambiente do R do seu servidor ou container Docker:
install.packages("devtools")
devtools::install_github("facebookincubator/GeoLift")
Abaixo está o módulo Python que gerencia o ciclo de vida dos dados e expõe as funções de preparação do GeoLift:
import os
import pandas as pd
import numpy as np
import rpy2.robjects as ro
from rpy2.robjects import pandas2ri
from rpy2.robjects.packages import importr
# Ativa a conversao automatica entre Pandas DataFrame e R data.frame
pandas2ri.activate()
# Importa os modulos centrais do R
base = importr('base')
utils = importr('utils')
geolift = importr('GeoLift')
def carregar_dados_painel(caminho_csv: str) -> ro.DataFrame:
"""
Carrega o dataset em Pandas, valida balanceamento e converte para R data.frame.
"""
df = pd.read_csv(caminho_csv)
df['date'] = pd.to_datetime(df['date'])
df['Y'] = df['Y'].astype(float)
df['location'] = df['location'].astype(str)
# Validacao de painel balanceado (mesmo numero de datas por localidade)
contagem_datas = df.groupby('location')['date'].nunique()
if contagem_datas.nunique() > 1:
raise ValueError("O painel nao esta balanceado. Algumas localidades possuem datas faltantes.")
# Converte para formato consumivel pelo R
r_df = pandas2ri.py2rpy(df)
return r_df
Análise de poder estatístico pré-teste: seleção de mercados e MDE
Iniciar um teste de incrementalidade sem análise de poder prévia é uma das formas mais rápidas de desperdiçar orçamento de publicidade. Se a intervenção for muito curta ou a verba muito baixa para o ruído histórico da região, o teste retornará inconclusivo, incapaz de distinguir o efeito do anúncio da variância natural das vendas.
O GeoLift resolve isso com simulações de poder estatístico baseadas em testes de placebo no período pré-tratamento. A análise responde a três questões estruturais:
- Qual a duração ideal do teste (15, 30 ou 45 dias)?
- Qual o Efeito Mínimo Detectável (Minimum Detectable Effect ou MDE)?
- Quais cidades ou estados devem compor o grupo de tratamento para minimizar o erro sintético sem contaminar o controle?
A função GeoLiftPowerFinder realiza uma busca combinatória para identificar os melhores grupos de tratamento para diferentes tamanhos de efeito simulados.
def executar_analise_de_poder(r_df, duracao_teste_dias: int = 30):
"""
Executa simulacoes de poder estatistico para encontrar os melhores mercados
e o MDE correspondente a 80% de poder com alpha de 0.10.
"""
ro.globalenv['dados_painel'] = r_df
# Configura a chamada do GeoLiftPowerFinder no R
script_r = f"""
mercados_recomendados <- GeoLiftPowerFinder(
data = dados_painel,
treatment_periods = c({duracao_teste_dias}),
N = c(2, 3, 4), # Quantidade de cidades/estados no grupo de tratamento
Y_id = "Y",
location_id = "location",
time_id = "date",
effect_size = seq(0.05, 0.30, 0.05), # Testa lifts de 5% a 30%
alpha = 0.1,
cpic = 1.0, # Custo estimado por incremento para calculo de orcamento
parallel = TRUE
)
"""
ro.reval(script_r)
# Coleta a tabela de resultados do R para o Python
tabela_poder = ro.globalenv['mercados_recomendados']
df_poder = pandas2ri.rpy2py(tabela_poder)
# Filtra as configuracoes que atingiram poder estatistico >= 80%
configuracoes_viaveis = df_poder[df_poder['Power'] >= 0.8].sort_values(
by=['EffectSize', 'ScaledL2Imbalance'], ascending=[True, True]
)
return configuracoes_viaveis
Interpretando a métrica Scaled L2 Imbalance
Ao analisar a saída da tabela de poder, o indicador mais importante além da taxa de falso positivo e poder estatístico é o Scaled L2 Imbalance.
Essa métrica avalia a distância quadrática média entre a série real pré-teste do grupo de tratamento e a série do controle sintético gerado, normalizada pela variância da série original.
Valores de Scaled L2 Imbalance inferiores a 0.20 indicam um controle sintético com alta aderência histórica. Valores acima de 0.50 sinalizam que o grupo de controle não consegue reproduzir satisfatoriamente o comportamento do tratamento, recomendando trocar os mercados escolhidos ou estender o histórico pré-teste.
Execução da inferência causal pós-teste
Finalizado o período de intervenção em campo, no qual a campanha foi ativada exclusivamente nas regiões de tratamento e pausada (ou mantida em nível estável de baseline) nas regiões de controle, executamos o modelo de inferência causal do GeoLift.
O script a seguir executa o cálculo do lift, gera os intervalos de confiança e extrai as métricas de negócio consolidadas:
def analisar_teste_geolift(
r_df,
locais_tratamento: list,
data_inicio_tratamento: str,
data_fim_tratamento: str
) -> dict:
"""
Executa a inferencia do GeoLift, computando lift absoluto, relativo e p-valor.
"""
ro.globalenv['dados_painel'] = r_df
ro.globalenv['locais_tratados'] = ro.StrVector(locais_tratamento)
script_inferencia = f"""
resultado_teste <- GeoLift(
data = dados_painel,
locations = locais_tratados,
treatment_start_time = "{data_inicio_tratamento}",
treatment_end_time = "{data_fim_tratamento}",
Y_id = "Y",
location_id = "location",
time_id = "date",
ConfidenceIntervals = TRUE,
alpha = 0.1
)
"""
ro.reval(script_inferencia)
# Extrai o objeto do R
res = ro.globalenv['resultado_teste']
# Mapeamento dos resultados escalares
lift_absoluto = float(ro.reval("resultado_teste$Incremental")[0])
lift_relativo = float(ro.reval("resultado_teste$IncrementalRelative")[0])
p_valor = float(ro.reval("resultado_teste$pvalue")[0])
ic_inferior = float(ro.reval("resultado_teste$LowerInterval")[0])
ic_superior = float(ro.reval("resultado_teste$UpperInterval")[0])
metricas = {
"lift_absoluto": lift_absoluto,
"lift_relativo_pct": lift_relativo * 100,
"p_valor": p_valor,
"ic_90_inferior": ic_inferior,
"ic_90_superior": ic_superior,
"estatisticamente_significativo": p_valor <= 0.10
}
return metricas
Cálculo financeiro: iROAS e iCPA
Com o efeito incremental absoluto estimado, passamos para a mensuração da eficiência financeira real da campanha.
$$\text{Incremental ROAS (iROAS)} = \frac{\Delta \text{Receita Incremental Estimada}}{\text{Investimento Total de Mídia no Tratamento}}$$
$$\text{Incremental CPA (iCPA)} = \frac{\text{Investimento Total de Mídia no Tratamento}}{\Delta \text{Conversões Incrementais Estimadas}}$$
Suponha que durante 30 dias de teste no estado do Paraná (PR), o investimento adicional em Meta Ads tenha sido de R$ 120.000,00. O painel da plataforma registrou R$ 600.000,00 em receita atribuída (ROAS de 5.0).
No entanto, o GeoLift calculou um lift absoluto incremental de R$ 210.000,00 (intervalo de confiança entre R$ 150.000 e R$ 270.000 com $p = 0.02$).
$$\text{iROAS Real} = \frac{210.000}{120.000} = 1.75$$
Esse resultado expõe a realidade da operação: para cada R$ 1,00 colocado na campanha, ela gerou R$ 1,75 em faturamento puramente novo, enquanto os outros R$ 3,25 reportados pelo painel do Meta Ads eram compras de clientes recorrentes que teriam comprado sem o anúncio. Se a margem de contribuição do negócio for inferior a 40%, esse canal operou com prejuízo econômico real, apesar do painel comemorar um ROAS aparente de 5.0.
Testes de placebo e robustez da inferência
Diferente de testes estatísticos clássicos que assumem observações independentes e identicamente distribuídas (i.i.d.), séries temporais geográficas apresentam forte autocorrelação temporal e dependência espacial. Por essa razão, testes de hipótese padrão (como o teste t de Student) geram falsos positivos excessivos.
O GeoLift emprega inferência não paramétrica por meio de testes de permutação e conformal inference:
- Placebos no espaço: O algoritmo finge que cada uma das unidades de controle recebeu o tratamento na mesma data e calcula o efeito fictício. O p-valor é a fração de placebos espaciais que apresentaram um efeito estimado igual ou maior ao efeito observado no mercado de teste real.
- Placebos no tempo: O algoritmo aplica o modelo em períodos históricos pré-tratamento nos mercados de teste onde se sabe que nenhuma intervenção ocorreu. Se o modelo detectar “efeitos significativos” em períodos sem anúncio, o modelo é rejeitado por instabilidade.
Apenas quando a probabilidade de o efeito observado ocorrer por mero acaso for menor que o limiar $\alpha$ estabelecido (geralmente 0.10 ou 0.05 para testes geográficos), aceita-se que o investimento em mídia provocou um lift causal positivo.
Integração de testes de incrementalidade com Marketing Mix Modeling (MMM)
Os testes de incrementalidade com GeoLift não funcionam de forma isolada. Eles representam a verdade de calibração para modelos macroeconômicos de atribuição.
Modelos de Marketing Mix Modeling, como o Google Meridian ou Meta Robyn, estimam as curvas de resposta e saturação de todos os canais de mídia simultaneamente por regressão bayesiana. O grande risco do MMM é a multicolinearidade: canais de mídia que aumentam o investimento nos mesmos períodos de vendas (Black Friday, Natal) podem ter seus efeitos confundidos pelo modelo.
A integração metodológica correta conecta essas duas disciplinas:
- O teste com GeoLift mede o lift causal isolado de um canal específico em um intervalo de tempo delimitado.
- O iROAS ou coeficiente de resposta obtido no teste é inserido no MMM como uma distribuição a priori (Bayesian prior).
- O MMM ajusta a curva de saturação do canal para respeitar a âncora empírica mensurada no mundo real pelo geo-experimento.
Essa sinergia está detalhada em nosso guia sobre Marketing Mix Modeling com Google Meridian e Python, demonstrando como combinar dados em nível macro com testes de intervenção controlada.
| Abordagem | Vantagem Principal | Limitação Principal | Papel no Stack Analítico |
|---|---|---|---|
| Atribuição Multitoque (MTA) | Granularidade por anúncio e criativo | Altamente enviesada, não mede causalidade, afetada por privacidade | Otimização tática intradia de criativos |
| GeoLift (ASCM) | Mede causalidade pura sem identificadores pessoais | Exige orçamento concentrado e períodos de teste de 15 a 45 dias | Padrão-ouro para provar incrementalidade de canais |
| Marketing Mix Modeling (MMM) | Visão holística de todos os canais e fatores exógenos | Requer calibração externa para evitar confusão de variáveis | Alocação orçamentária macro e planejamento de safra |
Boas práticas e armadilhas comuns em testes geográficos
A execução bem-sucedida de um geo-experimento depende do controle estrito de variáveis externas durante o período de intervenção.
Evite o vazamento geográfico (spillover effect)
Se a sua empresa seleciona Campinas como praça de tratamento e a Grande São Paulo como praça de controle, o trânsito diário de pessoas entre as duas regiões provocará contaminação. Usuários impactados pelo anúncio em uma região podem converter fisicamente ou via IP na outra.
Em mercados brasileiros, estados inteiros (UFs) ou grupos de DDDs isolados funcionam melhor como unidades geográficas do que municípios vizinhos conurbados.
Mantenha a estabilidade dos outros canais
Durante os dias do teste, nenhuma ação desbalanceada deve ser executada. Se a equipe de CRM disparar uma campanha agressiva de cupons de e-mail focada apenas nos clientes do Rio de Janeiro enquanto o Rio é seu mercado de teste de mídia paga, o efeito do e-mail será indevidamente creditado ao anúncio de Meta Ads ou Google Ads.
O SUTVA (Stable Unit Treatment Value Assumption) precisa ser respeitado: o tratamento de uma unidade não pode afetar o resultado de outras, e não pode haver variações ocultas no tratamento aplicado.
Não selecione mercados por intuição
O erro operacional mais frequente em equipes de crescimento é escolher a região de teste com base na conveniência comercial: “vamos testar em São Paulo porque é onde temos mais receita”.
São Paulo frequentemente não possui nenhum análogo sintético viável no Brasil, tornando impossível construir um controle sintético com baixo Scaled L2 Imbalance. A seleção deve sempre ser guiada pelo algoritmo combinatório do GeoLiftPowerFinder, priorizando praças que formem pares ideais com o restante do país.
Integrar testes de causalidade geográfica com o ferramental de dados corporativo transforma o marketing digital de um centro de custos guiado por métricas de vaidade em uma operação fundamentada em retorno financeiro incremental comprovado. Se você deseja auditar os canais da sua empresa ou estruturar uma esteira automatizada de geo-experimentos, conheça nossos serviços especializados de inteligência de dados e consultoria analítica ou entre em contato para estruturarmos seu primeiro teste de incrementalidade.