Javascript capturing user activity

2020-06-06 07:49发布

问题:

Is there an existing js lib for capturing user activity browser side?

ie. Scrolling, mouse moving, mouse clicking etc. I've been googling, searching stackoverflow and github but I keep getting links to paid analytic programs which aren't quite what I'm after.

I'm tempted to start building something myself, but the more I think about it, the harder I realise it'll be and I'd be better off using some existing lib if available.

What I'm thinking. Would this be an appropriate way to go about it?

  • I'm assuming the best way is to listen on the body or window element and capture all desired events that haven't had bubbling disabled.
  • It'd be nice to batch and minify data before emitting/posting to the server. As in remove mode or frequently occurring data. If a user scrolls I don't need all the scroll events, only the meaningful ones where they start, accelerate or stop.
  • Could emit batches every X number of events or X seconds. And send final batch window.onbeforeunload.

I found these two questions here & here. But aren't quite what I'm after.

I want to be able to configure the event aggregation to ask a question on user interaction. Admittedly I'm out of date with Google Analytic, and maybe I'm wrong, but at a glance custom event tracking doesn't seem to fit the bill. Logging specific individual actions isn't what I'm after.

回答1:

Maybe Something Like This:

DEMO

Relevant Code(JS and HTML):

<script type="text/javascript">
// Array of events you want to capture
var evnts=["mousedown","click","mouseup","focus","blur","keyup","keydown","keypressed"];
// You can also Use mousemove, resize and scroll
for(var i=0;i<evnts.length;i++){
//Attach Listener for all events from array
window.addEventListener(""+evnts[i]+"", function(e){ myFunction(e); }, false);
}
// Listener:- 
function myFunction(e){
//Check If event is passed
var evt=e||window.event;
if(evt){ // If event exists
if(evt.isPropagationStopped&&evt.isPropagationStopped()){
// if event's propagation(bubbling) is stopped then DO NOTHING simply return.
    return;
}
// Get Event Type (Click or Keyup or focus etc)
var et=evt.type?evt.type:evt;
// Get Events Target (Element from which event is bubbled)
var trgt=evt.target?evt.target:window;
// Timestamp of event you can also use evt.timeStamp if supported 
var time=Math.floor(Date.now() / 1000);
// Get Where Event Occured ? events X and Y co-ordinate on Page and Scrolltop of document
var x=0, y=0, scrolltop=0;
if(evt.pageX){
x=evt.pageX;
}
if(evt.pageY){
y=evt.pageY;
}
if(trgt.scrollTop){
scrolltop=trgt.scrollTop;
}
// Get id and class of element
if(trgt.className&&trgt.id){
// BOTH id and class exists
trgt="."+trgt.className+"#"+trgt.id;
}
else if(trgt.id){
// only id exists
trgt="#"+trgt.id;
}
else if(trgt.className){
// only class exists
trgt="."+trgt.className;
}
if(typeof(trgt)!="String"){
// Neither Class nor Id is defined
if(trgt.tagName){
// If it is html tag display its tag name
 trgt=trgt.tagName;
}
else{
// No class + No Id + Not a Html tag 
    trgt=trgt.toString().toLowerCase();
    trgt=trgt.replace("[object ","");
    trgt=trgt.replace("]","");
        trgt=trgt.replace("htmlbodyelement","BODY");

}
}
// Get extra information about event
var xtra="";
if(evt.keyCode){
// If keyboard Event? get Key code
xtra+=" KeyCode: "+evt.keyCode;
}
if(evt.shiftKey){
// was Shift key pressed during occcurance of event?
xtra+=" ShiftKey ";
}
if(evt.altKey){
// was alt key pressed during occcurance of event?
xtra+=" altKey ";
}
if(evt.metaKey){
// MetaKey is used on Mac instead of ctrl Key on PC
xtra+=" metaKey ";
}
if(evt.ctrlKey){
// was ctrl key pressed on pc during occcurance of event?
xtra+=" ctrlKey ";
}
// Get windows dimensions for catching resize event
var w = window,
    d = document,
    e = d.documentElement,
    g = d.getElementsByTagName('body')[0],
    xx = w.innerWidth || e.clientWidth || g.clientWidth,
    yy = w.innerHeight|| e.clientHeight|| g.clientHeight;
xtra+=" RES:"+xx+"X"+yy;

// pad output for displaying on console
et=("          " + et).slice(-10);
trgt=("               " + trgt).slice(-15);
x=("               " + x).slice(-15);
y=("               " + y).slice(-15);
scrolltop=("               " + scrolltop).slice(-15);
time=("              " + time).slice(-15);
// Show output on console
console.log("\n"+et+"\t"+trgt+"\t"+x+"\t"+y+"\t"+scrolltop+"\t"+time+"\t"+xtra);
}
}
</script> 
<!-- Some Xtra HTML To test -->
<div class="mnp" style="overflow:auto;clear:both;width:150px;height:150px;" onMouseUp="event.stopPropagation();" onMouseDown="event.stopPropagation();">
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />
XXX<br />XXX<br />
XXX<br />
</div>

For the next part, That is to send it to server periodically you can use AJAX with setTimeout by first of all saving data in variable(instead of padding and logging it). and clearing it(variable) on every successful ajax operation (ie on readyState==200). You can also send ajax request onbeforeunload.

Here is what that code actually does in a nutshell: It attaches the events from the array of evnts(you can also add events in that array) all to the window element(which is quite faster than attaching it to all elements) and then it get events details if it's propogation isn't stopped, For details on how it get event description read comments from code.

Hope it helps :)!



回答2:

You must write it yourself ( or at least that's what i did ).

Backup question : Is there any javascript library to capture mouse/keyboards events and send them to external server?

Here is a working jsfiddle: http://jsfiddle.net/94dd343y/

        $(document).ready(function(){
        $('html').mousemove(function(event){
            console.log("mouse move X:"+event.pageX+" Y:"+event.pageY);
        });

        $('html').click(function(event){
            console.log("mouse click X:"+event.pageX+" Y:"+event.pageY);
        });

        $('html').keyup(function(event){
            console.log("keyboard event: key pressed "+event.keyCode);
        });
    });

And so on.

If you want to capture all the events, here is a list:

  • abort
  • afterprint
  • beforeprint etc. Is it possible to programmatically catch all events on the page in the browser?