Início/ Materiais/ Auditoria de (not set) no GA4
Guia gratuito · GA4

Auditoria de (not set) no GA4

A ordem de investigação que levou uma operação de 20% para 0,8%. O que (not set) é e o que não é, as 7 famílias de causa, as consultas no BigQuery para achar cada uma e como provar que o número melhorou de verdade.

Versão 1 · outubro de 2026~15 min de leituraGA4 · BigQuery · SQL
Capa do guia Auditoria de (not set) no GA4

1. O que (not set) é, e o que não é

(not set) é o valor que o GA4 usa quando não recebeu informação nenhuma para aquela dimensão. Não é uma fonte de tráfego, nem um canal. É um buraco no dado com nome de categoria.

Três valores parecidos costumam ser confundidos com ele, e cada um pede uma investigação diferente:

ValorO que significaÉ problema?
(not set)O GA4 não recebeu o dado para a dimensãoSim. É o objeto deste guia
(direct) / (none)O GA4 recebeu a sessão, mas sem referência nem parâmetro de campanhaÀs vezes. Direto alto demais costuma esconder UTM perdida
(other)O relatório agrupou valores por limite de linhas (cardinalidade)Não é perda de dado. No BigQuery o valor real aparece
(data not available)O dado não está disponível para aquele período ou combinaçãoDepende. Leia a documentação antes de investigar

O segundo cuidado é o escopo. "(not set)" na origem da sessão, na origem do primeiro usuário, na página de entrada e na campanha do Google Ads são quatro problemas diferentes. Comece pela origem e mídia da sessão, que é a que pesa nas decisões de canal.

Regra do guia: trabalhe no BigQuery, não na interface. A interface aplica limiares, amostragem e agrupamentos que escondem justamente o padrão que você está procurando.

2. Meça do jeito certo

Antes de corrigir qualquer coisa, tire três números: o percentual de sessões, de conversões e de receita em (not set). O segundo e o terceiro importam mais que o primeiro. Uma operação com 15% das sessões em (not set) e 2% da receita tem outro problema, e outra urgência, do que uma com 5% das sessões e 30% da receita.

A consulta abaixo monta uma tabela de sessões a partir do export do GA4 e já marca os sinais que vamos usar nas próximas seções. Troque o dataset pelo seu.

