@xenia-martech/sdk-js 1.0.0-dev.25 → 1.0.0-dev.27

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.
Files changed (36) hide show
  1. package/README.md +31 -45
  2. package/dist/{actions-DfuHrjUL.d.cts → actions-CkiSdvSa.d.cts} +73 -11
  3. package/dist/{actions-DfuHrjUL.d.ts → actions-CkiSdvSa.d.ts} +73 -11
  4. package/dist/{chunk-PTYUK4P3.js → chunk-7D2HJMW6.js} +33 -4
  5. package/dist/chunk-7D2HJMW6.js.map +1 -0
  6. package/dist/{chunk-JEFNAD5J.cjs → chunk-UOW3GK4I.cjs} +34 -3
  7. package/dist/chunk-UOW3GK4I.cjs.map +1 -0
  8. package/dist/client/index.cjs +75 -9
  9. package/dist/client/index.cjs.map +1 -1
  10. package/dist/client/index.d.cts +2 -2
  11. package/dist/client/index.d.ts +2 -2
  12. package/dist/client/index.js +75 -9
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/client/react/index.cjs +75 -9
  15. package/dist/client/react/index.cjs.map +1 -1
  16. package/dist/client/react/index.d.cts +3 -3
  17. package/dist/client/react/index.d.ts +3 -3
  18. package/dist/client/react/index.js +75 -9
  19. package/dist/client/react/index.js.map +1 -1
  20. package/dist/{cookie-names-BQ-L04A8.d.cts → cookie-names-C3LKDhsg.d.cts} +42 -6
  21. package/dist/{cookie-names-BQ-L04A8.d.ts → cookie-names-C3LKDhsg.d.ts} +42 -6
  22. package/dist/index.cjs +23 -19
  23. package/dist/index.d.cts +25 -4
  24. package/dist/index.d.ts +25 -4
  25. package/dist/index.js +1 -1
  26. package/dist/server/index.cjs +53 -22
  27. package/dist/server/index.cjs.map +1 -1
  28. package/dist/server/index.d.cts +37 -14
  29. package/dist/server/index.d.ts +37 -14
  30. package/dist/server/index.js +43 -12
  31. package/dist/server/index.js.map +1 -1
  32. package/dist/xenia-sdk.iife.js +3 -3
  33. package/dist/xenia-sdk.iife.js.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-JEFNAD5J.cjs.map +0 -1
  36. package/dist/chunk-PTYUK4P3.js.map +0 -1
@@ -94,6 +94,7 @@ function parseActions(body) {
94
94
  }
95
95
 
96
96
  // src/core/http-client.ts
97
+ var DEFAULT_BASE_URL = "https://engine.xeniamartech.com/xenia";
97
98
  function isBrowser() {
98
99
  return typeof window !== "undefined" && typeof document !== "undefined";
99
100
  }
