@codeankitanime/eventlogger
Version:
A lightweight JavaScript event tracker that logs user interactions (clicks, inputs, scrolls, etc.) along with browser, OS, and optional geolocation/IP metadata. Ideal for building custom front-end analytics.
113 lines (91 loc) • 3.42 kB
JavaScript
import { collectUserMeta } from './meta';
let eventBuffer = [];
let config = {};
let meta = {};
let sessionStart = Date.now();
let visitorId = '';
let debounceTimeout;
let currentPage = window.location.pathname;
let pageEnterTime = Date.now();
// Utilities
function generateVisitorId() {
return '_' + Math.random().toString(36).substr(2, 9);
}
function getBufferedEvents() {
return [...eventBuffer];
}
function clearBufferedEvents() {
eventBuffer = [];
}
function flushEvents() {
if (config.onFlush && typeof config.onFlush === 'function' && eventBuffer.length > 0) {
const now = Date.now();
const sessionDuration = Math.round((now - sessionStart) / 1000); // seconds
const pageDuration = Math.round((now - pageEnterTime) / 1000);
config.onFlush({
visitorId,
sessionStart,
sessionDuration,
meta,
events: getBufferedEvents(),
page: {
path: currentPage,
duration: pageDuration
}
});
clearBufferedEvents();
currentPage = window.location.pathname;
pageEnterTime = Date.now();
}
}
function debounceFlush() {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(flushEvents, config.flushDelay || 4000);
}
function pushEvent(evt) {
eventBuffer.push({ ...evt, timestamp: Date.now() });
debounceFlush();
}
// ------ Event Handlers ------
function trackClick(e) {
pushEvent({ type: 'click', x: e.clientX, y: e.clientY, tag: e.target.tagName, id: e.target.id, class: e.target.className });
}
function trackScroll() {
pushEvent({ type: 'scroll', scrollY: window.scrollY });
}
function trackInput(e) {
pushEvent({ type: 'input', tag: e.target.tagName, name: e.target.name || '', value: e.target.value || '' });
}
function trackMouseMove(e) {
if (Math.random() < 0.05) {
pushEvent({ type: 'mousemove', x: e.clientX, y: e.clientY });
}
}
function trackKeyDown(e) {
pushEvent({ type: 'keydown', key: e.key, code: e.code, target: e.target.tagName });
}
function trackFocus(e) {
pushEvent({ type: 'focus', tag: e.target.tagName, id: e.target.id });
}
function trackBlur(e) {
pushEvent({ type: 'blur', tag: e.target.tagName, id: e.target.id });
}
// ------ Main Tracking Start ------
export async function startTracking(userConfig) {
config = userConfig;
meta = await collectUserMeta();
visitorId = localStorage.getItem('visitorId') || generateVisitorId();
localStorage.setItem('visitorId', visitorId);
const storedSessionStart = sessionStorage.getItem('sessionStart');
if (storedSessionStart) sessionStart = parseInt(storedSessionStart, 10);
else sessionStorage.setItem('sessionStart', sessionStart);
const evs = config.events || [];
if (evs.includes('click')) window.addEventListener('click', trackClick);
if (evs.includes('scroll')) window.addEventListener('scroll', trackScroll);
if (evs.includes('input')) document.addEventListener('input', trackInput);
if (evs.includes('mousemove')) window.addEventListener('mousemove', trackMouseMove);
if (evs.includes('keydown')) window.addEventListener('keydown', trackKeyDown);
if (evs.includes('focus')) window.addEventListener('focus', trackFocus, true);
if (evs.includes('blur')) window.addEventListener('blur', trackBlur, true);
window.addEventListener('beforeunload', flushEvents);
}