@action-x/ad-sdk 0.1.10 → 0.1.12

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 q {
2
2
  constructor() {
3
3
  this.events = {};
4
4
  }
@@ -23,8 +23,8 @@ class B {
23
23
  this.events[e] && this.events[e].forEach((i) => {
24
24
  try {
25
25
  i(...t);
26
- } catch (s) {
27
- console.error(`[EventEmitter] Error in event handler for "${e}":`, s);
26
+ } catch (n) {
27
+ console.error(`[EventEmitter] Error in event handler for "${e}":`, n);
28
28
  }
29
29
  });
30
30
  }
@@ -42,7 +42,10 @@ class B {
42
42
  return ((t = this.events[e]) == null ? void 0 : t.length) || 0;
43
43
  }
44
44
  }
45
- class w {
45
+ function m(o) {
46
+ return o.replace(/<[^>]+>/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&nbsp;/g, " ").replace(/\s{2,}/g, " ").trim();
47
+ }
48
+ class v {
46
49
  static getClickUrl(e) {
47
50
  return e.tracking.clickUrl || e.tracking.click_url || "#";
48
51
  }
@@ -61,27 +64,29 @@ class w {
61
64
  */
62
65
  static renderActionCard(e, t = {}) {
63
66
  var f;
64
- const { variant: i = "horizontal", includeWrapper: s = !0 } = t, n = e.adapted, r = this.getClickUrl(e), a = this.getImpressionUrl(e), c = (f = n.image) != null && f.url ? `<img
65
- src="${n.image.url}"
66
- alt="${n.title}"
67
- class="ax-ad-image"
68
- loading="lazy"
69
- />` : "", u = (n.brand || "").trim(), l = u && u.toLowerCase() !== "unknown" ? `<span class="ax-ad-brand">${n.brand}</span>` : "", d = `
67
+ const { variant: i = "horizontal", includeWrapper: n = !0 } = t, s = e.adapted, r = this.getClickUrl(e), a = this.getImpressionUrl(e), c = (f = s.image) != null && f.url ? `<div class="ax-ad-image-wrap">
68
+ <img
69
+ src="${s.image.url}"
70
+ alt="${s.title}"
71
+ class="ax-ad-image"
72
+ loading="lazy"
73
+ />
74
+ </div>` : "", d = (s.brand || "").trim(), l = d && d.toLowerCase() !== "unknown" ? `<span class="ax-ad-brand">${s.brand}</span>` : "", u = `
70
75
  ${c}
71
76
  <div class="ax-ad-content">
72
77
  ${l}
73
- <h3 class="ax-ad-title">${n.title}</h3>
74
- ${n.body ? `<p class="ax-ad-body">${n.body}</p>` : ""}
78
+ <h3 class="ax-ad-title">${s.title}</h3>
79
+ ${s.body ? `<p class="ax-ad-body">${m(s.body)}</p>` : ""}
75
80
  </div>
76
- `, h = s ? `<a
81
+ `, h = n ? `<a
77
82
  href="${r}"
78
83
  class="ax-ad-card ax-ad-card-${i} ax-ad-card-link"
79
84
  target="_blank"
80
85
  rel="sponsored noopener noreferrer"
81
86
  data-ad-id="${e.original.id}"
82
87
  data-impression-url="${a}"
83
- >` : "", p = s ? "</a>" : "";
84
- return h + d + p;
88
+ >` : "", p = n ? "</a>" : "";
89
+ return h + u + p;
85
90
  }
86
91
  /**
87
92
  * Render Suffix ad as HTML string
@@ -90,19 +95,19 @@ class w {
90
95
  * @returns HTML string
91
96
  */
92
97
  static renderSuffixAd(e) {
93
- const t = e.adapted, i = this.getClickUrl(e), s = this.getImpressionUrl(e);
98
+ const t = e.adapted, i = this.getClickUrl(e), n = this.getImpressionUrl(e);
94
99
  return `
95
100
  <div class="ax-ad-suffix" data-ad-id="${e.original.id}">
96
101
  <div class="ax-ad-suffix-content">
97
102
  ${t.title ? `<h4 class="ax-ad-suffix-title">${t.title}</h4>` : ""}
98
- ${t.body ? `<p class="ax-ad-suffix-body">${t.body}</p>` : ""}
103
+ ${t.body ? `<p class="ax-ad-suffix-body">${m(t.body)}</p>` : ""}
99
104
  <a
100
105
  href="${i}"
101
106
  class="ax-ad-suffix-link"
102
107
  target="_blank"
103
108
  rel="sponsored noopener noreferrer"
104
109
  data-ad-id="${e.original.id}"
105
- data-impression-url="${s}"
110
+ data-impression-url="${n}"
106
111
  >
107
112
  ${this.getCtaText(e)}
108
113
  </a>
@@ -117,8 +122,8 @@ class w {
117
122
  * @returns HTML string
118
123
  */
119
124
  static renderSponsoredSource(e) {
120
- var n;
121
- const t = e.adapted, i = this.getClickUrl(e), s = this.getImpressionUrl(e);
125
+ var s;
126
+ const t = e.adapted, i = this.getClickUrl(e), n = this.getImpressionUrl(e);
122
127
  return `
123
128
  <div class="ax-ad-source" data-ad-id="${e.original.id}">
124
129
  <a
@@ -127,12 +132,12 @@ class w {
127
132
  target="_blank"
128
133
  rel="sponsored noopener noreferrer"
129
134
  data-ad-id="${e.original.id}"
130
- data-impression-url="${s}"
135
+ data-impression-url="${n}"
131
136
  >
132
- ${(n = t.image) != null && n.url ? `<img src="${t.image.url}" alt="" class="ax-ad-source-icon" />` : ""}
137
+ ${(s = t.image) != null && s.url ? `<img src="${t.image.url}" alt="" class="ax-ad-source-icon" />` : ""}
133
138
  <div class="ax-ad-source-info">
134
139
  <span class="ax-ad-source-name">${t.title}</span>
135
- ${t.body ? `<span class="ax-ad-source-desc">${t.body}</span>` : ""}
140
+ ${t.body ? `<span class="ax-ad-source-desc">${m(t.body)}</span>` : ""}
136
141
  </div>
137
142
  <span class="ax-ad-source-badge">Sponsored</span>
138
143
  </a>
@@ -146,19 +151,19 @@ class w {
146
151
  * @returns HTML string
147
152
  */
148
153
  static renderLeadGenAd(e) {
149
- const t = e.adapted, i = this.getClickUrl(e), s = this.getImpressionUrl(e);
154
+ const t = e.adapted, i = this.getClickUrl(e), n = this.getImpressionUrl(e);
150
155
  return `
151
156
  <div class="ax-ad-leadgen" data-ad-id="${e.original.id}">
152
157
  <div class="ax-ad-leadgen-content">
153
158
  ${t.title ? `<h3 class="ax-ad-leadgen-title">${t.title}</h3>` : ""}
154
- ${t.body ? `<p class="ax-ad-leadgen-body">${t.body}</p>` : ""}
159
+ ${t.body ? `<p class="ax-ad-leadgen-body">${m(t.body)}</p>` : ""}
155
160
  <a
156
161
  href="${i}"
157
162
  class="ax-ad-leadgen-cta"
158
163
  target="_blank"
159
164
  rel="sponsored noopener noreferrer"
160
165
  data-ad-id="${e.original.id}"
161
- data-impression-url="${s}"
166
+ data-impression-url="${n}"
162
167
  >
163
168
  ${this.getCtaText(e)}
164
169
  </a>
@@ -173,13 +178,13 @@ class w {
173
178
  * @param renderFn - Render function to use
174
179
  * @returns HTML string with all ads
175
180
  */
176
- static renderAds(e, t = w.renderActionCard.bind(w)) {
181
+ static renderAds(e, t = v.renderActionCard.bind(v)) {
177
182
  return e.map(t).join(`
178
183
  `);
179
184
  }
180
185
  }
181
- const q = "ad_session_id";
182
- function L() {
186
+ const L = "ad_session_id";
187
+ function K() {
183
188
  if (typeof window < "u") {
184
189
  const o = window.__AD_CONFIG__;
185
190
  if (o != null && o.apiKey)
@@ -190,7 +195,7 @@ function R() {
190
195
  var o;
191
196
  return typeof window < "u" ? !!((o = window.__AD_CONFIG__) != null && o.debug) : !1;
192
197
  }
193
- function C(o) {
198
+ function U(o) {
194
199
  if (o) return o;
195
200
  if (typeof window < "u") {
196
201
  const e = window.__AD_CONFIG__;
@@ -199,9 +204,9 @@ function C(o) {
199
204
  }
200
205
  return "/api/v1";
201
206
  }
202
- class E {
207
+ class V {
203
208
  constructor(e = {}) {
204
- this.memoryCache = /* @__PURE__ */ new Map(), this.sessionKey = e.sessionKey || q, this.storage = e.storage || "sessionStorage", (typeof window > "u" || typeof window.sessionStorage > "u") && (this.storage = "memory");
209
+ this.memoryCache = /* @__PURE__ */ new Map(), this.sessionKey = e.sessionKey || L, this.storage = e.storage || "sessionStorage", (typeof window > "u" || typeof window.sessionStorage > "u") && (this.storage = "memory");
205
210
  }
206
211
  /**
207
212
  * 获取 Session ID
@@ -235,7 +240,7 @@ class E {
235
240
  this.storage === "sessionStorage" ? sessionStorage.removeItem(this.sessionKey) : this.memoryCache.delete(this.sessionKey);
236
241
  }
237
242
  }
238
- const K = new E(), b = () => K.getSessionId();
243
+ const N = new V(), w = () => N.getSessionId();
239
244
  class x {
240
245
  constructor(e = {}) {
241
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;
@@ -245,7 +250,7 @@ class x {
245
250
  */
246
251
  async trackImpression(e) {
247
252
  return this.sendRequest(
248
- `${C(this.explicitBaseUrl)}/ads/impression`,
253
+ `${U(this.explicitBaseUrl)}/ads/impression`,
249
254
  e,
250
255
  "impression"
251
256
  );
@@ -255,7 +260,7 @@ class x {
255
260
  */
256
261
  async trackClick(e) {
257
262
  return this.sendRequest(
258
- `${C(this.explicitBaseUrl)}/ads/click`,
263
+ `${U(this.explicitBaseUrl)}/ads/click`,
259
264
  e,
260
265
  "click"
261
266
  );
@@ -265,31 +270,31 @@ class x {
265
270
  * 自动添加 X-API-Key header
266
271
  */
267
272
  async sendRequest(e, t, i) {
268
- let s = null;
269
- for (let n = 0; n <= this.retryAttempts; n++) {
273
+ let n = null;
274
+ for (let s = 0; s <= this.retryAttempts; s++) {
270
275
  const r = this.debug || R();
271
276
  try {
272
- r && (console.log(`[Analytics] Request URL (${i}):`, e), console.log(`[Analytics] Sending ${i} event (attempt ${n + 1}):`, t));
273
- const a = new AbortController(), c = setTimeout(() => a.abort(), this.timeout), u = {
277
+ r && (console.log(`[Analytics] Request URL (${i}):`, e), console.log(`[Analytics] Sending ${i} event (attempt ${s + 1}):`, t));
278
+ const a = new AbortController(), c = setTimeout(() => a.abort(), this.timeout), d = {
274
279
  "Content-Type": "application/json"
275
- }, l = L();
276
- l && (u["X-API-Key"] = l, r && console.log(`[Analytics] Adding X-API-Key header for ${i} event`));
277
- const d = await fetch(e, {
280
+ }, l = K();
281
+ l && (d["X-API-Key"] = l, r && console.log(`[Analytics] Adding X-API-Key header for ${i} event`));
282
+ const u = await fetch(e, {
278
283
  method: "POST",
279
- headers: u,
284
+ headers: d,
280
285
  body: JSON.stringify(t),
281
286
  keepalive: !0,
282
287
  signal: a.signal
283
288
  });
284
- if (clearTimeout(c), !d.ok)
285
- throw new Error(`HTTP ${d.status}: ${d.statusText}`);
286
- const h = await d.json();
289
+ if (clearTimeout(c), !u.ok)
290
+ throw new Error(`HTTP ${u.status}: ${u.statusText}`);
291
+ const h = await u.json();
287
292
  return r && console.log(`[Analytics] ${i} event tracked successfully:`, h), h;
288
293
  } catch (a) {
289
- s = a, r && console.warn(`[Analytics] ${i} tracking failed (attempt ${n + 1}):`, a), n < this.retryAttempts && await this.delay(this.retryDelay * (n + 1));
294
+ n = a, r && console.warn(`[Analytics] ${i} tracking failed (attempt ${s + 1}):`, a), s < this.retryAttempts && await this.delay(this.retryDelay * (s + 1));
290
295
  }
291
296
  }
292
- return console.error(`[Analytics] ${i} tracking failed after ${this.retryAttempts + 1} attempts:`, s), null;
297
+ return console.error(`[Analytics] ${i} tracking failed after ${this.retryAttempts + 1} attempts:`, n), null;
293
298
  }
294
299
  /**
295
300
  * 延迟辅助方法
@@ -298,25 +303,25 @@ class x {
298
303
  return new Promise((t) => setTimeout(t, e));
299
304
  }
300
305
  }
301
- const P = new x(), I = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackImpression(o) : P.trackImpression(o), O = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackClick(o) : P.trackClick(o);
302
- function z(o, e) {
306
+ const P = new x(), T = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackImpression(o) : P.trackImpression(o), O = (o, e) => e != null && e.baseUrl ? new x({ baseUrl: e.baseUrl }).trackClick(o) : P.trackClick(o);
307
+ function J(o, e) {
303
308
  return `vt_${o}_${e}`;
304
309
  }
305
- async function j(o) {
306
- return Promise.all(o.map((e) => I(e)));
310
+ async function X(o) {
311
+ return Promise.all(o.map((e) => T(e)));
307
312
  }
308
- async function W(o) {
313
+ async function Z(o) {
309
314
  return Promise.all(o.map((e) => O(e)));
310
315
  }
311
- function Q(o) {
316
+ function Y(o) {
312
317
  const e = new x(o);
313
318
  return {
314
319
  trackImpression: (t) => e.trackImpression(t),
315
320
  trackClick: (t) => e.trackClick(t)
316
321
  };
317
322
  }
318
- function J(o = {}) {
319
- const e = new E(o);
323
+ function ee(o = {}) {
324
+ const e = new V(o);
320
325
  return {
321
326
  getSessionId: () => e.getSessionId(),
322
327
  regenerateSessionId: () => e.regenerateSessionId(),
@@ -338,20 +343,20 @@ const $ = class $ {
338
343
  * Render Action Card ad into container
339
344
  */
340
345
  static renderActionCard(e, t, i = {}) {
341
- t.innerHTML = w.renderActionCard(e, i);
342
- const s = t.querySelector(".ax-ad-card-link");
343
- return s && s.addEventListener("click", (n) => {
344
- n.preventDefault(), this.handleClick(e, i);
346
+ t.innerHTML = v.renderActionCard(e, i);
347
+ const n = t.querySelector(".ax-ad-card-link");
348
+ return n && n.addEventListener("click", (s) => {
349
+ s.preventDefault(), this.handleClick(e, i);
345
350
  }), this.trackImpression(e, t, i), t;
346
351
  }
347
352
  /**
348
353
  * Render Suffix ad into container
349
354
  */
350
355
  static renderSuffixAd(e, t, i = {}) {
351
- const s = i.variant || "block";
352
- t.innerHTML = this.generateSuffixAdHTML(e, s);
353
- const n = t.querySelector(".ax-ad-suffix-link");
354
- return n && n.addEventListener("click", (r) => {
356
+ const n = i.variant || "block";
357
+ t.innerHTML = this.generateSuffixAdHTML(e, n);
358
+ const s = t.querySelector(".ax-ad-suffix-link");
359
+ return s && s.addEventListener("click", (r) => {
355
360
  r.preventDefault(), this.handleClick(e, i);
356
361
  }), this.trackImpression(e, t, i), t;
357
362
  }
@@ -359,10 +364,10 @@ const $ = class $ {
359
364
  * Render Sponsored Source ad into container
360
365
  */
361
366
  static renderSponsoredSource(e, t, i = {}) {
362
- const s = i.variant || "card";
363
- t.innerHTML = this.generateSponsoredSourceHTML(e, s);
364
- const n = t.querySelector(".ax-ad-source-link");
365
- return n && n.addEventListener("click", (r) => {
367
+ const n = i.variant || "card";
368
+ t.innerHTML = this.generateSponsoredSourceHTML(e, n);
369
+ const s = t.querySelector(".ax-ad-source-link");
370
+ return s && s.addEventListener("click", (r) => {
366
371
  r.preventDefault(), this.handleClick(e, i);
367
372
  }), this.trackImpression(e, t, i), t;
368
373
  }
@@ -370,73 +375,73 @@ const $ = class $ {
370
375
  * Render Lead Gen ad into container
371
376
  */
372
377
  static renderLeadGenAd(e, t, i = {}) {
373
- t.innerHTML = w.renderLeadGenAd(e);
374
- const s = t.querySelector(".ax-ad-leadgen-cta");
375
- return s && s.addEventListener("click", (n) => {
376
- n.preventDefault(), this.handleClick(e, i);
378
+ t.innerHTML = v.renderLeadGenAd(e);
379
+ const n = t.querySelector(".ax-ad-leadgen-cta");
380
+ return n && n.addEventListener("click", (s) => {
381
+ s.preventDefault(), this.handleClick(e, i);
377
382
  }), this.trackImpression(e, t, i), t;
378
383
  }
379
384
  /**
380
385
  * Render multiple ads into container
381
386
  */
382
- static renderAds(e, t, i = this.renderActionCard.bind(this), s) {
387
+ static renderAds(e, t, i = this.renderActionCard.bind(this), n) {
383
388
  t.innerHTML = "";
384
- const n = document.createElement("div");
385
- return n.className = "ax-ads-container", e.forEach((r) => {
389
+ const s = document.createElement("div");
390
+ return s.className = "ax-ads-container", e.forEach((r) => {
386
391
  const a = document.createElement("div");
387
- a.className = "ax-ad-wrapper", i.call(this, r, a, s), n.appendChild(a);
388
- }), t.appendChild(n), t;
392
+ a.className = "ax-ad-wrapper", i.call(this, r, a, n), s.appendChild(a);
393
+ }), t.appendChild(s), t;
389
394
  }
390
395
  /**
391
396
  * Handle ad click
392
397
  * Directly opens click_url in a new window.
393
398
  */
394
399
  static handleClick(e, t) {
395
- const { onClick: i } = t, s = this.getClickUrl(e);
396
- if (!s) {
400
+ const { onClick: i } = t, n = this.getClickUrl(e);
401
+ if (!n) {
397
402
  console.warn("[DOMRenderer] Missing click url for ad:", e.original.id);
398
403
  return;
399
404
  }
400
- i && i(e), this.isDebugEnabled() && console.log("[DOMRenderer] Redirect URL:", s), window.open(s, "_blank", "noopener,noreferrer");
405
+ i && i(e), this.isDebugEnabled() && console.log("[DOMRenderer] Redirect URL:", n), window.open(n, "_blank", "noopener,noreferrer");
401
406
  }
402
407
  /**
403
408
  * Track ad impression using IntersectionObserver (50% visible + 1000ms delay)
404
409
  * Falls back to immediate tracking if IntersectionObserver is unavailable.
405
410
  */
406
411
  static trackImpression(e, t, i) {
407
- 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) || ""}`;
412
+ const { analytics: n, onImpression: s } = i, r = n ? `${n.requestId}:${n.slotId}:${e.original.id}:${this.getViewToken(e) || ""}` : `no-analytics:${e.original.id}:${this.getViewToken(e) || ""}`;
408
413
  if (this.trackedImpressionKeys.has(r))
409
414
  return;
410
415
  let a = !1;
411
416
  const c = () => {
412
- a || this.trackedImpressionKeys.has(r) || (a = !0, this.trackedImpressionKeys.add(r), u());
413
- }, u = () => {
414
- s ? I({
415
- requestId: s.requestId,
417
+ a || this.trackedImpressionKeys.has(r) || (a = !0, this.trackedImpressionKeys.add(r), d());
418
+ }, d = () => {
419
+ n ? T({
420
+ requestId: n.requestId,
416
421
  adId: e.original.id,
417
- slotId: s.slotId,
418
- position: s.position,
419
- totalAds: s.totalAds,
420
- sessionId: b(),
422
+ slotId: n.slotId,
423
+ position: n.position,
424
+ totalAds: n.totalAds,
425
+ sessionId: w(),
421
426
  adTitle: e.adapted.title,
422
427
  format: e.original.type,
423
428
  source: "internal",
424
429
  viewToken: this.getViewToken(e),
425
- userId: s.userId
426
- }, { baseUrl: s.apiBaseUrl }).then(() => {
427
- n && n(e);
430
+ userId: n.userId
431
+ }, { baseUrl: n.apiBaseUrl }).then(() => {
432
+ s && s(e);
428
433
  }).catch((l) => {
429
434
  console.error("[DOMRenderer] Analytics impression tracking failed:", l);
430
- }) : n && n(e);
435
+ }) : s && s(e);
431
436
  };
432
437
  if (typeof IntersectionObserver < "u") {
433
- let l = !1, d = null;
438
+ let l = !1, u = null;
434
439
  const h = new IntersectionObserver(
435
440
  (f) => {
436
- f.forEach((v) => {
437
- l = v.isIntersecting && v.intersectionRatio >= 0.5, l ? d || (d = setTimeout(() => {
438
- d = null, l && (c(), h.disconnect());
439
- }, 1e3)) : d && (clearTimeout(d), d = null);
441
+ f.forEach((k) => {
442
+ l = k.isIntersecting && k.intersectionRatio >= 0.5, l ? u || (u = setTimeout(() => {
443
+ u = null, l && (c(), h.disconnect());
444
+ }, 1e3)) : u && (clearTimeout(u), u = null);
440
445
  });
441
446
  },
442
447
  { threshold: 0.5 }
@@ -449,7 +454,7 @@ const $ = class $ {
449
454
  * Generate HTML for Suffix Ad variants
450
455
  */
451
456
  static generateSuffixAdHTML(e, t) {
452
- const i = e.adapted.title || "", s = e.adapted.body || "";
457
+ const i = e.adapted.title || "", n = m(e.adapted.body || "");
453
458
  return t === "inline" ? `
454
459
  <span class="ax-ad-suffix-link ax-ad-variant-inline" data-ad-id="${e.original.id}">
455
460
  ${i}
@@ -472,7 +477,7 @@ const $ = class $ {
472
477
  </svg>
473
478
  </div>
474
479
  </div>
475
- ${s ? `<p class="ax-ad-suffix-body">${s}</p>` : ""}
480
+ ${n ? `<p class="ax-ad-suffix-body">${n}</p>` : ""}
476
481
  </div>
477
482
  `;
478
483
  }
@@ -481,10 +486,10 @@ const $ = class $ {
481
486
  */
482
487
  static generateSponsoredSourceHTML(e, t) {
483
488
  var r;
484
- const i = e.adapted.title || "", s = e.adapted.body || "", n = ((r = e.adapted.image) == null ? void 0 : r.url) || "";
489
+ const i = e.adapted.title || "", n = m(e.adapted.body || ""), s = ((r = e.adapted.image) == null ? void 0 : r.url) || "";
485
490
  return t === "list-item" ? `
486
491
  <div class="ax-ad-source ax-ad-variant-list-item" data-ad-id="${e.original.id}">
487
- ${n ? `<img src="${n}" alt="${i}" loading="lazy" />` : ""}
492
+ ${s ? `<img src="${s}" alt="${i}" loading="lazy" />` : ""}
488
493
  <div class="ax-ad-source-info">
489
494
  <span class="ax-ad-source-name">${i}</span>
490
495
  <span class="ax-ad-sponsored-badge" style="font-size:9px">Ad</span>
@@ -496,20 +501,20 @@ const $ = class $ {
496
501
  ` : t === "minimal" ? `
497
502
  <div data-ad-id="${e.original.id}" style="display:inline-flex">
498
503
  <a class="ax-ad-source-link ax-ad-variant-minimal">
499
- ${n ? `<img src="${n}" alt="${i}" loading="lazy" style="width:16px;height:16px;border-radius:2px;object-fit:cover" />` : ""}
504
+ ${s ? `<img src="${s}" alt="${i}" loading="lazy" style="width:16px;height:16px;border-radius:2px;object-fit:cover" />` : ""}
500
505
  <span>${i}</span>
501
506
  <span class="ax-ad-sponsored-badge" style="font-size:9px">Ad</span>
502
507
  </a>
503
508
  </div>
504
509
  ` : `
505
510
  <div class="ax-ad-source ax-ad-variant-card" data-ad-id="${e.original.id}">
506
- ${n ? `<img src="${n}" alt="${i}" loading="lazy" style="width:48px;height:48px;border-radius:6px;object-fit:cover;flex-shrink:0" />` : ""}
511
+ ${s ? `<img src="${s}" alt="${i}" loading="lazy" style="width:48px;height:48px;border-radius:6px;object-fit:cover;flex-shrink:0" />` : ""}
507
512
  <div class="ax-ad-source-info">
508
513
  <div style="display:flex;align-items:center;gap:8px;margin-bottom:4px">
509
514
  <span class="ax-ad-source-name">${i}</span>
510
515
  <span class="ax-ad-sponsored-badge">Sponsored</span>
511
516
  </div>
512
- ${s ? `<p class="ax-ad-source-desc">${s}</p>` : ""}
517
+ ${n ? `<p class="ax-ad-source-desc">${n}</p>` : ""}
513
518
  </div>
514
519
  <svg width="16" height="16" fill="none" stroke="#d1d5db" viewBox="0 0 24 24" style="flex-shrink:0">
515
520
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
@@ -519,8 +524,8 @@ const $ = class $ {
519
524
  }
520
525
  };
521
526
  $.trackedImpressionKeys = /* @__PURE__ */ new Set();
522
- let m = $;
523
- class S {
527
+ let y = $;
528
+ class I {
524
529
  constructor() {
525
530
  this.cachedStaticInfo = null, this.cacheTimestamp = 0, this.CACHE_TTL = 36e5;
526
531
  }
@@ -535,13 +540,13 @@ class S {
535
540
  name: "Unknown App",
536
541
  publisher: { id: "unknown" }
537
542
  };
538
- const e = this.inferBundle(), t = this.inferAppName(), i = this.inferAppVersion(), s = this.inferPublisherId();
543
+ const e = this.inferBundle(), t = this.inferAppName(), i = this.inferAppVersion(), n = this.inferPublisherId();
539
544
  return {
540
545
  bundle: e,
541
546
  ver: i,
542
547
  name: t,
543
548
  publisher: {
544
- id: s,
549
+ id: n,
545
550
  domain: window.location.hostname
546
551
  }
547
552
  };
@@ -559,14 +564,14 @@ class S {
559
564
  * 自动推断应用名称
560
565
  */
561
566
  inferAppName() {
562
- var s, n;
567
+ var n, s;
563
568
  if (typeof document > "u") return "Unknown App";
564
569
  const e = document.title;
565
570
  if (e && e !== "Loading..." && e.length < 100)
566
571
  return e;
567
- const t = (s = document.querySelector('meta[property="og:title"]')) == null ? void 0 : s.getAttribute("content");
572
+ const t = (n = document.querySelector('meta[property="og:title"]')) == null ? void 0 : n.getAttribute("content");
568
573
  if (t) return t;
569
- const i = (n = document.querySelector('meta[name="application-name"]')) == null ? void 0 : n.getAttribute("content");
574
+ const i = (s = document.querySelector('meta[name="application-name"]')) == null ? void 0 : s.getAttribute("content");
570
575
  return i || "Unknown App";
571
576
  }
572
577
  /**
@@ -586,8 +591,8 @@ class S {
586
591
  if (i) {
587
592
  if (t.includes("manifest"))
588
593
  return "1.0.0";
589
- const s = i.getAttribute("content");
590
- if (s) return s;
594
+ const n = i.getAttribute("content");
595
+ if (n) return n;
591
596
  }
592
597
  }
593
598
  return "1.0.0";
@@ -596,18 +601,18 @@ class S {
596
601
  * 自动推断publisher ID
597
602
  */
598
603
  inferPublisherId() {
599
- var i, s;
604
+ var i, n;
600
605
  if (typeof document > "u") return "unknown";
601
606
  const e = (i = document.querySelector('meta[name="publisher-id"]')) == null ? void 0 : i.getAttribute("content");
602
607
  if (e) return e;
603
- const t = (s = window.location) == null ? void 0 : s.hostname;
608
+ const t = (n = window.location) == null ? void 0 : n.hostname;
604
609
  return t ? t.replace(/\./g, "_") : "unknown";
605
610
  }
606
611
  /**
607
612
  * Get singleton instance
608
613
  */
609
614
  static getInstance() {
610
- return this.instance || (this.instance = new S()), this.instance;
615
+ return this.instance || (this.instance = new I()), this.instance;
611
616
  }
612
617
  /**
613
618
  * Collect all available client information
@@ -729,11 +734,11 @@ class S {
729
734
  const i = e.match(/Android (\d+)\.(\d+)/);
730
735
  if (i)
731
736
  return `${i[1]}.${i[2]}`;
732
- const s = e.match(/Windows NT (\d+\.\d+)/);
733
- if (s)
734
- return s[1];
735
- const n = e.match(/Mac OS X (\d+[._]\d+)/);
736
- return n ? n[1].replace("_", ".") : "Unknown";
737
+ const n = e.match(/Windows NT (\d+\.\d+)/);
738
+ if (n)
739
+ return n[1];
740
+ const s = e.match(/Mac OS X (\d+[._]\d+)/);
741
+ return s ? s[1].replace("_", ".") : "Unknown";
737
742
  }
738
743
  /**
739
744
  * Detect Device Type (OpenRTB standard)
@@ -758,10 +763,10 @@ class S {
758
763
  const i = e.match(/Samsung-.*(SM-\w+)/);
759
764
  if (i) return i[1];
760
765
  if (/Pixel/.test(e)) return "Google Pixel";
761
- const s = e.match(/(BARC-|HUAWEI-)?([A-Z]{2}\-\w{4})/);
762
- if (s) return s[2];
763
- const n = e.match(/(MI|Redmi|POCO)\s([\w\s]+)/);
764
- if (n) return n[1] + " " + n[2];
766
+ const n = e.match(/(BARC-|HUAWEI-)?([A-Z]{2}\-\w{4})/);
767
+ if (n) return n[2];
768
+ const s = e.match(/(MI|Redmi|POCO)\s([\w\s]+)/);
769
+ if (s) return s[1] + " " + s[2];
765
770
  if (/OnePlus/.test(e)) {
766
771
  const r = e.match(/OnePlus\s([A-Z\d]+)/);
767
772
  return r ? "OnePlus " + r[1] : "OnePlus";
@@ -877,9 +882,9 @@ class S {
877
882
  if (t && i[t])
878
883
  return i[t];
879
884
  if (e) {
880
- const s = e.split("-")[1];
881
- if (s)
882
- return s.toUpperCase();
885
+ const n = e.split("-")[1];
886
+ if (n)
887
+ return n.toUpperCase();
883
888
  }
884
889
  }
885
890
  /**
@@ -910,35 +915,35 @@ class S {
910
915
  this.cachedStaticInfo = null, this.cacheTimestamp = 0;
911
916
  }
912
917
  }
913
- const T = () => S.getInstance();
914
- function y(o) {
915
- return T().collect(o);
918
+ const C = () => I.getInstance();
919
+ function b(o) {
920
+ return C().collect(o);
916
921
  }
917
- function X() {
918
- return y().device;
922
+ function te() {
923
+ return b().device;
919
924
  }
920
- function N() {
921
- return y().user;
925
+ function H() {
926
+ return b().user;
922
927
  }
923
- function Z() {
924
- return y().app;
928
+ function ie() {
929
+ return b().app;
925
930
  }
926
- function Y() {
927
- return y().geo;
931
+ function ne() {
932
+ return b().geo;
928
933
  }
929
- function H() {
930
- return N().id;
934
+ function D() {
935
+ return H().id;
931
936
  }
932
- function ee() {
933
- T().clearCache();
937
+ function se() {
938
+ C().clearCache();
934
939
  }
935
- function te(o) {
936
- const e = y(o);
940
+ function re(o) {
941
+ const e = b(o);
937
942
  return JSON.stringify(e, null, 2);
938
943
  }
939
- function ie() {
944
+ function oe() {
940
945
  var t;
941
- const o = y();
946
+ const o = b();
942
947
  return [
943
948
  o.device.os,
944
949
  o.device.osv,
@@ -947,11 +952,33 @@ function ie() {
947
952
  ((t = o.geo) == null ? void 0 : t.country) || "Unknown"
948
953
  ].join(" / ");
949
954
  }
950
- function U() {
955
+ function B() {
956
+ if (typeof crypto > "u" || !crypto.subtle)
957
+ throw new Error("Web Crypto API not supported");
958
+ }
959
+ async function G(o, e) {
960
+ B();
961
+ const t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e)), i = await crypto.subtle.importKey("raw", t, "AES-GCM", !1, ["encrypt"]), n = crypto.getRandomValues(new Uint8Array(12)), s = await crypto.subtle.encrypt(
962
+ { name: "AES-GCM", iv: n },
963
+ i,
964
+ new TextEncoder().encode(o)
965
+ ), r = new Uint8Array(n.length + s.byteLength);
966
+ return r.set(n), r.set(new Uint8Array(s), n.length), btoa(String.fromCharCode(...r));
967
+ }
968
+ async function F(o, e) {
969
+ B();
970
+ const t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e)), i = await crypto.subtle.importKey("raw", t, "AES-GCM", !1, ["decrypt"]), n = Uint8Array.from(atob(o), (c) => c.charCodeAt(0)), s = n.slice(0, 12), r = n.slice(12), a = await crypto.subtle.decrypt(
971
+ { name: "AES-GCM", iv: s },
972
+ i,
973
+ r
974
+ );
975
+ return new TextDecoder().decode(a);
976
+ }
977
+ function z() {
951
978
  var o;
952
979
  return typeof window < "u" ? !!((o = window.__AD_CONFIG__) != null && o.debug) : !1;
953
980
  }
954
- function se(o) {
981
+ function ae(o) {
955
982
  var e, t;
956
983
  return {
957
984
  id: o.original.id,
@@ -978,37 +1005,51 @@ function se(o) {
978
1005
  }
979
1006
  };
980
1007
  }
981
- async function D(o, e = {}) {
982
- const t = e.apiBaseUrl || "/api/v1", s = T().collect(), n = {
1008
+ async function j(o, e = {}) {
1009
+ const t = e.apiBaseUrl || "/api/v1", i = z(), s = C().collect(), r = {
983
1010
  ...o,
984
1011
  clientInfo: s
985
- // Auto-injected
986
- }, r = {
1012
+ }, a = {
987
1013
  "Content-Type": "application/json"
988
1014
  };
989
- e.apiKey && (r["X-API-Key"] = e.apiKey), U() && (console.log("[fetchAds] Request URL:", `${t}/ads/request`), console.log("[fetchAds] Request params:", o), console.log("[fetchAds] Request body:", n));
990
- const a = await fetch(`${t}/ads/request`, {
1015
+ e.apiKey && (a["X-API-Key"] = e.apiKey);
1016
+ let c;
1017
+ if (e.apiKey && !i)
1018
+ try {
1019
+ c = { encryptedPayload: await G(JSON.stringify(r), e.apiKey) };
1020
+ } catch (h) {
1021
+ i && console.warn("[fetchAds] Encryption failed, using plaintext:", h), c = r;
1022
+ }
1023
+ else
1024
+ c = r;
1025
+ i && (console.log("[fetchAds] Request URL:", `${t}/ads/request`), console.log("[fetchAds] Request body:", c));
1026
+ const d = await fetch(`${t}/ads/request`, {
991
1027
  method: "POST",
992
- headers: r,
993
- body: JSON.stringify(n)
1028
+ headers: a,
1029
+ body: JSON.stringify(c)
994
1030
  });
995
- if (!a.ok)
996
- throw new Error(`Ad request failed: ${a.status} ${a.statusText}`);
997
- const c = await a.json();
998
- if (U() && console.log("[fetchAds] Response:", c), !c.success)
999
- throw new Error(c.error || "Ad request failed");
1000
- return c.data;
1031
+ if (!d.ok)
1032
+ throw new Error(`Ad request failed: ${d.status} ${d.statusText}`);
1033
+ const l = await d.json();
1034
+ if (!l.success)
1035
+ throw new Error(l.error || "Ad request failed");
1036
+ let u = l.data;
1037
+ if (l.data.encryptedPayload && e.apiKey) {
1038
+ const h = await F(l.data.encryptedPayload, e.apiKey);
1039
+ u = JSON.parse(h);
1040
+ }
1041
+ return i && console.log("[fetchAds] Response:", u), u;
1001
1042
  }
1002
- const F = { width: 400, height: 200 }, A = {
1043
+ const W = { width: 400, height: 200 }, S = {
1003
1044
  variant: "horizontal",
1004
1045
  count: 1,
1005
1046
  preferences: {}
1006
1047
  };
1007
1048
  function M(o = {}) {
1008
1049
  const e = {
1009
- variant: o.variant ?? A.variant,
1010
- count: o.count ?? A.count,
1011
- preferences: { ...A.preferences, ...o.preferences }
1050
+ variant: o.variant ?? S.variant,
1051
+ count: o.count ?? S.count,
1052
+ preferences: { ...S.preferences, ...o.preferences }
1012
1053
  };
1013
1054
  return [
1014
1055
  {
@@ -1016,7 +1057,7 @@ function M(o = {}) {
1016
1057
  slotName: "Action Card",
1017
1058
  format: "action_card",
1018
1059
  variant: e.variant,
1019
- size: F,
1060
+ size: W,
1020
1061
  count: e.count,
1021
1062
  preferences: e.preferences,
1022
1063
  placement: { position: "below_fold", context: "post_response" }
@@ -1025,7 +1066,7 @@ function M(o = {}) {
1025
1066
  }
1026
1067
  const g = class g {
1027
1068
  constructor(e) {
1028
- 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 = M(e.cardOption), typeof window < "u" && (window.__AD_CONFIG__ = {
1069
+ this.slots = {}, this.isLoading = !1, this.currentRequestId = null, this.adsAnalyticsMap = /* @__PURE__ */ new Map(), this.config = e, this.enabled = e.enabled !== !1, this.eventBus = new q(), this.slots_config = M(e.cardOption), typeof window < "u" && (window.__AD_CONFIG__ = {
1029
1070
  ...window.__AD_CONFIG__ || {},
1030
1071
  apiKey: e.apiKey,
1031
1072
  apiBaseUrl: e.apiBaseUrl,
@@ -1039,24 +1080,24 @@ const g = class g {
1039
1080
  async requestAds(e) {
1040
1081
  const t = "conversationContext" in e ? e : { conversationContext: e };
1041
1082
  this.currentUserId = this.resolveUserId(t.userContext);
1042
- const i = this.buildRequestKey(t), s = g.inFlightRequests.get(i);
1043
- if (s)
1044
- return this.config.debug && console.log("[AdManager] Reusing in-flight request for identical context"), s;
1083
+ const i = this.buildRequestKey(t), n = g.inFlightRequests.get(i);
1084
+ if (n)
1085
+ return this.config.debug && console.log("[AdManager] Reusing in-flight request for identical context"), n;
1045
1086
  if (!this.enabled)
1046
1087
  throw this.config.debug && console.warn("[AdManager] Ads are disabled, skipping request"), new Error("Ads are disabled");
1047
1088
  if (this.isLoading)
1048
1089
  throw this.config.debug && console.warn("[AdManager] Request already in progress"), new Error("Request already in progress");
1049
1090
  this.isLoading = !0, this.eventBus.emit("adsLoading"), this.config.debug && console.log("[AdManager] Starting ad request...");
1050
- const n = (async () => {
1091
+ const s = (async () => {
1051
1092
  try {
1052
- const r = await D(
1093
+ const r = await j(
1053
1094
  {
1054
1095
  conversationContext: t.conversationContext,
1055
1096
  userContext: t.userContext ? {
1056
1097
  ...t.userContext,
1057
1098
  userId: t.userContext.userId ?? this.currentUserId,
1058
- sessionId: t.userContext.sessionId ?? b()
1059
- } : { userId: this.currentUserId, sessionId: b() },
1099
+ sessionId: t.userContext.sessionId ?? w()
1100
+ } : { userId: this.currentUserId, sessionId: w() },
1060
1101
  slots: this.slots_config
1061
1102
  },
1062
1103
  {
@@ -1065,9 +1106,9 @@ const g = class g {
1065
1106
  }
1066
1107
  );
1067
1108
  this.currentRequestId = r.requestId, this.adsAnalyticsMap.clear(), r.slots.forEach((c) => {
1068
- c.ads.forEach((u, l) => {
1069
- const d = u.original.id;
1070
- this.adsAnalyticsMap.set(d, {
1109
+ c.ads.forEach((d, l) => {
1110
+ const u = d.original.id;
1111
+ this.adsAnalyticsMap.set(u, {
1071
1112
  requestId: r.requestId,
1072
1113
  slotId: c.slotId,
1073
1114
  position: l,
@@ -1091,7 +1132,7 @@ const g = class g {
1091
1132
  this.isLoading = !1, g.inFlightRequests.delete(i);
1092
1133
  }
1093
1134
  })();
1094
- return g.inFlightRequests.set(i, n), n;
1135
+ return g.inFlightRequests.set(i, s), s;
1095
1136
  }
1096
1137
  buildRequestKey(e) {
1097
1138
  return JSON.stringify({
@@ -1106,30 +1147,30 @@ const g = class g {
1106
1147
  if (e != null && e.userId)
1107
1148
  return e.userId;
1108
1149
  try {
1109
- return H();
1150
+ return D();
1110
1151
  } catch {
1111
1152
  return;
1112
1153
  }
1113
1154
  }
1114
1155
  render(e, t, i = {}) {
1115
- const s = typeof e != "string", n = s ? g.DEFAULT_SLOT_ID : e, r = s ? e : t, a = (s ? t : i) || {};
1156
+ const n = typeof e != "string", s = n ? g.DEFAULT_SLOT_ID : e, r = n ? e : t, a = (n ? t : i) || {};
1116
1157
  if (!r)
1117
1158
  return this.config.debug && console.warn("[AdManager] Render container is required"), null;
1118
- const c = this.slots[n];
1159
+ const c = this.slots[s];
1119
1160
  if (!c || !c.ads || c.ads.length === 0)
1120
- return this.config.debug && console.warn("[AdManager] No ads in slot:", n), null;
1121
- const u = a.adIndex ?? 0, l = c.ads[u];
1161
+ return this.config.debug && console.warn("[AdManager] No ads in slot:", s), null;
1162
+ const d = a.adIndex ?? 0, l = c.ads[d];
1122
1163
  if (!l)
1123
- return this.config.debug && console.warn(`[AdManager] Ad at index ${u} not found in slot:`, n), null;
1124
- const d = this.adsAnalyticsMap.get(l.original.id), h = this.slots_config.find((v) => v.slotId === n), p = (h == null ? void 0 : h.format) || "action_card";
1164
+ return this.config.debug && console.warn(`[AdManager] Ad at index ${d} not found in slot:`, s), null;
1165
+ const u = this.adsAnalyticsMap.get(l.original.id), h = this.slots_config.find((k) => k.slotId === s), p = (h == null ? void 0 : h.format) || "action_card";
1125
1166
  r.innerHTML = "";
1126
1167
  const f = {
1127
- analytics: d,
1168
+ analytics: u,
1128
1169
  variant: a.variant,
1129
1170
  onClick: a.onClick,
1130
1171
  onImpression: a.onImpression
1131
1172
  };
1132
- return p === "suffix" ? m.renderSuffixAd(l, r, f) : p === "source" ? m.renderSponsoredSource(l, r, f) : p === "lead_gen" ? m.renderLeadGenAd(l, r, f) : m.renderActionCard(l, r, f);
1173
+ 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);
1133
1174
  }
1134
1175
  /**
1135
1176
  * Get ad slots data
@@ -1212,29 +1253,29 @@ const g = class g {
1212
1253
  getAdsAnalytics(e) {
1213
1254
  const t = /* @__PURE__ */ new Map();
1214
1255
  return e.forEach((i) => {
1215
- const s = this.adsAnalyticsMap.get(i);
1216
- s && t.set(i, s);
1256
+ const n = this.adsAnalyticsMap.get(i);
1257
+ n && t.set(i, n);
1217
1258
  }), t;
1218
1259
  }
1219
1260
  /**
1220
1261
  * Track ad click using Analytics API
1221
1262
  */
1222
1263
  async trackAdClick(e, t, i) {
1223
- const s = this.adsAnalyticsMap.get(e);
1224
- if (!s || !this.currentRequestId)
1264
+ const n = this.adsAnalyticsMap.get(e);
1265
+ if (!n || !this.currentRequestId)
1225
1266
  return this.config.debug && console.warn("[AdManager] No analytics info for ad:", e), null;
1226
- const n = b(), r = await O({
1267
+ const s = w(), r = await O({
1227
1268
  requestId: this.currentRequestId,
1228
1269
  adId: e,
1229
1270
  destinationUrl: t,
1230
- sessionId: n,
1231
- slotId: s.slotId,
1271
+ sessionId: s,
1272
+ slotId: n.slotId,
1232
1273
  adTitle: i == null ? void 0 : i.title,
1233
1274
  format: i == null ? void 0 : i.format,
1234
1275
  source: i == null ? void 0 : i.source,
1235
- userId: s.userId ?? this.currentUserId
1236
- }, { baseUrl: s.apiBaseUrl });
1237
- return r && (this.eventBus.emit("adClicked", e, s.slotId), this.config.debug && console.log("[AdManager] Click tracked via Analytics API:", r.eventId)), r;
1276
+ userId: n.userId ?? this.currentUserId
1277
+ }, { baseUrl: n.apiBaseUrl });
1278
+ return r && (this.eventBus.emit("adClicked", e, n.slotId), this.config.debug && console.log("[AdManager] Click tracked via Analytics API:", r.eventId)), r;
1238
1279
  }
1239
1280
  /**
1240
1281
  * Track ad impression using Analytics API
@@ -1243,20 +1284,20 @@ const g = class g {
1243
1284
  const i = this.adsAnalyticsMap.get(e);
1244
1285
  if (!i || !this.currentRequestId)
1245
1286
  return this.config.debug && console.warn("[AdManager] No analytics info for ad:", e), null;
1246
- const s = b(), n = await I({
1287
+ const n = w(), s = await T({
1247
1288
  requestId: this.currentRequestId,
1248
1289
  adId: e,
1249
1290
  slotId: i.slotId,
1250
1291
  position: i.position,
1251
1292
  totalAds: i.totalAds,
1252
- sessionId: s,
1293
+ sessionId: n,
1253
1294
  adTitle: t == null ? void 0 : t.title,
1254
1295
  format: t == null ? void 0 : t.format,
1255
1296
  source: t == null ? void 0 : t.source,
1256
1297
  viewToken: t == null ? void 0 : t.viewToken,
1257
1298
  userId: i.userId ?? this.currentUserId
1258
1299
  }, { baseUrl: i.apiBaseUrl });
1259
- return n && (this.eventBus.emit("adImpression", e, i.slotId), this.config.debug && console.log("[AdManager] Impression tracked via Analytics API:", n.eventId)), n;
1300
+ return s && (this.eventBus.emit("adImpression", e, i.slotId), this.config.debug && console.log("[AdManager] Impression tracked via Analytics API:", s.eventId)), s;
1260
1301
  }
1261
1302
  /**
1262
1303
  * Destroy the manager and clean up
@@ -1267,23 +1308,23 @@ const g = class g {
1267
1308
  };
1268
1309
  g.DEFAULT_SLOT_ID = "action_card", g.inFlightRequests = /* @__PURE__ */ new Map();
1269
1310
  let _ = g;
1270
- function V() {
1311
+ function E() {
1271
1312
  if (typeof window < "u") {
1272
1313
  const o = window.__AD_CONFIG__;
1273
1314
  if (o != null && o.apiKey)
1274
1315
  return o.apiKey;
1275
1316
  }
1276
1317
  }
1277
- class G {
1318
+ class Q {
1278
1319
  constructor(e = {}, t = "/api/v1") {
1279
- var i, s;
1320
+ var i, n;
1280
1321
  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 = {
1281
1322
  minVisiblePercentage: e.minVisiblePercentage ?? 50,
1282
1323
  minViewableDuration: e.minViewableDuration ?? 1e3,
1283
1324
  maxTrackingDuration: e.maxTrackingDuration ?? 6e4,
1284
1325
  batchConfig: {
1285
1326
  maxBatchSize: ((i = e.batchConfig) == null ? void 0 : i.maxBatchSize) ?? 5,
1286
- maxBatchWaitMs: ((s = e.batchConfig) == null ? void 0 : s.maxBatchWaitMs) ?? 1e4
1327
+ maxBatchWaitMs: ((n = e.batchConfig) == null ? void 0 : n.maxBatchWaitMs) ?? 1e4
1287
1328
  },
1288
1329
  debug: e.debug ?? !1
1289
1330
  }, this.baseUrl = t;
@@ -1291,7 +1332,7 @@ class G {
1291
1332
  /**
1292
1333
  * Start tracking viewability for an ad element
1293
1334
  */
1294
- startTracking(e, t, i, s, n) {
1335
+ startTracking(e, t, i, n, s) {
1295
1336
  if (this.isTracking.get(e)) {
1296
1337
  this.log(`[ViewabilityTracker] Already tracking ${e}, skipping`);
1297
1338
  return;
@@ -1309,14 +1350,14 @@ class G {
1309
1350
  };
1310
1351
  this.metrics.set(e, r), this.isTracking.set(e, !0), this.eventQueue.set(e, []);
1311
1352
  const a = new IntersectionObserver(
1312
- (u) => this.handleIntersection(e, u[0], i, s, n),
1353
+ (d) => this.handleIntersection(e, d[0], i, n, s),
1313
1354
  {
1314
1355
  threshold: this.createThresholds()
1315
1356
  }
1316
1357
  );
1317
- a.observe(t), this.observers.set(e, a), this.startMonitoring(e, i, s, n);
1358
+ a.observe(t), this.observers.set(e, a), this.startMonitoring(e, i, n, s);
1318
1359
  const c = setTimeout(() => {
1319
- this.endTracking(e, i, s, n);
1360
+ this.endTracking(e, i, n, s);
1320
1361
  }, this.config.maxTrackingDuration);
1321
1362
  this.timers.set(e, c);
1322
1363
  }
@@ -1336,36 +1377,36 @@ class G {
1336
1377
  * Handle IntersectionObserver callback
1337
1378
  * Event-driven: Only process when state actually changes
1338
1379
  */
1339
- handleIntersection(e, t, i, s, n) {
1380
+ handleIntersection(e, t, i, n, s) {
1340
1381
  const r = this.metrics.get(e);
1341
1382
  if (!r || !this.isTracking.get(e)) return;
1342
1383
  const a = r.isViewable, c = Math.round(t.intersectionRatio * 100);
1343
1384
  r.visiblePercentage = c, r.maxVisiblePercentage = Math.max(r.maxVisiblePercentage, c);
1344
- const u = Date.now(), l = c >= this.config.minVisiblePercentage;
1345
- if (l && !r.enteredViewportAt && (r.enteredViewportAt = u, r.enterCount++, this.log(`[ViewabilityTracker] ${e} entered viewport at ${u}`), this.queueEvent(e, {
1385
+ const d = Date.now(), l = c >= this.config.minVisiblePercentage;
1386
+ if (l && !r.enteredViewportAt && (r.enteredViewportAt = d, r.enterCount++, this.log(`[ViewabilityTracker] ${e} entered viewport at ${d}`), this.queueEvent(e, {
1346
1387
  adId: e,
1347
1388
  sessionId: i,
1348
- requestId: s,
1349
- viewToken: n,
1389
+ requestId: n,
1390
+ viewToken: s,
1350
1391
  eventType: "enter_viewport",
1351
1392
  visiblePercentage: c,
1352
1393
  maxVisiblePercentage: r.maxVisiblePercentage,
1353
1394
  totalVisibleTimeMs: r.totalVisibleTimeMs,
1354
1395
  isViewable: !1,
1355
- timestamp: u
1396
+ timestamp: d
1356
1397
  })), !l && r.enteredViewportAt) {
1357
- const d = u - r.enteredViewportAt;
1358
- r.totalVisibleTimeMs += d, r.enteredViewportAt = null, r.currentVisibleTimeMs = 0, this.log(`[ViewabilityTracker] ${e} exited viewport, total visible: ${r.totalVisibleTimeMs}ms`), this.queueEvent(e, {
1398
+ const u = d - r.enteredViewportAt;
1399
+ r.totalVisibleTimeMs += u, r.enteredViewportAt = null, r.currentVisibleTimeMs = 0, this.log(`[ViewabilityTracker] ${e} exited viewport, total visible: ${r.totalVisibleTimeMs}ms`), this.queueEvent(e, {
1359
1400
  adId: e,
1360
1401
  sessionId: i,
1361
- requestId: s,
1362
- viewToken: n,
1402
+ requestId: n,
1403
+ viewToken: s,
1363
1404
  eventType: "exit_viewport",
1364
1405
  visiblePercentage: c,
1365
1406
  maxVisiblePercentage: r.maxVisiblePercentage,
1366
1407
  totalVisibleTimeMs: r.totalVisibleTimeMs,
1367
1408
  isViewable: r.isViewable,
1368
- timestamp: u
1409
+ timestamp: d
1369
1410
  });
1370
1411
  }
1371
1412
  r.isViewable !== a && r.isViewable && this.log(`[ViewabilityTracker] ${e} became VIEWABLE!`), this.metrics.set(e, r);
@@ -1374,21 +1415,21 @@ class G {
1374
1415
  * Start monitoring loop for tracking duration
1375
1416
  * Runs every 100ms to track continuous visible time
1376
1417
  */
1377
- startMonitoring(e, t, i, s) {
1418
+ startMonitoring(e, t, i, n) {
1378
1419
  const r = setInterval(() => {
1379
1420
  const a = this.metrics.get(e);
1380
1421
  if (!a || !this.isTracking.get(e)) {
1381
1422
  clearInterval(r);
1382
1423
  return;
1383
1424
  }
1384
- const c = Date.now(), u = a.isViewable;
1425
+ const c = Date.now(), d = a.isViewable;
1385
1426
  if (a.enteredViewportAt) {
1386
1427
  const l = c - a.enteredViewportAt;
1387
- a.currentVisibleTimeMs = l, l >= this.config.minViewableDuration && a.visiblePercentage >= this.config.minVisiblePercentage && (a.isViewable = !0, u || (a.viewableAt = a.enteredViewportAt, this.log(`[ViewabilityTracker] ${e} BECAME VIEWABLE at ${a.viewableAt}`), this.queueEvent(e, {
1428
+ 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, {
1388
1429
  adId: e,
1389
1430
  sessionId: t,
1390
1431
  requestId: i,
1391
- viewToken: s,
1432
+ viewToken: n,
1392
1433
  eventType: "become_viewable",
1393
1434
  visiblePercentage: a.visiblePercentage,
1394
1435
  maxVisiblePercentage: a.maxVisiblePercentage,
@@ -1405,23 +1446,23 @@ class G {
1405
1446
  * Queue an event to be sent (batched)
1406
1447
  */
1407
1448
  queueEvent(e, t) {
1408
- var n, r;
1449
+ var s, r;
1409
1450
  const i = this.eventQueue.get(e);
1410
1451
  if (!i) {
1411
1452
  this.log(`[ViewabilityTracker] No queue found for ${e}, skipping event`);
1412
1453
  return;
1413
1454
  }
1414
1455
  i.push(t), this.log(`[ViewabilityTracker] Queued ${t.eventType} for ${e} (queue size: ${i.length})`);
1415
- const s = ((n = this.config.batchConfig) == null ? void 0 : n.maxBatchSize) ?? 5;
1416
- if (i.length >= s)
1456
+ const n = ((s = this.config.batchConfig) == null ? void 0 : s.maxBatchSize) ?? 5;
1457
+ if (i.length >= n)
1417
1458
  this.flushQueue(e);
1418
1459
  else {
1419
1460
  const a = this.batchTimers.get(e);
1420
1461
  a && clearTimeout(a);
1421
- const c = ((r = this.config.batchConfig) == null ? void 0 : r.maxBatchWaitMs) ?? 1e4, u = setTimeout(() => {
1462
+ const c = ((r = this.config.batchConfig) == null ? void 0 : r.maxBatchWaitMs) ?? 1e4, d = setTimeout(() => {
1422
1463
  this.flushQueue(e);
1423
1464
  }, c);
1424
- this.batchTimers.set(e, u);
1465
+ this.batchTimers.set(e, d);
1425
1466
  }
1426
1467
  }
1427
1468
  /**
@@ -1433,36 +1474,36 @@ class G {
1433
1474
  const i = [...t];
1434
1475
  t.length = 0, this.log(`[ViewabilityTracker] Flushing ${i.length} events for ${e}`);
1435
1476
  try {
1436
- const s = {
1477
+ const n = {
1437
1478
  "Content-Type": "application/json"
1438
- }, n = V();
1439
- n && (s["x-api-key"] = n), await fetch(`${this.baseUrl}/ads/viewability/batch`, {
1479
+ }, s = E();
1480
+ s && (n["x-api-key"] = s), await fetch(`${this.baseUrl}/ads/viewability/batch`, {
1440
1481
  method: "POST",
1441
- headers: s,
1482
+ headers: n,
1442
1483
  body: JSON.stringify({ events: i })
1443
1484
  }), this.log(`[ViewabilityTracker] Successfully sent ${i.length} events for ${e}`);
1444
- } catch (s) {
1445
- this.log(`[ViewabilityTracker] Failed to send events for ${e}:`, s), t.unshift(...i);
1485
+ } catch (n) {
1486
+ this.log(`[ViewabilityTracker] Failed to send events for ${e}:`, n), t.unshift(...i);
1446
1487
  }
1447
1488
  }
1448
1489
  /**
1449
1490
  * End tracking and send final metrics
1450
1491
  */
1451
- endTracking(e, t, i, s) {
1452
- const n = this.metrics.get(e);
1453
- if (!n) return;
1492
+ endTracking(e, t, i, n) {
1493
+ const s = this.metrics.get(e);
1494
+ if (!s) return;
1454
1495
  this.log(`[ViewabilityTracker] Ending tracking for ${e}`), this.flushQueue(e);
1455
1496
  const r = Date.now();
1456
1497
  this.queueEvent(e, {
1457
1498
  adId: e,
1458
1499
  sessionId: t,
1459
1500
  requestId: i,
1460
- viewToken: s,
1501
+ viewToken: n,
1461
1502
  eventType: "end_tracking",
1462
- visiblePercentage: n.visiblePercentage,
1463
- maxVisiblePercentage: n.maxVisiblePercentage,
1464
- totalVisibleTimeMs: n.totalVisibleTimeMs,
1465
- isViewable: n.isViewable,
1503
+ visiblePercentage: s.visiblePercentage,
1504
+ maxVisiblePercentage: s.maxVisiblePercentage,
1505
+ totalVisibleTimeMs: s.totalVisibleTimeMs,
1506
+ isViewable: s.isViewable,
1466
1507
  timestamp: r
1467
1508
  }), this.flushQueue(e), this.cleanup(e);
1468
1509
  }
@@ -1474,10 +1515,10 @@ class G {
1474
1515
  t && (t.disconnect(), this.observers.delete(e));
1475
1516
  const i = this.timers.get(e);
1476
1517
  i && (clearTimeout(i), this.timers.delete(e));
1477
- const s = this.timers.get(`${e}_monitoring`);
1478
- s && (clearInterval(s), this.timers.delete(`${e}_monitoring`));
1479
- const n = this.batchTimers.get(e);
1480
- n && (clearTimeout(n), this.batchTimers.delete(e)), this.flushQueue(e), this.isTracking.delete(e), this.metrics.delete(e), this.eventQueue.delete(e);
1518
+ const n = this.timers.get(`${e}_monitoring`);
1519
+ n && (clearInterval(n), this.timers.delete(`${e}_monitoring`));
1520
+ const s = this.batchTimers.get(e);
1521
+ s && (clearTimeout(s), this.batchTimers.delete(e)), this.flushQueue(e), this.isTracking.delete(e), this.metrics.delete(e), this.eventQueue.delete(e);
1481
1522
  }
1482
1523
  /**
1483
1524
  * Create thresholds for IntersectionObserver
@@ -1509,8 +1550,8 @@ class G {
1509
1550
  if (t && t.length > 0) {
1510
1551
  const i = {
1511
1552
  "Content-Type": "application/json"
1512
- }, s = V();
1513
- s && (i["x-api-key"] = s), fetch(`${this.baseUrl}/ads/viewability/batch`, {
1553
+ }, n = E();
1554
+ n && (i["x-api-key"] = n), fetch(`${this.baseUrl}/ads/viewability/batch`, {
1514
1555
  method: "POST",
1515
1556
  headers: i,
1516
1557
  keepalive: !0,
@@ -1521,39 +1562,41 @@ class G {
1521
1562
  });
1522
1563
  }
1523
1564
  }
1524
- let k = null;
1525
- function ne(o, e) {
1526
- return k || (k = new G(o, e), k.setupBeforeUnload()), k;
1565
+ let A = null;
1566
+ function ce(o, e) {
1567
+ return A || (A = new Q(o, e), A.setupBeforeUnload()), A;
1527
1568
  }
1528
- const re = "0.1.0";
1569
+ const le = "0.1.0";
1529
1570
  export {
1530
1571
  _ as AdManager,
1531
1572
  x as AnalyticsSender,
1532
- S as ClientInfoCollector,
1533
- m as DOMRenderer,
1534
- w as HTMLRenderer,
1535
- re as SDK_VERSION,
1536
- E as SessionManager,
1537
- G as ViewabilityTracker,
1538
- se as adaptAdToKoahAd,
1539
- ee as clearClientInfoCache,
1540
- Q as createAnalytics,
1541
- J as createSession,
1542
- D as fetchAds,
1543
- z as generateViewToken,
1544
- Z as getAppInfo,
1545
- y as getClientInfo,
1546
- T as getClientInfoCollector,
1547
- te as getClientInfoJSON,
1548
- ie as getClientInfoSummary,
1549
- X as getDeviceInfo,
1550
- Y as getGeoInfo,
1551
- b as getSessionId,
1552
- H as getUserId,
1553
- N as getUserInfo,
1554
- ne as getViewabilityTracker,
1573
+ I as ClientInfoCollector,
1574
+ y as DOMRenderer,
1575
+ v as HTMLRenderer,
1576
+ le as SDK_VERSION,
1577
+ V as SessionManager,
1578
+ Q as ViewabilityTracker,
1579
+ ae as adaptAdToKoahAd,
1580
+ se as clearClientInfoCache,
1581
+ Y as createAnalytics,
1582
+ ee as createSession,
1583
+ F as decryptAES,
1584
+ G as encryptAES,
1585
+ j as fetchAds,
1586
+ J as generateViewToken,
1587
+ ie as getAppInfo,
1588
+ b as getClientInfo,
1589
+ C as getClientInfoCollector,
1590
+ re as getClientInfoJSON,
1591
+ oe as getClientInfoSummary,
1592
+ te as getDeviceInfo,
1593
+ ne as getGeoInfo,
1594
+ w as getSessionId,
1595
+ D as getUserId,
1596
+ H as getUserInfo,
1597
+ ce as getViewabilityTracker,
1555
1598
  O as trackAdClick,
1556
- I as trackAdImpression,
1557
- W as trackClicksBatch,
1558
- j as trackImpressionsBatch
1599
+ T as trackAdImpression,
1600
+ Z as trackClicksBatch,
1601
+ X as trackImpressionsBatch
1559
1602
  };