-- Base de sessões com os sinais de diagnóstico (export do GA4 no BigQuery)
-- Troque `projeto.analytics_123456789` pelo dataset da sua propriedade
CREATE OR REPLACE TABLE `projeto.auditoria.sessoes_notset` AS
WITH eventos AS (
  SELECT
    event_date,
    user_pseudo_id,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id,
    event_name,
    event_timestamp,
    platform,
    stream_id,
    device.category                       AS device_category,
    privacy_info.analytics_storage        AS analytics_storage,
    collected_traffic_source.manual_source AS utm_source,
    collected_traffic_source.manual_medium AS utm_medium,
    collected_traffic_source.gclid        AS gclid,
    session_traffic_source_last_click.cross_channel_campaign.source AS sessao_source,
    session_traffic_source_last_click.cross_channel_campaign.medium AS sessao_medium,
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location,
    ecommerce.purchase_revenue            AS receita
  FROM `projeto.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY))
                          AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
)
SELECT
  user_pseudo_id,
  session_id,
  MIN(PARSE_DATE('%Y%m%d', event_date))                    AS dia,
  ARRAY_AGG(event_name ORDER BY event_timestamp LIMIT 1)[OFFSET(0)] AS primeiro_evento,
  COUNT(*)                                                 AS n_eventos,
  LOGICAL_OR(event_name = 'session_start')                 AS tem_session_start,
  LOGICAL_OR(event_name IN ('page_view', 'screen_view'))   AS tem_pageview,
  LOGICAL_OR(gclid IS NOT NULL)                            AS tem_gclid,
  LOGICAL_OR(utm_source IS NOT NULL AND utm_medium IS NULL) AS utm_incompleta,
  ANY_VALUE(platform)                                      AS platform,
  ANY_VALUE(stream_id)                                     AS stream_id,
  ANY_VALUE(device_category)                               AS device_category,
  MAX(analytics_storage)                                   AS analytics_storage,
  MAX(sessao_source)                                       AS sessao_source,
  MAX(sessao_medium)                                       AS sessao_medium,
  MAX(NET.HOST(page_location))                             AS host,
  COUNTIF(event_name = 'purchase')                         AS compras,
  SUM(IF(event_name = 'purchase', receita, 0))             AS receita
FROM eventos
WHERE user_pseudo_id IS NOT NULL AND session_id IS NOT NULL
GROUP BY 1, 2;
Confira no seu schema: o campo session_traffic_source_last_click entrou no export em 2024. Em exports mais antigos, ou se ele vier vazio, reconstrua a origem da sessão com collected_traffic_source e o parâmetro page_referrer do primeiro evento.

Com a tabela pronta, o número de partida:

-- Ponto de partida: quanto do dado está sem origem
SELECT
  COUNT(*) AS sessoes,
  ROUND(100 * COUNTIF(IFNULL(sessao_source, '(not set)') = '(not set)') / COUNT(*), 1) AS pct_sessoes_not_set,
  ROUND(100 * SUM(IF(IFNULL(sessao_source, '(not set)') = '(not set)', compras, 0)) / NULLIF(SUM(compras), 0), 1) AS pct_compras_not_set,
  ROUND(100 * SUM(IF(IFNULL(sessao_source, '(not set)') = '(not set)', receita, 0)) / NULLIF(SUM(receita), 0), 1) AS pct_receita_not_set
FROM `projeto.auditoria.sessoes_notset`;

Guarde esse resultado com a data. Ele é a linha de base da seção 6.

3. As 7 famílias de causa

(not set) quase nunca vem de um erro só. Ele é a soma de pequenas perdas, cada uma com um dono diferente: mídia, desenvolvimento, CRM, jurídico, produto. Por isso a investigação vai por família, da mais comum para a mais trabalhosa.

A. Google Ads sem vínculo ou gclid perdido

Sintoma
(not set) concentrado em sessões que têm gclid. A campanha do Google Ads aparece como (not set).
Por quê
Conta do Ads não vinculada à propriedade, outra conta anunciando o mesmo site sem vínculo, auto-tagging desligado, ou um redirect que derruba o parâmetro gclid no caminho.
Confirme
Consulta 4.1, linha tem_gclid = true. Teste a URL final com o parâmetro e veja se ele sobrevive ao redirect: curl -sIL "https://seusite.com.br/lp?gclid=teste123" | grep -i location
Corrija
Vincule todas as contas que anunciam o site, ligue o auto-tagging e ajuste os redirects (servidor, plugin, encurtador, app de links) para preservar a query string.

B. UTM incompleta ou fora do padrão

Sintoma
Sessões com utm_source e sem utm_medium. Fontes duplicadas por grafia: "Instagram", "instagram", "ig".
Por quê
Links de e-mail, WhatsApp, CRM e influenciador montados à mão, sem taxonomia.
Confirme
Consulta 4.1, linha utm_incompleta = true, e a lista de valores distintos de source e medium dos últimos 90 dias.
Corrija
Uma taxonomia escrita (source, medium e campaign obrigatórios, minúsculas, sem acento), um gerador de links que só aceita valores da lista e um dono para ela.

C. Sessão que começa sem page_view

Sintoma
O primeiro evento da sessão não é page_view nem session_start. Aparecem user_engagement, scroll, eventos de vídeo ou eventos próprios.
Por quê
Eventos disparando antes da tag do Google carregar, ou uma aba que fica aberta mais de 30 minutos e "acorda" a sessão com um evento que não carrega página nem referência.
Confirme
Consulta 4.1, coluna primeiro_evento, e a consulta 4.2.
Corrija
No GTM, a tag do Google no acionador de inicialização e os eventos dependentes dela. Revise eventos automáticos que disparam sem interação real.

D. Evento de servidor sem a sessão junto

Sintoma
O percentual de (not set) nas compras é bem maior que nas sessões. Compras em sessões com um evento só.
Por quê
A compra é confirmada pelo backend e enviada pelo Measurement Protocol, ou por um server-side mal configurado, sem o client_id e o session_id do navegador. O GA4 recebe a venda, mas não sabe de qual sessão ela veio.
Confirme
Consulta 4.3.
Corrija
Capture o client_id (cookie _ga) e o session_id (cookie _ga_<ID>) no checkout, guarde junto do pedido e envie os dois no evento de servidor.

E. Consentimento

Sintoma
Buracos concentrados em analytics_storage = 'No', eventos sem user_pseudo_id, quedas que coincidem com mudanças no banner de cookies.
Por quê
Com o Consent Mode, quem nega cookies gera pings sem identificador. Desde 15/06/2026, o ad_storage virou o único portão do dado entre GA4 e Google Ads. Banner que não envia o sinal certo apaga conversão sem avisar.
Confirme
Consulta 4.4. Teste o banner nas três situações: aceita, nega e ignora.
Corrija
Estado padrão definido antes de qualquer tag, atualização no clique do banner, sinais ad_storage, ad_user_data e ad_personalization mapeados. Valide com o jurídico, não só com o time de mídia.

F. Domínios e checkout fora do site

Sintoma
(not set) ou referral do próprio gateway concentrados em um host específico, normalmente o de pagamento, login ou um subdomínio.
Por quê
A sessão quebra quando o usuário passa para outro domínio e volta. A origem real fica para trás.
Confirme
Consulta 4.1, coluna host.
Corrija
Configuração de vários domínios na tag, gateway na lista de referências indesejadas e, quando houver login, user_id para costurar a jornada.

G. App e site misturados

Sintoma
(not set) concentrado em platform = 'ANDROID' ou 'IOS'.
Por quê
No app, a sessão costuma chegar sem dado de campanha quando a abertura não veio de um link com parâmetro. E a atribuição de instalação mora no MMP (AppsFlyer, Adjust), não no GA4.
Confirme
Consulta 4.1 separada por stream_id.
Corrija
Analise app e site separados. Para instalação, a fonte da verdade é o MMP. Para reengajamento, deep links com parâmetros de campanha.

4. As consultas de diagnóstico

4.1 Onde o (not set) se concentra

A consulta que mais rende. Ela cruza os sinais da tabela de sessões e mostra as combinações com mais sessões sem origem. Em geral, duas ou três linhas explicam a maior parte do problema.

SELECT
  primeiro_evento, tem_session_start, tem_pageview, tem_gclid, utm_incompleta,
  platform, analytics_storage, host,
  COUNT(*) AS sessoes,
  COUNTIF(IFNULL(sessao_source, '(not set)') = '(not set)') AS sessoes_not_set,
  ROUND(100 * COUNTIF(IFNULL(sessao_source, '(not set)') = '(not set)') / COUNT(*), 1) AS pct_not_set,
  SUM(compras) AS compras
FROM `projeto.auditoria.sessoes_notset`
GROUP BY ALL
HAVING sessoes >= 50
ORDER BY sessoes_not_set DESC
LIMIT 30;

4.2 Com que evento a sessão começa

SELECT
  primeiro_evento,
  COUNT(*) AS sessoes,
  ROUND(100 * COUNTIF(IFNULL(sessao_source, '(not set)') = '(not set)') / COUNT(*), 1) AS pct_not_set
FROM `projeto.auditoria.sessoes_notset`
GROUP BY 1
ORDER BY sessoes DESC;

Se page_view e session_start não dominarem o topo, a família C está pesando.

4.3 Compras que chegam sem sessão

-- Compras sem session_id e compras em sessões de um evento só
WITH compras AS (
  SELECT
    user_pseudo_id,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id
  FROM `projeto.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY))
                          AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
    AND event_name = 'purchase'
)
SELECT
  COUNT(*) AS compras,
  COUNTIF(c.session_id IS NULL) AS compras_sem_sessao,
  COUNTIF(s.n_eventos = 1) AS compras_em_sessao_de_1_evento
