@xenia-martech/sdk-js 1.2.0-dev.1 → 1.2.0-dev.3

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 (56) hide show
  1. package/README.md +6 -1
  2. package/dist/{actions-D9_aAvCv.d.cts → actions-Bhji05Pe.d.cts} +19 -4
  3. package/dist/{actions-D9_aAvCv.d.ts → actions-Bhji05Pe.d.ts} +19 -4
  4. package/dist/{api-CktVQ6Gl.d.ts → api-BqSvWgBZ.d.cts} +4 -2
  5. package/dist/{api-BEPW0Uan.d.cts → api-ByoECRhR.d.ts} +4 -2
  6. package/dist/{chunk-DWFVDNU5.js → chunk-INM2SPH4.js} +4 -4
  7. package/dist/chunk-INM2SPH4.js.map +1 -0
  8. package/dist/{chunk-7NGJC7CF.js → chunk-TGG5Y4QD.js} +17 -6
  9. package/dist/chunk-TGG5Y4QD.js.map +1 -0
  10. package/dist/{chunk-3PYPPIUM.cjs → chunk-TRRMMPBH.cjs} +13 -13
  11. package/dist/chunk-TRRMMPBH.cjs.map +1 -0
  12. package/dist/{chunk-IBNIRT7J.cjs → chunk-YZG6JR4E.cjs} +17 -6
  13. package/dist/chunk-YZG6JR4E.cjs.map +1 -0
  14. package/dist/client/index.cjs +43 -8
  15. package/dist/client/index.cjs.map +1 -1
  16. package/dist/client/index.d.cts +2 -2
  17. package/dist/client/index.d.ts +2 -2
  18. package/dist/client/index.js +43 -8
  19. package/dist/client/index.js.map +1 -1
  20. package/dist/client/react/index.cjs +46 -11
  21. package/dist/client/react/index.cjs.map +1 -1
  22. package/dist/client/react/index.d.cts +2 -2
  23. package/dist/client/react/index.d.ts +2 -2
  24. package/dist/client/react/index.js +46 -11
  25. package/dist/client/react/index.js.map +1 -1
  26. package/dist/cms/contentful.cjs +2 -1
  27. package/dist/cms/contentful.cjs.map +1 -1
  28. package/dist/cms/contentful.d.cts +1 -1
  29. package/dist/cms/contentful.d.ts +1 -1
  30. package/dist/cms/contentful.js +2 -1
  31. package/dist/cms/contentful.js.map +1 -1
  32. package/dist/{cookie-names-CLqtmGBM.d.ts → cookie-names-Bxd-VNyJ.d.ts} +1 -1
  33. package/dist/{cookie-names-BACctagz.d.cts → cookie-names-RXVfGYPE.d.cts} +1 -1
  34. package/dist/index.cjs +21 -21
  35. package/dist/index.d.cts +4 -4
  36. package/dist/index.d.ts +4 -4
  37. package/dist/index.js +1 -1
  38. package/dist/next/index.cjs +9 -9
  39. package/dist/next/index.d.cts +3 -3
  40. package/dist/next/index.d.ts +3 -3
  41. package/dist/next/index.js +2 -2
  42. package/dist/{personalize-content-Clc1oMYY.d.cts → personalize-content-Bf6YZdkZ.d.cts} +12 -1
  43. package/dist/{personalize-content-Clc1oMYY.d.ts → personalize-content-Bf6YZdkZ.d.ts} +12 -1
  44. package/dist/server/index.cjs +19 -19
  45. package/dist/server/index.d.cts +5 -5
  46. package/dist/server/index.d.ts +5 -5
  47. package/dist/server/index.js +3 -3
  48. package/dist/xenia-sdk.iife.js +3 -3
  49. package/dist/xenia-sdk.iife.js.map +1 -1
  50. package/dist/{xenia-server-BWhWD0La.d.ts → xenia-server-CcjQenru.d.ts} +2 -2
  51. package/dist/{xenia-server-o_wDOcei.d.cts → xenia-server-MlI3Khya.d.cts} +2 -2
  52. package/package.json +1 -1
  53. package/dist/chunk-3PYPPIUM.cjs.map +0 -1
  54. package/dist/chunk-7NGJC7CF.js.map +0 -1
  55. package/dist/chunk-DWFVDNU5.js.map +0 -1
  56. package/dist/chunk-IBNIRT7J.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ElementType, ComponentType } from 'react';
