web-collect-events-narayana
Version:
An sdk for collecting events from web pages
200 lines (173 loc) • 5.91 kB
text/typescript
import getBrowserProfile from "./helpers/browserProfile";
import getScrollState from "./helpers/scrollState";
import getDateTimeIndex from "./helpers/dateTimeIndex";
import getUserId from "./helpers/userId";
import getDomNodeProfile from "./helpers/domNodeProfile";
import { isNodeValid } from "./helpers/validNode";
import { postData } from "./helpers/api";
class GTETWebSDK {
private isPushNotificationScope: boolean = false;
private isCustomEventScope: boolean = false;
private _data: Record<string, any>[] = [];
constructor() {
this.checkScope();
this.initStorage();
console.log("GTETWebSDK started");
}
initStorage() {
this._data = [];
};
private setData(value: any) {
this._data.push(value);
}
private getData() {
return this._data;
};
private removeData() {
this._data = [];
};
private checkScope() {
this.isPushNotificationScope = typeof window !== "undefined" && typeof navigator !== "undefined";
this.isCustomEventScope = typeof window !== "undefined";
}
handleDocumentClick(e: MouseEvent) {
const targetNode = e.target as HTMLElement;
console.log(targetNode);
if (isNodeValid(targetNode)) {
const data = {
eventType: "click",
browserProfile: getBrowserProfile(),
scrollState: getScrollState(),
dateTimeIndex: getDateTimeIndex(),
userId: getUserId(),
domNodeProfile: getDomNodeProfile(e),
};
this.setData(data);
}
}
sendData() {
const data = this.getData();
const url = `${process.env.BASE_URL}/api/v1/stream`
if (data.length > 0) {
if (!url) {
console.log("POST_URL environment variable is not defined.");
return;
}
postData(url, data)
.then((response: any) => {
if (response.ok) {
console.log("Data sent successfully:", data);
this.removeData();
} else {
console.log("Failed to perform the POST request.");
}
})
.catch((error) => {
console.log(error);
});
}
}
selfAnalyze(url: string) {
if (this.isCustomEventScope) {
document.addEventListener("click", this.handleDocumentClick.bind(this)); // Bind the event handler
document.addEventListener("visibilitychange", () => {
const formdata = new FormData();
formdata.append("data", JSON.stringify(this.getData()));
navigator.sendBeacon(`${url}/api/v1/stream`, formdata);
}); // Bind the event handler
setInterval(this.sendData.bind(this, url), 60000); // Bind the method
console.log("Self analyze started");
} else {
console.log("This code is not running in a browser environment for selfAnalyze.");
}
}
customEvent(eventName: string, data: any) {
if (this.isCustomEventScope) {
const dataObject = {
eventType: eventName,
data: data,
};
this.setData(dataObject);
this.sendData();
} else {
console.log("This code is not running in a browser environment for customEvent.");
}
}
pushNotification(publicVapidKey: string, api: string, swfile?: string) {
if (this.isPushNotificationScope) {
if ("serviceWorker" in navigator && "PushManager" in window) {
if (swfile) {
this.registerServiceWorkerWithFile(swfile)
.then(() => this.sendSubscriptionToServer(publicVapidKey, api))
.catch((error) => console.error("Error:", error));
}
else {
this.registerServiceWorkerWithoutFile()
.then(() => this.sendSubscriptionToServer(publicVapidKey, api))
.catch((error) => console.error("Error:", error));
}
} else {
console.log("Service Worker or PushManager is not supported in this browser.");
}
} else {
console.log("This code is not running in a browser environment for pushNotification.");
}
}
async registerServiceWorkerWithFile(swfile: string) {
try {
const register = await navigator.serviceWorker.register(`/${swfile}.js`, {
scope: "/",
});
console.log("Service Worker registered:", register);
} catch (error) {
console.error("Failed to register Service Worker:", error);
throw error;
}
}
async registerServiceWorkerWithoutFile() {
try {
const register = await navigator.serviceWorker.register('https://push-notifications-narayana.s3.ap-south-1.amazonaws.com/service-worker.js',
{
scope: "/",
});
console.log("Service Worker registered:", register);
} catch (error) {
console.error("Failed to register Service Worker:", error);
throw error;
}
}
async sendSubscriptionToServer(publicVapidKey: string, api: string) {
try {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: this.urlBase64ToUint8Array(publicVapidKey),
});
+
await fetch(api, {
method: "POST",
body: JSON.stringify(subscription),
headers: {
"content-type": "application/json",
},
});
console.log("Push Sent...", JSON.stringify(subscription));
} catch (error) {
console.error("Failed to send subscription to the server:", error);
throw error;
}
}
urlBase64ToUint8Array(base64String: string) {
const padding = "=".repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
}
export default GTETWebSDK;