Last active
November 13, 2016 18:20
-
-
Save gleb-lobastov/9d19c6e006179629daa30c37a80c46bb to your computer and use it in GitHub Desktop.
Record user activity on scroll, move and click events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Record user activity on scroll, move and click events | |
* Collect bunches of events and prepare then to send to server | |
* @author Lobastov Gleb | |
*/ | |
(function captorUnit() { | |
var App = { | |
startTime: new Date().getTime(), | |
events: [], | |
/** | |
* Flushes all data from all captors to the server | |
*/ | |
flush: function () { | |
var captures = {}; | |
this.events.forEach(function (eventCaptor) { | |
captures[eventCaptor.eventName] = eventCaptor.collect(); | |
}); | |
console.log('send to server'); | |
console.dir(captures); | |
} | |
}; | |
/** | |
* EventCaptor is a constructor responsible for collecting and store events on clients before buffer | |
* is overflow, then it raises App.flush event which flushes all data from all captors to the server. | |
* | |
* @param options | |
* @param options.bunchSize | |
* Omitting that option means that event will never cause data flushing to server by itself. | |
* @param options.delay | |
* Omitting that option means that every event will be captured | |
* @param options.eventName | |
* @param options.fn Function that receive event and returns value characterizing event to save. | |
* @constructor | |
*/ | |
function EventCaptor(options) { | |
var self = this; | |
App.events.push(this); | |
this.bunchSize = options.bunchSize; | |
this.captured = []; | |
this.enabled = true; | |
this.eventName = options.eventName; | |
this.delay = options.delay; | |
this.fn = options.fn; | |
this.lastEvent = undefined; | |
window.addEventListener(options.eventName, function (event) { | |
self.capture(event); | |
}); | |
} | |
/** | |
* Handles every suitable event, and save value characterizing it to buffer, except case when delay is setup. | |
* In case with delay is on it handles only last event in each period, then add last value to buffer. | |
* | |
* @param event | |
*/ | |
EventCaptor.prototype.capture = function (event) { | |
var self = this; | |
if (this.delay) { | |
this.lastEvent = event; | |
if (this.enabled) { | |
this.enabled = false; | |
setTimeout(function () { | |
self.save(self.extractData(self.lastEvent)); | |
self.enabled = true; | |
}, this.delay) | |
} | |
} else { | |
this.save(this.extractData(event)); | |
} | |
}; | |
/** | |
* Calculate value chatacterizing event and append service data. | |
* Currently append time offset from page load. | |
* | |
* @param event | |
* @returns {{value: *, timeOffset: number}} | |
*/ | |
EventCaptor.prototype.extractData = function (event) { | |
return { | |
value: this.fn(event), | |
timeOffset: new Date().getTime() - App.startTime | |
} | |
}; | |
/** | |
* Save eventData to buffer and flush it to server when buffer becomes overflow | |
* @param eventData | |
*/ | |
EventCaptor.prototype.save = function (eventData) { | |
this.captured.push(eventData); | |
if (this.bunchSize && this.captured.length >= this.bunchSize) { | |
App.flush(); | |
} | |
}; | |
/** | |
* Extract all items from buffer and leaves it clear | |
* @returns {Array} | |
*/ | |
EventCaptor.prototype.collect = function () { | |
var captured = this.captured; | |
this.captured = []; | |
return captured; | |
}; | |
new EventCaptor({ | |
bunchSize: 5, | |
delay: 500, | |
eventName: 'scroll', | |
fn: function () { | |
return window.pageYOffset || document.documentElement.scrollTop | |
} | |
}); | |
new EventCaptor({ | |
bunchSize: 25, | |
delay: 200, | |
eventName: 'mousemove', | |
fn: function (event) { | |
return { | |
x: event.screenX, | |
y: event.screenY | |
} | |
} | |
}); | |
new EventCaptor({ | |
eventName: 'click', | |
fn: function (event) { | |
return { | |
x: event.screenX, | |
y: event.screenY | |
} | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment