@active-reach/web-sdk 1.14.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.
@@ -56,7 +56,7 @@ function generateMessageId() {
56
56
  class Logger {
57
57
  constructor() {
58
58
  this.enabled = false;
59
- this.prefix = "[Aegis SDK]";
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("[Aegis Storage] localStorage.setItem failed:", error);
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("[Aegis Storage] localStorage.getItem failed:", error);
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("[Aegis Storage] localStorage.removeItem failed:", error);
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("[Aegis Storage] localStorage.clear failed:", error);
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("[Aegis Storage] setCookie failed:", error);
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("[Aegis Storage] getCookie failed:", error);
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("[Aegis Storage] deleteCookie failed:", error);
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("[Aegis Storage] getRootDomain failed:", error);
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("[Aegis URL Parser] parseUTMParameters failed:", error);
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("[Aegis URL Parser] parseAdClickIDs failed:", error);
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("[Aegis Device] detectNetworkInfo failed:", error);
1134
+ console.warn("[Active Reach Device] detectNetworkInfo failed:", error);
1134
1135
  }
1135
1136
  return void 0;
1136
1137
  }
@@ -1855,7 +1856,7 @@ class RateLimiter {
1855
1856
  try {
1856
1857
  this.onDropBatch(this.droppedThisWindow, this.firstDroppedName);
1857
1858
  } catch (err) {
1858
- logger.warn("[Aegis] RateLimiter.onDropBatch threw:", err);
1859
+ logger.warn("[Active Reach] RateLimiter.onDropBatch threw:", err);
1859
1860
  }
1860
1861
  }
1861
1862
  this.droppedThisWindow = 0;
@@ -2227,7 +2228,7 @@ const _TraitGovernor = class _TraitGovernor {
2227
2228
  if (count >= _TraitGovernor.WARN_CAP) return;
2228
2229
  perVerdict.set(drop.verdict, count + 1);
2229
2230
  warnOnConsole(
2230
- `[Aegis SDK] trait ${drop.verdict}: ${drop.reason} (original key: ${JSON.stringify(drop.originalKey)}). Backend will reject; fix the SDK call to silence this warning.`
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.`
2231
2232
  );
2232
2233
  }
2233
2234
  };
@@ -2382,6 +2383,7 @@ class Aegis {
2382
2383
  this._lastEventIds = /* @__PURE__ */ new Map();
2383
2384
  this._workspaceCodes = /* @__PURE__ */ new Set();
2384
2385
  this._runtimeWorkspace = null;
2386
+ this._runtimeLocation = null;
2385
2387
  }
2386
2388
  async init(writeKey, config) {
2387
2389
  if (this.initPromise) {
@@ -2408,7 +2410,7 @@ class Aegis {
2408
2410
  if (this.config.debug) {
2409
2411
  logger.enable();
2410
2412
  }
2411
- logger.info("Initializing Aegis SDK...", this.config);
2413
+ logger.info("Initializing Active Reach SDK...", this.config);
2412
2414
  this.storage = new Storage({
2413
2415
  cookieDomain: this.config.cookie_domain,
2414
2416
  secureCookie: this.config.secure_cookie,
@@ -2468,7 +2470,7 @@ class Aegis {
2468
2470
  this.page();
2469
2471
  this.startSPATracking();
2470
2472
  }
2471
- logger.info("Aegis SDK initialized successfully");
2473
+ logger.info("Active Reach SDK initialized successfully");
2472
2474
  }
2473
2475
  /**
2474
2476
  * SPA navigation tracking — monkey-patches pushState/replaceState and
@@ -2611,6 +2613,113 @@ class Aegis {
2611
2613
  clearWorkspace() {
2612
2614
  this.setWorkspace(null);
2613
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
+ }
2614
2723
  /**
2615
2724
  * Inspect the URL's first path segment and return it if it's in the
2616
2725
  * org's workspace_code allowlist. Skips well-known non-workspace prefixes
@@ -2707,6 +2816,7 @@ class Aegis {
2707
2816
  userId: this.identity.getUserId() || void 0,
2708
2817
  sessionId: this.session.getSessionId(),
2709
2818
  workspace_id: this.getEffectiveWorkspaceId(),
2819
+ location_id: this.getEffectiveLocationId(),
2710
2820
  context: buildContext(this.config, this.session)
2711
2821
  };
2712
2822
  this._lastEventIds.set(eventName, messageId);
@@ -2726,6 +2836,7 @@ class Aegis {
2726
2836
  userId,
2727
2837
  sessionId: this.session.getSessionId(),
2728
2838
  workspace_id: this.getEffectiveWorkspaceId(),
2839
+ location_id: this.getEffectiveLocationId(),
2729
2840
  context: buildContext(this.config, this.session)
2730
2841
  };
2731
2842
  this.captureEvent(event);
@@ -2742,6 +2853,7 @@ class Aegis {
2742
2853
  userId: this.identity.getUserId() || void 0,
2743
2854
  sessionId: this.session.getSessionId(),
2744
2855
  workspace_id: this.getEffectiveWorkspaceId(),
2856
+ location_id: this.getEffectiveLocationId(),
2745
2857
  context: buildContext(this.config, this.session)
2746
2858
  };
2747
2859
  this.captureEvent(event);
@@ -2799,6 +2911,7 @@ class Aegis {
2799
2911
  userId: this.identity.getUserId() || void 0,
2800
2912
  sessionId: this.session.getSessionId(),
2801
2913
  workspace_id: this.getEffectiveWorkspaceId(),
2914
+ location_id: this.getEffectiveLocationId(),
2802
2915
  context: buildContext(this.config, this.session)
2803
2916
  };
2804
2917
  this.captureEvent(event);
@@ -3110,4 +3223,4 @@ export {
3110
3223
  logger as l,
3111
3224
  murmurhash3_x86_32 as m
3112
3225
  };
3113
- //# sourceMappingURL=analytics-DGt-CSgi.mjs.map
3226
+ //# sourceMappingURL=analytics-CjLItVo2.mjs.map