How do I query AI referral sessions in the GA4 BigQuery export?

The Citead team, updated

In short. Filter session attribution sources and count distinct user and session pairs from exported session_start events.

Definition: A source-filtered session query counts distinct sessions attributed to selected AI assistant sources in the Google Analytics 4 (GA4) BigQuery export. It uses session attribution fields and a session identifier paired with a user identifier.

Key facts

  • As of 17 October 2026, Google's traffic attribution documentation directs session analysis to session_traffic_source_last_click, available on every event.
  • Google's export schema defines traffic_source as the source that first acquired the user, while collected_traffic_source contains values collected with events.
  • Google's session documentation recommends combining a user identifier with the session ID for session analysis outside Analytics.
  • Google's AI assistants example classifies traffic through source-matching rules and says to update those rules when assistant URLs change.

Which attribution fields belong in the query?

Attribution assigns credit for a session to a traffic source. Google's traffic attribution guide identifies session_traffic_source_last_click.manual_campaign.source and .medium as common session fields. Its user-scoped fields describe the user's first arrival.

The export schema also documents session_traffic_source_last_click.cross_channel_campaign.source and .medium. The example below uses that cross-channel pair consistently. collected_traffic_source.manual_source holds the source collected with an event, including parsed referral parameters and UTM campaign parameters.

Google's session attribution explanation specifies non-direct last-click attribution: a later direct session can retain an earlier source. The resulting count therefore measures sessions attributed to the selected assistant source, including direct returns that retain that attribution.

What does a source-filtered query look like?

This original GoogleSQL example counts sessions with an exported session_start event in the selected daily tables. It extracts the session identifier from event_params and deduplicates the user and session pair within each source and medium.

Google's schema reference documents the daily table pattern events_YYYYMMDD and integer parameter values in event_params.value.int_value. The table path below contains placeholders for the project and property dataset.

WITH session_starts AS (
  SELECT
    user_pseudo_id,
    (SELECT value.int_value
     FROM UNNEST(event_params)
     WHERE key = 'ga_session_id') AS session_id,
    session_traffic_source_last_click
      .cross_channel_campaign.source AS source,
    session_traffic_source_last_click
      .cross_channel_campaign.medium AS medium
  FROM `PROJECT.analytics_PROPERTY_ID.events_*`
  WHERE _TABLE_SUFFIX BETWEEN @start_suffix AND @end_suffix
    AND event_name = 'session_start'
), unique_sessions AS (
  SELECT DISTINCT user_pseudo_id, session_id, source, medium
  FROM session_starts
  WHERE user_pseudo_id IS NOT NULL
    AND session_id IS NOT NULL
)
SELECT source, medium, COUNT(*) AS sessions
FROM unique_sessions
WHERE LOWER(source) = LOWER(@assistant_source)
GROUP BY source, medium
ORDER BY sessions DESC;

Google's parameterized query documentation explains named parameters prefixed with @. In the BigQuery editor's Query settings, the parameters start_suffix, end_suffix, and assistant_source each use type STRING. The date suffix values use YYYYMMDD; the source value matches an assistant source observed in the export. For several verified sources, the equality condition can become an explicit IN list. Medium remains visible as an output dimension.

Google's session ID guidance explains that ga_session_id is generated from the session start timestamp in seconds. Pairing it with user_pseudo_id avoids treating different users with the same session timestamp as one session.

How should the result be checked?

An initial inventory can omit the source condition and inspect the returned source and medium pairs. Google's custom channel guidance names ChatGPT, Gemini, Microsoft Copilot, Claude, and Perplexity as examples for AI assistant matching. The query's selected source values form its classification rule.

Google's session documentation describes cases where session_start is filtered out while a session ID still exists. Such sessions are excluded by this query. The same documentation explains that Analytics reports estimate session counts, while BigQuery can calculate precise counts from exported data.

FAQ

Can I filter on first-user source instead?

You can use traffic_source.source for a first-acquisition question. Google's attribution guide assigns session-source analysis to session_traffic_source_last_click.

Why can recent results change?

Google's export schema says daily tables accept late events for up to three days after the event date. You can rerun the same date range after that update window.

Sources

  1. Google Analytics, "Traffic attribution data", updated 14 April 2026
  2. Google Analytics Help, "BigQuery Export schema", accessed 17 October 2026
  3. Google Analytics Help, "About Analytics sessions", accessed 17 October 2026
  4. Google Analytics Help, "Custom channel groups", accessed 17 October 2026
  5. Google Cloud, "Run parameterized queries", accessed 17 October 2026

Check how a page reads to answer engines. Open the GEO score analyzer

Test a page and see what to fix first

The analysis usually takes less than 10 seconds and needs no account.

400,000+ pages scored in the public benchmark