@active-reach/web-sdk 1.37.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aegis.min.js +1 -1
- package/dist/aegis.min.js.map +1 -1
- package/dist/{analytics-Qyzk8JaB.mjs → analytics-Cz1ZBOxH.mjs} +244 -110
- package/dist/analytics-Cz1ZBOxH.mjs.map +1 -0
- package/dist/core/analytics.d.ts +10 -0
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/prefetch-bundle-client.d.ts +1 -0
- package/dist/core/prefetch-bundle-client.d.ts.map +1 -1
- package/dist/core/queue.d.ts.map +1 -1
- package/dist/core/session.d.ts +12 -1
- package/dist/core/session.d.ts.map +1 -1
- package/dist/ecommerce/index.d.ts.map +1 -1
- package/dist/inapp/AegisInAppManager.d.ts +17 -1
- package/dist/inapp/AegisInAppManager.d.ts.map +1 -1
- package/dist/inapp/actions.d.ts +7 -0
- package/dist/inapp/actions.d.ts.map +1 -1
- package/dist/inapp/index.d.ts +1 -1
- package/dist/inapp/index.d.ts.map +1 -1
- package/dist/inapp/renderers/card-template.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +181 -32
- package/dist/index.js.map +1 -1
- package/dist/react.js +1 -1
- package/dist/triggers/TriggerEngine.d.ts +5 -0
- package/dist/triggers/TriggerEngine.d.ts.map +1 -1
- package/dist/utils/device.d.ts.map +1 -1
- package/dist/utils/meta-cookies.d.ts +7 -0
- package/dist/utils/meta-cookies.d.ts.map +1 -1
- package/dist/utils/redact-url.d.ts +56 -0
- package/dist/utils/redact-url.d.ts.map +1 -0
- package/dist/utils/url-parser.d.ts +38 -0
- package/dist/utils/url-parser.d.ts.map +1 -1
- package/dist/utils/visitor.d.ts +43 -0
- package/dist/utils/visitor.d.ts.map +1 -0
- package/dist/widgets/AegisWidgetManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/analytics-Qyzk8JaB.mjs.map +0 -1
|
@@ -164,6 +164,7 @@ class Identity {
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
+
const LINK_ATTRIBUTION_DURABLE_DAYS = 30;
|
|
167
168
|
class SessionManager {
|
|
168
169
|
constructor(storage, sessionTimeoutMinutes = 30) {
|
|
169
170
|
this.eventCount = 0;
|
|
@@ -171,6 +172,7 @@ class SessionManager {
|
|
|
171
172
|
this.activityThrottle = 1e3;
|
|
172
173
|
this.lastActivityUpdate = 0;
|
|
173
174
|
this.adClickIDs = {};
|
|
175
|
+
this.linkAttribution = {};
|
|
174
176
|
this.storage = storage;
|
|
175
177
|
this.sessionTimeout = sessionTimeoutMinutes * 60 * 1e3;
|
|
176
178
|
this.lastActivityTime = Date.now();
|
|
@@ -183,6 +185,7 @@ class SessionManager {
|
|
|
183
185
|
this.eventCount = session.eventCount;
|
|
184
186
|
this.adClickIDs = session.adClickIDs || {};
|
|
185
187
|
this.landingPage = session.landingPage;
|
|
188
|
+
this.linkAttribution = session.linkAttribution || {};
|
|
186
189
|
logger.debug("Session loaded:", session);
|
|
187
190
|
} else {
|
|
188
191
|
this.sessionId = this.createNewSession();
|
|
@@ -228,7 +231,8 @@ class SessionManager {
|
|
|
228
231
|
lastActivityTime: this.lastActivityTime,
|
|
229
232
|
eventCount: this.eventCount,
|
|
230
233
|
adClickIDs: this.adClickIDs,
|
|
231
|
-
landingPage: this.landingPage
|
|
234
|
+
landingPage: this.landingPage,
|
|
235
|
+
linkAttribution: this.linkAttribution
|
|
232
236
|
};
|
|
233
237
|
this.storage.set("session", JSON.stringify(sessionData));
|
|
234
238
|
}
|
|
@@ -293,7 +297,8 @@ class SessionManager {
|
|
|
293
297
|
lastActivityTime: this.lastActivityTime,
|
|
294
298
|
eventCount: this.eventCount,
|
|
295
299
|
adClickIDs: this.adClickIDs,
|
|
296
|
-
landingPage: this.landingPage
|
|
300
|
+
landingPage: this.landingPage,
|
|
301
|
+
linkAttribution: this.linkAttribution
|
|
297
302
|
};
|
|
298
303
|
}
|
|
299
304
|
setAdClickIDs(adClickIDs, landingPage) {
|
|
@@ -334,6 +339,41 @@ class SessionManager {
|
|
|
334
339
|
getLandingPage() {
|
|
335
340
|
return this.landingPage;
|
|
336
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Record the landing's Aegis link attribution. LAST touch: a new `aegis_code`
|
|
344
|
+
* replaces the previous set whole — never merged, because the fields are the
|
|
345
|
+
* attributes of ONE link and a mix of two links describes neither.
|
|
346
|
+
* Session + durable (30d, the server's short-link attribution window) so a
|
|
347
|
+
* checkout in a later session can still name the send that brought them.
|
|
348
|
+
*/
|
|
349
|
+
setLinkAttribution(attribution) {
|
|
350
|
+
if (!attribution.aegis_code) return;
|
|
351
|
+
this.linkAttribution = { ...attribution };
|
|
352
|
+
this.persistSession();
|
|
353
|
+
try {
|
|
354
|
+
this.storage.set(
|
|
355
|
+
"link_attribution",
|
|
356
|
+
JSON.stringify(this.linkAttribution),
|
|
357
|
+
LINK_ATTRIBUTION_DURABLE_DAYS
|
|
358
|
+
);
|
|
359
|
+
} catch {
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
getLinkAttribution() {
|
|
363
|
+
if (!this.linkAttribution.aegis_code) {
|
|
364
|
+
try {
|
|
365
|
+
const durable = this.storage.get("link_attribution");
|
|
366
|
+
if (durable) {
|
|
367
|
+
const parsed = JSON.parse(durable);
|
|
368
|
+
if (parsed && parsed.aegis_code) {
|
|
369
|
+
this.linkAttribution = parsed;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return this.linkAttribution;
|
|
376
|
+
}
|
|
337
377
|
destroy() {
|
|
338
378
|
if (this.checkInterval) {
|
|
339
379
|
clearInterval(this.checkInterval);
|
|
@@ -341,6 +381,97 @@ class SessionManager {
|
|
|
341
381
|
}
|
|
342
382
|
}
|
|
343
383
|
}
|
|
384
|
+
const FBP_COOKIE = "_fbp";
|
|
385
|
+
const FBC_COOKIE = "_fbc";
|
|
386
|
+
const COOKIE_LIFETIME_DAYS = 90;
|
|
387
|
+
function readCookie(name) {
|
|
388
|
+
if (typeof document === "undefined") return null;
|
|
389
|
+
try {
|
|
390
|
+
const target = `${name}=`;
|
|
391
|
+
const parts = document.cookie.split(";");
|
|
392
|
+
for (let i = 0; i < parts.length; i++) {
|
|
393
|
+
let c = parts[i];
|
|
394
|
+
while (c.charAt(0) === " ") c = c.substring(1);
|
|
395
|
+
if (c.indexOf(target) === 0) {
|
|
396
|
+
return decodeURIComponent(c.substring(target.length));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
function writeCookie(name, value, days) {
|
|
404
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
405
|
+
try {
|
|
406
|
+
const expiry = new Date(Date.now() + days * 24 * 60 * 60 * 1e3).toUTCString();
|
|
407
|
+
const domain = getRootDomain();
|
|
408
|
+
const isHttps = window.location.protocol === "https:";
|
|
409
|
+
let cookieStr = `${name}=${encodeURIComponent(value)};expires=${expiry};path=/;SameSite=Lax`;
|
|
410
|
+
if (isHttps) cookieStr += ";Secure";
|
|
411
|
+
if (domain) cookieStr += `;domain=${domain}`;
|
|
412
|
+
document.cookie = cookieStr;
|
|
413
|
+
} catch {
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function getRootDomain() {
|
|
417
|
+
if (typeof window === "undefined") return null;
|
|
418
|
+
const host = window.location.hostname;
|
|
419
|
+
if (!host || host === "localhost") return null;
|
|
420
|
+
if (/^\d+\.\d+\.\d+\.\d+$/.test(host)) return null;
|
|
421
|
+
const parts = host.split(".");
|
|
422
|
+
if (parts.length < 2) return null;
|
|
423
|
+
return "." + parts.slice(-2).join(".");
|
|
424
|
+
}
|
|
425
|
+
function subdomainIndex() {
|
|
426
|
+
if (typeof window === "undefined") return 1;
|
|
427
|
+
const host = window.location.hostname;
|
|
428
|
+
if (!host || host === "localhost" || /^\d+\.\d+\.\d+\.\d+$/.test(host)) return 1;
|
|
429
|
+
const parts = host.split(".");
|
|
430
|
+
return Math.max(1, parts.length - 1);
|
|
431
|
+
}
|
|
432
|
+
function randomToken() {
|
|
433
|
+
const n = Math.floor(Math.random() * 1e10);
|
|
434
|
+
return n.toString().padStart(10, "0");
|
|
435
|
+
}
|
|
436
|
+
function ensureFbp() {
|
|
437
|
+
const existing = readCookie(FBP_COOKIE);
|
|
438
|
+
if (existing) return existing;
|
|
439
|
+
const fbp = `fb.${subdomainIndex()}.${Date.now()}.${randomToken()}`;
|
|
440
|
+
writeCookie(FBP_COOKIE, fbp, COOKIE_LIFETIME_DAYS);
|
|
441
|
+
return fbp;
|
|
442
|
+
}
|
|
443
|
+
function ensureFbc() {
|
|
444
|
+
const existing = readCookie(FBC_COOKIE);
|
|
445
|
+
if (existing) return existing;
|
|
446
|
+
const fbclid = readFbclidFromUrl();
|
|
447
|
+
if (!fbclid) return null;
|
|
448
|
+
const fbc = `fb.${subdomainIndex()}.${Date.now()}.${fbclid}`;
|
|
449
|
+
writeCookie(FBC_COOKIE, fbc, COOKIE_LIFETIME_DAYS);
|
|
450
|
+
return fbc;
|
|
451
|
+
}
|
|
452
|
+
function readFbclidFromUrl() {
|
|
453
|
+
if (typeof window === "undefined") return null;
|
|
454
|
+
try {
|
|
455
|
+
return new URLSearchParams(window.location.search).get("fbclid");
|
|
456
|
+
} catch {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function captureMetaCookies() {
|
|
461
|
+
return {
|
|
462
|
+
fbp: ensureFbp(),
|
|
463
|
+
fbc: ensureFbc(),
|
|
464
|
+
fbclid: readFbclidFromUrl()
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function redactMetaCookies(event) {
|
|
468
|
+
const props = event == null ? void 0 : event.properties;
|
|
469
|
+
if (!props || props.fbc === void 0 && props.fbp === void 0) return event;
|
|
470
|
+
const masked = { ...props };
|
|
471
|
+
if (masked.fbc !== void 0) masked.fbc = "[redacted]";
|
|
472
|
+
if (masked.fbp !== void 0) masked.fbp = "[redacted]";
|
|
473
|
+
return { ...event, properties: masked };
|
|
474
|
+
}
|
|
344
475
|
class EventQueue {
|
|
345
476
|
constructor(config, transport, storage) {
|
|
346
477
|
this.buffer = [];
|
|
@@ -428,7 +559,7 @@ class EventQueue {
|
|
|
428
559
|
return;
|
|
429
560
|
}
|
|
430
561
|
this.buffer.push(event);
|
|
431
|
-
logger.debug("Event queued:", event.type, event);
|
|
562
|
+
logger.debug("Event queued:", event.type, redactMetaCookies(event));
|
|
432
563
|
if (this.buffer.length >= this.config.batchSize) {
|
|
433
564
|
this.flush();
|
|
434
565
|
}
|
|
@@ -980,6 +1111,20 @@ class Storage {
|
|
|
980
1111
|
}
|
|
981
1112
|
}
|
|
982
1113
|
}
|
|
1114
|
+
const CREDENTIAL_URL_PARAMS = ["t", "k", "code", "session_code", "aegis_pair", "u"];
|
|
1115
|
+
const REDACTED = "REDACTED";
|
|
1116
|
+
const CREDENTIAL_PARAM_PATTERN = new RegExp(
|
|
1117
|
+
`([?&])(${CREDENTIAL_URL_PARAMS.join("|")})=([^&#\\s"'<>]+)`,
|
|
1118
|
+
"g"
|
|
1119
|
+
);
|
|
1120
|
+
function redactUrl(value) {
|
|
1121
|
+
if (typeof value !== "string" || value.length === 0) return value;
|
|
1122
|
+
try {
|
|
1123
|
+
return value.replace(CREDENTIAL_PARAM_PATTERN, `$1$2=${REDACTED}`);
|
|
1124
|
+
} catch {
|
|
1125
|
+
return value;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
983
1128
|
function parseUTMParameters(url) {
|
|
984
1129
|
try {
|
|
985
1130
|
const searchParams = url ? new URL(url).searchParams : new URLSearchParams(window.location.search);
|
|
@@ -1010,6 +1155,8 @@ function parseAdClickIDs(url) {
|
|
|
1010
1155
|
const adClickIDs = {};
|
|
1011
1156
|
const clickIDKeys = [
|
|
1012
1157
|
"gclid",
|
|
1158
|
+
"gbraid",
|
|
1159
|
+
"wbraid",
|
|
1013
1160
|
"fbclid",
|
|
1014
1161
|
"msclkid",
|
|
1015
1162
|
"ctwa_clid",
|
|
@@ -1031,6 +1178,30 @@ function parseAdClickIDs(url) {
|
|
|
1031
1178
|
function hasAdClickIDs(adClickIDs) {
|
|
1032
1179
|
return Object.keys(adClickIDs).length > 0;
|
|
1033
1180
|
}
|
|
1181
|
+
const LINK_ATTRIBUTION_KEYS = [
|
|
1182
|
+
"aegis_code",
|
|
1183
|
+
"aegis_campaign",
|
|
1184
|
+
"aegis_journey",
|
|
1185
|
+
"aegis_playbook",
|
|
1186
|
+
"aegis_button"
|
|
1187
|
+
];
|
|
1188
|
+
function parseLinkAttribution(url) {
|
|
1189
|
+
try {
|
|
1190
|
+
const searchParams = url ? new URL(url).searchParams : new URLSearchParams(window.location.search);
|
|
1191
|
+
if (!searchParams.get("aegis_code")) return {};
|
|
1192
|
+
const attribution = {};
|
|
1193
|
+
LINK_ATTRIBUTION_KEYS.forEach((key) => {
|
|
1194
|
+
const value = searchParams.get(key);
|
|
1195
|
+
if (value) {
|
|
1196
|
+
attribution[key] = value;
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
return attribution;
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
console.warn("[Active Reach URL Parser] parseLinkAttribution failed:", error);
|
|
1202
|
+
return {};
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1034
1205
|
function buildContext(config, session) {
|
|
1035
1206
|
const utm = config.capture_utm ? parseUTMParameters() : void 0;
|
|
1036
1207
|
const device = detectDevice();
|
|
@@ -1038,18 +1209,22 @@ function buildContext(config, session) {
|
|
|
1038
1209
|
const browser = detectBrowser();
|
|
1039
1210
|
const network = detectNetworkInfo();
|
|
1040
1211
|
const adClickIDs = session == null ? void 0 : session.getAdClickIDs();
|
|
1041
|
-
const
|
|
1212
|
+
const storedLandingPage = session == null ? void 0 : session.getLandingPage();
|
|
1213
|
+
const landingPage = storedLandingPage ? redactUrl(storedLandingPage) : void 0;
|
|
1042
1214
|
return {
|
|
1043
1215
|
library: {
|
|
1044
1216
|
name: "@active-reach/web-sdk",
|
|
1045
1217
|
version: "1.0.0"
|
|
1046
1218
|
},
|
|
1219
|
+
// Credential params (`k`, `t`, `code`, ...) keep their key and lose their
|
|
1220
|
+
// value here, where the URL enters the page object. The referrer is
|
|
1221
|
+
// redacted too: the previous page can be our own order/landing link.
|
|
1047
1222
|
page: {
|
|
1048
1223
|
path: window.location.pathname,
|
|
1049
|
-
referrer: config.capture_referrer ? document.referrer : "",
|
|
1050
|
-
search: window.location.search,
|
|
1224
|
+
referrer: config.capture_referrer ? redactUrl(document.referrer) : "",
|
|
1225
|
+
search: redactUrl(window.location.search),
|
|
1051
1226
|
title: document.title,
|
|
1052
|
-
url: window.location.href,
|
|
1227
|
+
url: redactUrl(window.location.href),
|
|
1053
1228
|
hash: window.location.hash
|
|
1054
1229
|
},
|
|
1055
1230
|
userAgent: navigator.userAgent,
|
|
@@ -1525,96 +1700,13 @@ class ConsentManager {
|
|
|
1525
1700
|
updateGoogleConsent();
|
|
1526
1701
|
}
|
|
1527
1702
|
}
|
|
1528
|
-
const FBP_COOKIE = "_fbp";
|
|
1529
|
-
const FBC_COOKIE = "_fbc";
|
|
1530
|
-
const COOKIE_LIFETIME_DAYS = 90;
|
|
1531
|
-
function readCookie(name) {
|
|
1532
|
-
if (typeof document === "undefined") return null;
|
|
1533
|
-
try {
|
|
1534
|
-
const target = `${name}=`;
|
|
1535
|
-
const parts = document.cookie.split(";");
|
|
1536
|
-
for (let i = 0; i < parts.length; i++) {
|
|
1537
|
-
let c = parts[i];
|
|
1538
|
-
while (c.charAt(0) === " ") c = c.substring(1);
|
|
1539
|
-
if (c.indexOf(target) === 0) {
|
|
1540
|
-
return decodeURIComponent(c.substring(target.length));
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
} catch {
|
|
1544
|
-
}
|
|
1545
|
-
return null;
|
|
1546
|
-
}
|
|
1547
|
-
function writeCookie(name, value, days) {
|
|
1548
|
-
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1549
|
-
try {
|
|
1550
|
-
const expiry = new Date(Date.now() + days * 24 * 60 * 60 * 1e3).toUTCString();
|
|
1551
|
-
const domain = getRootDomain();
|
|
1552
|
-
const isHttps = window.location.protocol === "https:";
|
|
1553
|
-
let cookieStr = `${name}=${encodeURIComponent(value)};expires=${expiry};path=/;SameSite=Lax`;
|
|
1554
|
-
if (isHttps) cookieStr += ";Secure";
|
|
1555
|
-
if (domain) cookieStr += `;domain=${domain}`;
|
|
1556
|
-
document.cookie = cookieStr;
|
|
1557
|
-
} catch {
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
function getRootDomain() {
|
|
1561
|
-
if (typeof window === "undefined") return null;
|
|
1562
|
-
const host = window.location.hostname;
|
|
1563
|
-
if (!host || host === "localhost") return null;
|
|
1564
|
-
if (/^\d+\.\d+\.\d+\.\d+$/.test(host)) return null;
|
|
1565
|
-
const parts = host.split(".");
|
|
1566
|
-
if (parts.length < 2) return null;
|
|
1567
|
-
return "." + parts.slice(-2).join(".");
|
|
1568
|
-
}
|
|
1569
|
-
function subdomainIndex() {
|
|
1570
|
-
if (typeof window === "undefined") return 1;
|
|
1571
|
-
const host = window.location.hostname;
|
|
1572
|
-
if (!host || host === "localhost" || /^\d+\.\d+\.\d+\.\d+$/.test(host)) return 1;
|
|
1573
|
-
const parts = host.split(".");
|
|
1574
|
-
return Math.max(1, parts.length - 1);
|
|
1575
|
-
}
|
|
1576
|
-
function randomToken() {
|
|
1577
|
-
const n = Math.floor(Math.random() * 1e10);
|
|
1578
|
-
return n.toString().padStart(10, "0");
|
|
1579
|
-
}
|
|
1580
|
-
function ensureFbp() {
|
|
1581
|
-
const existing = readCookie(FBP_COOKIE);
|
|
1582
|
-
if (existing) return existing;
|
|
1583
|
-
const fbp = `fb.${subdomainIndex()}.${Date.now()}.${randomToken()}`;
|
|
1584
|
-
writeCookie(FBP_COOKIE, fbp, COOKIE_LIFETIME_DAYS);
|
|
1585
|
-
return fbp;
|
|
1586
|
-
}
|
|
1587
|
-
function ensureFbc() {
|
|
1588
|
-
const existing = readCookie(FBC_COOKIE);
|
|
1589
|
-
if (existing) return existing;
|
|
1590
|
-
const fbclid = readFbclidFromUrl();
|
|
1591
|
-
if (!fbclid) return null;
|
|
1592
|
-
const fbc = `fb.${subdomainIndex()}.${Date.now()}.${fbclid}`;
|
|
1593
|
-
writeCookie(FBC_COOKIE, fbc, COOKIE_LIFETIME_DAYS);
|
|
1594
|
-
return fbc;
|
|
1595
|
-
}
|
|
1596
|
-
function readFbclidFromUrl() {
|
|
1597
|
-
if (typeof window === "undefined") return null;
|
|
1598
|
-
try {
|
|
1599
|
-
return new URLSearchParams(window.location.search).get("fbclid");
|
|
1600
|
-
} catch {
|
|
1601
|
-
return null;
|
|
1602
|
-
}
|
|
1603
|
-
}
|
|
1604
|
-
function captureMetaCookies() {
|
|
1605
|
-
return {
|
|
1606
|
-
fbp: ensureFbp(),
|
|
1607
|
-
fbc: ensureFbc(),
|
|
1608
|
-
fbclid: readFbclidFromUrl()
|
|
1609
|
-
};
|
|
1610
|
-
}
|
|
1611
1703
|
function sumItems(products) {
|
|
1612
1704
|
return products.reduce((sum, p) => sum + (p.quantity ?? 1), 0);
|
|
1613
1705
|
}
|
|
1614
1706
|
function mapProducts(products) {
|
|
1615
1707
|
return products.map((p) => ({
|
|
1616
1708
|
product_id: p.product_id,
|
|
1617
|
-
sku: p.sku
|
|
1709
|
+
sku: p.sku,
|
|
1618
1710
|
name: p.name,
|
|
1619
1711
|
price: p.price,
|
|
1620
1712
|
quantity: p.quantity ?? 1,
|
|
@@ -1653,7 +1745,7 @@ class EcommerceTracker {
|
|
|
1653
1745
|
productViewed(product) {
|
|
1654
1746
|
this.aegis.track("product_viewed", {
|
|
1655
1747
|
product_id: product.product_id,
|
|
1656
|
-
sku: product.sku
|
|
1748
|
+
sku: product.sku,
|
|
1657
1749
|
name: product.name,
|
|
1658
1750
|
price: product.price,
|
|
1659
1751
|
currency: product.currency ?? "INR",
|
|
@@ -1666,17 +1758,29 @@ class EcommerceTracker {
|
|
|
1666
1758
|
});
|
|
1667
1759
|
}
|
|
1668
1760
|
productListViewed(list) {
|
|
1761
|
+
const products = mapProducts(list.products);
|
|
1669
1762
|
this.aegis.track("product_list_viewed", {
|
|
1670
1763
|
list_id: list.list_id,
|
|
1671
1764
|
list_name: list.list_name,
|
|
1672
1765
|
category: list.category,
|
|
1673
|
-
products
|
|
1766
|
+
products,
|
|
1767
|
+
// `items` as well as `products` — a THIRD spelling of the same fact was
|
|
1768
|
+
// one spelling too many. Every product reader in the platform looks for
|
|
1769
|
+
// `items` (or `line_items`, the Shopify shape); this event alone said
|
|
1770
|
+
// `products`, so a list view showed N products and contributed nothing to
|
|
1771
|
+
// any of them. On ST that was 4 views recorded as `not measured`, and it
|
|
1772
|
+
// is the same defect that made every Shopify order invisible.
|
|
1773
|
+
//
|
|
1774
|
+
// `products` is kept so nothing already reading it breaks. mapProducts
|
|
1775
|
+
// already emits product_id / sku / name / price / quantity, which is
|
|
1776
|
+
// exactly the canonical item shape — no second mapping to drift.
|
|
1777
|
+
items: products
|
|
1674
1778
|
});
|
|
1675
1779
|
}
|
|
1676
1780
|
productClicked(product, source) {
|
|
1677
1781
|
this.aegis.track("product_clicked", {
|
|
1678
1782
|
product_id: product.product_id,
|
|
1679
|
-
sku: product.sku
|
|
1783
|
+
sku: product.sku,
|
|
1680
1784
|
name: product.name,
|
|
1681
1785
|
price: product.price,
|
|
1682
1786
|
currency: product.currency ?? "INR",
|
|
@@ -1691,7 +1795,7 @@ class EcommerceTracker {
|
|
|
1691
1795
|
productImpressed(product, source) {
|
|
1692
1796
|
this.aegis.track("product_impression", {
|
|
1693
1797
|
product_id: product.product_id,
|
|
1694
|
-
sku: product.sku
|
|
1798
|
+
sku: product.sku,
|
|
1695
1799
|
name: product.name,
|
|
1696
1800
|
price: product.price,
|
|
1697
1801
|
currency: product.currency ?? "INR",
|
|
@@ -1720,7 +1824,7 @@ class EcommerceTracker {
|
|
|
1720
1824
|
const qty = product.quantity ?? 1;
|
|
1721
1825
|
this.aegis.track("cart_item_added", {
|
|
1722
1826
|
product_id: product.product_id,
|
|
1723
|
-
sku: product.sku
|
|
1827
|
+
sku: product.sku,
|
|
1724
1828
|
name: product.name,
|
|
1725
1829
|
price: product.price,
|
|
1726
1830
|
quantity: qty,
|
|
@@ -1739,7 +1843,7 @@ class EcommerceTracker {
|
|
|
1739
1843
|
const qty = product.quantity ?? 1;
|
|
1740
1844
|
this.aegis.track("cart_item_removed", {
|
|
1741
1845
|
product_id: product.product_id,
|
|
1742
|
-
sku: product.sku
|
|
1846
|
+
sku: product.sku,
|
|
1743
1847
|
name: product.name,
|
|
1744
1848
|
price: product.price,
|
|
1745
1849
|
quantity: qty,
|
|
@@ -1834,7 +1938,7 @@ class EcommerceTracker {
|
|
|
1834
1938
|
wishlist_id: wishlist.wishlist_id,
|
|
1835
1939
|
wishlist_name: wishlist.wishlist_name,
|
|
1836
1940
|
product_id: wishlist.product.product_id,
|
|
1837
|
-
sku: wishlist.product.sku
|
|
1941
|
+
sku: wishlist.product.sku,
|
|
1838
1942
|
name: wishlist.product.name,
|
|
1839
1943
|
price: wishlist.product.price,
|
|
1840
1944
|
variant_id: wishlist.product.variant_id
|
|
@@ -1845,7 +1949,7 @@ class EcommerceTracker {
|
|
|
1845
1949
|
wishlist_id: wishlist.wishlist_id,
|
|
1846
1950
|
wishlist_name: wishlist.wishlist_name,
|
|
1847
1951
|
product_id: wishlist.product.product_id,
|
|
1848
|
-
sku: wishlist.product.sku
|
|
1952
|
+
sku: wishlist.product.sku,
|
|
1849
1953
|
name: wishlist.product.name,
|
|
1850
1954
|
price: wishlist.product.price,
|
|
1851
1955
|
variant_id: wishlist.product.variant_id
|
|
@@ -1862,7 +1966,7 @@ class EcommerceTracker {
|
|
|
1862
1966
|
productWaitlisted(waitlist) {
|
|
1863
1967
|
this.aegis.track("product_waitlisted", {
|
|
1864
1968
|
product_id: waitlist.product.product_id,
|
|
1865
|
-
sku: waitlist.product.sku
|
|
1969
|
+
sku: waitlist.product.sku,
|
|
1866
1970
|
variant_id: waitlist.product.variant_id,
|
|
1867
1971
|
name: waitlist.product.name,
|
|
1868
1972
|
price: waitlist.product.price,
|
|
@@ -2569,6 +2673,7 @@ class Aegis {
|
|
|
2569
2673
|
if (currentUrl === this._lastPageUrl) return;
|
|
2570
2674
|
this._lastPageUrl = currentUrl;
|
|
2571
2675
|
setTimeout(() => {
|
|
2676
|
+
if (!this._popstateHandler) return;
|
|
2572
2677
|
this.page();
|
|
2573
2678
|
}, 50);
|
|
2574
2679
|
};
|
|
@@ -2617,9 +2722,13 @@ class Aegis {
|
|
|
2617
2722
|
if (!this.session) return;
|
|
2618
2723
|
const adClickIDs = parseAdClickIDs();
|
|
2619
2724
|
if (hasAdClickIDs(adClickIDs)) {
|
|
2620
|
-
this.session.setAdClickIDs(adClickIDs, window.location.href);
|
|
2725
|
+
this.session.setAdClickIDs(adClickIDs, redactUrl(window.location.href));
|
|
2621
2726
|
logger.info("Ad click IDs captured on page load:", adClickIDs);
|
|
2622
2727
|
}
|
|
2728
|
+
const linkAttribution = parseLinkAttribution();
|
|
2729
|
+
if (linkAttribution.aegis_code) {
|
|
2730
|
+
this.session.setLinkAttribution(linkAttribution);
|
|
2731
|
+
}
|
|
2623
2732
|
}
|
|
2624
2733
|
async initializePlugins() {
|
|
2625
2734
|
if (!this.config) return;
|
|
@@ -3028,26 +3137,38 @@ class Aegis {
|
|
|
3028
3137
|
}
|
|
3029
3138
|
const ctx = event.context;
|
|
3030
3139
|
const props = event.properties;
|
|
3031
|
-
if ((ctx == null ? void 0 : ctx.campaign) && props
|
|
3140
|
+
if ((ctx == null ? void 0 : ctx.campaign) && props) {
|
|
3032
3141
|
const utm = ctx.campaign;
|
|
3033
|
-
if (utm.
|
|
3034
|
-
if (utm.
|
|
3035
|
-
if (utm.
|
|
3036
|
-
if (utm.content) props.
|
|
3037
|
-
if (utm.term) props.
|
|
3142
|
+
if (utm.source && !props.utm_source) props.utm_source = utm.source;
|
|
3143
|
+
if (utm.medium && !props.utm_medium) props.utm_medium = utm.medium;
|
|
3144
|
+
if (utm.campaign && !props.utm_campaign) props.utm_campaign = utm.campaign;
|
|
3145
|
+
if (utm.content && !props.utm_content) props.utm_content = utm.content;
|
|
3146
|
+
if (utm.term && !props.utm_term) props.utm_term = utm.term;
|
|
3038
3147
|
}
|
|
3039
3148
|
if ((ctx == null ? void 0 : ctx.adClickIDs) && props) {
|
|
3040
3149
|
const clicks = ctx.adClickIDs;
|
|
3150
|
+
if (clicks.gclid && !props.gclid) props.gclid = clicks.gclid;
|
|
3151
|
+
if (clicks.gbraid && !props.gbraid) props.gbraid = clicks.gbraid;
|
|
3152
|
+
if (clicks.wbraid && !props.wbraid) props.wbraid = clicks.wbraid;
|
|
3153
|
+
if (clicks.fbclid && !props.fbclid) props.fbclid = clicks.fbclid;
|
|
3041
3154
|
const clickId = clicks.gclid || clicks.fbclid || clicks.ctwa_clid || clicks.msclkid || clicks.ttclid;
|
|
3042
3155
|
if (clickId && !props.campaign_click_id) props.campaign_click_id = clickId;
|
|
3043
3156
|
}
|
|
3157
|
+
if (props && this.session) {
|
|
3158
|
+
const link = this.session.getLinkAttribution();
|
|
3159
|
+
if (link.aegis_code) {
|
|
3160
|
+
for (const [key, value] of Object.entries(link)) {
|
|
3161
|
+
if (value && !props[key]) props[key] = value;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3044
3165
|
if (props) {
|
|
3045
3166
|
const meta = captureMetaCookies();
|
|
3046
3167
|
if (meta.fbp && !props.fbp) props.fbp = meta.fbp;
|
|
3047
3168
|
if (meta.fbc && !props.fbc) props.fbc = meta.fbc;
|
|
3048
3169
|
if (meta.fbclid && !props.fbclid) props.fbclid = meta.fbclid;
|
|
3049
3170
|
}
|
|
3050
|
-
logger.debug("Capturing event:", event);
|
|
3171
|
+
logger.debug("Capturing event:", redactMetaCookies(event));
|
|
3051
3172
|
const transformedEvent = await this.plugins.executeHookChain(
|
|
3052
3173
|
"beforeEventCapture",
|
|
3053
3174
|
event
|
|
@@ -3154,6 +3275,18 @@ class Aegis {
|
|
|
3154
3275
|
if (!this.identity) return null;
|
|
3155
3276
|
return this.identity.getUserId();
|
|
3156
3277
|
}
|
|
3278
|
+
/**
|
|
3279
|
+
* The Aegis short-link attribution captured from this visitor's landing URL
|
|
3280
|
+
* (`aegis_code` + the link row's `aegis_campaign` / `aegis_journey` /
|
|
3281
|
+
* `aegis_playbook` / `aegis_button`), or `{}` when they did not arrive
|
|
3282
|
+
* through one. Hosts forward `aegis_code` with an order so the order can be
|
|
3283
|
+
* joined to the send that brought the shopper. Never contains `utm_*`, `k`,
|
|
3284
|
+
* `t` or `u`.
|
|
3285
|
+
*/
|
|
3286
|
+
getLinkAttribution() {
|
|
3287
|
+
if (!this.session) return {};
|
|
3288
|
+
return { ...this.session.getLinkAttribution() };
|
|
3289
|
+
}
|
|
3157
3290
|
/**
|
|
3158
3291
|
* Fetch the identified contact's REDEEMABLE rewards — coupon codes the
|
|
3159
3292
|
* storefront can auto-apply at checkout + loyalty points balance/tier.
|
|
@@ -3345,6 +3478,7 @@ export {
|
|
|
3345
3478
|
Storage as S,
|
|
3346
3479
|
UserNamespace as U,
|
|
3347
3480
|
logger as l,
|
|
3348
|
-
murmurhash3_x86_32 as m
|
|
3481
|
+
murmurhash3_x86_32 as m,
|
|
3482
|
+
redactUrl as r
|
|
3349
3483
|
};
|
|
3350
|
-
//# sourceMappingURL=analytics-
|
|
3484
|
+
//# sourceMappingURL=analytics-Cz1ZBOxH.mjs.map
|