watusertracking
Version:
User activity tracking package
609 lines (516 loc) • 21.6 kB
TypeScript
export function watusertracking() {
const getDate = new Date();
const year = getDate.getFullYear();
const month = (getDate.getMonth() + 1).toString().padStart(2, "0");
const day = getDate.getDate();
const date = formatDate(getDate);
const hh = getDate.getHours();
const mm = getDate.getMinutes();
const ss = getDate.getSeconds();
const times = `${hh.toLocaleString()}:${mm.toLocaleString()}:${ss.toLocaleString()}`;
const browserNameMapping = {
Firefox: "Mozilla Firefox",
"Edg/": "Microsoft Edge",
Chrome: "Google Chrome",
Safari: "Apple Safari",
Opera: "Opera",
MSIE: "Internet Explorer",
"Trident/": "Internet Explorer",
};
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const titleElements = document.querySelectorAll("title");
const clientName = titleElements[0].innerHTML;
// HTML template for cookie prompt
// const htmlTemplate = `
// <div id="cookiePopup" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 9999;">
// <div class="wrapper" style="background: #fff; position: fixed; bottom: 20px; left: 50px; max-width: 500px; border-radius: 15px; text-align: center; border: 1px solid #493179; padding: 25px; overflow: hidden; box-shadow: 0 0 18px rgba(0, 0, 0, 0.13);">
// <img src="../../assets/img/cookie.png" alt="" style="max-width: 90px;">
// <div class="content" style="margin-top: 10px;">
// <header style="font-size: 25px; font-weight: 600;">Cookies</header>
// <h1 style="font-size: 25px; font-weight: 600;">GDPR Compliance Notice</h1>
// <h5>What data do we collect?</h5>
// <ul style="list-style-type: disc; text-align: left;">
// <li>We collect personal information such as your name, email address, and location when you sign up for our service or interact with our platform.</li>
// <li>We also gather data on your usage patterns, preferences, and interactions with our website/application/service to improve your experience and tailor our offerings to your needs.</li>
// </ul>
// <div class="buttons" style="display: flex; justify-content: center; align-items: center;">
// <button class="item cancel" onclick="onBlock()" style="padding: 10px 20px; margin: 0 5px; border: none; outline: none; font-size: 16px; font-weight: 500; border-radius: 5px; cursor: pointer; background: #eee; color: #333;">Cancel</button>
// <button class="item accept" onclick="onAccept()" style="padding: 10px 20px; margin: 0 5px; border: none; outline: none; font-size: 16px; font-weight: 500; border-radius: 5px; cursor: pointer; background: #493179; color: #fff;">Accept</button>
// </div>
// </div>
// </div>
// </div>
// `;
let userDetail = {};
let pageName = "";
let newPageName = "";
let isPageChanged = false;
let id;
let time;
let serverUpdateTime;
let isResponseToDB = false;
let ipAddress;
let ls = {};
let clickCounts = {};
let data = ["wat_userevents", "wat_usernames"];
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
}
const generateString = (length) => {
let result = "";
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
const userAgent = navigator.userAgent;
const browserName =
Object.keys(browserNameMapping).find((key) => userAgent.includes(key)) ||
"Unknown Browser";
function storeUserName(value) {
sessionStorage.setItem(data[1], JSON.stringify(value));
}
if (!getCookie("deviceType")) {
let deviceTypeInfo = detectDeviceType();
setCookie("deviceType", deviceTypeInfo, 24);
}
//to get ip adress
fetch("https://api.ipify.org?format=json")
.then((response) => response.json())
.then((data) => {
ipAddress = data.ip;
const deviceType = getCookie("deviceType");
console.log("Device Type:", deviceType);
userDetail = {
userInfo: [
{
ip: ipAddress,
userName: generateString(5),
browserName: browserName,
dates: date,
time: times,
deviceType: deviceType,
clientName: clientName,
},
],
};
try {
const userNameKey = JSON.parse(sessionStorage.wat_usernames);
const ipCheck = userNameKey.userInfo[0].ip;
} catch {
storeUserName(userDetail);
}
const userNameKey = JSON.parse(sessionStorage.wat_usernames);
const ipCheck = userNameKey.userInfo[0].ip;
if (ipAddress != ipCheck) {
storeUserName(userDetail);
}
})
.catch((error) => {
console.error("Error:", error);
});
// Event handler functions
let isCookieCancel = false;
function onAccept() {
this.getUserRegion();
closeCookiePopup();
}
function onBlock() {
closeCookiePopup();
isCookieCancel = false;
if (isCookieCancel) {
sendUserInfoToConfig(userDetail.userInfo[0]);
}
}
// Function to close the cookie popup
function closeCookiePopup() {
const cookiePopup = document.getElementById("cookiePopup");
if (cookiePopup) {
cookiePopup.remove();
}
}
// Function to set cookie with expiry time
function setCookie(name, value, hours) {
const expires = new Date();
expires.setTime(expires.getTime() + hours * 60 * 60 * 1000); // Convert hours to milliseconds
document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;
}
/** Disbaling for time being. TODO: Attribution required for Location API */
function getUserRegion() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
let userType;
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
/** TODO: Attribution is required */
// const url = `https://nominatim.openstreetmap.org/reverse?lat=${latitude}&lon=${longitude}&format=json`;
// fetch(url)
// .then((res) => res.json())
// .then((data) => {
// const country = data.address.country;
// const city = data.address.county;
// });
const storedUserData = sessionStorage.getItem("wat_usernames");
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
}
if (storedUserData) {
userType = "Authenticated";
} else {
userType = "Anonymous";
}
const deviceType = getCookie("deviceType");
console.log("Device Type:", deviceType);
const userInfo = {
ip: ipAddress,
userName: generateString(5),
userType: userType,
browserName: browserName,
dates: date,
time: times,
clientName: clientName,
deviceType: deviceType,
};
const locationInfo = {
clientName: clientName,
latitude: latitude.toString(),
longitude: longitude.toString(),
// cityName: city.toString(),
// country: country.toString() //Disableing for time being, Need to add more atrribute for location api
};
const deviceTypeInfo = {
clientName: clientName,
DeviceName: deviceType,
};
sendUserInfoToConfig(userInfo, locationInfo, deviceTypeInfo);
setCookie("cookieAccepted", "true", 24);
},
(error) => {
console.error("Error getting user location:", error);
}
);
} else {
console.log("Geolocation is not supported by this browser.");
}
}
async function sendUserInfoToConfig(userInfo, locationInfo, deviceTypeInfo) {
try {
const response = await fetch("http://192.168.10.152/config", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
userInfo: userInfo,
}),
});
if (!response.ok) {
throw new Error(
`Error sending userInfo to config API: ${response.status}`
);
}
const configData = await response.json();
console.log("Config Data:", configData);
id = configData._id;
time = configData.serverUpdateTime;
setCookie("serverUpdateTime", time, 30);
setCookie("userId", id, 30);
locationInfo._id = id;
deviceTypeInfo._id = id;
sendUserLocation(locationInfo);
sendDeviceInfo(deviceTypeInfo);
} catch (error) {
console.error("Error sending userInfo to config API:", error);
}
}
async function sendUserLocation(loctioninfo) {
try {
const response = await fetch("http://192.168.10.152/saveMapData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(loctioninfo),
});
if (!response.ok) {
throw new Error(
`Error sending loctioninfo to saveMapData API: ${response.status}`
);
}
const locationData = await response.json();
console.log("Location Data:", locationData);
} catch (error) {
console.error(
"Error sending Location Information to Location API:",
error
);
}
}
async function sendDeviceInfo(deviceTypeInfo) {
try {
const response = await fetch("http://192.168.10.152/saveDeviceData", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(deviceTypeInfo),
});
if (!response.ok) {
throw new Error(
`Error sending loctioninfo to saveMapData API: ${response.status}`
);
}
const deviceData = await response.json();
console.log("Device Data:", deviceData);
} catch (error) {
console.error("Error sending Device Information to Device API:", error);
}
}
function detectDeviceType() {
const userAgent = navigator.userAgent.toLowerCase();
if (/ipad|tablet|playbook|silk/i.test(userAgent)) {
return "tablet";
} else if (
/mobile|iphone|ipod|blackberry|opera mini|iemobile|windows phone|trident|opera mobi|mobilesafari|htc|nokia|symbian|samsung|lg|mot/i.test(
userAgent
)
) {
return "mobile";
} else {
return "pc";
}
}
const deviceType = getCookie("deviceType");
console.log("Device Type:", deviceType);
function getCookie(cookieName) {
const cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.indexOf(cookieName + "=") === 0) {
return cookie.substring(cookieName.length + 1);
}
}
return null;
}
// Function to inject HTML into the DOM
function injectHTML(html) {
const sessionDetails = getCookie("cookieAccepted");
if (!sessionDetails) {
getUserRegion();
// const container = document.createElement("div");
// container.innerHTML = htmlTemplate.trim();
// document.body.appendChild(container.firstChild);
}
}
// Inject HTML template into the DOM after DOMContentLoaded
document.addEventListener("DOMContentLoaded", function () {
injectHTML();
});
function storeUserEvent(value) {
sessionStorage.setItem(data[0], JSON.stringify(value));
isResponseToDB = true;
}
function determineCurrentScreen() {
const currentURL = window.location.href;
pageName = currentURL.substring(currentURL.lastIndexOf("/") + 1);
}
document.addEventListener("DOMContentLoaded", () => {
determineCurrentScreen();
});
function changedPageName(isPageChangedtoOtherScreen) {
if (isPageChangedtoOtherScreen) {
pageName = newPageName;
}
return pageName;
}
(function () {
let captureObject = {};
let clickCounts = {};
let responseToDB;
let requesteDataToDB;
function updateClickCount(tagId, tagType) {
if (!clickCounts[tagId]) {
clickCounts[tagId] = 1;
} else {
clickCounts[tagId]++;
}
const clickCountDisplay = document.getElementById(
`${tagType}${tagId}_click_count`
);
if (clickCountDisplay) {
clickCountDisplay.textContent = clickCounts[tagId];
}
if (!captureObject[pageName]) {
captureObject[pageName] = {};
}
userDetail.userEvents = [];
captureObject[pageName][`${tagType}${tagId}`] = clickCounts[tagId];
userDetail.userEvents = [{ ...captureObject }];
console.log("User Clicked Events: " + JSON.stringify(userDetail));
captureObject = {};
clickCounts = {};
let oldObject;
let userEventDetail = sessionStorage.getItem("wat_userevents");
let newObject = JSON.parse(JSON.stringify(userDetail));
let currentUserEvents;
let newDerivedObject;
oldObject = [userEventDetail];
if (oldObject == "" || oldObject == undefined) {
currentUserEvents = [JSON.parse(JSON.stringify(newObject))];
newObject.userEvents[0].date = date;
console.log(`New derived object: ${JSON.stringify(newObject)}`);
storeUserEvent([newObject]);
} else {
let todayObject = oldObject;
if (!todayObject) {
currentUserEvents = oldObject;
newObject.userEvents.forEach((newEvent) => {
console.log(JSON.stringify(newEvent));
currentUserEvents[0].userEvents.push(newEvent);
});
} else {
newDerivedObject = JSON.parse(todayObject);
if (newObject.userEvents && Array.isArray(newObject.userEvents)) {
newObject.userEvents.forEach((newEvent, index) => {
newDerivedObject[0].userEvents[index] =
newDerivedObject[0].userEvents[index] || {};
for (let screen in newEvent) {
newDerivedObject[0].userEvents[index][screen] =
newDerivedObject[0].userEvents[index][screen] || {};
for (let button in newEvent[screen]) {
newDerivedObject[0].userEvents[index][screen][button] =
(newDerivedObject[0].userEvents[index][screen][button] ||
0) + (newEvent[screen][button] || 0);
}
}
});
}
newDerivedObject[0].userEvents[0].date = date;
console.log("New Dervied Object" + JSON.stringify(newDerivedObject));
const requestData = newDerivedObject[0];
storeUserEvent([requestData]);
}
}
responseToDB = sessionStorage.getItem("wat_userevents");
if (responseToDB) {
const parsedData = JSON.parse(responseToDB);
// Access userEvents key
const userEvents = parsedData[0].userEvents;
requesteDataToDB = JSON.stringify(userEvents);
}
}
console.log("responseToDB", responseToDB);
async function sendUserEventData() {
if (isResponseToDB) {
const userId = getCookie("userId");
const response = await fetch(
`http://192.168.10.152/updateUserEvents/${userId}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: requesteDataToDB,
}
);
if (!response.ok) {
throw new Error(`Error fetching config data: ${response.status}`);
}
const configData = await response.json();
console.log("Config Data:", configData);
// sessionStorage.clear();
for (let skeys of data) {
sessionStorage.removeItem(skeys);
}
// for (let i = sessionStorage.length - 1; i >= 0; i--) {
// const key = sessionStorage.key(i);
// if (key.startsWith("wat_")) {
// sessionStorage.removeItem(key);
// }
// }
if (requesteDataToDB.length) {
isResponseToDB = false;
requesteDataToDB = [];
}
}
}
sendUserEventData(); // Call sendData immediately if there's data
function sendUserEventDataCall() {
serverUpdateTime = getCookie("serverUpdateTime");
if (serverUpdateTime != null) {
console.log("Server update time" + serverUpdateTime);
setInterval(sendUserEventData, serverUpdateTime);
clearInterval(setTintervalTimer);
}
}
const setTintervalTimer = setInterval(sendUserEventDataCall, 1000);
function handleButtonClick(event) {
const target = event.target;
const isButton = target.tagName === "BUTTON" || target.closest("button");
const linkElement = target.tagName === "A" ? target : target.closest("a");
if (isButton) {
const buttonElement =
target.tagName === "BUTTON" ? target : target.closest("button");
const parentButtonContent = getParentContent(buttonElement, "button");
updateClickCount(parentButtonContent, "btn_");
changedPageName(isPageChanged);
} else if (linkElement) {
const parentLinkContent = getParentContent(linkElement, "link");
updateClickCount(parentLinkContent, "link_");
changedPageName(isPageChanged);
}
}
function getParentContent(element, type) {
let parentContent = element.textContent.trim();
let parentElement = element.parentElement.closest(type);
while (parentElement) {
parentContent = parentElement.textContent.trim();
parentElement = parentElement.parentElement.closest(type);
}
return parentContent;
}
document.addEventListener("click", handleButtonClick);
})();
function startObserving() {
const observer = new MutationObserver(() => {
const currentUrl = window.location.href;
const urlObj = new URL(currentUrl);
const pathSegments = urlObj.pathname.split("/").filter(Boolean);
if (pathSegments.length >= 2) {
const lastSegment = pathSegments[pathSegments.length - 1];
if (!isNaN(lastSegment)) {
const beforeLastSegment = pathSegments[pathSegments.length - 2];
console.log("Before Last Segment:", beforeLastSegment);
const params = {};
urlObj.searchParams.forEach((value, key) => {
params[key] = value;
});
console.log("Query Parameters:", params);
}
}
});
const targetNode = document.body;
const observerConfig = { subtree: true, childList: true };
observer.observe(targetNode, observerConfig);
}
// function startObserving() {
// const observer = new MutationObserver(() => {
// const currentUrl = window.location.href;
// newPageName = currentUrl.substring(currentUrl.lastIndexOf("/") + 1);
// if (newPageName !== pageName) {
// isPageChanged = true;
// }
// });
// const targetNode = document.body;
// const observerConfig = { subtree: true, childList: true };
// observer.observe(targetNode, observerConfig);
// }
document.addEventListener("DOMContentLoaded", startObserving);
}
module.exports = { watusertracking };