Engagement Timer Recipe for GTM
Adds engagement time tracking to every page on your site and sends events to Google Analytics.
By default, this tracks events every 15 seconds up to a maximum of 30 minutes, and pauses when the page is not the active tab in the browser or when the user hasn’t moved the mouse or pressed a key in the page in the last 65 seconds. (These values are configurable via variables.)
Instructions
1. Download Container File
Download the container JSON file.
(You may need to right-click on the link and choose “Save Link As” or “Save Target As” to save the JSON file to your computer.)
2. Import JSON File into GTM
Log into your own Google Tag Manager container and head to the Admin section of the site. Under Container options, select Import Container. Check out this blog post for more details about importing a container file.
3. Update With Your Own Tracking ID
Update or create a new Constant Variable named {{YOUR_GA_TRACKING_ID}} with your Google Analytics Tracking ID (a.k.a. UA Number).
4. Preview & Publish
Use the Preview options to test this container on your own site. Try testing each of the events to make sure they’re working properly. If everything looks good, go ahead and publish!
Optional - Update Timer Interval and Limits
You can customize how often events fire by editing the variables:
Engagement Timer Interval Milliseconds
- How often do we send events to Google?
- (Default – 15000 milliseconds, or 15 seconds)
Engagement Timer Idle Milliseconds
- How many seconds of inactivity until we pause?
- (Default – 65000 milliseconds, or 65 seconds)
Engagement Timer Limit Seconds
- What is the max amount of seconds we continue to send events?
- (Default – 1800 seconds, or 30 minutes)
Documentation
Time-on-page Engagement Timer Library & Google Tag Manager Plugin
Plug-and-play dependency-free engagement timer for observing user time on page engagement on the web. Supports everything north of IE9. Intervals can be set for every n
seconds or at specific time milestones.
The timer can be set to go idle if the user stops triggering events in the targeted context. Any event that can be passed to context#addEventListener
can be used. By default, the timer will not go idle.
Installation
Include the library in your code, then construct an EngagementTimer
. Register a handler for emitted interval
events by calling the EngagementTimer#on()
method.
Include the library in your code, then construct an ScrollTracker
. NOTE: It’s up to you to ensure the DOM is ready before constructing your tracker. Register handlers for pixels, percentages, or elements by calling .on()
and passing in a configuration object:
Tracking w/ SPAs
To track scrolling with single-page applications (e.g. Angular apps), call EngagementTimer#reset()
when a new “page” is rendered. This will reset the internal cache of marks that have been tracked and the time tracked so far. For example, using Angular 1.X.X & ngRoute:
// In your Config somewhere
$rootScope.$on('$routeChangeSuccess', function() {
$engagementTimer.reset();
});
Google Analytics
To track page engagement with Google Analytics, replace YOUR_GA_PROPERTY_ID with your UA number and adjust the opts
variable to track what you’d like. Below is an example using all available configurations.
<!-- Default Google Analytics snippet somewhere up here -->
<!-- yadda yadda yadda -->
<script>
(function(document, window) {
var opts = {
each: [5 * 60, 7 * 60], // Track when we reach 5 minutes and 7 minutes
every: [5], // Track every 5 seconds
startTime: new Date(), // With the engagement time starting now
idleAfter: 5, // Go idle after 5 seconds unless
engagementEvents: [ // one of these events fire in the context
'click',
'mousedown',
'touchstart',
'keydown',
'scroll'
],
context: '#content', // Set the context to be an element w/ id content
idleOnVisibilityChange: true, // Go idle when the user switches tabs
max: 60 * 15, // Stop tracking after 15 minutes
min: 10 // Wait a minimum of 10 seconds before starting to track the time
};
var trackerId = YOUR_GA_PROPERTY_ID; // e.g. UA-000000-00
getTracker(trackerId, registerEngagementTimer);
function registerEngagementTimer(tracker) {
var timer = window.EngagementTimer(opts);
timer.on('interval', function(evt) {
tracker.send('event', {
eventCategory: 'Engagement Timing',
eventAction: evt.data.time,
eventLabel: document.location.pathname,
nonInteraction: true
});
});
}
function getTracker(trackerId, cb, ran) {
var ga = window[window.GoogleAnalyticsObject] ;
ga(function() {
var trackers = ga.getAll();
var len = trackers.length;
var tracker;
var i;
for (i = 0; i < len; i++) {
tracker = trackers[i];
if (tracker.get('trackingId') === trackerId) return cb(tracker);
}
if (!ran) {
setTimeout(function() {
getTracker(trackerId, cb, true);
}, 0);
}
});
}
})(document, window);
</script>
Google Tag Manager Plugin
Note: Google Tag Manager offers timers natively. Consider these first. If you need to monitor when a user is idle, use this library instead.
- Download the file ‘luna-engagement-timer.json‘ from the Github repository.
- In Google Tag Manager, navigate to the Admin tab.
- Under the Container column, select Import Container.
- Click Choose Container File and select the ‘luna-engagement-timer.json’ file you downloaded.
- Select Merge from the radio selector beneath the Choose Container File button.
- Select Rename from the radio selector that appears beneath the Merge selector.
- Click Continue, then Confirm.
- Navigate to the Tags interface – select the tag imported tag named GA Event – Scroll Tracking.
- Change the {{YOUR_GA_TRACKING_ID}} in the Tracking ID field to your Google Analytics Tracking ID (a.k.a. UA Number).
Once you publish your next container, engagement tracking will begin working immediately.
Technical Documentation
EngagementTimer(opts)
Constructs an EngagementTimer instance.
opts.each {number[]}
Track each time in seconds once. Either opts.each
or opts.every
must be set.
var contentTimer = EngagementTimer({
each: [10, 25] // Emits interval at 10 and 25 seconds.
});
opts.every {number[]}
Track every n seconds. Either opts.each
or opts.every
must be set.
var contentTimer = EngagementTimer({
every: [10] // Emits interval every 10 seconds
});
[opts.context]
HTMLElement to treat as timing context. Defaults to document
. Can be a CSS selector or HTMLElement
.
var contentTimer = EngagementTimer({
context: document.getElementById('content'),
every: [10]
});
[opts.idleAfter] {number}
Number of seconds to wait before pausing engagement timer counter and entering ‘idle’ mode. A pause
event will be emitted when the timer goes idle. Requires opts.engagementEvents
to also be set. The idle countdown will reset whenever one of opts.engagementEvents
is emitted by the context
.
var contentTimer = EngagementTimer({
every: [10],
idleAfter: 5,
engagementEvents: [
'click',
'mousedown',
'touchstart',
'keydown',
'scroll'
]
});
[opts.engagementEvents] {string[]}
Events that will prevent the timer from entering ‘idle’ mode if emitted by the context. A pause
event will be emitted when the timer goes idle. Requires opts.engagementEvents
to also be set. The number of seconds that can pass between each of these events is controlled by the opts.idleAfter
setting.
var contentTimer = EngagementTimer({
every: [10],
idleAfter: 5,
engagementEvents: [
'click',
'mousedown',
'touchstart',
'keydown',
'scroll'
]
});
[opts.startTime] {number} – UNIX timestamp
UNIX timestamp used to calculate the initial amount of time that has passed (defaults to when the script loads).
var contentTimer = EngagementTimer({
every: [10],
startTime: +new Date
});
[opts.idleOnVisibilityChange] {boolean}
Idles the tracker when the user switches their browser tab. Defaults to false.
var contentTimer = EngagementTimer({
every: [10],
idleOnVisibilityChange: true
});
[opts.max] {number}
A maximum number of seconds to emit intervals for. Once the max has been passed, EngagementTimer#destroy
is automatically called.
var contentTimer = EngagementTimer({
every: [10],
max: 10 * 60 // Stops tracking after 10 minutes
});
[opts.min] {number}
A minimum number of seconds to record before emitting interval
events.
var contentTimer = EngagementTimer({
every: [10],
min: 10 // Waits 10 seconds before starting to track
});
EngagementTimer#on(event, handler)
Registers a handler for a given event.
contentTimer.on('interval', function(evt) {
notifySomeService(evt.data.time);
});
EngagementTimer#reset()
Resets the time tracked and start time. Emits an reset
event.
contentTimer.reset();
EngagementTimer#start()
Starts the counter. Emits a start
event.
contentTimer.start();
EngagementTimer#pause()
Stops the counter. Emits a pause
event.
contentTimer.pause();
EngagementTimer#emit(name, data)
Emits an event and calls all handlers registered to the event. It is unlikely to be necessary to trigger an event manually.
contentTimer.emit('interval', {
time: 10000
});
EngagementTimer#destroy()
Destroys an EngagementTimer (unhooks the internal timers). The object will remain until garbage collected.