@active-reach/web-sdk 1.36.9 → 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 +18 -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 +217 -30
- 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
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as Storage, l as logger, A as Aegis } from "./analytics-
|
|
2
|
-
import { B, E, N, R, U, m } from "./analytics-
|
|
1
|
+
import { S as Storage, r as redactUrl, l as logger, A as Aegis } from "./analytics-Cz1ZBOxH.mjs";
|
|
2
|
+
import { B, E, N, R, U, m } from "./analytics-Cz1ZBOxH.mjs";
|
|
3
3
|
import { AegisWebPush } from "./push/AegisWebPush.js";
|
|
4
4
|
function debounce(func, wait) {
|
|
5
5
|
let timeoutId = null;
|
|
@@ -26,6 +26,13 @@ function throttle(func, limit) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
const PDP_SKU_RE = /\/p\/([^/?#]+)/;
|
|
29
|
+
function productPath(sku) {
|
|
30
|
+
const encoded = encodeURIComponent(sku).replace(
|
|
31
|
+
/[!'()*]/g,
|
|
32
|
+
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
|
33
|
+
);
|
|
34
|
+
return `/p/${encoded}`;
|
|
35
|
+
}
|
|
29
36
|
function parseAction(actionUrl, meta) {
|
|
30
37
|
const url = (actionUrl ?? "").trim();
|
|
31
38
|
const m2 = meta ?? {};
|
|
@@ -61,7 +68,7 @@ function parseAction(actionUrl, meta) {
|
|
|
61
68
|
case "open-product":
|
|
62
69
|
case "product": {
|
|
63
70
|
const sku = params.get("sku") || m2.sku || void 0;
|
|
64
|
-
return { type: "open_product", sku, productId: m2.product_id, url: sku ?
|
|
71
|
+
return { type: "open_product", sku, productId: m2.product_id, url: sku ? productPath(sku) : void 0 };
|
|
65
72
|
}
|
|
66
73
|
default:
|
|
67
74
|
return { type: "custom", name: verb || "unknown", payload: Object.fromEntries(params) };
|
|
@@ -96,7 +103,7 @@ function parseAction(actionUrl, meta) {
|
|
|
96
103
|
}
|
|
97
104
|
return { type: "dismiss" };
|
|
98
105
|
}
|
|
99
|
-
function fallbackUrlForAction(a, productUrl =
|
|
106
|
+
function fallbackUrlForAction(a, productUrl = productPath) {
|
|
100
107
|
switch (a.type) {
|
|
101
108
|
case "navigate":
|
|
102
109
|
return a.url;
|
|
@@ -652,9 +659,11 @@ function appendRatingThanks(wrap, el2, ctx, fg, accent, isHigh) {
|
|
|
652
659
|
cta.textContent = el2.rating_high_cta || "Leave a review";
|
|
653
660
|
cta.style.cssText = `margin:4px auto 0;display:block;padding:9px 18px;border:none;border-radius:999px;background:${accent};color:#fff;font-size:13px;font-weight:800;cursor:pointer;`;
|
|
654
661
|
cta.addEventListener("click", () => {
|
|
662
|
+
var _a;
|
|
655
663
|
ctx.trackEvent(ctx.campaign.id, "clicked", {
|
|
656
664
|
meta: { element: "rating_input", cta: "high_review" }
|
|
657
665
|
});
|
|
666
|
+
void ((_a = ctx.submitResponse) == null ? void 0 : _a.call(ctx, "review_redirect", { cta: "high_review" }));
|
|
658
667
|
if (ctx.navigate) ctx.navigate(url, "cta");
|
|
659
668
|
else window.location.href = url;
|
|
660
669
|
});
|
|
@@ -821,6 +830,7 @@ function buildProductRatingListElement(el2, ctx, fg) {
|
|
|
821
830
|
const orderId = slot.getAttribute("data-order-id");
|
|
822
831
|
const billCode = slot.getAttribute("data-bill-code");
|
|
823
832
|
const token = slot.getAttribute("data-token");
|
|
833
|
+
const reviewsViaPage = Boolean(slot.getAttribute("data-reviews-url"));
|
|
824
834
|
const reviewsUrl = slot.getAttribute("data-reviews-url") || el2.rating_high_url || null;
|
|
825
835
|
const scale = typeof el2.rating_scale === "number" && el2.rating_scale >= 2 && el2.rating_scale <= 10 ? Math.floor(el2.rating_scale) : 5;
|
|
826
836
|
const showThumb = el2.show_thumbnail !== false && el2.rating_layout !== "compact";
|
|
@@ -1071,6 +1081,12 @@ function buildProductRatingListElement(el2, ctx, fg) {
|
|
|
1071
1081
|
a.href = ctx.sanitizeUrl(reviewsUrl) || "#";
|
|
1072
1082
|
a.textContent = el2.rating_high_cta || "Share a review";
|
|
1073
1083
|
a.style.cssText = `display:inline-block;margin-top:6px;font-size:12px;font-weight:700;color:${accent};text-decoration:none;`;
|
|
1084
|
+
if (!reviewsViaPage) {
|
|
1085
|
+
a.addEventListener("click", () => {
|
|
1086
|
+
var _a2;
|
|
1087
|
+
void ((_a2 = ctx.submitResponse) == null ? void 0 : _a2.call(ctx, "review_redirect", { cta: "item_rating_review" }));
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1074
1090
|
ack.appendChild(a);
|
|
1075
1091
|
}
|
|
1076
1092
|
wrap.appendChild(ack);
|
|
@@ -1247,9 +1263,11 @@ function appendNpsThanks(wrap, el2, ctx, fg, accent, isPromoter) {
|
|
|
1247
1263
|
cta.textContent = el2.nps_promoter_cta || "Leave a review";
|
|
1248
1264
|
cta.style.cssText = `margin:4px auto 0;display:block;padding:9px 18px;border:none;border-radius:999px;background:${accent};color:#fff;font-size:13px;font-weight:800;cursor:pointer;`;
|
|
1249
1265
|
cta.addEventListener("click", () => {
|
|
1266
|
+
var _a;
|
|
1250
1267
|
ctx.trackEvent(ctx.campaign.id, "clicked", {
|
|
1251
1268
|
meta: { element: "nps", cta: "promoter_review" }
|
|
1252
1269
|
});
|
|
1270
|
+
void ((_a = ctx.submitResponse) == null ? void 0 : _a.call(ctx, "review_redirect", { cta: "promoter_review" }));
|
|
1253
1271
|
if (ctx.navigate) ctx.navigate(url, "cta");
|
|
1254
1272
|
else window.location.href = url;
|
|
1255
1273
|
});
|
|
@@ -4937,7 +4955,7 @@ class TriggerEngine {
|
|
|
4937
4955
|
this.exitIntentFired = true;
|
|
4938
4956
|
this.emit("exit_intent", {
|
|
4939
4957
|
client_y: event.clientY,
|
|
4940
|
-
page_url: window.location.href,
|
|
4958
|
+
page_url: redactUrl(window.location.href),
|
|
4941
4959
|
time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1e3 : 0
|
|
4942
4960
|
});
|
|
4943
4961
|
}
|
|
@@ -4958,7 +4976,7 @@ class TriggerEngine {
|
|
|
4958
4976
|
scroll_velocity: velocity,
|
|
4959
4977
|
scroll_distance: distance,
|
|
4960
4978
|
current_position: currentY,
|
|
4961
|
-
page_url: window.location.href,
|
|
4979
|
+
page_url: redactUrl(window.location.href),
|
|
4962
4980
|
time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1e3 : 0
|
|
4963
4981
|
});
|
|
4964
4982
|
this.scrollVelocityCooldownTimer = window.setTimeout(() => {
|
|
@@ -4972,12 +4990,12 @@ class TriggerEngine {
|
|
|
4972
4990
|
this.handleVisibilityChange = () => {
|
|
4973
4991
|
if (document.hidden) {
|
|
4974
4992
|
this.emit("visibility_hidden", {
|
|
4975
|
-
page_url: window.location.href,
|
|
4993
|
+
page_url: redactUrl(window.location.href),
|
|
4976
4994
|
time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1e3 : 0
|
|
4977
4995
|
});
|
|
4978
4996
|
} else {
|
|
4979
4997
|
this.emit("visibility_visible", {
|
|
4980
|
-
page_url: window.location.href
|
|
4998
|
+
page_url: redactUrl(window.location.href)
|
|
4981
4999
|
});
|
|
4982
5000
|
}
|
|
4983
5001
|
};
|
|
@@ -4988,7 +5006,7 @@ class TriggerEngine {
|
|
|
4988
5006
|
this.backButtonFired = true;
|
|
4989
5007
|
window.history.pushState(null, "", window.location.href);
|
|
4990
5008
|
this.emit("back_button", {
|
|
4991
|
-
page_url: window.location.href,
|
|
5009
|
+
page_url: redactUrl(window.location.href),
|
|
4992
5010
|
time_on_page: this.pageLoadTime ? (Date.now() - this.pageLoadTime) / 1e3 : 0
|
|
4993
5011
|
});
|
|
4994
5012
|
};
|
|
@@ -5016,7 +5034,7 @@ class TriggerEngine {
|
|
|
5016
5034
|
const timerId = window.setTimeout(() => {
|
|
5017
5035
|
this.emit(`time_on_page_${seconds}`, {
|
|
5018
5036
|
seconds,
|
|
5019
|
-
page_url: window.location.href
|
|
5037
|
+
page_url: redactUrl(window.location.href)
|
|
5020
5038
|
});
|
|
5021
5039
|
this.timeOnPageTargets.delete(seconds);
|
|
5022
5040
|
}, seconds * 1e3);
|
|
@@ -5936,6 +5954,54 @@ function renderReviewsOverlay(ctx, creds) {
|
|
|
5936
5954
|
document.body.appendChild(overlay);
|
|
5937
5955
|
renderReviewsInline(ctx, body, creds);
|
|
5938
5956
|
}
|
|
5957
|
+
const RETURNING_MARKER_KEY = "aegis_returning_user";
|
|
5958
|
+
const SESSION_VERDICT_KEY = "aegis_new_visitor_session";
|
|
5959
|
+
let cachedVerdict = null;
|
|
5960
|
+
function readSessionVerdict() {
|
|
5961
|
+
try {
|
|
5962
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
5963
|
+
const stored = sessionStorage.getItem(SESSION_VERDICT_KEY);
|
|
5964
|
+
if (stored === "1") return true;
|
|
5965
|
+
if (stored === "0") return false;
|
|
5966
|
+
return null;
|
|
5967
|
+
} catch {
|
|
5968
|
+
return null;
|
|
5969
|
+
}
|
|
5970
|
+
}
|
|
5971
|
+
function writeSessionVerdict(verdict) {
|
|
5972
|
+
try {
|
|
5973
|
+
if (typeof sessionStorage === "undefined") return;
|
|
5974
|
+
sessionStorage.setItem(SESSION_VERDICT_KEY, verdict ? "1" : "0");
|
|
5975
|
+
} catch {
|
|
5976
|
+
}
|
|
5977
|
+
}
|
|
5978
|
+
function readMarkerVerdict() {
|
|
5979
|
+
try {
|
|
5980
|
+
if (typeof localStorage === "undefined") return false;
|
|
5981
|
+
return localStorage.getItem(RETURNING_MARKER_KEY) === null;
|
|
5982
|
+
} catch {
|
|
5983
|
+
return false;
|
|
5984
|
+
}
|
|
5985
|
+
}
|
|
5986
|
+
function isNewVisitor() {
|
|
5987
|
+
if (cachedVerdict !== null) return cachedVerdict;
|
|
5988
|
+
const sessionVerdict = readSessionVerdict();
|
|
5989
|
+
if (sessionVerdict !== null) {
|
|
5990
|
+
cachedVerdict = sessionVerdict;
|
|
5991
|
+
return cachedVerdict;
|
|
5992
|
+
}
|
|
5993
|
+
cachedVerdict = readMarkerVerdict();
|
|
5994
|
+
writeSessionVerdict(cachedVerdict);
|
|
5995
|
+
return cachedVerdict;
|
|
5996
|
+
}
|
|
5997
|
+
function markReturningVisitor() {
|
|
5998
|
+
isNewVisitor();
|
|
5999
|
+
try {
|
|
6000
|
+
if (typeof localStorage === "undefined") return;
|
|
6001
|
+
localStorage.setItem(RETURNING_MARKER_KEY, "1");
|
|
6002
|
+
} catch {
|
|
6003
|
+
}
|
|
6004
|
+
}
|
|
5939
6005
|
function readAnonIdFromStorage$1() {
|
|
5940
6006
|
if (typeof document === "undefined") return void 0;
|
|
5941
6007
|
try {
|
|
@@ -5945,6 +6011,11 @@ function readAnonIdFromStorage$1() {
|
|
|
5945
6011
|
return void 0;
|
|
5946
6012
|
}
|
|
5947
6013
|
}
|
|
6014
|
+
const JOURNEY_ACK_ACTION = {
|
|
6015
|
+
impression: "viewed",
|
|
6016
|
+
clicked: "clicked",
|
|
6017
|
+
dismissed: "dismissed"
|
|
6018
|
+
};
|
|
5948
6019
|
function svgNode(svg) {
|
|
5949
6020
|
try {
|
|
5950
6021
|
const doc = new DOMParser().parseFromString(svg, "image/svg+xml");
|
|
@@ -5955,9 +6026,41 @@ function svgNode(svg) {
|
|
|
5955
6026
|
return null;
|
|
5956
6027
|
}
|
|
5957
6028
|
}
|
|
6029
|
+
const productIdentityCache = /* @__PURE__ */ new WeakMap();
|
|
6030
|
+
const UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6031
|
+
function productIdentitiesFor(campaign) {
|
|
6032
|
+
const ic = campaign == null ? void 0 : campaign.interactive_config;
|
|
6033
|
+
const cards = ic && Array.isArray(ic.cards) ? ic.cards : [];
|
|
6034
|
+
if (cards.length === 0) return void 0;
|
|
6035
|
+
const cached = productIdentityCache.get(cards);
|
|
6036
|
+
if (cached !== void 0) return cached || void 0;
|
|
6037
|
+
const items = [];
|
|
6038
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6039
|
+
for (const card of cards.slice(0, 24)) {
|
|
6040
|
+
const meta = (card == null ? void 0 : card.metadata) || {};
|
|
6041
|
+
const rawId = String(meta.product_id || "").trim();
|
|
6042
|
+
const rawSku = String(meta.sku || "").trim();
|
|
6043
|
+
const platformId = String(meta.platform_product_id || "").trim();
|
|
6044
|
+
const productId = UUID_SHAPE.test(rawId) ? rawId : "";
|
|
6045
|
+
const sku = rawSku && !UUID_SHAPE.test(rawSku) ? rawSku : rawId && !productId ? rawId : "";
|
|
6046
|
+
const identity = productId || sku || platformId;
|
|
6047
|
+
if (!identity || seen.has(identity)) continue;
|
|
6048
|
+
seen.add(identity);
|
|
6049
|
+
items.push({
|
|
6050
|
+
...productId ? { product_id: productId } : {},
|
|
6051
|
+
...sku ? { sku } : {},
|
|
6052
|
+
...!productId && !sku && platformId ? { platform_product_id: platformId } : {},
|
|
6053
|
+
name: String((card == null ? void 0 : card.title) || identity),
|
|
6054
|
+
quantity: 1
|
|
6055
|
+
});
|
|
6056
|
+
}
|
|
6057
|
+
const encoded = items.length > 0 ? JSON.stringify(items) : "";
|
|
6058
|
+
productIdentityCache.set(cards, encoded);
|
|
6059
|
+
return encoded || void 0;
|
|
6060
|
+
}
|
|
5958
6061
|
const _AegisInAppManager = class _AegisInAppManager {
|
|
5959
6062
|
constructor(config) {
|
|
5960
|
-
this.productUrl =
|
|
6063
|
+
this.productUrl = productPath;
|
|
5961
6064
|
this.campaigns = [];
|
|
5962
6065
|
this.displayedCampaigns = /* @__PURE__ */ new Set();
|
|
5963
6066
|
this._displaySizeMul = 1;
|
|
@@ -5983,6 +6086,8 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
5983
6086
|
this.slotUnfilledBeaconed = /* @__PURE__ */ new Set();
|
|
5984
6087
|
this.slotUnfilledSweepTimer = null;
|
|
5985
6088
|
this._pushOptInLoading = false;
|
|
6089
|
+
this.journeyStepByCampaign = /* @__PURE__ */ new Map();
|
|
6090
|
+
this.journeyAcks = /* @__PURE__ */ new Set();
|
|
5986
6091
|
this.writeKey = config.writeKey;
|
|
5987
6092
|
this.apiHost = config.apiHost || "https://api.aegis.ai";
|
|
5988
6093
|
this.userId = config.userId ?? readAnonIdFromStorage$1();
|
|
@@ -6088,13 +6193,13 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6088
6193
|
this.log("AegisInApp already initialized");
|
|
6089
6194
|
return;
|
|
6090
6195
|
}
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6196
|
+
markReturningVisitor();
|
|
6197
|
+
try {
|
|
6198
|
+
if (typeof localStorage !== "undefined") {
|
|
6094
6199
|
const pv = parseInt(localStorage.getItem("aegis_pv_count") || "0", 10);
|
|
6095
6200
|
localStorage.setItem("aegis_pv_count", String(pv + 1));
|
|
6096
|
-
} catch {
|
|
6097
6201
|
}
|
|
6202
|
+
} catch {
|
|
6098
6203
|
}
|
|
6099
6204
|
ensureInAppFont();
|
|
6100
6205
|
await this.refreshCampaigns();
|
|
@@ -6471,9 +6576,11 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6471
6576
|
try {
|
|
6472
6577
|
const context = new URLSearchParams({
|
|
6473
6578
|
device_type: this.detectDeviceType(),
|
|
6474
|
-
|
|
6579
|
+
// Credential params keep their key and lose their value, so a
|
|
6580
|
+
// `*placed=1*` / `*?step=cart*` rule still matches.
|
|
6581
|
+
page_url: typeof window !== "undefined" ? redactUrl(window.location.pathname + window.location.search) : "/"
|
|
6475
6582
|
});
|
|
6476
|
-
context.set("is_new_user",
|
|
6583
|
+
context.set("is_new_user", isNewVisitor() ? "true" : "false");
|
|
6477
6584
|
if (this.currentSurface) {
|
|
6478
6585
|
context.set("current_surface", this.currentSurface);
|
|
6479
6586
|
}
|
|
@@ -6555,28 +6662,29 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
6555
6662
|
if (/iPad|Tablet/i.test(ua)) return "tablet";
|
|
6556
6663
|
return "desktop";
|
|
6557
6664
|
}
|
|
6558
|
-
isNewUser() {
|
|
6559
|
-
if (typeof localStorage === "undefined") return true;
|
|
6560
|
-
return !localStorage.getItem("aegis_returning_user");
|
|
6561
|
-
}
|
|
6562
6665
|
// --- A/B Assignment Persistence (Critical Fix C) ---
|
|
6666
|
+
// Both A/B helpers sit on the campaign-fetch path, so blocked storage
|
|
6667
|
+
// (where even `typeof localStorage` throws) must not abort the fetch.
|
|
6563
6668
|
getABAssignments() {
|
|
6564
|
-
if (typeof localStorage === "undefined") return {};
|
|
6565
6669
|
try {
|
|
6670
|
+
if (typeof localStorage === "undefined") return {};
|
|
6566
6671
|
return JSON.parse(localStorage.getItem("aegis_ab_assignments") || "{}");
|
|
6567
6672
|
} catch {
|
|
6568
6673
|
return {};
|
|
6569
6674
|
}
|
|
6570
6675
|
}
|
|
6571
6676
|
processABAssignments(campaigns) {
|
|
6572
|
-
if (typeof localStorage === "undefined") return;
|
|
6573
6677
|
const stored = this.getABAssignments();
|
|
6574
6678
|
for (const campaign of campaigns) {
|
|
6575
6679
|
if (campaign.assigned_variant_id) {
|
|
6576
6680
|
stored[campaign.id] = campaign.assigned_variant_id;
|
|
6577
6681
|
}
|
|
6578
6682
|
}
|
|
6579
|
-
|
|
6683
|
+
try {
|
|
6684
|
+
if (typeof localStorage === "undefined") return;
|
|
6685
|
+
localStorage.setItem("aegis_ab_assignments", JSON.stringify(stored));
|
|
6686
|
+
} catch {
|
|
6687
|
+
}
|
|
6580
6688
|
}
|
|
6581
6689
|
getVariantId(campaignId) {
|
|
6582
6690
|
const assignments = this.getABAssignments();
|
|
@@ -11788,6 +11896,20 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
11788
11896
|
// to in_app_events.surface so the property By-screen breakdown can
|
|
11789
11897
|
// show real per-screen impressions/CTR.
|
|
11790
11898
|
current_surface: this.currentSurface ?? void 0,
|
|
11899
|
+
// The products this card actually rendered. Lands on the canonical
|
|
11900
|
+
// event's `properties.items` (gateway → switchboard), which is the
|
|
11901
|
+
// same array shape the bill page and the purchase event use, so ONE
|
|
11902
|
+
// materialized view turns every surface into per-product impressions.
|
|
11903
|
+
// See `productIdentitiesFor` for why this exists.
|
|
11904
|
+
//
|
|
11905
|
+
// ONLY on `impression` and `clicked`. `served` means "the SDK received
|
|
11906
|
+
// the payload", not "a customer saw it" — on ST there are 3,179 served
|
|
11907
|
+
// against 1,077 impressions, so counting both would treble the
|
|
11908
|
+
// impression denominator with renders that never reached a screen, and
|
|
11909
|
+
// put ~2KB of product JSON on three times as many requests for the
|
|
11910
|
+
// privilege. dismissed / anchor_unresolved / slot_unfilled describe the
|
|
11911
|
+
// widget, not the products.
|
|
11912
|
+
items: eventType === "impression" || eventType === "clicked" ? productIdentitiesFor(trackedCampaign) : void 0,
|
|
11791
11913
|
// P3 — optional step_id surfaces multi-step granularity
|
|
11792
11914
|
// (WEB_SDK_DLR_ENHANCEMENT_TRACKER P3). Server validator + CH
|
|
11793
11915
|
// schema accept null/empty as the single-step default.
|
|
@@ -11826,6 +11948,67 @@ const _AegisInAppManager = class _AegisInAppManager {
|
|
|
11826
11948
|
} catch (error) {
|
|
11827
11949
|
this.log(`Error tracking event: ${error}`, "error");
|
|
11828
11950
|
}
|
|
11951
|
+
const step = (trackedCampaign == null ? void 0 : trackedCampaign.journey_step_execution_id) || this.journeyStepByCampaign.get(campaignId);
|
|
11952
|
+
const ackAction = JOURNEY_ACK_ACTION[eventType];
|
|
11953
|
+
if (step) {
|
|
11954
|
+
this.journeyStepByCampaign.set(campaignId, step);
|
|
11955
|
+
if (ackAction) void this.ackJourneyQueueItem(step, ackAction);
|
|
11956
|
+
}
|
|
11957
|
+
}
|
|
11958
|
+
/**
|
|
11959
|
+
* POST /v1/in-app/widgets/{step}/ack — the canonical writer of a queue row's
|
|
11960
|
+
* seen-state (the same endpoint the Android and iOS SDKs call). Fail-soft by
|
|
11961
|
+
* construction: it runs after the render, is never awaited by it, and never
|
|
11962
|
+
* throws. A network error or 5xx is retried once; if that also fails the key
|
|
11963
|
+
* is released, so the next render of the (still re-served) message tries
|
|
11964
|
+
* again. A 4xx is the server's answer and is not retried. The server side is
|
|
11965
|
+
* idempotent — a repeated action is answered `late_arrival` and writes
|
|
11966
|
+
* nothing — so a duplicate ack is harmless.
|
|
11967
|
+
*/
|
|
11968
|
+
async ackJourneyQueueItem(step, action, attempt = 0) {
|
|
11969
|
+
const key = `${step}:${action}`;
|
|
11970
|
+
if (attempt === 0) {
|
|
11971
|
+
if (this.journeyAcks.has(key)) return;
|
|
11972
|
+
this.journeyAcks.add(key);
|
|
11973
|
+
}
|
|
11974
|
+
const headers = {
|
|
11975
|
+
"Content-Type": "application/json",
|
|
11976
|
+
"X-Aegis-Write-Key": this.writeKey
|
|
11977
|
+
};
|
|
11978
|
+
if (this.organizationId) headers["X-Organization-ID"] = this.organizationId;
|
|
11979
|
+
if (this.userId) headers["X-User-ID"] = this.userId;
|
|
11980
|
+
if (this.contactId) headers["X-Contact-ID"] = this.contactId;
|
|
11981
|
+
let retryable = true;
|
|
11982
|
+
try {
|
|
11983
|
+
const response = await fetch(
|
|
11984
|
+
`${this.apiHost}/v1/in-app/widgets/${encodeURIComponent(step)}/ack`,
|
|
11985
|
+
{
|
|
11986
|
+
method: "POST",
|
|
11987
|
+
headers,
|
|
11988
|
+
body: JSON.stringify({ action }),
|
|
11989
|
+
credentials: "include",
|
|
11990
|
+
// A click usually navigates away at once; keepalive lets the ack
|
|
11991
|
+
// outlive the page instead of being cancelled with it.
|
|
11992
|
+
keepalive: true
|
|
11993
|
+
}
|
|
11994
|
+
);
|
|
11995
|
+
if (response.ok) {
|
|
11996
|
+
this.log(`Acknowledged queued message ${step}: ${action}`);
|
|
11997
|
+
return;
|
|
11998
|
+
}
|
|
11999
|
+
retryable = response.status >= 500 || response.status === 408 || response.status === 429;
|
|
12000
|
+
this.log(`Queue ack ${action} for ${step} failed: HTTP ${response.status}`, "warn");
|
|
12001
|
+
} catch (error) {
|
|
12002
|
+
this.log(`Queue ack ${action} for ${step} failed: ${error}`, "warn");
|
|
12003
|
+
}
|
|
12004
|
+
if (!retryable) return;
|
|
12005
|
+
if (attempt === 0) {
|
|
12006
|
+
setTimeout(() => {
|
|
12007
|
+
void this.ackJourneyQueueItem(step, action, 1);
|
|
12008
|
+
}, _AegisInAppManager.JOURNEY_ACK_RETRY_MS);
|
|
12009
|
+
return;
|
|
12010
|
+
}
|
|
12011
|
+
this.journeyAcks.delete(key);
|
|
11829
12012
|
}
|
|
11830
12013
|
log(message, level = "log") {
|
|
11831
12014
|
if (this.debugMode) {
|
|
@@ -11876,6 +12059,7 @@ _AegisInAppManager.KNOWN_SURFACES = /* @__PURE__ */ new Set([
|
|
|
11876
12059
|
"external_mobile_screen"
|
|
11877
12060
|
]);
|
|
11878
12061
|
_AegisInAppManager.SERVED_DEDUP_PREFIX = "aegis_served_fired:";
|
|
12062
|
+
_AegisInAppManager.JOURNEY_ACK_RETRY_MS = 2e3;
|
|
11879
12063
|
let AegisInAppManager = _AegisInAppManager;
|
|
11880
12064
|
function renderPreview(config, opts) {
|
|
11881
12065
|
document.querySelectorAll(
|
|
@@ -12594,9 +12778,10 @@ class PrefetchBundleClient {
|
|
|
12594
12778
|
const ctx = this.contextProvider();
|
|
12595
12779
|
const qs = new URLSearchParams();
|
|
12596
12780
|
if (ctx.device_type) qs.set("device_type", ctx.device_type);
|
|
12597
|
-
if (ctx.page_url) qs.set("page_url", ctx.page_url);
|
|
12781
|
+
if (ctx.page_url) qs.set("page_url", redactUrl(ctx.page_url));
|
|
12598
12782
|
if (ctx.geo) qs.set("geo", ctx.geo);
|
|
12599
|
-
|
|
12783
|
+
const isNewUser = ctx.is_new_user ?? isNewVisitor();
|
|
12784
|
+
qs.set("is_new_user", isNewUser ? "true" : "false");
|
|
12600
12785
|
const url = `${this.apiHost}/v1/sdk/prefetch-bundle?${qs.toString()}`;
|
|
12601
12786
|
const headers = {
|
|
12602
12787
|
"X-Aegis-Write-Key": this.writeKey,
|
|
@@ -13478,8 +13663,8 @@ class AegisWidgetManager {
|
|
|
13478
13663
|
cart_items: this.cartData.cart_items,
|
|
13479
13664
|
user_email: this.userId,
|
|
13480
13665
|
abandoned_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13481
|
-
page_url: window.location.href,
|
|
13482
|
-
referrer: document.referrer
|
|
13666
|
+
page_url: redactUrl(window.location.href),
|
|
13667
|
+
referrer: redactUrl(document.referrer)
|
|
13483
13668
|
};
|
|
13484
13669
|
const beaconUrl = `${this.apiHost}/v1/widgets/beacon/cart-abandoned`;
|
|
13485
13670
|
if (navigator.sendBeacon) {
|
|
@@ -13983,7 +14168,9 @@ class AegisWidgetManager {
|
|
|
13983
14168
|
cart_total: ((_c = data.cart) == null ? void 0 : _c.cart_total) || 0,
|
|
13984
14169
|
cart_currency: ((_d = data.cart) == null ? void 0 : _d.cart_currency) || "USD",
|
|
13985
14170
|
cart_items: ((_e = data.cart) == null ? void 0 : _e.cart_items) || [],
|
|
13986
|
-
|
|
14171
|
+
// Redacted: a stored cart URL is re-sent later as a recovery link, and a
|
|
14172
|
+
// credential in it (`?t=` / `?k=`) must not outlive this page view.
|
|
14173
|
+
cart_url: redactUrl(window.location.href),
|
|
13987
14174
|
platform: "web",
|
|
13988
14175
|
geo_region: geoRegion,
|
|
13989
14176
|
device_type: deviceType,
|
|
@@ -15099,7 +15286,7 @@ const _AegisMessageRuntime = class _AegisMessageRuntime {
|
|
|
15099
15286
|
var _a;
|
|
15100
15287
|
this.initialized = false;
|
|
15101
15288
|
{
|
|
15102
|
-
const v = "1.
|
|
15289
|
+
const v = "1.38.0";
|
|
15103
15290
|
try {
|
|
15104
15291
|
globalThis.__AEGIS_SDK_VERSION__ = v;
|
|
15105
15292
|
} catch {
|