Slides from my SMX Munich 2018 talk.
How to measure engagement with the web analytics tools at our disposal?
How to turn reports more meaningful for our particular organizational idiosyncracies and goals?
How to become more critical about the data that is spoon-fed to us by the default installations of our favorite tools?
1. Search Marketing Tweaks
For Google Analytics and Google Tag Manager
SMX München - 20 March 2018
@SimoAhava from @ReaktorNow
2. Search Marketing Tweaks
For Google Analytics and Google Tag Manager
SMX München - 20 March 2018
@SimoAhava from @ReaktorNow
3. Simo Ahava
Senior Data Advocate, Reaktor
Google Developer Expert, Google Analytics
Blogger, developer, www.simoahava.com
Twitter-er, @SimoAhava
Google+:er, +SimoAhava
9. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
10. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
Page visibility Content visibility
11. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
Click Scroll Keypress Long press Drag Resize Highlight Copy
12. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
SERP bounce Idle time Active time Read time
13. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
Mailing list Favorite Print Comment Share
14. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
$
Followers More RPU Recruitment Better rankings
15. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
$
Buzz Feedback Session rec. Heatmaps Polls
16. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
$
17. The many dimensions of engagement
Visibility
Interaction
Dwell time
Short-term goals
Long-term goals
Qualitative
I love you
$
26. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
27. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
28. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
29. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
30. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
31. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
32. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
33. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
34. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
Except if you’ve implemented THAT incorrectly…
35. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
Except if you’ve implemented THAT incorrectly…
There’s also the sessionControl parameter…
36. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
Except if you’ve implemented THAT incorrectly…
There’s also the sessionControl parameter…
Lets not forget mobile and single-page apps!
37. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
Except if you’ve implemented THAT incorrectly…
There’s also the sessionControl parameter…
Lets not forget mobile and single-page apps!
Who knows what else happens server-side?
38. Google Analytics Session
Group of interactions that takes place on a website
That expires after 30 minutes of inactivity…
Or at the end of the day…
Or when acquisition campaign changes…
Unless the referral is in the Referral Exclusion List…
Or traffic is cross-domain, and cross-domain tracking is implemented…
Unless it’s implemented incorrectly…
Which is likely since it’s so !#/%(“% difficult…
Unless you’re using Google Tag Manager…
Except if you’ve implemented THAT incorrectly…
There’s also the sessionControl parameter…
Lets not forget mobile and single-page apps!
Who knows what else happens server-side?
Cookies, localStorage, persistent data stores!?
47. Google Tag Manager
Lets you create and deploy tracking
and measurement scripts with ease.
Facilitates interaction between various
departments within your organization.
48. Google Tag Manager
Lets you create and deploy tracking
and measurement scripts with ease.
Facilitates interaction between various
departments within your organization.
Allows you to focus your time on analysis
rather than implementation.
59. a:not([href*="mydomain.com"])
Clicks on links that do not redirect to a page on mydomain.com.
a[href$=".pdf"]
Clicks on links that end with ".pdf".
a[href^="mailto:"]
Clicks on links that start with "mailto:".
a[href*="#"]
Clicks on links that jump to page anchors.
10 Useful CSS Selectors: https://goo.gl/JXv7u6
60. #2: Track (relevant) other clicks
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH
64. WORKS BEST WHEN:
-- All content is included in the HTML file (no dynamic
content)
-- No single-page transitions
-- Content fills (most of) the page from top-to-bottom
See also https://goo.gl/9XrPtQ for tips on how to customize the trigger!
65. #4: Track element visibility
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH
https://goo.gl/NTkTqK
76. #6: Track article attributes as content groups
https://goo.gl/NTkTqK
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH
77. Custom JS Variable: {{JS - Blog Images}}
function() {
// Make sure the selector points to your content element
var content = document.querySelector('.entry-content');
var imgs = content.querySelectorAll('img').length - 1;
if (imgs>20) return '21+';
else if (imgs>15) return '16-20';
else if (imgs>10) return '11-15';
else if (imgs>7) return '8-10';
else if (imgs>5) return '6-7';
else if (imgs>3) return '4-5';
else if (imgs>1) return '2-3';
else if (imgs>0) return '1';
else return '0';
}
78. Custom JS Variable: {{JS - Blog Length}}
function() {
// Make sure the selector matches your content element
var content = document.querySelector('.entry-content');
var wCount = 0;
var cText = content.textContent || content.innerText;
cText = cText.replace(/(^s*)|(s*$)/gi,'');
cText = cText.replace(/[ ]{2,}/gi,' ');
cText = cText.replace(/n /,'n');
wCount = cText.split(' ').length;
if (wCount>3000) return '3k+';
else if (wCount>2500) return '2.5k-3k';
else if (wCount>2000) return '2k-2.5k';
else if (wCount>1500) return '1.5k-2k';
else if (wCount>1100) return '1.1k-1.5k';
else if (wCount>800) return '800-1.1k';
else if (wCount>500) return '500-800';
else if (wCount>200) return '200-500';
else return '<200';
}
79. Custom JS Variable: {{JS - Blog Title Length}}
function() {
var title = document.title;
var wCount;
title = title.replace(/(^s*)|(s*$)/gi,'');
title = title.replace(/[ ]{2,}/gi,' ');
wCount = title.split(' ').length;
if (wCount>20) return '21+';
else if (wCount>16) return '17-20';
else if (wCount>12) return '13-16';
else if (wCount>10) return '11-12';
else if (wCount>8) return '9-10';
else if (wCount>6) return '7-8';
else if (wCount>4) return '5-6';
else if (wCount>2) return '3-4';
else return '<3';
}
97. <script>
(function() {
var s = document.location.search;
var h = document.location.hash;
var e = {{Event}};
var n = {{New History Fragment}};
var o = {{Old History Fragment}};
// Only run if the History API is supported
if (window.history) {
// Create a new history state if the user lands from Google's SERP
if (e === 'gtm.js' &&
document.referrer.indexOf('www.google.') > -1 &&
s.indexOf('gclid') === -1 &&
s.indexOf('utm_') === -1 &&
h !== '#gref') {
window.oldFragment = false;
window.history.pushState(null,null,'#gref');
} else if (e === 'gtm.js') {
window.oldFragment = true;
}
// When the user tries to return to the SERP using browser back, fire the
// Google Analytics timing event, and after it's dispatched, manually
// navigate to the previous history entry, i.e. the SERP
if (e === 'gtm.historyChange' &&
n === '' &&
o === 'gref') {
var time = new Date().getTime() - {{DLV - gtm.start}};
if (!window.oldFragment) {
dataLayer.push({
'event' : 'returnToSerp',
'timeToSerp' : time,
'eventCallback' : function() {
window.history.go(-1);
}
});
} else {
window.history.go(-1);
}
}
}
})();
</script>
Custom HTML Tag
109. #8: Measure content interactive time
https://goo.gl/6HciRy
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH
110. Average engagement = Time when user is actively interacting with the page (keyboard and mouse)
111. Average engagement = Time when user is actively interacting with the page (keyboard and mouse)
= 8 x
= 6 x
= 5 x
= 5 x
= 6 x
= 6 x
= 5 x
= 3 x
= 6 x
= 6 x
112. <script>
(function() {
var startEngage = new Date().getTime();
var timeEngaged = 0;
var idleTime = 0;
var idle = true;
var idleReport = false;
var idleTimer, reportTimer;
/* Set the user as idle, and calculate the time
they were non-idle */
var setIdle = function() {
idleTime = new Date().getTime();
timeEngaged += idleTime - startEngage;
idle = true;
};
/* Reset the 5 second idle timer.
If the user was idle, start the non-idle timer */
var pulse = function(evt) {
if (idle) {
idle = false;
startEngage = new Date().getTime();
idleReport = false;
}
window.clearTimeout(idleTimer);
idleTimer = window.setTimeout(setIdle, 5000);
};
// Utility function for attaching listeners to the window
var addListener = function(evt, cb) {
if (window.addEventListener) {
window.addEventListener(evt, cb);
} else if (window.attachEvent) {
window.attachEvent('on' + evt, cb);
}
};
/* Push an event to dataLayer every 15 seconds
unless the user is idle.
Also, push an event when the user leaves the page */
var report = function(evt) {
if (!idle) {
timeEngaged += new Date().getTime() - startEngage;
}
// Push the payload to dataLayer, and only push valid time values
if (!idleReport && timeEngaged > 0 && timeEngaged < 3600000) {
window.dataLayer.push({
'event' : 'nonIdle',
'nonIdleTimeElapsed' : timeEngaged
});
}
if (idle) {
idleReport = true;
}
// Fix possible beforeunload duplication problem
if (evt && evt.type === 'beforeunload') {
window.removeEventListener('beforeunload', report);
}
timeEngaged = 0;
startEngage = new Date().getTime();
reportTimer = window.setTimeout(report, 15000);
};
addListener('mousedown', pulse);
addListener('keydown', pulse);
addListener('scroll', pulse);
addListener('mousemove', pulse);
addListener('beforeunload', report);
idleTimer = window.setTimeout(setIdle, 5000);
reportTimer = window.setTimeout(report, 15000);
})();
</script>
Custom HTML Tag
121. Average engagement = Time when user is actively interacting with the page (keyboard and mouse)
122. Average engagement = Time when user is actively interacting with the page (keyboard and mouse)
= 8 x
= 6 x
= 5 x
= 5 x
= 6 x
= 6 x
= 5 x
= 3 x
= 6 x
= 6 x
123. #9: Track content as Ecommerce
https://goo.gl/EiuayM
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH
124. #9: Track content as Ecommerce
https://goo.gl/EiuayM
Complexity
Metric impact
LOW
MEDIUM
HIGH
LOW
MEDIUM
HIGH