@croct/plug
Version:
A fully-featured devkit for building natively personalized applications.
167 lines (166 loc) • 5.89 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var autoTracking_exports = {};
__export(autoTracking_exports, {
AutoTrackingPlugin: () => AutoTrackingPlugin,
factory: () => factory
});
module.exports = __toCommonJS(autoTracking_exports);
var import_structuredData = require('./structuredData.cjs');
class AutoTrackingPlugin {
constructor(configuration) {
this.scanTimeout = null;
this.tab = configuration.tab;
this.tracker = configuration.tracker;
this.options = configuration.options;
this.trackStructuredData = this.trackStructuredData.bind(this);
this.trackLinkOpened = this.trackLinkOpened.bind(this);
this.handleUrlChange = this.handleUrlChange.bind(this);
}
isDisabled() {
return this.options?.disablePostViewed === true && this.options?.disableProductViewed === true && this.options?.disableLinkOpened === true;
}
enable() {
if (this.isDisabled()) {
return;
}
this.trackStructuredData();
this.tab.addListener("urlChange", this.handleUrlChange);
if (this.options?.disableLinkOpened !== true) {
document.addEventListener("click", this.trackLinkOpened, true);
}
}
disable() {
if (this.scanTimeout !== null) {
clearTimeout(this.scanTimeout);
this.scanTimeout = null;
}
this.tab.removeListener("urlChange", this.handleUrlChange);
document.removeEventListener("click", this.trackLinkOpened, true);
}
handleUrlChange() {
if (this.scanTimeout !== null) {
clearTimeout(this.scanTimeout);
}
this.scanTimeout = setTimeout(
() => {
this.scanTimeout = null;
this.trackStructuredData();
},
1e3
);
}
trackStructuredData() {
const structuredDataElements = document.querySelectorAll('script[type="application/ld+json"]');
for (const element of structuredDataElements) {
const entity = (0, import_structuredData.parseEntity)(element.textContent ?? "");
switch (entity?.type) {
case "post":
if (this.options?.disablePostViewed !== true) {
this.trackPostViewed(entity);
}
break;
case "product":
case "service":
if (this.options?.disableProductViewed !== true) {
this.trackProductViewed(entity);
}
break;
}
}
}
trackPostViewed(info) {
let postId = info.id;
if (postId === void 0 && info.url !== void 0) {
const parsedUrl = new URL(info.url);
const pathSegments = parsedUrl.pathname.split("/").filter((segment) => segment.length > 0);
if (pathSegments.length > 0) {
postId = pathSegments[pathSegments.length - 1];
}
}
if (postId === void 0 || info.title === void 0) {
return;
}
this.tracker.track("postViewed", {
post: AutoTrackingPlugin.clean({
postId: AutoTrackingPlugin.truncate(postId, 200),
title: AutoTrackingPlugin.truncate(info.title, 200),
url: info.url,
tags: info.tags?.map((tag) => AutoTrackingPlugin.truncate(tag, 50)),
categories: info.categories?.map((category) => AutoTrackingPlugin.truncate(category, 50)),
authors: info.authors?.map((author) => AutoTrackingPlugin.truncate(author, 100)),
publishTime: info.publishTime ?? Date.now(),
updateTime: info.updateTime
})
});
}
trackProductViewed(info) {
if (info.id === void 0 || info.name === void 0 || info.displayPrice === void 0) {
return;
}
this.tracker.track("productViewed", {
product: AutoTrackingPlugin.clean({
productId: AutoTrackingPlugin.truncate(info.id, 50),
name: AutoTrackingPlugin.truncate(info.name, 200),
displayPrice: info.displayPrice,
url: info.url,
sku: info.sku !== void 0 ? AutoTrackingPlugin.truncate(info.sku, 50) : void 0,
brand: info.brand !== void 0 ? AutoTrackingPlugin.truncate(info.brand, 100) : void 0,
variant: info.variant !== void 0 ? AutoTrackingPlugin.truncate(info.variant, 50) : void 0,
category: info.category !== void 0 ? AutoTrackingPlugin.truncate(info.category, 100) : void 0,
originalPrice: info.originalPrice,
imageUrl: info.imageUrl
})
});
}
trackLinkOpened(event) {
if (event.target instanceof HTMLElement) {
const link = event.target.closest("a");
if (link?.href !== void 0 && URL.canParse(link.href, document.baseURI)) {
this.tracker.track("linkOpened", {
link: new URL(link.href, document.baseURI).toString()
});
}
}
}
static truncate(value, maxLength) {
if (value.length <= maxLength) {
return value;
}
return value.slice(0, maxLength);
}
static clean(obj) {
const result = { ...obj };
for (const key of Object.keys(result)) {
if (result[key] === void 0) {
delete result[key];
}
}
return result;
}
}
const factory = ((props) => new AutoTrackingPlugin({
tab: props.sdk.tab,
tracker: props.sdk.tracker,
options: props.options
}));
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AutoTrackingPlugin,
factory
});