Session duration tells you how long users actually spend on your site, but GA4 doesn't surface it the same way Universal Analytics did. You'll need to either pull it from Reports with the right dimensions, query the Data API, or analyze raw event data in BigQuery. Here's how.
View Session Metrics in the Google Analytics 4 Reports UI
The fastest way to see session duration is through GA4's built-in reports.
Open the Engagement report and look for session insights
Log into your Google Analytics 4 property and go to Reports > Engagement. GA4 shows you Sessions and Average session duration by default. The Average session duration card displays the mean duration across all sessions for the selected date range.
Create a custom report to segment session duration by dimension
Click Create custom report in the Reports UI. Add Sessions as a metric, then add a dimension like Default channel grouping or Device category to see how session duration varies by source or device type. This breaks down which traffic sources keep users engaged longest.
// In GA4 UI: Reports > Engagement > Create custom report
// Configure:
// Dimensions: Default channel grouping, Country, Device category
// Metrics: Sessions, Engagement rate
// GA4 automatically calculates average session duration per dimension groupUse segments to filter sessions by duration
Click the Segments button and create a segment for users whose sessions lasted longer than a threshold (e.g., > 3 minutes). Apply this segment to your report to see which users are most engaged.
Query Session Metrics with the Google Analytics Data API
For programmatic access or automation, use the Data API to fetch session duration metrics.
Install the Google Analytics Data client library
Add the @google-analytics/data library to your project via npm. This library handles authentication and API requests to GA4's Data API.
Authenticate and call runReport
Create a service account in Google Cloud Console and use its JSON key to authenticate. Call the runReport method to query userEngagementDuration (measured in seconds) grouped by date or dimension.
const {BetaAnalyticsDataClient} = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient({
projectId: 'YOUR_GCP_PROJECT_ID',
});
async function visualizeSessionDuration() {
const request = {
property: `properties/YOUR_GA4_PROPERTY_ID`,
dateRanges: [
{
startDate: '2024-01-01',
endDate: '2024-01-31',
},
],
metrics: [
{ name: 'sessions' },
{ name: 'userEngagementDuration' },
],
dimensions: [
{ name: 'date' },
{ name: 'defaultChannelGroup' },
],
};
const response = await client.runReport(request);
response[0].rows.forEach((row) => {
const date = row.dimensionValues[0].value;
const channel = row.dimensionValues[1].value;
const sessions = row.metricValues[0].value;
const engagementSeconds = row.metricValues[1].value;
const avgDuration = (engagementSeconds / sessions).toFixed(2);
console.log(`${date} - ${channel}: ${sessions} sessions, ${avgDuration}s avg`);
});
}
visualizeSessionDuration();Calculate average session duration from the response
The API returns userEngagementDuration as a total, not an average. Divide by session count to get the average duration per session. This is the only way to get session duration from the Data API—there's no dedicated "session duration" metric like there was in Universal Analytics.
userEngagementDuration in seconds, not milliseconds. This is the total engaged time across all sessions in your query, so you must divide by session count to get the average. Bounced sessions (zero duration) are not included in this metric, so it tends to be higher than the average shown in Reports.Analyze Session-Level Duration in BigQuery
For deep analysis, export GA4 data to BigQuery and query the raw events table.
Enable BigQuery export in GA4 property settings
Go to Admin > Data collection and modification > Google Cloud Platform and link your BigQuery project. GA4 exports raw events to a dataset called analytics_{PROPERTY_ID}.
Query the events table to calculate session duration
Write a SQL query that groups events by session_id and calculates the time between the first and last event. Use the event_timestamp field (in microseconds) to compute duration.
SELECT
user_pseudo_id,
(SELECT value.int_value FROM UNNEST(event_params) WHERE key='ga_session_id') as session_id,
COUNT(*) as event_count,
TIMESTAMP_MICROS(MIN(event_timestamp)) as session_start,
TIMESTAMP_MICROS(MAX(event_timestamp)) as session_end,
ROUND((MAX(event_timestamp) - MIN(event_timestamp)) / 1000000, 2) as session_duration_seconds
FROM
`YOUR_PROJECT.analytics_YOUR_GA4_PROPERTY_ID.events_*`
WHERE
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
GROUP BY
user_pseudo_id,
session_id
ORDER BY
session_start DESC
LIMIT 1000;Aggregate by traffic source or user property to find patterns
Add GROUP BY on dimensions like traffic_source or device.category to see which segments have the longest sessions. Join the user_properties table if you need to segment by custom user attributes.
Common Pitfalls
- Confusing
userEngagementDuration(the Data API metric) with raw event timestamp differences. They calculate duration differently—the metric excludes bounced sessions, while raw events include them. - Forgetting that GA4 counts zero-duration sessions (immediate bounces) in Reports, which lowers your average. The Data API excludes them, so Data API averages always look higher.
- Using UTC timestamps from BigQuery without converting to the user's timezone. Sessions in GA4 are defined by user timezone, so raw event timestamps may not align visually with session boundaries in Reports.
- Querying only the most recent day in BigQuery (
events_20240101) instead of using wildcard tables (events_*). Single-day queries miss data—use_TABLE_SUFFIXfilters to scan the full date range.
Wrapping Up
Session duration in GA4 is accessible three ways: through the Reports UI for quick summaries, the Data API for automated reporting, and BigQuery for granular analysis. Pick the method that fits your workflow—Reports are fastest, the API is most flexible, and BigQuery is best for custom aggregations. If you want to track session behavior automatically across all your tools and connect it to product metrics, Product Analyst can help.