@active-reach/web-sdk 1.13.0 → 1.14.1
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-Mh4H4ekQ.mjs → analytics-CjLItVo2.mjs} +287 -23
- package/dist/analytics-CjLItVo2.mjs.map +1 -0
- package/dist/core/analytics.d.ts +137 -0
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts +25 -0
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/session.d.ts.map +1 -1
- package/dist/ecommerce/index.d.ts +8 -3
- package/dist/ecommerce/index.d.ts.map +1 -1
- package/dist/ecommerce/types.d.ts +4 -0
- package/dist/ecommerce/types.d.ts.map +1 -1
- package/dist/inapp/AegisInAppManager.d.ts +11 -0
- package/dist/inapp/AegisInAppManager.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -7
- package/dist/index.js.map +1 -1
- package/dist/placements/AegisPlacementManager.d.ts +9 -0
- package/dist/placements/AegisPlacementManager.d.ts.map +1 -1
- package/dist/push/AegisWebPush.js +7 -7
- package/dist/push/AegisWebPush.js.map +1 -1
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/runtime/AegisMessageRuntime.d.ts.map +1 -1
- package/dist/snippet.min.js +1 -1
- package/dist/types/events.d.ts +20 -0
- package/dist/types/events.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/widgets/AegisWidgetManager.d.ts +9 -0
- package/dist/widgets/AegisWidgetManager.d.ts.map +1 -1
- package/package.json +5 -4
- package/dist/analytics-Mh4H4ekQ.mjs.map +0 -1
|
@@ -56,7 +56,7 @@ function generateMessageId() {
|
|
|
56
56
|
class Logger {
|
|
57
57
|
constructor() {
|
|
58
58
|
this.enabled = false;
|
|
59
|
-
this.prefix = "[
|
|
59
|
+
this.prefix = "[Active Reach SDK]";
|
|
60
60
|
}
|
|
61
61
|
enable() {
|
|
62
62
|
this.enabled = true;
|
|
@@ -216,6 +216,7 @@ class SessionManager {
|
|
|
216
216
|
this.sessionStartTime = Date.now();
|
|
217
217
|
this.lastActivityTime = Date.now();
|
|
218
218
|
this.eventCount = 0;
|
|
219
|
+
this.sessionId = newSessionId;
|
|
219
220
|
this.persistSession();
|
|
220
221
|
logger.info("New session created:", newSessionId);
|
|
221
222
|
return newSessionId;
|
|
@@ -824,7 +825,7 @@ class Storage {
|
|
|
824
825
|
};
|
|
825
826
|
localStorage.setItem(fullKey, JSON.stringify(item));
|
|
826
827
|
} catch (error) {
|
|
827
|
-
console.warn("[
|
|
828
|
+
console.warn("[Active Reach Storage] localStorage.setItem failed:", error);
|
|
828
829
|
}
|
|
829
830
|
}
|
|
830
831
|
this.setCookie(fullKey, value, expiryDays);
|
|
@@ -843,7 +844,7 @@ class Storage {
|
|
|
843
844
|
}
|
|
844
845
|
}
|
|
845
846
|
} catch (error) {
|
|
846
|
-
console.warn("[
|
|
847
|
+
console.warn("[Active Reach Storage] localStorage.getItem failed:", error);
|
|
847
848
|
}
|
|
848
849
|
}
|
|
849
850
|
return this.getCookie(fullKey);
|
|
@@ -854,7 +855,7 @@ class Storage {
|
|
|
854
855
|
try {
|
|
855
856
|
localStorage.removeItem(fullKey);
|
|
856
857
|
} catch (error) {
|
|
857
|
-
console.warn("[
|
|
858
|
+
console.warn("[Active Reach Storage] localStorage.removeItem failed:", error);
|
|
858
859
|
}
|
|
859
860
|
}
|
|
860
861
|
this.deleteCookie(fullKey);
|
|
@@ -869,7 +870,7 @@ class Storage {
|
|
|
869
870
|
}
|
|
870
871
|
});
|
|
871
872
|
} catch (error) {
|
|
872
|
-
console.warn("[
|
|
873
|
+
console.warn("[Active Reach Storage] localStorage.clear failed:", error);
|
|
873
874
|
}
|
|
874
875
|
}
|
|
875
876
|
const cookies = document.cookie.split(";");
|
|
@@ -900,7 +901,7 @@ class Storage {
|
|
|
900
901
|
}
|
|
901
902
|
document.cookie = cookieStr;
|
|
902
903
|
} catch (error) {
|
|
903
|
-
console.warn("[
|
|
904
|
+
console.warn("[Active Reach Storage] setCookie failed:", error);
|
|
904
905
|
}
|
|
905
906
|
}
|
|
906
907
|
getCookie(name) {
|
|
@@ -917,7 +918,7 @@ class Storage {
|
|
|
917
918
|
}
|
|
918
919
|
}
|
|
919
920
|
} catch (error) {
|
|
920
|
-
console.warn("[
|
|
921
|
+
console.warn("[Active Reach Storage] getCookie failed:", error);
|
|
921
922
|
}
|
|
922
923
|
return null;
|
|
923
924
|
}
|
|
@@ -934,7 +935,7 @@ class Storage {
|
|
|
934
935
|
}
|
|
935
936
|
document.cookie = cookieStr;
|
|
936
937
|
} catch (error) {
|
|
937
|
-
console.warn("[
|
|
938
|
+
console.warn("[Active Reach Storage] deleteCookie failed:", error);
|
|
938
939
|
}
|
|
939
940
|
}
|
|
940
941
|
getRootDomain() {
|
|
@@ -952,7 +953,7 @@ class Storage {
|
|
|
952
953
|
}
|
|
953
954
|
return `.${parts.slice(-2).join(".")}`;
|
|
954
955
|
} catch (error) {
|
|
955
|
-
console.warn("[
|
|
956
|
+
console.warn("[Active Reach Storage] getRootDomain failed:", error);
|
|
956
957
|
return null;
|
|
957
958
|
}
|
|
958
959
|
}
|
|
@@ -977,7 +978,7 @@ function parseUTMParameters(url) {
|
|
|
977
978
|
});
|
|
978
979
|
return utm;
|
|
979
980
|
} catch (error) {
|
|
980
|
-
console.warn("[
|
|
981
|
+
console.warn("[Active Reach URL Parser] parseUTMParameters failed:", error);
|
|
981
982
|
return {};
|
|
982
983
|
}
|
|
983
984
|
}
|
|
@@ -1001,7 +1002,7 @@ function parseAdClickIDs(url) {
|
|
|
1001
1002
|
});
|
|
1002
1003
|
return adClickIDs;
|
|
1003
1004
|
} catch (error) {
|
|
1004
|
-
console.warn("[
|
|
1005
|
+
console.warn("[Active Reach URL Parser] parseAdClickIDs failed:", error);
|
|
1005
1006
|
return {};
|
|
1006
1007
|
}
|
|
1007
1008
|
}
|
|
@@ -1130,7 +1131,7 @@ function detectNetworkInfo() {
|
|
|
1130
1131
|
};
|
|
1131
1132
|
}
|
|
1132
1133
|
} catch (error) {
|
|
1133
|
-
console.warn("[
|
|
1134
|
+
console.warn("[Active Reach Device] detectNetworkInfo failed:", error);
|
|
1134
1135
|
}
|
|
1135
1136
|
return void 0;
|
|
1136
1137
|
}
|
|
@@ -1764,6 +1765,24 @@ class EcommerceTracker {
|
|
|
1764
1765
|
variant_id: wishlist.product.variant_id
|
|
1765
1766
|
});
|
|
1766
1767
|
}
|
|
1768
|
+
// -- Back-in-stock waitlist --
|
|
1769
|
+
//
|
|
1770
|
+
// Server-side substrate: contact_events row keyed on
|
|
1771
|
+
// (organization_id, contact_id, event_name='product_waitlisted',
|
|
1772
|
+
// event_properties['product_id']). Resolved by
|
|
1773
|
+
// product_event_trigger_service._get_waitlisted_contacts and fanned out via
|
|
1774
|
+
// catalog.back_in_stock journey trigger when stock_event_handler_worker
|
|
1775
|
+
// detects the SKU flipping back into stock.
|
|
1776
|
+
productWaitlisted(waitlist) {
|
|
1777
|
+
this.aegis.track("product_waitlisted", {
|
|
1778
|
+
product_id: waitlist.product.product_id,
|
|
1779
|
+
sku: waitlist.product.sku ?? waitlist.product.product_id,
|
|
1780
|
+
variant_id: waitlist.product.variant_id,
|
|
1781
|
+
name: waitlist.product.name,
|
|
1782
|
+
price: waitlist.product.price,
|
|
1783
|
+
channels: waitlist.channels
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1767
1786
|
// -- Promotions --
|
|
1768
1787
|
promotionViewed(promo) {
|
|
1769
1788
|
this.aegis.track("promotion_viewed", { ...promo });
|
|
@@ -1837,7 +1856,7 @@ class RateLimiter {
|
|
|
1837
1856
|
try {
|
|
1838
1857
|
this.onDropBatch(this.droppedThisWindow, this.firstDroppedName);
|
|
1839
1858
|
} catch (err) {
|
|
1840
|
-
logger.warn("[
|
|
1859
|
+
logger.warn("[Active Reach] RateLimiter.onDropBatch threw:", err);
|
|
1841
1860
|
}
|
|
1842
1861
|
}
|
|
1843
1862
|
this.droppedThisWindow = 0;
|
|
@@ -2209,7 +2228,7 @@ const _TraitGovernor = class _TraitGovernor {
|
|
|
2209
2228
|
if (count >= _TraitGovernor.WARN_CAP) return;
|
|
2210
2229
|
perVerdict.set(drop.verdict, count + 1);
|
|
2211
2230
|
warnOnConsole(
|
|
2212
|
-
`[
|
|
2231
|
+
`[Active Reach SDK] trait ${drop.verdict}: ${drop.reason} (original key: ${JSON.stringify(drop.originalKey)}). Backend will reject; fix the SDK call to silence this warning.`
|
|
2213
2232
|
);
|
|
2214
2233
|
}
|
|
2215
2234
|
};
|
|
@@ -2362,6 +2381,9 @@ class Aegis {
|
|
|
2362
2381
|
this._originalPushState = null;
|
|
2363
2382
|
this._originalReplaceState = null;
|
|
2364
2383
|
this._lastEventIds = /* @__PURE__ */ new Map();
|
|
2384
|
+
this._workspaceCodes = /* @__PURE__ */ new Set();
|
|
2385
|
+
this._runtimeWorkspace = null;
|
|
2386
|
+
this._runtimeLocation = null;
|
|
2365
2387
|
}
|
|
2366
2388
|
async init(writeKey, config) {
|
|
2367
2389
|
if (this.initPromise) {
|
|
@@ -2388,7 +2410,7 @@ class Aegis {
|
|
|
2388
2410
|
if (this.config.debug) {
|
|
2389
2411
|
logger.enable();
|
|
2390
2412
|
}
|
|
2391
|
-
logger.info("Initializing
|
|
2413
|
+
logger.info("Initializing Active Reach SDK...", this.config);
|
|
2392
2414
|
this.storage = new Storage({
|
|
2393
2415
|
cookieDomain: this.config.cookie_domain,
|
|
2394
2416
|
secureCookie: this.config.secure_cookie,
|
|
@@ -2448,7 +2470,7 @@ class Aegis {
|
|
|
2448
2470
|
this.page();
|
|
2449
2471
|
this.startSPATracking();
|
|
2450
2472
|
}
|
|
2451
|
-
logger.info("
|
|
2473
|
+
logger.info("Active Reach SDK initialized successfully");
|
|
2452
2474
|
}
|
|
2453
2475
|
/**
|
|
2454
2476
|
* SPA navigation tracking — monkey-patches pushState/replaceState and
|
|
@@ -2543,6 +2565,244 @@ class Aegis {
|
|
|
2543
2565
|
removePlugin(name) {
|
|
2544
2566
|
this.plugins.unregister(name);
|
|
2545
2567
|
}
|
|
2568
|
+
/**
|
|
2569
|
+
* Plugin-handshake P1 — ingest the workspace_code allowlist from the
|
|
2570
|
+
* bootstrap response. Pass `result.workspaceCodes` from `bootstrap()`
|
|
2571
|
+
* here so the SDK can do path-segment workspace detection on
|
|
2572
|
+
* customer-facing pages like `/south/rewards`, `/ghatkopar/feedback`.
|
|
2573
|
+
*
|
|
2574
|
+
* Empty array is the right answer for single-outlet tenants — SDK
|
|
2575
|
+
* will skip the path cascade and fall through to query param /
|
|
2576
|
+
* setWorkspace() / gateway origin lookup.
|
|
2577
|
+
*
|
|
2578
|
+
* Safe to call before init() — the set is consulted at event-fire time.
|
|
2579
|
+
*/
|
|
2580
|
+
ingestWorkspaceCodes(codes) {
|
|
2581
|
+
this._workspaceCodes = new Set(
|
|
2582
|
+
(codes ?? []).filter((c) => typeof c === "string" && c.length > 0)
|
|
2583
|
+
);
|
|
2584
|
+
logger.debug("Workspace codes ingested", { count: this._workspaceCodes.size });
|
|
2585
|
+
}
|
|
2586
|
+
/**
|
|
2587
|
+
* Plugin-handshake P1 (Track E) — explicitly set the workspace for
|
|
2588
|
+
* subsequent events. Used by:
|
|
2589
|
+
* - SPAs where workspace context changes via in-app routing
|
|
2590
|
+
* - Mobile / RN apps that have no URL
|
|
2591
|
+
* - Custom integrations that resolve workspace from their own state
|
|
2592
|
+
*
|
|
2593
|
+
* Pass null to clear (or call clearWorkspace()).
|
|
2594
|
+
*
|
|
2595
|
+
* Persisted to sessionStorage so SPA reloads / page transitions on the
|
|
2596
|
+
* same outlet inherit it without re-calling.
|
|
2597
|
+
*/
|
|
2598
|
+
setWorkspace(codeOrId) {
|
|
2599
|
+
this._runtimeWorkspace = codeOrId;
|
|
2600
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
2601
|
+
try {
|
|
2602
|
+
if (codeOrId) {
|
|
2603
|
+
window.sessionStorage.setItem("aegis_runtime_ws", codeOrId);
|
|
2604
|
+
} else {
|
|
2605
|
+
window.sessionStorage.removeItem("aegis_runtime_ws");
|
|
2606
|
+
}
|
|
2607
|
+
} catch {
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
logger.debug("Runtime workspace set", { value: codeOrId });
|
|
2611
|
+
}
|
|
2612
|
+
/** Symmetric helper to clear the runtime workspace. */
|
|
2613
|
+
clearWorkspace() {
|
|
2614
|
+
this.setWorkspace(null);
|
|
2615
|
+
}
|
|
2616
|
+
// ── P15.1 — location (outlet) facade ─────────────────────────
|
|
2617
|
+
//
|
|
2618
|
+
// Under the post-2026-05-26 canonical hierarchy:
|
|
2619
|
+
// workspace_id = brand-tenant (one per brand)
|
|
2620
|
+
// location_id = outlet within a brand
|
|
2621
|
+
// The two are distinct dimensions. Both can be stamped on the
|
|
2622
|
+
// same event. These methods mirror the workspace facade but
|
|
2623
|
+
// resolve the outlet specifically.
|
|
2624
|
+
/**
|
|
2625
|
+
* P15.1 — ingest the outlet-code allowlist from bootstrap. The
|
|
2626
|
+
* SDK consults this set when reading the URL path segment to
|
|
2627
|
+
* decide whether `location.pathname.split('/')[1]` is a valid
|
|
2628
|
+
* outlet code vs a generic route.
|
|
2629
|
+
*
|
|
2630
|
+
* Empty array = single-outlet tenant; SDK skips the path-segment
|
|
2631
|
+
* cascade for location resolution.
|
|
2632
|
+
*
|
|
2633
|
+
* Safe to call before init(); the set is consulted at event-
|
|
2634
|
+
* fire time.
|
|
2635
|
+
*/
|
|
2636
|
+
ingestLocationCodes(codes) {
|
|
2637
|
+
this._workspaceCodes = new Set(
|
|
2638
|
+
(codes ?? []).filter((c) => typeof c === "string" && c.length > 0)
|
|
2639
|
+
);
|
|
2640
|
+
logger.debug("Location codes ingested", { count: this._workspaceCodes.size });
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2643
|
+
* P15.1 — explicitly set the active outlet for subsequent events.
|
|
2644
|
+
* Used by:
|
|
2645
|
+
* - Storefronts where outlet picker fires `aegis.setLocation()`
|
|
2646
|
+
* on selection (so events that follow carry that outlet's
|
|
2647
|
+
* location_id without the SDK having to re-parse the URL).
|
|
2648
|
+
* - SPAs where outlet context changes via in-app routing.
|
|
2649
|
+
* - Mobile/RN apps that have no URL.
|
|
2650
|
+
*
|
|
2651
|
+
* Pass null to clear (or call clearLocation()).
|
|
2652
|
+
*
|
|
2653
|
+
* Persisted to sessionStorage so SPA reloads + route transitions
|
|
2654
|
+
* on the same outlet inherit it without re-calling.
|
|
2655
|
+
*/
|
|
2656
|
+
setLocation(codeOrId) {
|
|
2657
|
+
this._runtimeLocation = codeOrId;
|
|
2658
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
2659
|
+
try {
|
|
2660
|
+
if (codeOrId) {
|
|
2661
|
+
window.sessionStorage.setItem("aegis_runtime_location", codeOrId);
|
|
2662
|
+
} else {
|
|
2663
|
+
window.sessionStorage.removeItem("aegis_runtime_location");
|
|
2664
|
+
}
|
|
2665
|
+
} catch {
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
logger.debug("Runtime location set", { value: codeOrId });
|
|
2669
|
+
}
|
|
2670
|
+
/** Symmetric helper to clear the runtime location. */
|
|
2671
|
+
clearLocation() {
|
|
2672
|
+
this.setLocation(null);
|
|
2673
|
+
}
|
|
2674
|
+
/**
|
|
2675
|
+
* P15.1 — same logic as `getPathWorkspaceCode()` but expresses
|
|
2676
|
+
* the semantic correctly: under the new hierarchy, the first
|
|
2677
|
+
* path segment after the brand subdomain IS the outlet code.
|
|
2678
|
+
* Returns `undefined` when no outlet code matches the allowlist.
|
|
2679
|
+
*/
|
|
2680
|
+
getPathLocationCode() {
|
|
2681
|
+
return this.getPathWorkspaceCode();
|
|
2682
|
+
}
|
|
2683
|
+
/**
|
|
2684
|
+
* P15.1 — resolve the effective `location_id` for the next event.
|
|
2685
|
+
* Independent of `getEffectiveWorkspaceId()`: both run on every
|
|
2686
|
+
* event so workspace_id (brand) and location_id (outlet) land
|
|
2687
|
+
* on the same event when both are resolvable.
|
|
2688
|
+
*
|
|
2689
|
+
* Cascade (highest precedence first):
|
|
2690
|
+
* 1. `this.config.location_id` — explicit operator config.
|
|
2691
|
+
* 2. `?location=` query param (also accepts `?ws=` for back-
|
|
2692
|
+
* compat with storefronts that pass outlet via the old
|
|
2693
|
+
* param name — the value is the same; param naming only).
|
|
2694
|
+
* 3. URL path segment matching the outlet-code allowlist.
|
|
2695
|
+
* 4. Runtime `aegis.setLocation()` (in-memory).
|
|
2696
|
+
* 5. sessionStorage `aegis_runtime_location`.
|
|
2697
|
+
* 6. `undefined` — event-ingress treats as brand-tier
|
|
2698
|
+
* (no outlet attribution).
|
|
2699
|
+
*/
|
|
2700
|
+
getEffectiveLocationId() {
|
|
2701
|
+
var _a;
|
|
2702
|
+
const configured = (_a = this.config) == null ? void 0 : _a.location_id;
|
|
2703
|
+
if (configured) return configured;
|
|
2704
|
+
if (typeof window === "undefined") return void 0;
|
|
2705
|
+
try {
|
|
2706
|
+
const search = new URLSearchParams(window.location.search);
|
|
2707
|
+
const loc = search.get("location") || search.get("ws");
|
|
2708
|
+
if (loc && loc.length > 0) return loc;
|
|
2709
|
+
} catch {
|
|
2710
|
+
}
|
|
2711
|
+
const pathLoc = this.getPathLocationCode();
|
|
2712
|
+
if (pathLoc) return pathLoc;
|
|
2713
|
+
if (this._runtimeLocation) return this._runtimeLocation;
|
|
2714
|
+
try {
|
|
2715
|
+
if (window.sessionStorage) {
|
|
2716
|
+
const cached = window.sessionStorage.getItem("aegis_runtime_location");
|
|
2717
|
+
if (cached && cached.length > 0) return cached;
|
|
2718
|
+
}
|
|
2719
|
+
} catch {
|
|
2720
|
+
}
|
|
2721
|
+
return void 0;
|
|
2722
|
+
}
|
|
2723
|
+
/**
|
|
2724
|
+
* Inspect the URL's first path segment and return it if it's in the
|
|
2725
|
+
* org's workspace_code allowlist. Skips well-known non-workspace prefixes
|
|
2726
|
+
* (e.g. `b` for bill short codes; `s` is the storefront app slug).
|
|
2727
|
+
*
|
|
2728
|
+
* Returns undefined when:
|
|
2729
|
+
* - window is undefined (SSR / Node)
|
|
2730
|
+
* - path is empty / root
|
|
2731
|
+
* - first segment isn't in `_workspaceCodes` (e.g. /products, /cart)
|
|
2732
|
+
*
|
|
2733
|
+
* The returned value is a workspace CODE (slug like "south"), not a
|
|
2734
|
+
* UUID. The gateway normalizes code → UUID server-side via
|
|
2735
|
+
* workspace_subaccounts lookup with Redis cache.
|
|
2736
|
+
*/
|
|
2737
|
+
getPathWorkspaceCode() {
|
|
2738
|
+
if (typeof window === "undefined") return void 0;
|
|
2739
|
+
if (this._workspaceCodes.size === 0) return void 0;
|
|
2740
|
+
try {
|
|
2741
|
+
const segments = window.location.pathname.split("/").filter(Boolean);
|
|
2742
|
+
if (segments.length === 0) return void 0;
|
|
2743
|
+
const first = segments[0].toLowerCase();
|
|
2744
|
+
return this._workspaceCodes.has(first) ? first : void 0;
|
|
2745
|
+
} catch {
|
|
2746
|
+
return void 0;
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
/**
|
|
2750
|
+
* Resolve the effective `workspace_id` for the next event.
|
|
2751
|
+
*
|
|
2752
|
+
* Cascade (highest precedence first):
|
|
2753
|
+
* 1. `this.config.workspace_id` — explicit operator config (headless
|
|
2754
|
+
* SDK usage, server-rendered apps, native shells).
|
|
2755
|
+
* 2. `?ws=` query param on the current URL — the P3 storefront URL
|
|
2756
|
+
* contract. The outlet picker writes this via `router.replace`.
|
|
2757
|
+
* 3. URL path segment (P1 Track A) — `/south/rewards` → "south" when
|
|
2758
|
+
* "south" is in the org's workspace_code allowlist.
|
|
2759
|
+
* 4. `aegis.setWorkspace()` runtime override (P1 Track E) — SPAs +
|
|
2760
|
+
* mobile + custom integrations.
|
|
2761
|
+
* 5. sessionStorage `aegis_runtime_ws` — persists setWorkspace across
|
|
2762
|
+
* reloads/SPA route changes.
|
|
2763
|
+
* 6. `undefined` — gateway falls back to `resolveByOrigin` lookup
|
|
2764
|
+
* against the property's allowed_origins.
|
|
2765
|
+
*
|
|
2766
|
+
* The returned value can be EITHER a UUID (from config / ?ws=) or a
|
|
2767
|
+
* workspace CODE slug (from path / setWorkspace). The gateway
|
|
2768
|
+
* normalizes slug → UUID server-side; analytics layer never needs to
|
|
2769
|
+
* worry about the difference.
|
|
2770
|
+
*
|
|
2771
|
+
* See docs/architecture/MULTI_OUTLET_URL_STRATEGY.md §2.3 and
|
|
2772
|
+
* docs/architecture/PLUGIN_HANDSHAKE_AUTOMATION.md §2.
|
|
2773
|
+
*/
|
|
2774
|
+
/**
|
|
2775
|
+
* Public so peer SDK surfaces (AegisMessageRuntime / AegisInAppManager /
|
|
2776
|
+
* AegisPlacementManager / AegisWidgetManager) can plumb the same
|
|
2777
|
+
* resolved workspace into their own gateway POSTs. Each manager calls
|
|
2778
|
+
* the gateway on its own endpoint (`/v1/in_app/events`,
|
|
2779
|
+
* `/v1/placements/track`, `/v1/widgets/track-event`); without this,
|
|
2780
|
+
* those events arrive at event-ingress with no workspace_id stamped
|
|
2781
|
+
* → impressions/clicks fall back to the org's primary workspace and
|
|
2782
|
+
* cross-outlet attribution breaks.
|
|
2783
|
+
*/
|
|
2784
|
+
getEffectiveWorkspaceId() {
|
|
2785
|
+
var _a;
|
|
2786
|
+
const configured = (_a = this.config) == null ? void 0 : _a.workspace_id;
|
|
2787
|
+
if (configured) return configured;
|
|
2788
|
+
if (typeof window === "undefined") return void 0;
|
|
2789
|
+
try {
|
|
2790
|
+
const ws = new URLSearchParams(window.location.search).get("ws");
|
|
2791
|
+
if (ws && ws.length > 0) return ws;
|
|
2792
|
+
} catch {
|
|
2793
|
+
}
|
|
2794
|
+
const pathWs = this.getPathWorkspaceCode();
|
|
2795
|
+
if (pathWs) return pathWs;
|
|
2796
|
+
if (this._runtimeWorkspace) return this._runtimeWorkspace;
|
|
2797
|
+
try {
|
|
2798
|
+
if (window.sessionStorage) {
|
|
2799
|
+
const cached = window.sessionStorage.getItem("aegis_runtime_ws");
|
|
2800
|
+
if (cached && cached.length > 0) return cached;
|
|
2801
|
+
}
|
|
2802
|
+
} catch {
|
|
2803
|
+
}
|
|
2804
|
+
return void 0;
|
|
2805
|
+
}
|
|
2546
2806
|
track(eventName, properties) {
|
|
2547
2807
|
if (!this.assertInitialized()) return;
|
|
2548
2808
|
const messageId = generateMessageId();
|
|
@@ -2555,7 +2815,8 @@ class Aegis {
|
|
|
2555
2815
|
anonymousId: this.identity.getAnonymousId(),
|
|
2556
2816
|
userId: this.identity.getUserId() || void 0,
|
|
2557
2817
|
sessionId: this.session.getSessionId(),
|
|
2558
|
-
workspace_id: this.
|
|
2818
|
+
workspace_id: this.getEffectiveWorkspaceId(),
|
|
2819
|
+
location_id: this.getEffectiveLocationId(),
|
|
2559
2820
|
context: buildContext(this.config, this.session)
|
|
2560
2821
|
};
|
|
2561
2822
|
this._lastEventIds.set(eventName, messageId);
|
|
@@ -2563,7 +2824,7 @@ class Aegis {
|
|
|
2563
2824
|
}
|
|
2564
2825
|
identify(userId, traits) {
|
|
2565
2826
|
if (!this.assertInitialized()) return;
|
|
2566
|
-
const wsForGovernor = this.
|
|
2827
|
+
const wsForGovernor = this.getEffectiveWorkspaceId() || null;
|
|
2567
2828
|
const { sanitized: governedTraits } = this.traitGovernor.process(traits, wsForGovernor);
|
|
2568
2829
|
this.identity.setUserId(userId, governedTraits);
|
|
2569
2830
|
const event = {
|
|
@@ -2574,7 +2835,8 @@ class Aegis {
|
|
|
2574
2835
|
anonymousId: this.identity.getAnonymousId(),
|
|
2575
2836
|
userId,
|
|
2576
2837
|
sessionId: this.session.getSessionId(),
|
|
2577
|
-
workspace_id: this.
|
|
2838
|
+
workspace_id: this.getEffectiveWorkspaceId(),
|
|
2839
|
+
location_id: this.getEffectiveLocationId(),
|
|
2578
2840
|
context: buildContext(this.config, this.session)
|
|
2579
2841
|
};
|
|
2580
2842
|
this.captureEvent(event);
|
|
@@ -2590,14 +2852,15 @@ class Aegis {
|
|
|
2590
2852
|
anonymousId: this.identity.getAnonymousId(),
|
|
2591
2853
|
userId: this.identity.getUserId() || void 0,
|
|
2592
2854
|
sessionId: this.session.getSessionId(),
|
|
2593
|
-
workspace_id: this.
|
|
2855
|
+
workspace_id: this.getEffectiveWorkspaceId(),
|
|
2856
|
+
location_id: this.getEffectiveLocationId(),
|
|
2594
2857
|
context: buildContext(this.config, this.session)
|
|
2595
2858
|
};
|
|
2596
2859
|
this.captureEvent(event);
|
|
2597
2860
|
}
|
|
2598
2861
|
group(groupId, traits) {
|
|
2599
2862
|
if (!this.assertInitialized()) return;
|
|
2600
|
-
const wsForGovernor = this.
|
|
2863
|
+
const wsForGovernor = this.getEffectiveWorkspaceId() || null;
|
|
2601
2864
|
const { sanitized: governedTraits } = this.traitGovernor.process(traits, wsForGovernor);
|
|
2602
2865
|
const event = {
|
|
2603
2866
|
type: "group",
|
|
@@ -2647,7 +2910,8 @@ class Aegis {
|
|
|
2647
2910
|
anonymousId: this.identity.getAnonymousId(),
|
|
2648
2911
|
userId: this.identity.getUserId() || void 0,
|
|
2649
2912
|
sessionId: this.session.getSessionId(),
|
|
2650
|
-
workspace_id: this.
|
|
2913
|
+
workspace_id: this.getEffectiveWorkspaceId(),
|
|
2914
|
+
location_id: this.getEffectiveLocationId(),
|
|
2651
2915
|
context: buildContext(this.config, this.session)
|
|
2652
2916
|
};
|
|
2653
2917
|
this.captureEvent(event);
|
|
@@ -2959,4 +3223,4 @@ export {
|
|
|
2959
3223
|
logger as l,
|
|
2960
3224
|
murmurhash3_x86_32 as m
|
|
2961
3225
|
};
|
|
2962
|
-
//# sourceMappingURL=analytics-
|
|
3226
|
+
//# sourceMappingURL=analytics-CjLItVo2.mjs.map
|