Track session duration conversions in GA4

Google’s Universal Analytics had a built-in session duration goal conversion type, and it was very useful for sites that value user engagement. GA4 does not have similar functionality, but there are several ways to accomplish something similar. In this post, we describe both approaches.

The first we’ll cover entails setting up an audience based on a session duration target, and then creating an audience trigger to send an event to GA4 each time a user is added to the audience. This approach is the easier of the two, but audience-triggered events have a significant downside: they result in sessions being added to a (not set) row in the Landing page report. 

That downside is why we recommend the second approach, which uses a custom JavaScript tag in Google Tag Manager to set a cookie to keep track of how long a user has been on the site. This approach is more flexible and doesn’t result in Landing page = (not set), but it is a bit more effort to set up.

Approach 1: using an audience-triggered event

Step 1 - create the audience

Create an audience with the criteria:

  • Include users when Session duration is greater than or equal to your desired threshold. The metric is measured in seconds.
  • It’s fine to leave condition scoping as ‘Across all sessions’, which is the default. The session duration metric is session-scoped, so it won’t actually track duration across sessions.
  • It’s fine to leave the membership duration at the default 30 days, since we are just creating the audience to make use of the audience trigger. 
  • Click ‘Create new’ below AUDIENCE TRIGGER to add the trigger. You can name your event whatever you’d like, but for consistency it’s good to follow GA4’s convention of lowercase letters and underscores instead of spaces. The ‘Log an additional event when audience membership refreshes’ setting is a bit tricky. We want to be able to count the event if a user exceeds the threshold in two different visits, but we don’t really want it to count more than once in a single session. If you select this option, you will overcount the event, because inevitably some users will more than double your threshold in a single session. If you don’t select it, it will undercount, since some users will exceed the threshold across multiple sessions. If both of these possibilities are problematic for you, I recommend using the GTM/JavaScript approach described below.
Audience dialog - Session duration >= 180 seconds

Step 2 - flag the event as a conversion

The event won’t show up in Admin > Events right away. In my experience, it generally won’t show up until the next day. Once it does, you can flip the toggle to the right of the event to count it as a conversion. 


Event conversion toggle

You can also go to Admin > Conversions and click ‘New conversion event’ and enter the conversion name. This works even if the event hasn’t shown up on the Events tab yet.

Approach 2: GTM & custom JS

Step 1: create the custom HTML tag in Google Tag Manager

Below is the code that goes in the tag. The only thing you may need to change is the value of the sessionDurationThreshold variable. The current value of 120 means that the conversion event will fire if a user is on the site for 120 seconds. A few more things to know about the code:
  • It keeps track of session length by setting a 1st-party cookie
  • The cookie has a duration of 30 minutes – so if the event hasn’t fired after 30 minutes from the start of a session, it will reset the start time.
  • Once the event has fired, the script sets a cookie to indicate that the threshold has been met. This prevents the script from sending multiple events for a given user.
  set the threshold for the session_duration_conv event here (in seconds)
  if a session passes this threshold, a session_duration_conv event will
  be pushed to the datalayer
var sessionDurationThreshold = 120;

function gtm_getCookie(name) {
  var cookies = decodeURIComponent(document.cookie);
  var cookiesArray = cookies.split(';');
  var cookie = cookiesArray.find(function (item) {
    return name == item.trim().substring(0, name.length);
  return cookie;

(function() {
  var startCookie = gtm_getCookie("gtm_session_start");
  var thresholdCookie = gtm_getCookie("gtm_session_threshold");
  var d1 =  new Date();
  // The getTime() method returns the number of milliseconds from 
  //midnight of January 1, 1970 to the specified date
  var now = d1.getTime();
  // convert the threshold to milliseconds
  var durationThreshold = sessionDurationThreshold*1000-1;
  var cookieExpiry = new Date();
  // Set expiry time of 30 mins (in milliseconds)
  cookieExpiry.setTime(cookieExpiry.getTime() + 30 * 60 * 1000);
  var expires = "expires=" + cookieExpiry.toUTCString();
  // if no session start cookie exists, create it and be done
  if (!startCookie) {
   document.cookie = "gtm_session_start" + "=" + now + ";" + expires + ";path=/";
  } else if (!thresholdCookie){
   // get the start time - the slice removes the name of the cookie
   var startTime = startCookie.trim().slice(18);
   var elapsedTime = now - startTime;
   if (elapsedTime > durationThreshold) {
    window.dataLayer = window.dataLayer || [];
    dataLayer.push({ 'event': 'session_duration_conv' });
    // once the event has been sent, set a threshold cookie so we
    // don't send it again
    document.cookie = "gtm_session_threshold=true;" + expires + ";path=/";

 Special thanks to Jude Onyejekwe’s detailed post on pages per session conversions on, which was the inspiration for this approach.

Below is the configuration of the tag in Tag Manager. In addition to the All Pages trigger, I added History Change and Scroll Depth triggers. The website I was setting it up for uses history changes rather than full page reloads, hence the History Change trigger. I also added a scroll depth trigger, since a user might spend a while reading a single page, then leave. My scroll depth trigger fires on 25%, 50%, 75% and 100% vertical scrolls. A video commenter also suggested adding a Timer trigger, which is a good way to ensure that the tag always keeps track of how long is on the site. I’m fairly judicious about using Timer triggers, since they add a little bit of overhead to a page, but depending on your circumstance you may want to add that too.

screenshot cHTML tag

Step 2: add the Custom Event trigger to fire on the session_duration_conv dataLayer event

It should look like this.

Screenshot of GTM UI for adding a custom event

Step 3: create the GA4 Event tag in Tag Manager

I kept things simple and just used the same event name all the way through. Fire the tag on the trigger you just created.
gtm session duration conv event

That’s it for Tag Manager and you’re nearly done! I always recommend testing changes in Tag Assistant before publishing. When you do, you should see the Custom HTML tag firing on page views and whatever other triggers you added. Then, after your duration threshold is met, you should see the GA4 event tag fire.

Step 4: flag the event as a conversion in GA4

In GA4, go to Admin > Events and mark the event you created as a conversion. You may have to wait until the next day for it to show up.
flagging session duration conv

If you’d like help with this or any other analytics projects or tasks, reach out! We also do training.

Notify of

1 Comment
Newest Most Voted
Inline Feedbacks
View all comments
Gonçalo Albuquerque
Gonçalo Albuquerque
16 days ago

Nice solution! Thank you for sharing this 🙂

Share This Post

Share This Post

Bot Traffic in GA4

Dealing with bot traffic in GA4 can require some advanced techniques (and persistence!). Learn the process from analytics expert Nico Brooks.

➔ Read more

master GA4

with personalized training

A training program like no other. Work with expert marketers for 1:1 training to maximize learning & impact.

have you registered?

Our next free digital marketing seminar is coming soon!

[MEC id="946"]