3
- import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions-D9_aAvCv.cjs';
4
- export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions-D9_aAvCv.cjs';
3
+ import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions-Bhji05Pe.cjs';
4
+ export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions-Bhji05Pe.cjs';
5
5
 
6
6
  interface XeniaProviderProps extends XeniaClientOptions {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ElementType, ComponentType } from 'react';
3
- import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions-D9_aAvCv.js';
4
- export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions-D9_aAvCv.js';
3
+ import { E as XeniaClientOptions, D as XeniaClient, w as ResolveResult, u as ResolveBatchResult, J as JsonValue, x as WebhookResponse, R as ResolveBatchItem, g as AnalyticsEventName, T as TrackOptions, P as PagePersonalizeOptions, j as AppliedSwap, s as PageRef, e as XeniaAction, I as InteractionType, q as MessageMountContext, c as MessageComponentRenderer } from '../../actions-Bhji05Pe.js';
4
+ export { A as AnalyticsContext, h as AnalyticsIdentity, i as AnalyticsIngestResponse, k as ClientEvent, l as CmsAdapter, C as ConsentState, m as ContentSwap, n as IdentifyRequest, o as IdentifyResponse, M as MessageCta, f as MessagePlacement, r as MessageRenderContext, b as MessageTemplateFn, t as PersonalizationSwap, v as ResolveOptions, X as XeniaConfig, a as XeniaEvent, F as XeniaMarker, G as createXeniaClient, H as extractContentSwaps, K as parseActions, L as pendingTargets, N as personalizeContent, O as personalizePage, Q as spliceSlots } from '../../actions-Bhji05Pe.js';
5
5
 
