How to Calculate Session Duration in GA4 BigQuery Data

Last updated August 29, 2026 · By the SaturnSQL team

event_timestamp is microseconds since the epoch, so session duration is MAX minus MIN per session divided by 1,000,000. Note this is not the same metric as the GA4 UI's engagement time.

WITH events AS (
  SELECT
    user_pseudo_id,
    (SELECT value.int_value
     FROM UNNEST(event_params)
     WHERE key = 'ga_session_id') AS session_id,
    event_timestamp
  FROM `myproject.analytics_123456789.events_20260828`
)
SELECT
  user_pseudo_id,
  session_id,
  ROUND((MAX(event_timestamp) - MIN(event_timestamp)) / 1e6, 1) AS duration_seconds
FROM events
WHERE session_id IS NOT NULL
GROUP BY user_pseudo_id, session_id;

Average session duration

WITH sessions AS (
  SELECT
    user_pseudo_id,
    (SELECT value.int_value
     FROM UNNEST(event_params)
     WHERE key = 'ga_session_id') AS session_id,
    (MAX(event_timestamp) - MIN(event_timestamp)) / 1e6 AS duration_seconds
  FROM `myproject.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN '20260801' AND '20260828'
  GROUP BY user_pseudo_id, session_id
)
SELECT ROUND(AVG(duration_seconds), 1) AS avg_session_seconds
FROM sessions
WHERE session_id IS NOT NULL;

Duration is not engagement time

The microseconds trap: forgetting to divide by 1e6 yields durations in the millions. And first-to-last-event duration is a different metric from the GA4 UI's average engagement time, which sums the engagement_time_msec parameter (milliseconds, not microseconds) and only while the page is in the foreground. Pick one definition and label the column honestly.

Run this in SaturnSQL

SaturnSQL is a browser-based SQL editor for teams: shared query library, schema-aware autocomplete, and scheduled exports to Google Sheets and Slack.

Try it free

Do more with BigQuery

Related BigQuery guides