Measure Users' Time Since Last Session in Google Analytics
The concept of sessions in Google Analytics is a strange one. Part of that strangeness is that a session times out on its own after exactly 30 minutes of inactivity. By default that is. Or that it expires at midnight. Or when the campaign source changes - even mid visit (which is why you should never use UTM tags on internal links).
Often times, the expiration of sessions isn’t that big of a deal. The time between returning visitors' sessions is often days, weeks or even months.
But recently, I worked with a website operated by a BtB wholesaler. Their core business is to offer, sell and ship spare parts for a wide range of electronic products. Their customers are extremely frequent visitors with multiple sessions per day. So we needed to understand their visit pattern on individual days - not over weeks or months.
The problem is that Google Analytics doesn’t measure this very well. The Days Since Last Session is insufficient in this case. And it quickly becomes too complicated to use the Date, Hour and Minute dimensions to do the calculations. Specially if we want to build segments for users with based on the time between sessions (not sure if it’s even possible!).
The end goal
At this point, I can safely say that I found a solution. And this is the type of report I ended up with:
Now, the screenshot is filtered to show data for just a single Client ID with two entries. Note that the value for Time Since Last Session for the first session is 00:00:00. This means that this was indeed the first session (ever!) from this Client ID.
The second row then shows the elapsed time between the last (interactive) hit in the first session up until the first (interactive) hit in the second session.
For single page visits without any other interactive hits, the elapsed time should correspond nicely with what Google Analytics has recorded. In this case, the first session occurred at 18:22 on May 2nd and the second session occured the next day at 10:47. The time between those two timestamps is 16 hours and 25 minutes.
But the Time Since Last Session has recorded 16 hours and 22 minutes. Almost the same. As mentioned, the difference is that this custom dimension measures the time between the last (interactive) hit in the first session and the first (interactive) hit in the second session.
Another difference is that Google Analytics doesn’t record the elapsed time by itself. Yes, you can calculate it manually, but having it as a custom dimension allows for all kinds of possibilites. Like segments and audiences, detailed insights into returning visits and more.
Take a look at this report where I have setup a calculated metric for the Average Time between Sessions:
From there, it should be easy enough to imagine how to setup segments or audiences that could target users with a certain average amount of time between sessions. Or just use it as a part of other segments.
How to measure exact time between sessions
The solution is actually rather simple since it just involves a set of timestamps and a simple calculation. There are a few things (apart from a working Google Tag Manager) you need in place for this to work:
- Custom Dimension with the Client ID
- Custom Dimension with a Session ID
Both are setup easily if you follow Simo Ahava’s guide for setting up useful custom dimensions. In fact, I’ve written up the solution as a custom task and I have shamefully copied the syntax used by Simo Ahava in his Custom Task Builder.
It’s not because I’m lazy (I am, which is why I automise almost everything), but because it just makes it easier to implement the solution if you already have a custom task variable built with his (awesome) tool. And I would guess a lot of people have that.
How to set it up
For the purpose of this post, I’m assuming you don’t have a custom task variable already. If you do, it should be rather straightforward to modify the script and add it to your existing variable.
Anyhow, follow these steps in Google Analytics:
- Add a
Custom Metric
of the typeTime
and name itTime Since Last Session
- Add a
Calculated Metric
of the typeTime
and name itAvg. Time between Sessions
- Enter the formula for the calculated metric:
{{Time Since Last Session}} / {{Sessions}}
Then open up Google Tag Manager:
- Add a
Variable
of the typeCustom JavaScript
and name itCustom Tasks
- Copy and paste the code below into the variable
- Make sure to edit the value of the
timeSinceLastSessionIndex
variable so it uses the same metric index as you added previously - Also, if you have changed your default session timeout setting from 30 minutes to something else, you must edit the value of the
sessionTimeout
variable; just change30
to whatever number of minutes you’ve used as a custom session timeout - Open your Google Analytics settings variable (or your main pageview tag) and add the field
customTask
and set its value to{{Custom Tasks}}
And that’s it! And here’s the code:
function() { var timeSinceLastSessionIndex = 5; var globalSendHitTaskName = '_ga_originalSendHitTask'; return function (customTaskModel) { window[globalSendHitTaskName] = window[globalSendHitTaskName] || customTaskModel.get('sendHitTask'); var tempFieldObject, dimensionIndex, count, ga, tracker, decorateTimer, decorateIframe, iframe; // timeSinceLastSessionIndex var ni = (customTaskModel.get('nonInteraction') === true) ? true : false; if (typeof timeSinceLastSessionIndex === 'number' && ni === false) { var sessionTimeout = 30; // minutes sessionTimeout = sessionTimeout * 60 * 1000; // milliseconds var lastSession = window.localStorage.getItem("lastSession"); var dateNow = new Date(); var timeNow = dateNow.getTime(); // milliseconds var elapsed = (lastSession == undefined) ? 0 : (timeNow - lastSession); // milliseconds var time = undefined; window.localStorage.setItem('lastSession', timeNow); if (elapsed > sessionTimeout) { time = elapsed / 1000; // seconds } customTaskModel.set('metric' + timeSinceLastSessionIndex, time); } // /timeSinceLastSessionIndex customTaskModel.set('sendHitTask', function (sendHitTaskModel) { var originalSendHitTaskModel = sendHitTaskModel, originalSendHitTask = window[globalSendHitTaskName]; var hitPayload, hitPayloadParts, param, val, regexI, trackingId, snowplowVendor, snowplowVersion, snowplowPath, request, originalTrackingId, hitType, nonInteraction, d; try { originalSendHitTask(sendHitTaskModel); } catch (e) { originalSendHitTask(originalSendHitTaskModel); } }); }; }
How it works
First of all, the script starts by determining if the current hit is interactive or non-interactive. The script only proceeds if the hit is in fact interactive.
From there, it starts by looking for the last timestamp - if there is any. There won’t be for new users/sessions. The time difference between that timestamp and now is then calculated. And if that difference exceeds the session timeout setting, the difference is then sent with the hit.
Meanwhile, the script also makes sure to update the last timestamp.
Drawbacks
As mentioned, sessions in Google Analytics are strange. And this solution suffers from that. For instance, it’s not possible to detect if a new session is started because of a change in acquisition source (thanks to @AnalyticsNinja) for pointing it out.
On the other hand, while Google Analytics may start a new session when an acquisition source changes mid session, from a user perspective, that’s may not really a new session. The same argument also kind of applies to the situation where a user starts a session in the morning, leave the browser tab alone, a continues browsing in the afternoon. Is that really a new session?
I’d appreciate any comments or tweets with your thoughts.