@@ -123,7 +124,7 @@ var HttpClient = class {
123
124
  retry;
124
125
  debug;
125
126
  constructor(opts) {
126
- this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
127
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
127
128
  this.defaultHeaders = opts.defaultHeaders ?? {};
128
129
  this.timeout = opts.timeout ?? 8e3;
129
130
  this.retry = {
@@ -972,6 +973,40 @@ var Identity = class {
972
973
  return null;
973
974
  }
974
975
  }
976
+ // ── Customer id / email ──────────────────────────────────────────────────
977
+ //
978
+ // Ambient, persisted the same way as the visitor id, so a value set once
979
+ // (typically alongside `identify()`) rides on every later `resolve()` call
980
+ // without the caller having to pass it again — the SDK-provided-fields
981
+ // parity list on the Personalization Resolve trigger includes both.
982
+ setCustomerId(customerId) {
983
+ try {
984
+ if (customerId) localStorage.setItem(this.key("customer_id"), customerId);
985
+ else localStorage.removeItem(this.key("customer_id"));
986
+ } catch {
987
+ }
988
+ }
989
+ getCustomerId() {
990
+ try {
991
+ return localStorage.getItem(this.key("customer_id"));
992
+ } catch {
993
+ return null;
994
+ }
995
+ }
996
+ setEmail(email) {
997
+ try {
998
+ if (email) localStorage.setItem(this.key("email"), email);
999
+ else localStorage.removeItem(this.key("email"));
1000
+ } catch {
1001
+ }
1002
+ }
1003
+ getEmail() {
1004
+ try {
1005
+ return localStorage.getItem(this.key("email"));
1006
+ } catch {
1007
+ return null;
1008
+ }
1009
+ }
975
1010
  // ── Session id ───────────────────────────────────────────────────────────────
976
1011
  /**
977
1012
  * Resolve the current session id: reused while activity continues within
@@ -1435,10 +1470,16 @@ var XeniaClient = class {
1435
1470
  * Persist a visitor id, attached to every subsequent event, and bind it to
1436
1471
  * a known user server-side (`POST /api/events/v1/identify`, fire-and-
1437
1472
  * forget — resolves to an `"identify"` client event carrying `personId`).
1473
+ *
1474
+ * `extra.customerId`/`extra.email`, when supplied, are also persisted
1475
+ * ambiently (like the visitor id) so they ride on every later `resolve()`
1476
+ * call automatically — part of the SDK-provided-fields parity list.
1438
1477
  */
1439
- identify(visitorId) {
1478
+ identify(visitorId, extra) {
1440
1479
  this.identity.identify(visitorId);
1441
- void this.api.identify({ xeniaVisitorId: visitorId }).then((res) => this.emit("identify", res)).catch((err) => this.emitError(err));
1480
+ if (extra?.customerId !== void 0) this.identity.setCustomerId(extra.customerId);
1481
+ if (extra?.email !== void 0) this.identity.setEmail(extra.email);
1482
+ void this.api.identify({ xeniaVisitorId: visitorId, userId: extra?.customerId, email: extra?.email }).then((res) => this.emit("identify", res)).catch((err) => this.emitError(err));
1442
1483
  }
1443
1484
  /** Override the customer-journey UUID (else derived from utm_id). */
1444
1485
  setJourneyId(id) {
@@ -1556,15 +1597,40 @@ var XeniaClient = class {
1556
1597
  return this.identity.getVisitorId() ?? this.identity.getDeviceId() ?? void 0;
1557
1598
  }
1558
1599
  /**
1559
- * Stamp the SDK-owned visitor id into the resolve `data` under the reserved
1560
- * `_xenia_vid` key so the backend can bucket holdout experiments and record
1561
- * exposure per visitor (it reads visitor identity from `data`). Set last so a
1562
- * caller can't override it; a no-op when no visitor id is resolvable yet.
1600
+ * Stamp the full set of SDK-provided fields into the resolve `data` —
1601
+ * `path`, `query`, `deviceId`, `visitorId`, `customerId`, `email`, `url`,
1602
+ * `referrer`, and the five `utm*` fields — the same field-name/type parity
1603
+ * the webhook trigger's "SDK-provided fields" already promises, now native
1604
+ * (always attached, no marketer toggle) for the Personalization Resolve
1605
+ * trigger too. Plus the reserved `_xenia_vid` key the backend reads for
1606
+ * holdout/exposure bucketing. All of these are spread LAST (after the
1607
+ * caller's own `data`) so none can be overridden per call — the same
1608
+ * override-protection guarantee `_xenia_vid` alone used to have, now
1609
+ * widened to the full set. A no-op (returns `opts` unchanged) when nothing
1610
+ * is resolvable yet (e.g. called before `init()` on a fresh visit with no
1611
+ * page context available).
1563
1612
  */
1564
1613
  withVisitor(opts) {
1614
+ const ctx = this.identity.collectContext();
1565
1615
  const vid = this.resolveVisitorId();
1566
- if (!vid) return opts;
1567
- return { ...opts, data: { ...opts?.data ?? {}, _xenia_vid: vid } };
1616
+ const sdkFields = compact({
1617
+ path: ctx.path,
1618
+ query: ctx.query,
1619
+ deviceId: this.identity.getDeviceId() ?? void 0,
1620
+ visitorId: vid,
1621
+ customerId: this.identity.getCustomerId() ?? void 0,
1622
+ email: this.identity.getEmail() ?? void 0,
1623
+ url: ctx.url,
1624
+ referrer: ctx.referrer,
1625
+ utmSource: ctx.utmSource,
1626
+ utmMedium: ctx.utmMedium,
1627
+ utmCampaign: ctx.utmCampaign,
1628
+ utmContent: ctx.utmContent,
1629
+ utmId: ctx.utmId
1630
+ });
1631
+ if (vid) sdkFields._xenia_vid = vid;
1632
+ if (Object.keys(sdkFields).length === 0) return opts;
1633
+ return { ...opts, data: { ...opts?.data ?? {}, ...sdkFields } };
1568
1634
  }
1569
1635
  dntBlocked() {
1570
1636
  if (this.options.respectDnt === false) return false;