@aller/blink
Version:
A library for tracking user behaviour.
149 lines • 5.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateEventTime = exports.discardUnrealisticallyHighInscreen = exports.hasFinalStopTime = void 0;
/**
* Checks if there is a stop time present.
*/
function hasFinalStopTime(times) {
var lastTime = times[times.length - 1];
return !times.length || (lastTime && lastTime.type === 'stop');
}
exports.hasFinalStopTime = hasFinalStopTime;
/**
* Skips duplicate start and end times. Could occur if
* the machine has a hick-up when updating the inscreen time.
*
* [ { start 1 }, { start 2 }, { end 1 } ]
* Would be converted to:
* [ { start 1 }, { end 1 } ]
*/
function mergeDuplicateTimesTogether(times) {
return times.filter(function (_a, index) {
var type = _a.type;
var prevTime = times[index - 1];
var prevTimeIsADuplicate = prevTime && type === prevTime.type;
return !prevTimeIsADuplicate;
});
}
function integrateScreenEvents(times, screenEvents) {
var allTimes = times
.concat(screenEvents)
.sort(function (a, b) { return a.time.getTime() - b.time.getTime(); });
return allTimes.filter(function (current, index) {
var prev = allTimes[index - 1];
var prevType = prev ? prev.type : 'none';
// Remove stop after hide
if (prevType === 'hide' && current.type === 'stop') {
return false;
}
// Remove show after start
if (prevType === 'start' && current.type === 'show') {
return false;
}
// Only accept start event as event after stop
if (prevType === 'stop' &&
(current.type === 'hide' || current.type === 'show')) {
return false;
}
return true;
});
}
function convertScreenToTimeEvents(times) {
return times.map(function (timeEv) {
if (timeEv.type === 'show') {
var event_1 = {
time: timeEv.time,
type: 'start',
};
return event_1;
}
if (timeEv.type === 'hide') {
var event_2 = {
time: timeEv.time,
type: 'stop',
};
return event_2;
}
return timeEv;
});
}
/**
* Removs a stop time if there is one at the beginning.
* This can happen in some in-view libraries when the page
* loads elements outside of the screen
*
* [ {stop 1 }, { start 2 }, { stop 3 } ]
* Would be converted to:
* [ { start 2 }, { stop 3 } ]
*/
function removeStopTimeAtBeginningIfPresent(times) {
if (times.length > 0 && times[0].type === 'stop') {
return times.slice(1);
}
return times;
}
/**
* Appends a stop time if there is no end to the tracking.
* This can happen if a user closes her browser while an
* impression is inscreen.
*
* [ { start 1 } ]
* Would be converted to:
* [ { start 1 }, { end 1 } ]
*/
function appendStopTimeIfNotPresent(times, now, maxIdleTime) {
if (now === void 0) { now = new Date(); }
if (!(now instanceof Date)) {
throw Error('Now must be of the Date type. Are you mapping?');
}
if (hasFinalStopTime(times)) {
return times;
}
var lastTimeEvent = times[times.length - 1];
var maxTime = lastTimeEvent
? new Date(lastTimeEvent.time.getTime() + maxIdleTime)
: now;
// Add a stop event with whichever is smaller: the maxTime or current time
return times.concat([{ type: 'stop', time: maxTime < now ? maxTime : now }]);
}
/**
* Sets any values that are unrealistically high to zero.
*/
function discardUnrealisticallyHighInscreen(inscreenTime) {
var twoHours = 2 * 60 * 60 * 1000;
return inscreenTime < twoHours ? inscreenTime : 0;
}
exports.discardUnrealisticallyHighInscreen = discardUnrealisticallyHighInscreen;
/**
* Adds together all the intervals that were recorded
* while an impression was inscreen.
*/
function sumStartAndStopTimes(times) {
return times.reduce(function (total, _a) {
var type = _a.type, time = _a.time;
if (type === 'start') {
return total - time.getTime();
}
return total + time.getTime();
}, 0);
}
/**
* Calculates the total inscreen time in milliseconds from
* a list of start and end times.
*/
function calculateEventTime(input) {
if (!input.times || input.times.length === 0) {
return 0;
}
var times = integrateScreenEvents(input.times, input.screenEvents || []);
times = convertScreenToTimeEvents(times);
times = appendStopTimeIfNotPresent(times, input.now || new Date(), input.maxIdleTime || 10000);
times = mergeDuplicateTimesTogether(times);
var cleanedInterval = removeStopTimeAtBeginningIfPresent(times);
var summedInterval = sumStartAndStopTimes(cleanedInterval);
var positiveInterval = Math.max(0, summedInterval);
var realisticInterval = discardUnrealisticallyHighInscreen(positiveInterval);
return realisticInterval;
}
exports.calculateEventTime = calculateEventTime;
//# sourceMappingURL=event-time.js.map