Skip to content

Instantly share code, notes, and snippets.

@Shoora
Forked from dvygolov/ywactivitytracker.js
Last active April 7, 2024 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shoora/71b3d28013cc2172880d96e54e0cc820 to your computer and use it in GitHub Desktop.
Save Shoora/71b3d28013cc2172880d96e54e0cc820 to your computer and use it in GitHub Desktop.
Script that measures interactions on your landing page. If the user is active for "checkTime" seconds - an interval is valid, if total count of valid seconds = totalTime - the goal is reached and sent to Yandex.Metrika.
class ActivityTracker {
constructor(totalTime, checkTime, metrikaId, debug = false) {
this.events = [
"touchmove",
"blur",
"focus",
"focusin",
"focusout",
"load",
"resize",
"scroll",
"unload",
"click",
"dblclick",
"mousedown",
"mouseup",
"mousemove",
"mouseover",
"mouseout",
"mouseenter",
"mouseleave",
"change",
"select",
"submit",
"keydown",
"keypress",
"keyup",
"error",
];
this.need = totalTime;
this.checkTime = checkTime;
this.IDmetrika = metrikaId;
this.loop = true;
this.counter = 0;
this.activeParts = 0;
this.timer = 0;
this.cookieName = `${this.counter * this.need}sec_ap`;
this.parts = Math.ceil(this.need / this.checkTime);
this.period = { start: 0, end: 0, events: false };
this.timeoutId = null;
this.debug = debug;
}
setEvents() {
this.events.forEach((eventName) => {
window.addEventListener(eventName, (e) => {
if (e.isTrusted) {
this.period.events = true;
}
});
});
}
getCookie(name) {
const nameEQ = `${name}=`;
const ca = document.cookie.split(";");
for (let c of ca) {
c = c.trim();
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length);
}
return null;
}
setCookie(name, value, days = 0) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
expires = `; expires=${date.toUTCString()}`;
}
document.cookie = `${name}=${value}${expires}; path=/`;
}
checkCookie() {
const cookieValue = this.getCookie(this.cookieName);
if (!cookieValue) {
return true;
}
const value = parseInt(cookieValue, 10);
if (value >= this.parts && !this.loop) {
return false;
}
this.activeParts = value;
return true;
}
start() {
this.setPeriod();
this.runPeriod();
}
setPeriod() {
this.period.start = Date.now() / 1000;
this.period.end = this.period.start + this.checkTime;
this.period.events = false;
}
runPeriod() {
this.timeoutId = setTimeout(
() => this.checkPeriod(),
this.checkTime * 1000,
);
}
checkPeriod() {
if (this.period.events) {
this.log("This part of interaction looks real!");
this.activeParts++;
} else {
this.log("This part of interaction DOES NOT look real!");
}
this.timer = this.activeParts * this.checkTime;
if (this.timer >= this.need) {
this.sendGoal();
if (this.loop) {
this.reset();
}
} else {
this.start();
}
this.setCookie(this.cookieName, this.activeParts);
}
sendGoal() {
this.log("Activity goal reached: 60sec");
// fbq('init',this.IDmetrika);
// fbq('track','Lead');
ym(this.IDmetrika, "reachGoal", "60sec", Object.fromEntries(new URLSearchParams(window.location.search)));
if (!this.loop) {
clearTimeout(this.timeoutId);
}
}
reset() {
this.counter++;
this.timer = 0;
this.activeParts = 0;
this.cookieName = `${this.counter * this.need}sec_ap`;
}
init() {
if (this.checkCookie()) {
this.log("Starting to monitor activity...");
this.setEvents();
this.start();
}
}
log(msg) {
if (this.debug) console.log(msg);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment