GA4 Sessions Explained - BigQuery & Basics

Lets dive into the humble session. We’re going to cover:

  • Basics & Interface
    • What is a session?
    • How can we make sessions more useful?
    • What are engaged sessions & how can we customise them?
  • How do sessions work in BigQuery?
    • How does it work?
    • Why don’t BigQuery sessions match GA4 UI sessions?
    • Example GA4 BQ Queries

Our goal here is to give you a solid understanding of how sessions work on GA4.

Once you've got that, we'll show you how to start using it in BigQuery.

Let’s dive in.

What is a session on GA4?

When someone visits a site, the actions they take during that visit are grouped into a “session”.

This session includes everything they do, such as viewing different pages, making a purchase or clicking on specific links.

A single session could be landing on a blog page, scrolling down for a few seconds, moving on and never returning.

simple session

Another single session could be visiting numerous pages, adding a million items into their cart and then spending £4000 on Oasis tickets.

advanced session

How does GA4 decide where a session starts and ends?

A session starts when you visit a website and then lasts (by default) for up to 30 minutes.

If you visit after 30 minutes it’s a new session.

So if we visit a 3 times, here’s how it breaks into sessions:

  • 00:00 - Visit a page - Session 1
  • 10:00 - Visit a page - Session 1
  • 40:01 - Visit a page - Session 2

Our 3rd session is after 30 minutes (by one second) so it’s a new session.

Technically speaking, the session would start when either:

  • A user opens your app in the foreground
  • A user views a page or screen

And the session timeout period can be adjusted in GA4.

All session aren’t equal

However eventful or uneventful your visit is to the site, it will still only count as a single session.

You may be thinking “Wait, so how do we tell which sessions are actually valuable for us?”

That’s where engaged sessions come in.

What are engaged sessions?

An engaged session is a default metric provided by GA4 to let you to measure the “higher quality” sessions.

Any session which does any one of these 3 things is considered “engaged”:

  1. The session lasts for more than 10 seconds.
  2. The session features a conversion event.
  3. Includes at least two pageviews (or two screenviews on an app).

engaged session

Why do we care about engaged sessions? Engaged sessions are a quick way to tell if a session was valuable.

In Universal Analytics people would often use non-bounce sessions in the same way.

Our goal here is to measure a funnel. Not many people convert. Lots of people visit.

Having steps in the middle like engaged sessions, help us find out what is doing well without needing to get full conversions.

What happened to bounce rate?

Bounce Rate is a metric from Universal Analytics that shows the percentage of sessions where a user leaves the site without a single event firing.

People used this to measure sessions where you visited one page.

But it had problems:

  • Bounces weren’t always bad: The problem was sometimes a bounce is a good experience. If I visit a tutorial, spend 10 minutes reading it and making notes and leave. That’s a bounce.
  • If you added other metrics bounce rate could change wildly: Remember our definition was “sessions where there was only 1 event” that means if you fired anything else e.g. scroll rate, any scrolling would immediately remove the bounce. This meant it was easy to break and a lot of people made metrics like “adjusted bounce rate”.

The goal with engaged sessions is to make something more accurate and less robust to breaking.

We made bounce rate anyway

For historical consistency we’ve added bounce rate to our Pipeline product. (Specifically the single page version).

But once you’ve gotten the basics down we’d recommend moving onto engaged sessions and customising it!

How can we customise engaged sessions?

Each business and website is different. A valuable session for a new user, might look different to a returning one.

If someone is top of the funnel and looking for content, a valuable visit from them probably isn’t the same as someone looking to buy then and there.

A valuable content visit might be:

  • Signing to the newsletter
  • Watching a video
  • Revisiting the same content over the last 7 days

A valuable visit to a product page might be:

  • Engaged with reviews
  • Using the FAQ accordion
  • Looking at the different colour options, for example.

In order to make this kind of custom metric, you’ll need to use the raw GA4 BigQuery export. We've got a blog post coming on how to do this, but it's a little long for this one!

If you’re interested in how we support this with Pipeline please take a look at our documentation where we’ll show you how to create custom measures of engagement.

How do you calculate sessions in BigQuery?

To get the most out of GA4 you’re going to want to set-up the BigQuery export.

But it’s quite complex so let’s talk about how to use it.

In the GA4 export every single row of data is an event - whether it be a page_view, purchase, or view_item_list.

So how do sessions work? There are two ways we can identify sessions in BigQuery.

The session_start event

The first is the session_start event itself which signifies the start of the session. GA4 automatically fires this at the start of a session.

session start

We can session_starts to get the number of sessions.

And we can look at the information that event gets sent with to pull out other dimensions like:

  • page_location - Sessions Landing Page
  • page_title - Sessions Landing Page Title

The ga_session _id

The second thing which shows a session is the ga_session_id .

This is the number GA4 automatically assigns to a session and is fired with all events in the session.

The example below shows a view_item event with the ga_session_id.

ga_session_id example event

This can technically repeat across different users so to truly identify a session we need to combine it with user_pseudo_id.

We could concatenate user_pseudo_id and ga_session_id and then count the unique values.

We’d suggest using the second

Typically we’d recommend this as sometimes (very occasionally) we’ve found session_start has been missing.

Sidenote: If you consent mode is on and user does not accept the tracking then ga_session_id and user_pseudo_id will not be returned. So if you're seeing a lot of missing data it's typicall this.

Aligning on traffic source

This is the other largest challenge that you run into with sessions, which is getting traffic source correct.

This is long enough that we made our own article.

Example Queries for GA4 BigQuery

If you’re just looking for copy paste queries you can use those below.

If you’d like direct access to this data without having to handle all the complex SQL we’ve got a product coming soon and please get on our email list if you’re interested!

Customise the queries.

Set-up variables to customise our BigQuery queries for your setup.

Calculating Sessions

This query pulls the number of sessions in the selected time period.

WITH unnest_data AS (
    SELECT
        user_pseudo_id,
        (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id
    FROM
    -- This table will need to be updated
        `@project.analytics_@analytics_property_id.@event_type*`
    WHERE
    -- The date range being selected will need to be updated
        _table_suffix BETWEEN '@start_date' AND '@end_date'
)

-- Count distinct user-session combinations
SELECT
    COUNT(DISTINCT CONCAT(user_pseudo_id, session_id)) AS sessions
FROM
    unnest_data;

Calculating Engaged Sessions

This query generates the number of sessions throughout a defined time period.

WITH unnest_data AS (
    SELECT
        user_pseudo_id,
        (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'session_engaged') AS session_engaged,
        (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id
    FROM
    -- This table will need to be updated
        `@project.analytics_@analytics_property_id.@event_type*`
    WHERE
    -- The date range being selected will need to be updated
         _table_suffix BETWEEN '@start_date' AND '@end_date'
)

-- Count distinct engaged user-session combinations
SELECT
    COUNT(DISTINCT CASE WHEN session_engaged = '1' THEN CONCAT(user_pseudo_id, session_id) END) AS engaged_sessions
FROM
    unnest_data;

How do I see Sessions on the GA4 interface?

If you navigate to Acquisition > Traffic Acquisition you can see the Sessions and Engaged Sessions broken down by Primary Channel Group.

Where are sessions in the GA4 interface

Dom Woodman Headshot
By Dominic Woodman -- I'm the founder of Piped Out and have never loved 3rd person bio's.