Track user behavior during online tests
npm install cheatingtrackerCheatingTracker - is a JavaScript library for tracking suspicious actions on the part of the client
The CheatingTracker package It contains functionality for tracking changes in page focus.
createScreenTracker - Creates definition pressed ScreenShots on keyboard and type Operating System
- events: returns array all pressed screens on keyboard with title and time
- lastEvent: returns trying last screen or
```
{
title: '',
time: null,
}
_Returns:_
`
type Nullable
interface IScreenDetect {
title: string;
time: Nullable
}
{
lastEvent: () => IScreenDetect;
events: () => IScreenDetect[];
cleanup: () => void;
}
`
- React:
`
import React, { useState, useEffect, useRef } from 'react';
import { createScreenTracker } from 'cheatingtracker';
const Home = () => {
const [events, setEvents] = useState([]);
const [lastEvent, setLastEvent] = useState(null);
const screenTrackerRef = useRef(null);
useEffect(() => {
const screenTracker = createScreenTracker((newEvents) => {
setEvents(newEvents);
if (screenTrackerRef.current) {
const last = screenTrackerRef.current.lastEvent();
setLastEvent(last);
}
});
screenTrackerRef.current = screenTracker;
return () => {
screenTracker.cleanup();
};
}, []);
return (
{lastEvent.title} at {lastEvent.time}
export default Home;
`
- JavaScript Native:
`
import { createScreenTracker } from 'cheatingtracker';
const tracker = createScreenTracker();
const btn = document.getElementById('btn')
btn.addEventListener('click', () => {
console.log(tracker.events());
console.log(tracker.lastEvent());
})
`
createBlurTracker - Creates a focus loss tracker.
- getCount: returns count blur count times
_Returns:_
`
{
getCount: () => number;
cleanup: () => void;
}
`
- React:
`
import React, { useEffect, useState } from 'react';
import { createBlurTracker } from 'cheatingtracker';
const Reviews = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const tracker = createBlurTracker(setCount);
return () => {
tracker.cleanup();
};
}, []);
return (
export default Reviews;
`
- JavaScript Native:
`
import { createBlurTracker } from 'cheatingtracker';
const tracker = createBlurTracker(0);
const btn = document.getElementById('btn')
btn.addEventListener('click', () => {
console.log(tracker.getCount());
})
`
___
createAltTabTracker - Determines whether the Alt+Tab key combination or a similar focus switch was performed in combination with the pressed Alt. It also records what time it happened and how long the user was absent from the page.
- events: returns array all pressed alt + tabalt
- lastEvent: returns trying last + tab
`
type Nullable
interface IAltTabEvent {
at: string;
durationMs: Nullable
}
{
lastEvent: () => IAltTabEvent;
events: () => IAltTabEvent[];
destroy: () => void;
}
`
_Returns:_
: () => IAltTabEvent;This method returns an object with the last Alt+Tab event (or a similar focus switch) fixed during operation.
The returned object has the following contents:
`
{
at: string; // example: "02:23:50".
durationMs: Nullable; // duration: 1583
}
`at: is the time when the event occurred. This time is in the hh:mm:ss format, for example: 02:23:50.
durationMs – length of time during which there was no focus on the page (in milliseconds). If focus has been restored, the value will be specified, if not, it will be null.
examples:
`
{
at: '02:23:50',
durationMs: 1500
}
`or
`
{
at: '',
durationMs: null
}
`Events:
events: () => IAltTabEvent[];This method returns an array of all Alt+Tab (or similar focus switches) that have been captured.
The returned array contains objects in the following format:
`
{
at: string; // example: "02:23:50".
durationMs: Nullable; // duration: 1583
}
`Example of the returned array:
[
{ at: '02:23:50', durationMs: 1500 },
{ at: '03:15:42', durationMs: 1200 },
]
___
EXAMPLES:
JavaScript Native
`
import { createAltTabTracker } from "./src/altTab/altTab.js";const btn = document.getElementById('btn');
const tracker = createAltTabTracker();
btn.addEventListener('click', () => {
console.log(tracker.events());
console.log(tracker.lastEvent());
});
`
React
`
import React, { useEffect, useState, useRef } from 'react';
import { createAltTabTracker } from 'cheatingtracker';const AltTabLog = () => {
const [events, setEvents] = useState([]);
const [lastEvent, setLastEvent] = useState(null);
const trackerRef = useRef(null);
useEffect(() => {
const tracker = createAltTabTracker(() => {
const all = tracker.events();
setEvents(all);
setLastEvent(tracker.lastEvent());
});
trackerRef.current = tracker;
return () => {
tracker.destroy();
};
}, []);
return (
Alt+Tab events:
{events.map((e, idx) => (
{e.at} ({e.durationMs} мс)
))}
Last Event:
{lastEvent && (
{lastEvent.at} ({lastEvent.durationMs} мс)
)}
);
};export default AltTabLog;
`---
INACTIVITY
createInactivityTracker - Creates and returns a tracker object that tracks the user's periods of inactivity on a web page. If the user is inactive for a set number of seconds and the page is active, information about inactivity is recorded in the console and an array of events, and then about the moment when they return to activity.
__Returned methods__:
start()
Starts tracking. It attaches listeners to activity events and monitors the visibility of the page.stop()
Stops tracking. Deletes all listeners and clears the timer.getEvents()
Returns an array of all recorded events of inactivity and return to activity.$3
`
{
type: 'inactivity',
time: '03:05:23',
message: 'Пользователь был бездействующим 5 секунд',
activityAfterSeconds: 7,
activityType: 'mousemove'
}`
- type: Type of event
- time: The time when inactivity was recorded (local)
- message: message
- activityAfterSeconds: How many seconds after inactivity did the user become active
- activityType: Activity type: mousemove, keydown, etc.Behaviour:
- Listens to the following activities: mousemove, keydown, mousedown, touchstart.
- Counts only when the page is active
- Activity events are displayed in the console, but only if they occurred after a period of inactivity.
- All events are saved to an array accessible via getEvents().
Notes:
- The tracker's default value is 60 seconds
- Each period of inactivity is recorded once, and only after it is the moment of the next activity monitored.
- Time is saved in a readable format: HH:MM:CC in local time.
EXAMPLES:
- JavaScript Native
`
import { createInactivityTracker } from "./src/inactivity/inactivity.js"; const tracker = createInactivityTracker(30 );
tracker.start();
const start = document.getElementById('start')
const end = document.getElementById('end')
start.addEventListener('click', () => {
console.log(tracker.events())
})
end.addEventListener('click', () => {
tracker.stop();
})
`
- React`
import React, { useEffect, useState } from 'react';
import { createInactivityTracker } from 'cheatingtracker';export default function App() {
const [events, setEvents] = useState([]);
useEffect(() => {
const tracker = createInactivityTracker(5); // 5-second timeout
tracker.start();
return () => {
tracker.stop();
clearInterval(interval);
};
}, []);
return (
🛑 Inactivity Tracker
Try not moving your mouse or pressing keys for 5 seconds...
{events.map((event, index) => (
{event.time} — {event.message}
{event.activityAfterSeconds !== undefined && (
↪ Activity: {event.activityType} after{' '}
{event.activityAfterSeconds} sec.
)}
))}
);
}`
___Copy:
createInactivityTracker - Creates and returns a tracker object that listens to the user's copy actions on the page.
__Returned methods__:
start()
Starts tracking. It attaches listeners to activity events and monitors the copy of the page.stop()
Stops tracking. Deletes all listeners and clears the timer.getEvents()
Returns an array of all recorded events of copy and return to activity.
$3
`
{
type: 'question' | 'answer',
copiedText: string,
time: '13:42:08' // (local time, formatted as HH:MM:SS)
}
`-
type: What was copied — either a question or an answer option
- copiedText: The actual string that was copied by the user
- time: '13:42:08' // (local time, formatted as HH:MM:SS)Behaviour:
- Tracks only content defined in the questions array (including options)
- Listens globally on the document for copy events
- Compares copied text against the questions and options
- Invokes onCopyEvent with event data whenever a match is detected
EXAMPLES:
- REACT
`
import React, { useEffect, useState } from 'react';
import { createQuestionCopyTracker } from 'cheatingtracker';const questions = [
{
question: 'What is the color of the sky?',
options: ['a. Blue', 'b. Green', 'c. Red', 'd. Black'],
},
{
question: 'How many legs does a spider have?',
options: ['a. 4', 'b. 6', 'c. 8', 'd. 10'],
},
];
const QuestionPage = () => {
const [showLogs, setShowLogs] = useState(false);
const [logs, setLogs] = useState([]);
useEffect(() => {
const tracker = createQuestionCopyTracker(questions, (newEvent) => {
setLogs(prevLogs => [...prevLogs, newEvent]);
});
tracker.start();
return () => {
tracker.stop();
};
}, []);
const handleAnswerClick = () => {
setShowLogs(true);
};
const handleLogClick = () => {
console.log(logs);
};
return (
Online Quiz
{questions.map((q, index) => (
{index + 1}. {q.question}
{q.options.map((opt, i) => (
))}
))}
{showLogs && (
Copy Logs:
{logs.length > 0 ? (
logs.map((log, idx) => (
{log.time} — {log.type === 'question' ? 'Question: ' : 'Answer: '} {log.copiedText}
))
) : (
No logs
)}
)}
);
};export default QuestionPage;
`____
Captcha
SimpleCaptcha - Creates and returns a tracker object that makes captcha
__Returned methods__:
showCaptcha()Manually triggers the CAPTCHA overlay.
destroy()Removes CAPTCHA overlay and detaches listeners.
eventsLogs of all successful CAPTCHA completions. Each entry includes: at (time), timeIsCorrect (attempts), howLongIsCorrect (ms to solve).
$3
`
{
at: string,
timeIsCorrect: number,
howLongIsCorrect: number,
}`
at - the time when the CAPTCHA was createdtimeIsCorrect - how many times was the CAPTCHA correctly solvedtimeIsCorrect - time how long did it take to solve it
EXAMPLES:
- Native JavaScript
`
import { SimpleCaptcha } from 'cheatingtracker';const captcha = SimpleCaptcha.create('captcha', 10000);
const button = document.getElementById('btn');
button.addEventListener('click', () => {
console.log(captcha.events);
});
``