FROM compras c
LEFT JOIN `projeto.auditoria.sessoes_notset` s
  ON s.user_pseudo_id = c.user_pseudo_id AND s.session_id = c.session_id;

4.4 Peso do consentimento

SELECT
  PARSE_DATE('%Y%m%d', event_date) AS dia,
  COUNT(*) AS eventos,
  ROUND(100 * COUNTIF(privacy_info.analytics_storage = 'No') / COUNT(*), 1) AS pct_analytics_negado,
  ROUND(100 * COUNTIF(user_pseudo_id IS NULL) / COUNT(*), 1) AS pct_sem_identificador
FROM `projeto.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY))
                        AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
GROUP BY 1
ORDER BY 1;

Uma mudança brusca nessa série quase sempre tem uma data de publicação do banner por trás.

5. Priorize pelo dinheiro

Com as causas na mesa, a tentação é corrigir a mais fácil. A ordem certa é outra: a família que concentra mais receita em (not set) vem primeiro, mesmo que dê mais trabalho.

FamíliaPeso típicoEsforçoQuem resolve
A. Google Ads e gclidAlto em operação com muita mídia de buscaBaixoMídia + desenvolvimento
B. UTMMédio, cresce com CRM e influênciaBaixo, mas contínuoCRM, mídia e conteúdo
C. Sessão sem page_viewMédioMédioAnalytics + desenvolvimento
D. Evento de servidorAlto nas conversõesMédioDesenvolvimento backend
E. ConsentimentoVaria muitoMédioAnalytics + jurídico
F. Domínios e checkoutAlto em e-commerce com gateway externoBaixo a médioAnalytics
G. App e siteAlto em operação com appMédioAnalytics + produto
Escreva um dono e uma data para cada família antes de começar. (not set) volta quando ninguém responde por ele.

6. Prove que melhorou

A melhoria tem que aparecer numa série, não numa captura de tela. Rode a consulta abaixo toda semana e anote no gráfico a data de cada correção.

SELECT
  dia,
  COUNT(*) AS sessoes,
  ROUND(100 * COUNTIF(IFNULL(sessao_source, '(not set)') = '(not set)') / COUNT(*), 1) AS pct_not_set,
  ROUND(100 * SUM(IF(IFNULL(sessao_source, '(not set)') = '(not set)', compras, 0)) / NULLIF(SUM(compras), 0), 1) AS pct_compras_not_set
FROM `projeto.auditoria.sessoes_notset`
GROUP BY 1
ORDER BY 1;

Duas checagens evitam a melhoria falsa:

7. Checklist de auditoria

Quer guardar para consultar depois? O guia completo em PDF, com todas as consultas.

Baixar o PDF ↓

Quer que eu olhe o (not set) da sua conta?

30 minutos, de graça. Entro no seu GA4 e mostro de onde vem o tráfego sem origem.

Quero meu diagnóstico grátis →