6
6
  interface XeniaProviderProps extends XeniaClientOptions {
7
7
  children: ReactNode;
@@ -553,7 +553,7 @@ var XeniaApi = class {
553
553
  * ({@link personalizeContent}) calls this once per round with the runtime
554
554
  * targets it found; callers rarely need it directly.
555
555
  */
556
- async resolveEntries(entryIds, opts = {}) {
556
+ async resolveEntries(entryIds, opts) {
557
557
  const { data } = await this.http.request({
558
558
  method: "POST",
559
559
  path: "/api/personalization/resolve-entries",
@@ -561,7 +561,8 @@ var XeniaApi = class {
561
561
  body: compact({
562
562
  entryIds,
563
563
  data: opts.data,
564
- locale: opts.locale
564
+ locale: opts.locale,
565
+ contentKey: opts.contentKey
565
566
  })
566
567
  });
567
568
  return data;
@@ -685,7 +686,7 @@ var DEFAULT_TIMEOUT_MS = 300;
685
686
  var DEFAULT_MAX_ROUNDS = 3;
686
687
  var copyOf = (v) => v && typeof v === "object" && typeof structuredClone === "function" ? structuredClone(v) : v;
687
688
  async function personalizeContent(payload, options) {
688
- const { cms } = options;
689
+ const cms = scopedAdapter(options.cms, options.contentKey);
689
690
  const maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;
690
691
  const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
691
692
  const applied = [];
@@ -884,7 +885,8 @@ function withDeadline(promise, deadline) {
884
885
  })
885
886
  ]).finally(() => clearTimeout(timer));
886
887
  }
887
- function pendingTargets(payload, cms) {
888
+ function pendingTargets(payload, adapter, contentKey) {
889
+ const cms = scopedAdapter(adapter, contentKey);
888
890
  try {
889
891
  let content = typeof structuredClone === "function" ? structuredClone(payload) : payload;
890
892
  content = cms.prepare ? cms.prepare(content) : content;
@@ -895,6 +897,15 @@ function pendingTargets(payload, cms) {
895
897
  return [];
896
898
  }
897
899
  }
900
+ function scopedAdapter(cms, contentKey) {
901
+ return {
902
+ ...cms,
903
+ marker(entry) {
904
+ const m = cms.marker(entry);
905
+ return m && contentKey && m.keys?.includes(contentKey) ? m : null;
906
+ }
907
+ };
908
+ }
898
909
  async function personalizePage(ref, options) {
899
910
  let page;
900
911
  try {
@@ -1236,6 +1247,20 @@ var AutoTracker = class {
1236
1247
  }
1237
1248
  };
1238
1249
 
1250
+ // src/server/cookies.ts
1251
+ function parseCookies(header) {
1252
+ const out = {};
1253
+ if (!header) return out;
1254
+ for (const part of header.split(";")) {
1255
+ const idx = part.indexOf("=");
1256
+ if (idx === -1) continue;
1257
+ const key = part.slice(0, idx).trim();
1258
+ const value = part.slice(idx + 1).trim();
1259
+ if (key) out[key] = decodeURIComponent(value);
1260
+ }
1261
+ return out;
1262
+ }
1263
+
1239
1264
  // src/client/identity.ts
1240
1265
  var SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
1241
1266
  var Identity = class {
@@ -1283,10 +1308,19 @@ var Identity = class {
1283
1308
  } catch {
1284
1309
  }
1285
1310
  }
1311
+ /** The visitor id already in the cookie — e.g. minted by `xeniaProxy()` on the first request. */
1312
+ readVisitorCookie() {
1313
+ if (!this.cookie || typeof document === "undefined") return null;
1314
+ try {
1315
+ return parseCookies(document.cookie)[this.cookieName()] || null;
1316
+ } catch {
1317
+ return null;
1318
+ }
1319
+ }
1286
1320
  // ── Device id ────────────────────────────────────────────────────────────
1287
1321
  /**
1288
- * Resolve a stable device id: localStorage cache → MediaDevices → SHA-256
1289
- * browser fingerprint. Cached for the session and across reloads.
1322
+ * Resolve a stable device id: localStorage cache → the visitor cookie a server already set →
1323
+ * MediaDevices → SHA-256 browser fingerprint. Cached for the session and across reloads.
1290
1324
  */
1291
1325
  async resolveDeviceId() {
1292
1326
  if (this.deviceId) {
@@ -1303,7 +1337,8 @@ var Identity = class {
1303
1337
  }
1304
1338
  } catch {
1305
1339
  }
1306
- let id = await this.mediaDeviceId();
1340
+ let id = this.readVisitorCookie();
1341
+ if (!id) id = await this.mediaDeviceId();
1307
1342
  if (!id) id = await this.fingerprint();
1308
1343
  this.deviceId = id;
1309
1344
  try {
@@ -2382,7 +2417,7 @@ var XeniaClient = class {
2382
2417
  return personalizePage(ref, { ...opts, resolve: this.entryResolver(opts) });
2383
2418
  }
2384
2419
  entryResolver(opts) {
2385
- const resolveOpts = this.withVisitor({ data: opts.data, locale: opts.locale });
2420
+ const resolveOpts = { ...this.withVisitor({ data: opts.data, locale: opts.locale }), contentKey: opts.contentKey };
2386
2421
  return async (ids) => (await this.api.resolveEntries(ids, resolveOpts)).decisions ?? [];
2387
2422
  }
2388
2423
  /** The SDK-owned visitor anchor: the `identify()`/`config.visitorId` id, else the device id. */
@@ -2799,8 +2834,8 @@ function usePersonalizedContent(page, opts) {
2799
2834
  const xenia = useXenia();
2800
2835
  const hide = opts.render === "hide-until-resolved";
2801
2836
  const initialPending = useMemo(
2802
- () => new Set(page == null ? [] : pendingTargets(page, opts.cms)),
2803
- [page]
2837
+ () => new Set(page == null ? [] : pendingTargets(page, opts.cms, opts.contentKey)),
2838
+ [page, opts.contentKey]
2804
2839
  // markers live in `page`; a new adapter object for the same page changes nothing
2805
2840
  );
2806
2841
  const [state, setState] = useState(
@@ -2808,7 +2843,7 @@ function usePersonalizedContent(page, opts) {
2808
2843
  );
2809
2844
  const optsRef = useRef(opts);
2810
2845
  optsRef.current = opts;
2811
- const optsKey = JSON.stringify({ data: opts.data ?? {}, locale: opts.locale });
2846
+ const optsKey = JSON.stringify({ data: opts.data ?? {}, locale: opts.locale, contentKey: opts.contentKey });
2812
2847
  useEffect(() => {
2813
2848
  if (page == null) return;
2814
2849
  let active = true;