Skip to content

Instantly share code, notes, and snippets.

@adgad
Last active August 29, 2015 14:04
Show Gist options
  • Save adgad/7c0244f491618a7f6078 to your computer and use it in GitHub Desktop.
Save adgad/7c0244f491618a7f6078 to your computer and use it in GitHub Desktop.
Attention Minutes
(function () {
var totalAttentionTime = 0,
startAttentionTime,
endAttentionTime,
attentionTimeout,
constantAttentionInterval,
ATTENTION_INTERVAL = 5000,
ATTENTION_EVENTS = ['load', 'click', 'focus', 'scroll', 'mousemove', 'touchstart', 'touchend', 'touchcancel', 'touchleave'],
UNATTENTION_EVENTS = ['blur'],
eventToSend = ('onbeforeunload' in window) ? 'beforeunload' : 'unload',
hasSent = false,
i;
//Use Page Visibility API if it exists
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
if(hidden) {
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
//Add video events
if(FTVideo) {
var videoPlayers = document.getElementsByClassName('BrightcoveExperience');
for(var i=0; i<videoPlayers.length;i++) {
FTVideo.createPlayerAsync(videoPlayers[i].id, function(player) {
player.on(player.MEDIA_PLAY_EVENT, startConstantAttention);
player.on(player.MEDIA_STOP_EVENT, endConstantAttention);
});
}
}
function handleVisibilityChange(e) {
if(document[hidden]) {
endAttention(e);
} else {
startAttention(e);
}
}
//Add events for all the other Attention events
for(i=0;i<ATTENTION_EVENTS.length; i++) {
addEvent(ATTENTION_EVENTS[i], startAttention);
}
for(i=0;i<UNATTENTION_EVENTS.length; i++) {
addEvent(UNATTENTION_EVENTS[i], endAttention);
}
function startAttention(e) {
clearTimeout(attentionTimeout);
if(!startAttentionTime) {
startAttentionTime = (new Date()).getTime();
}
attentionTimeout = setTimeout(endAttention, ATTENTION_INTERVAL);
}
function startConstantAttention() {
constantAttentionInterval = setInterval(startAttention, ATTENTION_INTERVAL);
}
function endConstantAttention() {
endAttention();
clearInterval(constantAttentionInterval);
}
function endAttention() {
if(startAttentionTime) {
endAttentionTime = (new Date()).getTime();
totalAttentionTime += Math.round((endAttentionTime - startAttentionTime)/1000);
clearTimeout(attentionTimeout);
startAttentionTime = null;
}
}
function track(type, time) {
if ( FT && FT.analytics && FT.analytics.siteIntelligence) {
FT.analytics.siteIntelligence.addTrackParam("attention",time);
FT.analytics.siteIntelligence.sendTrackParams();
}
}
function addEvent(ev, func) {
if(typeof window.addEventListener === 'function') {
window.addEventListener(ev, func, false);
} else if(typeof window.attachEvent === 'function') {
window.attachEvent('on' + ev, func);
}
}
addEvent(eventToSend, function() {
endAttention();
track(eventToSend, totalAttentionTime);
});
}());
@commuterjoy
Copy link

/cc @adgad

Window unload doesn't seem to be a reliable way of sending the data.

The future is this, http://www.w3.org/TR/beacon/

So need to work out a good way of sending the data

I've seen systems poll an intermediary every n seconds then flush the data to the stats system when the polling stops. Complicated, but quite good.

Others I've seen write data to localStorage and flush it to the stats system on the next page view. Simple, but you lose a bit of data.

I think you can also add an event to every link on the page to delay it by a few 100 ms, to give the beacon a chance to send. Bad UX, but simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment