@action-x/ad-sdk 0.1.6 → 0.1.8

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- class B {
1
+ class O {
2
2
  constructor() {
3
3
  this.events = {};
4
4
  }
@@ -60,25 +60,21 @@ class w {
60
60
  * @returns HTML string
61
61
  */
62
62
  static renderActionCard(e, t = {}) {
63
- var m;
64
- const { variant: i = "horizontal", includeWrapper: s = !0 } = t, n = e.adapted, o = this.getClickUrl(e), a = this.getImpressionUrl(e), c = s ? `<div class="ax-ad-card ax-ad-card-${i}" data-ad-id="${e.original.id}">` : "", l = (m = n.image) != null && m.url ? `<img
63
+ var f;
64
+ const { variant: i = "horizontal", includeWrapper: s = !0 } = t, n = e.adapted, r = this.getClickUrl(e), a = this.getImpressionUrl(e), c = s ? `<div class="ax-ad-card ax-ad-card-${i}" data-ad-id="${e.original.id}">` : "", d = (f = n.image) != null && f.url ? `<img
65
65
  src="${n.image.url}"
66
66
  alt="${n.title}"
67
67
  class="ax-ad-image"
68
68
  loading="lazy"
69
- />` : "", d = n.price ? `<span class="ax-ad-price">${n.price.display || n.price.value}</span>` : "", u = n.rating ? `<div class="ax-ad-rating" aria-label="Rating: ${n.rating}">
70
- ${"★".repeat(Math.floor(n.rating))}${"☆".repeat(5 - Math.floor(n.rating))}
71
- </div>` : "", h = n.brand ? `<span class="ax-ad-brand">${n.brand}</span>` : "", p = `
72
- ${l}
69
+ />` : "", l = (n.brand || "").trim(), u = l && l.toLowerCase() !== "unknown" ? `<span class="ax-ad-brand">${n.brand}</span>` : "", h = `
70
+ ${d}
73
71
  <div class="ax-ad-content">
74
- ${h}
72
+ ${u}
75
73
  <h3 class="ax-ad-title">${n.title}</h3>
76
74
  ${n.body ? `<p class="ax-ad-body">${n.body}</p>` : ""}
77
- ${u}
78
75
  <div class="ax-ad-footer">
79
- ${d}
80
76
  <a
81
- href="${o}"
77
+ href="${r}"
82
78
  class="ax-ad-cta"
83
79
  target="_blank"
84
80
  rel="sponsored noopener noreferrer"
@@ -89,8 +85,8 @@ class w {
89
85
  </a>
90
86
  </div>
91
87
  </div>
92
- `, f = s ? "</div>" : "";
93
- return c + p + f;
88
+ `, p = s ? "</div>" : "";
89
+ return c + h + p;
94
90
  }
95
91
  /**
96
92
  * Render Suffix ad as HTML string
@@ -190,17 +186,17 @@ class w {
190
186
  const q = "ad_session_id";
191
187
  function L() {
192
188
  if (typeof window < "u") {
193
- const r = window.__AD_CONFIG__;
194
- if (r != null && r.apiKey)
195
- return r.apiKey;
189
+ const o = window.__AD_CONFIG__;
190
+ if (o != null && o.apiKey)
191
+ return o.apiKey;
196
192
  }
197
193
  }
198
194
  function R() {
199
- var r;
200
- return typeof window < "u" ? !!((r = window.__AD_CONFIG__) != null && r.debug) : !1;
195
+ var o;
196
+ return typeof window < "u" ? !!((o = window.__AD_CONFIG__) != null && o.debug) : !1;
201
197
  }
202
- function U(r) {
203
- if (r) return r;
198
+ function U(o) {
199
+ if (o) return o;
204
200
  if (typeof window < "u") {
205
201
  const e = window.__AD_CONFIG__;
206
202
  if (e != null && e.apiBaseUrl)
@@ -244,7 +240,7 @@ class P {
244
240
  this.storage === "sessionStorage" ? sessionStorage.removeItem(this.sessionKey) : this.memoryCache.delete(this.sessionKey);
245
241
  }
246
242
  }
247
- const K = new P(), y = () => K.getSessionId();
243
+ const K = new P(), m = () => K.getSessionId();
248
244
  class x {
249
245
  constructor(e = {}) {
250
246
  this.explicitBaseUrl = e.baseUrl, this.timeout = e.timeout || 1e4, this.retryAttempts = e.retryAttempts ?? 2, this.retryDelay = e.retryDelay || 1e3, this.debug = e.debug || !1;
@@ -276,16 +272,16 @@ class x {
276
272
  async sendRequest(e, t, i) {
277
273
  let s = null;
278
274
  for (let n = 0; n <= this.retryAttempts; n++) {
279
- const o = this.debug || R();
275
+ const r = this.debug || R();
280
276
  try {
281
- o && (console.log(`[Analytics] Request URL (${i}):`, e), console.log(`[Analytics] Sending ${i} event (attempt ${n + 1}):`, t));
282
- const a = new AbortController(), c = setTimeout(() => a.abort(), this.timeout), l = {
277
+ r && (console.log(`[Analytics] Request URL (${i}):`, e), console.log(`[Analytics] Sending ${i} event (attempt ${n + 1}):`, t));
278
+ const a = new AbortController(), c = setTimeout(() => a.abort(), this.timeout), d = {
283
279
  "Content-Type": "application/json"
284
- }, d = L();
285
- d && (l["X-API-Key"] = d, o && console.log(`[Analytics] Adding X-API-Key header for ${i} event`));
280
+ }, l = L();
281
+ l && (d["X-API-Key"] = l, r && console.log(`[Analytics] Adding X-API-Key header for ${i} event`));
286
282
  const u = await fetch(e, {
287
283
  method: "POST",
288
- headers: l,
284
+ headers: d,
289
285
  body: JSON.stringify(t),
290
286
  keepalive: !0,
291
287
  signal: a.signal
@@ -293,9 +289,9 @@ class x {
293
289
  if (clearTimeout(c), !u.ok)
294
290
  throw new Error(`HTTP ${u.status}: ${u.statusText}`);
295
291
  const h = await u.json();
296
- return o && console.log(`[Analytics] ${i} event tracked successfully:`, h), h;
292
+ return r && console.log(`[Analytics] ${i} event tracked successfully:`, h), h;
297
293
  } catch (a) {
298
- s = a, o && console.warn(`[Analytics] ${i} tracking failed (attempt ${n + 1}):`, a), n < this.retryAttempts && await this.delay(this.retryDelay * (n + 1));
294
+ s = a, r && console.warn(`[Analytics] ${i} tracking failed (attempt ${n + 1}):`, a), n < this.retryAttempts && await this.delay(this.retryDelay * (n + 1));
299
295
  }
300
296
  }
301
297
  return console.error(`[Analytics] ${i} tracking failed after ${this.retryAttempts + 1} attempts:`, s), null;
@@ -307,25 +303,25 @@ class x {
307
303
  return new Promise((t) => setTimeout(t, e));
308
304
  }
309
305
  }
310
- const O = new x(), I = (r, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackImpression(r) : O.trackImpression(r), T = (r, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackClick(r) : O.trackClick(r);
311
- function G(r, e) {
312
- return `vt_${r}_${e}`;
306
+ const B = new x(), I = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackImpression(o) : B.trackImpression(o), T = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackClick(o) : B.trackClick(o);
307
+ function z(o, e) {
308
+ return `vt_${o}_${e}`;
313
309
  }
314
- async function j(r) {
315
- return Promise.all(r.map((e) => I(e)));
310
+ async function j(o) {
311
+ return Promise.all(o.map((e) => I(e)));
316
312
  }
317
- async function z(r) {
318
- return Promise.all(r.map((e) => T(e)));
313
+ async function W(o) {
314
+ return Promise.all(o.map((e) => T(e)));
319
315
  }
320
- function W(r) {
321
- const e = new x(r);
316
+ function Q(o) {
317
+ const e = new x(o);
322
318
  return {
323
319
  trackImpression: (t) => e.trackImpression(t),
324
320
  trackClick: (t) => e.trackClick(t)
325
321
  };
326
322
  }
327
- function Q(r = {}) {
328
- const e = new P(r);
323
+ function J(o = {}) {
324
+ const e = new P(o);
329
325
  return {
330
326
  getSessionId: () => e.getSessionId(),
331
327
  regenerateSessionId: () => e.regenerateSessionId(),
@@ -360,8 +356,8 @@ const C = class C {
360
356
  const s = i.variant || "block";
361
357
  t.innerHTML = this.generateSuffixAdHTML(e, s);
362
358
  const n = t.querySelector(".ax-ad-suffix-link");
363
- return n && n.addEventListener("click", (o) => {
364
- o.preventDefault(), this.handleClick(e, i);
359
+ return n && n.addEventListener("click", (r) => {
360
+ r.preventDefault(), this.handleClick(e, i);
365
361
  }), this.trackImpression(e, t, i), t;
366
362
  }
367
363
  /**
@@ -371,8 +367,8 @@ const C = class C {
371
367
  const s = i.variant || "card";
372
368
  t.innerHTML = this.generateSponsoredSourceHTML(e, s);
373
369
  const n = t.querySelector(".ax-ad-source-link");
374
- return n && n.addEventListener("click", (o) => {
375
- o.preventDefault(), this.handleClick(e, i);
370
+ return n && n.addEventListener("click", (r) => {
371
+ r.preventDefault(), this.handleClick(e, i);
376
372
  }), this.trackImpression(e, t, i), t;
377
373
  }
378
374
  /**
@@ -391,9 +387,9 @@ const C = class C {
391
387
  static renderAds(e, t, i = this.renderActionCard.bind(this), s) {
392
388
  t.innerHTML = "";
393
389
  const n = document.createElement("div");
394
- return n.className = "ax-ads-container", e.forEach((o) => {
390
+ return n.className = "ax-ads-container", e.forEach((r) => {
395
391
  const a = document.createElement("div");
396
- a.className = "ax-ad-wrapper", i.call(this, o, a, s), n.appendChild(a);
392
+ a.className = "ax-ad-wrapper", i.call(this, r, a, s), n.appendChild(a);
397
393
  }), t.appendChild(n), t;
398
394
  }
399
395
  /**
@@ -411,12 +407,12 @@ const C = class C {
411
407
  adId: e.original.id,
412
408
  destinationUrl: n,
413
409
  slotId: i.slotId,
414
- sessionId: y(),
410
+ sessionId: m(),
415
411
  adTitle: e.adapted.title,
416
412
  format: e.original.type,
417
413
  userId: i.userId
418
- }, { baseUrl: i.apiBaseUrl }).catch((o) => {
419
- console.error("[DOMRenderer] Analytics click tracking failed:", o);
414
+ }, { baseUrl: i.apiBaseUrl }).catch((r) => {
415
+ console.error("[DOMRenderer] Analytics click tracking failed:", r);
420
416
  }), this.isDebugEnabled() && console.log("[DOMRenderer] Redirect URL:", n), window.open(n, "_blank", "noopener,noreferrer");
421
417
  }
422
418
  /**
@@ -424,20 +420,20 @@ const C = class C {
424
420
  * Falls back to immediate tracking if IntersectionObserver is unavailable.
425
421
  */
426
422
  static trackImpression(e, t, i) {
427
- const { analytics: s, onImpression: n } = i, o = s ? `${s.requestId}:${s.slotId}:${e.original.id}:${this.getViewToken(e) || ""}` : `no-analytics:${e.original.id}:${this.getViewToken(e) || ""}`;
428
- if (this.trackedImpressionKeys.has(o))
423
+ const { analytics: s, onImpression: n } = i, r = s ? `${s.requestId}:${s.slotId}:${e.original.id}:${this.getViewToken(e) || ""}` : `no-analytics:${e.original.id}:${this.getViewToken(e) || ""}`;
424
+ if (this.trackedImpressionKeys.has(r))
429
425
  return;
430
426
  let a = !1;
431
427
  const c = () => {
432
- a || this.trackedImpressionKeys.has(o) || (a = !0, this.trackedImpressionKeys.add(o), l());
433
- }, l = () => {
428
+ a || this.trackedImpressionKeys.has(r) || (a = !0, this.trackedImpressionKeys.add(r), d());
429
+ }, d = () => {
434
430
  s ? I({
435
431
  requestId: s.requestId,
436
432
  adId: e.original.id,
437
433
  slotId: s.slotId,
438
434
  position: s.position,
439
435
  totalAds: s.totalAds,
440
- sessionId: y(),
436
+ sessionId: m(),
441
437
  adTitle: e.adapted.title,
442
438
  format: e.original.type,
443
439
  source: "internal",
@@ -445,17 +441,17 @@ const C = class C {
445
441
  userId: s.userId
446
442
  }, { baseUrl: s.apiBaseUrl }).then(() => {
447
443
  n && n(e);
448
- }).catch((d) => {
449
- console.error("[DOMRenderer] Analytics impression tracking failed:", d);
444
+ }).catch((l) => {
445
+ console.error("[DOMRenderer] Analytics impression tracking failed:", l);
450
446
  }) : n && n(e);
451
447
  };
452
448
  if (typeof IntersectionObserver < "u") {
453
- let d = !1, u = null;
449
+ let l = !1, u = null;
454
450
  const h = new IntersectionObserver(
455
451
  (f) => {
456
- f.forEach((m) => {
457
- d = m.isIntersecting && m.intersectionRatio >= 0.5, d ? u || (u = setTimeout(() => {
458
- u = null, d && (c(), h.disconnect());
452
+ f.forEach((v) => {
453
+ l = v.isIntersecting && v.intersectionRatio >= 0.5, l ? u || (u = setTimeout(() => {
454
+ u = null, l && (c(), h.disconnect());
459
455
  }, 1e3)) : u && (clearTimeout(u), u = null);
460
456
  });
461
457
  },
@@ -500,8 +496,8 @@ const C = class C {
500
496
  * Generate HTML for Sponsored Source Ad variants
501
497
  */
502
498
  static generateSponsoredSourceHTML(e, t) {
503
- var o;
504
- const i = e.adapted.title || "", s = e.adapted.body || "", n = ((o = e.adapted.image) == null ? void 0 : o.url) || "";
499
+ var r;
500
+ const i = e.adapted.title || "", s = e.adapted.body || "", n = ((r = e.adapted.image) == null ? void 0 : r.url) || "";
505
501
  return t === "list-item" ? `
506
502
  <div class="ax-ad-source ax-ad-variant-list-item" data-ad-id="${e.original.id}">
507
503
  ${n ? `<img src="${n}" alt="${i}" loading="lazy" />` : ""}
@@ -539,7 +535,7 @@ const C = class C {
539
535
  }
540
536
  };
541
537
  C.trackedImpressionKeys = /* @__PURE__ */ new Set();
542
- let b = C;
538
+ let y = C;
543
539
  class S {
544
540
  constructor() {
545
541
  this.cachedStaticInfo = null, this.cacheTimestamp = 0, this.CACHE_TTL = 36e5;
@@ -783,8 +779,8 @@ class S {
783
779
  const n = e.match(/(MI|Redmi|POCO)\s([\w\s]+)/);
784
780
  if (n) return n[1] + " " + n[2];
785
781
  if (/OnePlus/.test(e)) {
786
- const o = e.match(/OnePlus\s([A-Z\d]+)/);
787
- return o ? "OnePlus " + o[1] : "OnePlus";
782
+ const r = e.match(/OnePlus\s([A-Z\d]+)/);
783
+ return r ? "OnePlus " + r[1] : "OnePlus";
788
784
  }
789
785
  }
790
786
  /**
@@ -931,85 +927,85 @@ class S {
931
927
  }
932
928
  }
933
929
  const $ = () => S.getInstance();
934
- function v(r) {
935
- return $().collect(r);
930
+ function b(o) {
931
+ return $().collect(o);
936
932
  }
937
- function J() {
938
- return v().device;
933
+ function X() {
934
+ return b().device;
939
935
  }
940
936
  function N() {
941
- return v().user;
942
- }
943
- function X() {
944
- return v().app;
937
+ return b().user;
945
938
  }
946
939
  function Z() {
947
- return v().geo;
940
+ return b().app;
948
941
  }
949
942
  function Y() {
943
+ return b().geo;
944
+ }
945
+ function D() {
950
946
  return N().id;
951
947
  }
952
948
  function ee() {
953
949
  $().clearCache();
954
950
  }
955
- function te(r) {
956
- const e = v(r);
951
+ function te(o) {
952
+ const e = b(o);
957
953
  return JSON.stringify(e, null, 2);
958
954
  }
959
955
  function ie() {
960
956
  var t;
961
- const r = v();
957
+ const o = b();
962
958
  return [
963
- r.device.os,
964
- r.device.osv,
965
- r.app.name,
966
- r.user.id.slice(0, 8) + "...",
967
- ((t = r.geo) == null ? void 0 : t.country) || "Unknown"
959
+ o.device.os,
960
+ o.device.osv,
961
+ o.app.name,
962
+ o.user.id.slice(0, 8) + "...",
963
+ ((t = o.geo) == null ? void 0 : t.country) || "Unknown"
968
964
  ].join(" / ");
969
965
  }
970
966
  function M() {
971
- var r;
972
- return typeof window < "u" ? !!((r = window.__AD_CONFIG__) != null && r.debug) : !1;
967
+ var o;
968
+ return typeof window < "u" ? !!((o = window.__AD_CONFIG__) != null && o.debug) : !1;
973
969
  }
974
- function se(r) {
970
+ function se(o) {
975
971
  var e, t;
976
972
  return {
977
- id: r.original.id,
978
- type: r.original.type,
979
- score: r.original.score,
973
+ id: o.original.id,
974
+ type: o.original.type,
975
+ score: o.original.score,
980
976
  source: "internal",
981
977
  // Default source
982
978
  content: {
983
- title: r.adapted.title,
984
- body: r.adapted.body,
985
- image: (e = r.adapted.image) == null ? void 0 : e.url,
986
- cta_text: r.adapted.ctaText,
987
- price: (t = r.adapted.price) == null ? void 0 : t.display,
988
- rating: r.adapted.rating,
989
- brand: r.adapted.brand
979
+ title: o.adapted.title,
980
+ body: o.adapted.body,
981
+ image: (e = o.adapted.image) == null ? void 0 : e.url,
982
+ cta_text: o.adapted.ctaText,
983
+ price: (t = o.adapted.price) == null ? void 0 : t.display,
984
+ rating: o.adapted.rating,
985
+ brand: o.adapted.brand
990
986
  },
991
987
  tracking: {
992
- click_url: r.tracking.clickUrl || r.tracking.click_url || "",
993
- impression_url: r.tracking.impressionUrl || r.tracking.impression_url || ""
988
+ click_url: o.tracking.clickUrl || o.tracking.click_url || "",
989
+ impression_url: o.tracking.impressionUrl || o.tracking.impression_url || ""
994
990
  },
995
991
  metadata: {
996
- viewToken: r.tracking.viewToken || r.tracking.view_token,
997
- styling: r.adapted.styling
992
+ viewToken: o.tracking.viewToken || o.tracking.view_token,
993
+ styling: o.adapted.styling
998
994
  }
999
995
  };
1000
996
  }
1001
- async function D(r, e = {}) {
997
+ async function H(o, e = {}) {
1002
998
  const t = e.apiBaseUrl || "/api/v1", s = $().collect(), n = {
1003
- ...r,
999
+ ...o,
1004
1000
  clientInfo: s
1005
1001
  // Auto-injected
1006
- }, o = {
1002
+ }, r = {
1007
1003
  "Content-Type": "application/json"
1008
1004
  };
1009
- e.apiKey && (o["X-API-Key"] = e.apiKey), M() && (console.log("[fetchAds] Request URL:", `${t}/ads/request`), console.log("[fetchAds] Request params:", r), console.log("[fetchAds] Request body:", n));
1005
+ e.apiKey && (r["X-API-Key"] = e.apiKey), M() && (console.log("[fetchAds] Request URL:", `${t}/ads/request`), console.log("[fetchAds] Request params:", o), console.log("[fetchAds] Request body:", n));
1010
1006
  const a = await fetch(`${t}/ads/request`, {
1011
1007
  method: "POST",
1012
- headers: o,
1008
+ headers: r,
1013
1009
  body: JSON.stringify(n)
1014
1010
  });
1015
1011
  if (!a.ok)
@@ -1019,16 +1015,16 @@ async function D(r, e = {}) {
1019
1015
  throw new Error(c.error || "Ad request failed");
1020
1016
  return c.data;
1021
1017
  }
1022
- const H = { width: 400, height: 200 }, A = {
1018
+ const F = { width: 400, height: 200 }, A = {
1023
1019
  variant: "horizontal",
1024
1020
  count: 1,
1025
1021
  preferences: {}
1026
1022
  };
1027
- function _(r = {}) {
1023
+ function _(o = {}) {
1028
1024
  const e = {
1029
- variant: r.variant ?? A.variant,
1030
- count: r.count ?? A.count,
1031
- preferences: { ...A.preferences, ...r.preferences }
1025
+ variant: o.variant ?? A.variant,
1026
+ count: o.count ?? A.count,
1027
+ preferences: { ...A.preferences, ...o.preferences }
1032
1028
  };
1033
1029
  return [
1034
1030
  {
@@ -1036,7 +1032,7 @@ function _(r = {}) {
1036
1032
  slotName: "Action Card",
1037
1033
  format: "action_card",
1038
1034
  variant: e.variant,
1039
- size: H,
1035
+ size: F,
1040
1036
  count: e.count,
1041
1037
  preferences: e.preferences,
1042
1038
  placement: { position: "below_fold", context: "post_response" }
@@ -1045,7 +1041,7 @@ function _(r = {}) {
1045
1041
  }
1046
1042
  const g = class g {
1047
1043
  constructor(e) {
1048
- this.slots = {}, this.isLoading = !1, this.currentRequestId = null, this.adsAnalyticsMap = /* @__PURE__ */ new Map(), this.config = e, this.enabled = e.enabled !== !1, this.eventBus = new B(), this.slots_config = _(e.cardOption), typeof window < "u" && (window.__AD_CONFIG__ = {
1044
+ this.slots = {}, this.isLoading = !1, this.currentRequestId = null, this.adsAnalyticsMap = /* @__PURE__ */ new Map(), this.config = e, this.enabled = e.enabled !== !1, this.eventBus = new O(), this.slots_config = _(e.cardOption), typeof window < "u" && (window.__AD_CONFIG__ = {
1049
1045
  ...window.__AD_CONFIG__ || {},
1050
1046
  apiKey: e.apiKey,
1051
1047
  apiBaseUrl: e.apiBaseUrl,
@@ -1057,9 +1053,8 @@ const g = class g {
1057
1053
  });
1058
1054
  }
1059
1055
  async requestAds(e) {
1060
- var o;
1061
1056
  const t = "conversationContext" in e ? e : { conversationContext: e };
1062
- this.currentUserId = (o = t.userContext) == null ? void 0 : o.userId;
1057
+ this.currentUserId = this.resolveUserId(t.userContext);
1063
1058
  const i = this.buildRequestKey(t), s = g.inFlightRequests.get(i);
1064
1059
  if (s)
1065
1060
  return this.config.debug && console.log("[AdManager] Reusing in-flight request for identical context"), s;
@@ -1070,10 +1065,14 @@ const g = class g {
1070
1065
  this.isLoading = !0, this.eventBus.emit("adsLoading"), this.config.debug && console.log("[AdManager] Starting ad request...");
1071
1066
  const n = (async () => {
1072
1067
  try {
1073
- const a = await D(
1068
+ const r = await H(
1074
1069
  {
1075
1070
  conversationContext: t.conversationContext,
1076
- userContext: t.userContext ? { ...t.userContext, sessionId: t.userContext.sessionId ?? y() } : { sessionId: y() },
1071
+ userContext: t.userContext ? {
1072
+ ...t.userContext,
1073
+ userId: t.userContext.userId ?? this.currentUserId,
1074
+ sessionId: t.userContext.sessionId ?? m()
1075
+ } : { userId: this.currentUserId, sessionId: m() },
1077
1076
  slots: this.slots_config
1078
1077
  },
1079
1078
  {
@@ -1081,29 +1080,29 @@ const g = class g {
1081
1080
  apiKey: this.config.apiKey
1082
1081
  }
1083
1082
  );
1084
- this.currentRequestId = a.requestId, this.adsAnalyticsMap.clear(), a.slots.forEach((l) => {
1085
- l.ads.forEach((d, u) => {
1086
- const h = d.original.id;
1087
- this.adsAnalyticsMap.set(h, {
1088
- requestId: a.requestId,
1089
- slotId: l.slotId,
1090
- position: u,
1091
- totalAds: l.ads.length,
1083
+ this.currentRequestId = r.requestId, this.adsAnalyticsMap.clear(), r.slots.forEach((c) => {
1084
+ c.ads.forEach((d, l) => {
1085
+ const u = d.original.id;
1086
+ this.adsAnalyticsMap.set(u, {
1087
+ requestId: r.requestId,
1088
+ slotId: c.slotId,
1089
+ position: l,
1090
+ totalAds: c.ads.length,
1092
1091
  apiBaseUrl: this.config.apiBaseUrl,
1093
1092
  userId: this.currentUserId
1094
1093
  });
1095
1094
  });
1096
1095
  });
1097
- const c = {};
1098
- return a.slots.forEach((l) => {
1099
- c[l.slotId] = l;
1100
- }), this.slots = c, this.eventBus.emit("adsUpdated", this.slots), this.config.debug && console.log("[AdManager] Ads received:", {
1096
+ const a = {};
1097
+ return r.slots.forEach((c) => {
1098
+ a[c.slotId] = c;
1099
+ }), this.slots = a, this.eventBus.emit("adsUpdated", this.slots), this.config.debug && console.log("[AdManager] Ads received:", {
1101
1100
  slotCount: Object.keys(this.slots).length,
1102
1101
  slots: Object.keys(this.slots)
1103
- }), a;
1104
- } catch (a) {
1105
- const c = a;
1106
- throw this.eventBus.emit("adsError", c), c;
1102
+ }), r;
1103
+ } catch (r) {
1104
+ const a = r;
1105
+ throw this.eventBus.emit("adsError", a), a;
1107
1106
  } finally {
1108
1107
  this.isLoading = !1, g.inFlightRequests.delete(i);
1109
1108
  }
@@ -1119,25 +1118,34 @@ const g = class g {
1119
1118
  slots: this.slots_config
1120
1119
  });
1121
1120
  }
1121
+ resolveUserId(e) {
1122
+ if (e != null && e.userId)
1123
+ return e.userId;
1124
+ try {
1125
+ return D();
1126
+ } catch {
1127
+ return;
1128
+ }
1129
+ }
1122
1130
  render(e, t, i = {}) {
1123
- const s = typeof e != "string", n = s ? g.DEFAULT_SLOT_ID : e, o = s ? e : t, a = (s ? t : i) || {};
1124
- if (!o)
1131
+ const s = typeof e != "string", n = s ? g.DEFAULT_SLOT_ID : e, r = s ? e : t, a = (s ? t : i) || {};
1132
+ if (!r)
1125
1133
  return this.config.debug && console.warn("[AdManager] Render container is required"), null;
1126
1134
  const c = this.slots[n];
1127
1135
  if (!c || !c.ads || c.ads.length === 0)
1128
1136
  return this.config.debug && console.warn("[AdManager] No ads in slot:", n), null;
1129
- const l = a.adIndex ?? 0, d = c.ads[l];
1130
- if (!d)
1131
- return this.config.debug && console.warn(`[AdManager] Ad at index ${l} not found in slot:`, n), null;
1132
- const u = this.adsAnalyticsMap.get(d.original.id), h = this.slots_config.find((m) => m.slotId === n), p = (h == null ? void 0 : h.format) || "action_card";
1133
- o.innerHTML = "";
1137
+ const d = a.adIndex ?? 0, l = c.ads[d];
1138
+ if (!l)
1139
+ return this.config.debug && console.warn(`[AdManager] Ad at index ${d} not found in slot:`, n), null;
1140
+ const u = this.adsAnalyticsMap.get(l.original.id), h = this.slots_config.find((v) => v.slotId === n), p = (h == null ? void 0 : h.format) || "action_card";
1141
+ r.innerHTML = "";
1134
1142
  const f = {
1135
1143
  analytics: u,
1136
1144
  variant: a.variant,
1137
1145
  onClick: a.onClick,
1138
1146
  onImpression: a.onImpression
1139
1147
  };
1140
- return p === "suffix" ? b.renderSuffixAd(d, o, f) : p === "source" ? b.renderSponsoredSource(d, o, f) : p === "lead_gen" ? b.renderLeadGenAd(d, o, f) : b.renderActionCard(d, o, f);
1148
+ return p === "suffix" ? y.renderSuffixAd(l, r, f) : p === "source" ? y.renderSponsoredSource(l, r, f) : p === "lead_gen" ? y.renderLeadGenAd(l, r, f) : y.renderActionCard(l, r, f);
1141
1149
  }
1142
1150
  /**
1143
1151
  * Get ad slots data
@@ -1231,7 +1239,7 @@ const g = class g {
1231
1239
  const s = this.adsAnalyticsMap.get(e);
1232
1240
  if (!s || !this.currentRequestId)
1233
1241
  return this.config.debug && console.warn("[AdManager] No analytics info for ad:", e), null;
1234
- const n = y(), o = await T({
1242
+ const n = m(), r = await T({
1235
1243
  requestId: this.currentRequestId,
1236
1244
  adId: e,
1237
1245
  destinationUrl: t,
@@ -1242,7 +1250,7 @@ const g = class g {
1242
1250
  source: i == null ? void 0 : i.source,
1243
1251
  userId: s.userId ?? this.currentUserId
1244
1252
  }, { baseUrl: s.apiBaseUrl });
1245
- return o && (this.eventBus.emit("adClicked", e, s.slotId), this.config.debug && console.log("[AdManager] Click tracked via Analytics API:", o.eventId)), o;
1253
+ return r && (this.eventBus.emit("adClicked", e, s.slotId), this.config.debug && console.log("[AdManager] Click tracked via Analytics API:", r.eventId)), r;
1246
1254
  }
1247
1255
  /**
1248
1256
  * Track ad impression using Analytics API
@@ -1251,7 +1259,7 @@ const g = class g {
1251
1259
  const i = this.adsAnalyticsMap.get(e);
1252
1260
  if (!i || !this.currentRequestId)
1253
1261
  return this.config.debug && console.warn("[AdManager] No analytics info for ad:", e), null;
1254
- const s = y(), n = await I({
1262
+ const s = m(), n = await I({
1255
1263
  requestId: this.currentRequestId,
1256
1264
  adId: e,
1257
1265
  slotId: i.slotId,
@@ -1277,12 +1285,12 @@ g.DEFAULT_SLOT_ID = "action_card", g.inFlightRequests = /* @__PURE__ */ new Map(
1277
1285
  let V = g;
1278
1286
  function E() {
1279
1287
  if (typeof window < "u") {
1280
- const r = window.__AD_CONFIG__;
1281
- if (r != null && r.apiKey)
1282
- return r.apiKey;
1288
+ const o = window.__AD_CONFIG__;
1289
+ if (o != null && o.apiKey)
1290
+ return o.apiKey;
1283
1291
  }
1284
1292
  }
1285
- class F {
1293
+ class G {
1286
1294
  constructor(e = {}, t = "/api/v1") {
1287
1295
  var i, s;
1288
1296
  this.observers = /* @__PURE__ */ new Map(), this.metrics = /* @__PURE__ */ new Map(), this.timers = /* @__PURE__ */ new Map(), this.batchTimers = /* @__PURE__ */ new Map(), this.eventQueue = /* @__PURE__ */ new Map(), this.isTracking = /* @__PURE__ */ new Map(), this.config = {
@@ -1305,7 +1313,7 @@ class F {
1305
1313
  return;
1306
1314
  }
1307
1315
  this.log(`[ViewabilityTracker] Starting tracking for ${e}`);
1308
- const o = {
1316
+ const r = {
1309
1317
  visiblePercentage: 0,
1310
1318
  maxVisiblePercentage: 0,
1311
1319
  totalVisibleTimeMs: 0,
@@ -1315,9 +1323,9 @@ class F {
1315
1323
  enteredViewportAt: null,
1316
1324
  enterCount: 0
1317
1325
  };
1318
- this.metrics.set(e, o), this.isTracking.set(e, !0), this.eventQueue.set(e, []);
1326
+ this.metrics.set(e, r), this.isTracking.set(e, !0), this.eventQueue.set(e, []);
1319
1327
  const a = new IntersectionObserver(
1320
- (l) => this.handleIntersection(e, l[0], i, s, n),
1328
+ (d) => this.handleIntersection(e, d[0], i, s, n),
1321
1329
  {
1322
1330
  threshold: this.createThresholds()
1323
1331
  }
@@ -1345,54 +1353,54 @@ class F {
1345
1353
  * Event-driven: Only process when state actually changes
1346
1354
  */
1347
1355
  handleIntersection(e, t, i, s, n) {
1348
- const o = this.metrics.get(e);
1349
- if (!o || !this.isTracking.get(e)) return;
1350
- const a = o.isViewable, c = Math.round(t.intersectionRatio * 100);
1351
- o.visiblePercentage = c, o.maxVisiblePercentage = Math.max(o.maxVisiblePercentage, c);
1352
- const l = Date.now(), d = c >= this.config.minVisiblePercentage;
1353
- if (d && !o.enteredViewportAt && (o.enteredViewportAt = l, o.enterCount++, this.log(`[ViewabilityTracker] ${e} entered viewport at ${l}`), this.queueEvent(e, {
1356
+ const r = this.metrics.get(e);
1357
+ if (!r || !this.isTracking.get(e)) return;
1358
+ const a = r.isViewable, c = Math.round(t.intersectionRatio * 100);
1359
+ r.visiblePercentage = c, r.maxVisiblePercentage = Math.max(r.maxVisiblePercentage, c);
1360
+ const d = Date.now(), l = c >= this.config.minVisiblePercentage;
1361
+ if (l && !r.enteredViewportAt && (r.enteredViewportAt = d, r.enterCount++, this.log(`[ViewabilityTracker] ${e} entered viewport at ${d}`), this.queueEvent(e, {
1354
1362
  adId: e,
1355
1363
  sessionId: i,
1356
1364
  requestId: s,
1357
1365
  viewToken: n,
1358
1366
  eventType: "enter_viewport",
1359
1367
  visiblePercentage: c,
1360
- maxVisiblePercentage: o.maxVisiblePercentage,
1361
- totalVisibleTimeMs: o.totalVisibleTimeMs,
1368
+ maxVisiblePercentage: r.maxVisiblePercentage,
1369
+ totalVisibleTimeMs: r.totalVisibleTimeMs,
1362
1370
  isViewable: !1,
1363
- timestamp: l
1364
- })), !d && o.enteredViewportAt) {
1365
- const u = l - o.enteredViewportAt;
1366
- o.totalVisibleTimeMs += u, o.enteredViewportAt = null, o.currentVisibleTimeMs = 0, this.log(`[ViewabilityTracker] ${e} exited viewport, total visible: ${o.totalVisibleTimeMs}ms`), this.queueEvent(e, {
1371
+ timestamp: d
1372
+ })), !l && r.enteredViewportAt) {
1373
+ const u = d - r.enteredViewportAt;
1374
+ r.totalVisibleTimeMs += u, r.enteredViewportAt = null, r.currentVisibleTimeMs = 0, this.log(`[ViewabilityTracker] ${e} exited viewport, total visible: ${r.totalVisibleTimeMs}ms`), this.queueEvent(e, {
1367
1375
  adId: e,
1368
1376
  sessionId: i,
1369
1377
  requestId: s,
1370
1378
  viewToken: n,
1371
1379
  eventType: "exit_viewport",
1372
1380
  visiblePercentage: c,
1373
- maxVisiblePercentage: o.maxVisiblePercentage,
1374
- totalVisibleTimeMs: o.totalVisibleTimeMs,
1375
- isViewable: o.isViewable,
1376
- timestamp: l
1381
+ maxVisiblePercentage: r.maxVisiblePercentage,
1382
+ totalVisibleTimeMs: r.totalVisibleTimeMs,
1383
+ isViewable: r.isViewable,
1384
+ timestamp: d
1377
1385
  });
1378
1386
  }
1379
- o.isViewable !== a && o.isViewable && this.log(`[ViewabilityTracker] ${e} became VIEWABLE!`), this.metrics.set(e, o);
1387
+ r.isViewable !== a && r.isViewable && this.log(`[ViewabilityTracker] ${e} became VIEWABLE!`), this.metrics.set(e, r);
1380
1388
  }
1381
1389
  /**
1382
1390
  * Start monitoring loop for tracking duration
1383
1391
  * Runs every 100ms to track continuous visible time
1384
1392
  */
1385
1393
  startMonitoring(e, t, i, s) {
1386
- const o = setInterval(() => {
1394
+ const r = setInterval(() => {
1387
1395
  const a = this.metrics.get(e);
1388
1396
  if (!a || !this.isTracking.get(e)) {
1389
- clearInterval(o);
1397
+ clearInterval(r);
1390
1398
  return;
1391
1399
  }
1392
- const c = Date.now(), l = a.isViewable;
1400
+ const c = Date.now(), d = a.isViewable;
1393
1401
  if (a.enteredViewportAt) {
1394
- const d = c - a.enteredViewportAt;
1395
- a.currentVisibleTimeMs = d, d >= this.config.minViewableDuration && a.visiblePercentage >= this.config.minVisiblePercentage && (a.isViewable = !0, l || (a.viewableAt = a.enteredViewportAt, this.log(`[ViewabilityTracker] ${e} BECAME VIEWABLE at ${a.viewableAt}`), this.queueEvent(e, {
1402
+ const l = c - a.enteredViewportAt;
1403
+ a.currentVisibleTimeMs = l, l >= this.config.minViewableDuration && a.visiblePercentage >= this.config.minVisiblePercentage && (a.isViewable = !0, d || (a.viewableAt = a.enteredViewportAt, this.log(`[ViewabilityTracker] ${e} BECAME VIEWABLE at ${a.viewableAt}`), this.queueEvent(e, {
1396
1404
  adId: e,
1397
1405
  sessionId: t,
1398
1406
  requestId: i,
@@ -1407,13 +1415,13 @@ class F {
1407
1415
  }
1408
1416
  a.enteredViewportAt && (a.totalVisibleTimeMs += 100), this.metrics.set(e, a);
1409
1417
  }, 100);
1410
- this.timers.set(`${e}_monitoring`, o);
1418
+ this.timers.set(`${e}_monitoring`, r);
1411
1419
  }
1412
1420
  /**
1413
1421
  * Queue an event to be sent (batched)
1414
1422
  */
1415
1423
  queueEvent(e, t) {
1416
- var n, o;
1424
+ var n, r;
1417
1425
  const i = this.eventQueue.get(e);
1418
1426
  if (!i) {
1419
1427
  this.log(`[ViewabilityTracker] No queue found for ${e}, skipping event`);
@@ -1426,10 +1434,10 @@ class F {
1426
1434
  else {
1427
1435
  const a = this.batchTimers.get(e);
1428
1436
  a && clearTimeout(a);
1429
- const c = ((o = this.config.batchConfig) == null ? void 0 : o.maxBatchWaitMs) ?? 1e4, l = setTimeout(() => {
1437
+ const c = ((r = this.config.batchConfig) == null ? void 0 : r.maxBatchWaitMs) ?? 1e4, d = setTimeout(() => {
1430
1438
  this.flushQueue(e);
1431
1439
  }, c);
1432
- this.batchTimers.set(e, l);
1440
+ this.batchTimers.set(e, d);
1433
1441
  }
1434
1442
  }
1435
1443
  /**
@@ -1460,7 +1468,7 @@ class F {
1460
1468
  const n = this.metrics.get(e);
1461
1469
  if (!n) return;
1462
1470
  this.log(`[ViewabilityTracker] Ending tracking for ${e}`), this.flushQueue(e);
1463
- const o = Date.now();
1471
+ const r = Date.now();
1464
1472
  this.queueEvent(e, {
1465
1473
  adId: e,
1466
1474
  sessionId: t,
@@ -1471,7 +1479,7 @@ class F {
1471
1479
  maxVisiblePercentage: n.maxVisiblePercentage,
1472
1480
  totalVisibleTimeMs: n.totalVisibleTimeMs,
1473
1481
  isViewable: n.isViewable,
1474
- timestamp: o
1482
+ timestamp: r
1475
1483
  }), this.flushQueue(e), this.cleanup(e);
1476
1484
  }
1477
1485
  /**
@@ -1530,38 +1538,38 @@ class F {
1530
1538
  }
1531
1539
  }
1532
1540
  let k = null;
1533
- function ne(r, e) {
1534
- return k || (k = new F(r, e), k.setupBeforeUnload()), k;
1541
+ function ne(o, e) {
1542
+ return k || (k = new G(o, e), k.setupBeforeUnload()), k;
1535
1543
  }
1536
1544
  const re = "0.1.0";
1537
1545
  export {
1538
1546
  V as AdManager,
1539
1547
  x as AnalyticsSender,
1540
1548
  S as ClientInfoCollector,
1541
- b as DOMRenderer,
1549
+ y as DOMRenderer,
1542
1550
  w as HTMLRenderer,
1543
1551
  re as SDK_VERSION,
1544
1552
  P as SessionManager,
1545
- F as ViewabilityTracker,
1553
+ G as ViewabilityTracker,
1546
1554
  se as adaptAdToKoahAd,
1547
1555
  ee as clearClientInfoCache,
1548
- W as createAnalytics,
1549
- Q as createSession,
1550
- D as fetchAds,
1551
- G as generateViewToken,
1552
- X as getAppInfo,
1553
- v as getClientInfo,
1556
+ Q as createAnalytics,
1557
+ J as createSession,
1558
+ H as fetchAds,
1559
+ z as generateViewToken,
1560
+ Z as getAppInfo,
1561
+ b as getClientInfo,
1554
1562
  $ as getClientInfoCollector,
1555
1563
  te as getClientInfoJSON,
1556
1564
  ie as getClientInfoSummary,
1557
- J as getDeviceInfo,
1558
- Z as getGeoInfo,
1559
- y as getSessionId,
1560
- Y as getUserId,
1565
+ X as getDeviceInfo,
1566
+ Y as getGeoInfo,
1567
+ m as getSessionId,
1568
+ D as getUserId,
1561
1569
  N as getUserInfo,
1562
1570
  ne as getViewabilityTracker,
1563
1571
  T as trackAdClick,
1564
1572
  I as trackAdImpression,
1565
- z as trackClicksBatch,
1573
+ W as trackClicksBatch,
1566
1574
  j as trackImpressionsBatch
1567
1575
  };