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