@bidkernel/analytics 0.1.0

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.mjs ADDED
@@ -0,0 +1,1365 @@
1
+ // ../../protogen/trace_event.ts
2
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
3
+ var TraceEventType = {
4
+ TRACE_EVENT_TYPE_UNSPECIFIED: 0,
5
+ AUCTION_START: 1,
6
+ AUCTION_END: 2,
7
+ BID_REQUEST: 3,
8
+ BID_RESPONSE: 4,
9
+ BID_WIN: 5,
10
+ BID_TIMEOUT: 6,
11
+ /** IMPRESSION - ad rendered into DOM */
12
+ IMPRESSION: 7,
13
+ /** VIEWABLE - IAB viewability threshold met (boolean, once per render cycle) */
14
+ VIEWABLE: 8,
15
+ /** TIME_IN_VIEW - accumulated in-viewport duration (once per render cycle end) */
16
+ TIME_IN_VIEW: 14,
17
+ REFRESH: 9,
18
+ ERROR: 10,
19
+ SLOT_DEFINED: 11,
20
+ SLOT_DESTROYED: 12,
21
+ /** CLICK - ad click-through */
22
+ CLICK: 13,
23
+ /** NO_BID - bidder responded with no bid */
24
+ NO_BID: 15,
25
+ /** AD_RENDER_FAILED - Prebid failed to render the winning ad */
26
+ AD_RENDER_FAILED: 16,
27
+ UNRECOGNIZED: -1
28
+ };
29
+ function createBaseTraceEventBatch() {
30
+ return {
31
+ propertyId: "",
32
+ pageviewId: "",
33
+ sessionId: "",
34
+ pageUrl: "",
35
+ country: "",
36
+ region: "",
37
+ deviceType: "",
38
+ userId: "",
39
+ domain: "",
40
+ events: [],
41
+ browser: "",
42
+ deviceManufacturer: "",
43
+ deviceModel: "",
44
+ city: "",
45
+ postalCode: ""
46
+ };
47
+ }
48
+ var TraceEventBatch = {
49
+ encode(message, writer = new BinaryWriter()) {
50
+ if (message.propertyId !== void 0 && message.propertyId !== "") {
51
+ writer.uint32(10).string(message.propertyId);
52
+ }
53
+ if (message.pageviewId !== void 0 && message.pageviewId !== "") {
54
+ writer.uint32(18).string(message.pageviewId);
55
+ }
56
+ if (message.sessionId !== void 0 && message.sessionId !== "") {
57
+ writer.uint32(26).string(message.sessionId);
58
+ }
59
+ if (message.pageUrl !== void 0 && message.pageUrl !== "") {
60
+ writer.uint32(34).string(message.pageUrl);
61
+ }
62
+ if (message.country !== void 0 && message.country !== "") {
63
+ writer.uint32(42).string(message.country);
64
+ }
65
+ if (message.region !== void 0 && message.region !== "") {
66
+ writer.uint32(50).string(message.region);
67
+ }
68
+ if (message.deviceType !== void 0 && message.deviceType !== "") {
69
+ writer.uint32(58).string(message.deviceType);
70
+ }
71
+ if (message.userId !== void 0 && message.userId !== "") {
72
+ writer.uint32(66).string(message.userId);
73
+ }
74
+ if (message.domain !== void 0 && message.domain !== "") {
75
+ writer.uint32(74).string(message.domain);
76
+ }
77
+ if (message.events !== void 0 && message.events.length !== 0) {
78
+ for (const v of message.events) {
79
+ TraceEvent.encode(v, writer.uint32(82).fork()).join();
80
+ }
81
+ }
82
+ if (message.browser !== void 0 && message.browser !== "") {
83
+ writer.uint32(90).string(message.browser);
84
+ }
85
+ if (message.deviceManufacturer !== void 0 && message.deviceManufacturer !== "") {
86
+ writer.uint32(98).string(message.deviceManufacturer);
87
+ }
88
+ if (message.deviceModel !== void 0 && message.deviceModel !== "") {
89
+ writer.uint32(106).string(message.deviceModel);
90
+ }
91
+ if (message.city !== void 0 && message.city !== "") {
92
+ writer.uint32(114).string(message.city);
93
+ }
94
+ if (message.postalCode !== void 0 && message.postalCode !== "") {
95
+ writer.uint32(122).string(message.postalCode);
96
+ }
97
+ return writer;
98
+ },
99
+ decode(input, length) {
100
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
101
+ const end = length === void 0 ? reader.len : reader.pos + length;
102
+ const message = createBaseTraceEventBatch();
103
+ while (reader.pos < end) {
104
+ const tag = reader.uint32();
105
+ switch (tag >>> 3) {
106
+ case 1: {
107
+ if (tag !== 10) {
108
+ break;
109
+ }
110
+ message.propertyId = reader.string();
111
+ continue;
112
+ }
113
+ case 2: {
114
+ if (tag !== 18) {
115
+ break;
116
+ }
117
+ message.pageviewId = reader.string();
118
+ continue;
119
+ }
120
+ case 3: {
121
+ if (tag !== 26) {
122
+ break;
123
+ }
124
+ message.sessionId = reader.string();
125
+ continue;
126
+ }
127
+ case 4: {
128
+ if (tag !== 34) {
129
+ break;
130
+ }
131
+ message.pageUrl = reader.string();
132
+ continue;
133
+ }
134
+ case 5: {
135
+ if (tag !== 42) {
136
+ break;
137
+ }
138
+ message.country = reader.string();
139
+ continue;
140
+ }
141
+ case 6: {
142
+ if (tag !== 50) {
143
+ break;
144
+ }
145
+ message.region = reader.string();
146
+ continue;
147
+ }
148
+ case 7: {
149
+ if (tag !== 58) {
150
+ break;
151
+ }
152
+ message.deviceType = reader.string();
153
+ continue;
154
+ }
155
+ case 8: {
156
+ if (tag !== 66) {
157
+ break;
158
+ }
159
+ message.userId = reader.string();
160
+ continue;
161
+ }
162
+ case 9: {
163
+ if (tag !== 74) {
164
+ break;
165
+ }
166
+ message.domain = reader.string();
167
+ continue;
168
+ }
169
+ case 10: {
170
+ if (tag !== 82) {
171
+ break;
172
+ }
173
+ const el = TraceEvent.decode(reader, reader.uint32());
174
+ if (el !== void 0) {
175
+ message.events.push(el);
176
+ }
177
+ continue;
178
+ }
179
+ case 11: {
180
+ if (tag !== 90) {
181
+ break;
182
+ }
183
+ message.browser = reader.string();
184
+ continue;
185
+ }
186
+ case 12: {
187
+ if (tag !== 98) {
188
+ break;
189
+ }
190
+ message.deviceManufacturer = reader.string();
191
+ continue;
192
+ }
193
+ case 13: {
194
+ if (tag !== 106) {
195
+ break;
196
+ }
197
+ message.deviceModel = reader.string();
198
+ continue;
199
+ }
200
+ case 14: {
201
+ if (tag !== 114) {
202
+ break;
203
+ }
204
+ message.city = reader.string();
205
+ continue;
206
+ }
207
+ case 15: {
208
+ if (tag !== 122) {
209
+ break;
210
+ }
211
+ message.postalCode = reader.string();
212
+ continue;
213
+ }
214
+ }
215
+ if ((tag & 7) === 4 || tag === 0) {
216
+ break;
217
+ }
218
+ reader.skip(tag & 7);
219
+ }
220
+ return message;
221
+ },
222
+ create(base) {
223
+ return TraceEventBatch.fromPartial(base ?? {});
224
+ },
225
+ fromPartial(object) {
226
+ const message = createBaseTraceEventBatch();
227
+ message.propertyId = object.propertyId ?? "";
228
+ message.pageviewId = object.pageviewId ?? "";
229
+ message.sessionId = object.sessionId ?? "";
230
+ message.pageUrl = object.pageUrl ?? "";
231
+ message.country = object.country ?? "";
232
+ message.region = object.region ?? "";
233
+ message.deviceType = object.deviceType ?? "";
234
+ message.userId = object.userId ?? "";
235
+ message.domain = object.domain ?? "";
236
+ message.events = object.events?.map((e) => TraceEvent.fromPartial(e)) || [];
237
+ message.browser = object.browser ?? "";
238
+ message.deviceManufacturer = object.deviceManufacturer ?? "";
239
+ message.deviceModel = object.deviceModel ?? "";
240
+ message.city = object.city ?? "";
241
+ message.postalCode = object.postalCode ?? "";
242
+ return message;
243
+ }
244
+ };
245
+ function createBaseTraceEvent() {
246
+ return {
247
+ timestampMs: 0,
248
+ type: 0,
249
+ eventName: "",
250
+ auctionId: "",
251
+ transactionId: "",
252
+ adUnitCode: "",
253
+ bid: void 0,
254
+ namespace: "",
255
+ eventId: "",
256
+ metadata: {},
257
+ viewableDurationMs: void 0
258
+ };
259
+ }
260
+ var TraceEvent = {
261
+ encode(message, writer = new BinaryWriter()) {
262
+ if (message.timestampMs !== void 0 && message.timestampMs !== 0) {
263
+ writer.uint32(9).double(message.timestampMs);
264
+ }
265
+ if (message.type !== void 0 && message.type !== 0) {
266
+ writer.uint32(16).int32(message.type);
267
+ }
268
+ if (message.eventName !== void 0 && message.eventName !== "") {
269
+ writer.uint32(26).string(message.eventName);
270
+ }
271
+ if (message.auctionId !== void 0 && message.auctionId !== "") {
272
+ writer.uint32(34).string(message.auctionId);
273
+ }
274
+ if (message.transactionId !== void 0 && message.transactionId !== "") {
275
+ writer.uint32(42).string(message.transactionId);
276
+ }
277
+ if (message.adUnitCode !== void 0 && message.adUnitCode !== "") {
278
+ writer.uint32(50).string(message.adUnitCode);
279
+ }
280
+ if (message.bid !== void 0) {
281
+ BidTrace.encode(message.bid, writer.uint32(58).fork()).join();
282
+ }
283
+ if (message.namespace !== void 0 && message.namespace !== "") {
284
+ writer.uint32(66).string(message.namespace);
285
+ }
286
+ if (message.eventId !== void 0 && message.eventId !== "") {
287
+ writer.uint32(74).string(message.eventId);
288
+ }
289
+ globalThis.Object.entries(message.metadata || {}).forEach(([key, value]) => {
290
+ TraceEvent_MetadataEntry.encode({ key, value }, writer.uint32(82).fork()).join();
291
+ });
292
+ if (message.viewableDurationMs !== void 0) {
293
+ writer.uint32(89).double(message.viewableDurationMs);
294
+ }
295
+ return writer;
296
+ },
297
+ decode(input, length) {
298
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
299
+ const end = length === void 0 ? reader.len : reader.pos + length;
300
+ const message = createBaseTraceEvent();
301
+ while (reader.pos < end) {
302
+ const tag = reader.uint32();
303
+ switch (tag >>> 3) {
304
+ case 1: {
305
+ if (tag !== 9) {
306
+ break;
307
+ }
308
+ message.timestampMs = reader.double();
309
+ continue;
310
+ }
311
+ case 2: {
312
+ if (tag !== 16) {
313
+ break;
314
+ }
315
+ message.type = reader.int32();
316
+ continue;
317
+ }
318
+ case 3: {
319
+ if (tag !== 26) {
320
+ break;
321
+ }
322
+ message.eventName = reader.string();
323
+ continue;
324
+ }
325
+ case 4: {
326
+ if (tag !== 34) {
327
+ break;
328
+ }
329
+ message.auctionId = reader.string();
330
+ continue;
331
+ }
332
+ case 5: {
333
+ if (tag !== 42) {
334
+ break;
335
+ }
336
+ message.transactionId = reader.string();
337
+ continue;
338
+ }
339
+ case 6: {
340
+ if (tag !== 50) {
341
+ break;
342
+ }
343
+ message.adUnitCode = reader.string();
344
+ continue;
345
+ }
346
+ case 7: {
347
+ if (tag !== 58) {
348
+ break;
349
+ }
350
+ message.bid = BidTrace.decode(reader, reader.uint32());
351
+ continue;
352
+ }
353
+ case 8: {
354
+ if (tag !== 66) {
355
+ break;
356
+ }
357
+ message.namespace = reader.string();
358
+ continue;
359
+ }
360
+ case 9: {
361
+ if (tag !== 74) {
362
+ break;
363
+ }
364
+ message.eventId = reader.string();
365
+ continue;
366
+ }
367
+ case 10: {
368
+ if (tag !== 82) {
369
+ break;
370
+ }
371
+ const entry10 = TraceEvent_MetadataEntry.decode(reader, reader.uint32());
372
+ if (entry10.value !== void 0) {
373
+ message.metadata[entry10.key] = entry10.value;
374
+ }
375
+ continue;
376
+ }
377
+ case 11: {
378
+ if (tag !== 89) {
379
+ break;
380
+ }
381
+ message.viewableDurationMs = reader.double();
382
+ continue;
383
+ }
384
+ }
385
+ if ((tag & 7) === 4 || tag === 0) {
386
+ break;
387
+ }
388
+ reader.skip(tag & 7);
389
+ }
390
+ return message;
391
+ },
392
+ create(base) {
393
+ return TraceEvent.fromPartial(base ?? {});
394
+ },
395
+ fromPartial(object) {
396
+ const message = createBaseTraceEvent();
397
+ message.timestampMs = object.timestampMs ?? 0;
398
+ message.type = object.type ?? 0;
399
+ message.eventName = object.eventName ?? "";
400
+ message.auctionId = object.auctionId ?? "";
401
+ message.transactionId = object.transactionId ?? "";
402
+ message.adUnitCode = object.adUnitCode ?? "";
403
+ message.bid = object.bid !== void 0 && object.bid !== null ? BidTrace.fromPartial(object.bid) : void 0;
404
+ message.namespace = object.namespace ?? "";
405
+ message.eventId = object.eventId ?? "";
406
+ message.metadata = globalThis.Object.entries(object.metadata ?? {}).reduce(
407
+ (acc, [key, value]) => {
408
+ if (value !== void 0) {
409
+ acc[key] = globalThis.String(value);
410
+ }
411
+ return acc;
412
+ },
413
+ {}
414
+ );
415
+ message.viewableDurationMs = object.viewableDurationMs ?? void 0;
416
+ return message;
417
+ }
418
+ };
419
+ function createBaseTraceEvent_MetadataEntry() {
420
+ return { key: "", value: "" };
421
+ }
422
+ var TraceEvent_MetadataEntry = {
423
+ encode(message, writer = new BinaryWriter()) {
424
+ if (message.key !== "") {
425
+ writer.uint32(10).string(message.key);
426
+ }
427
+ if (message.value !== "") {
428
+ writer.uint32(18).string(message.value);
429
+ }
430
+ return writer;
431
+ },
432
+ decode(input, length) {
433
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
434
+ const end = length === void 0 ? reader.len : reader.pos + length;
435
+ const message = createBaseTraceEvent_MetadataEntry();
436
+ while (reader.pos < end) {
437
+ const tag = reader.uint32();
438
+ switch (tag >>> 3) {
439
+ case 1: {
440
+ if (tag !== 10) {
441
+ break;
442
+ }
443
+ message.key = reader.string();
444
+ continue;
445
+ }
446
+ case 2: {
447
+ if (tag !== 18) {
448
+ break;
449
+ }
450
+ message.value = reader.string();
451
+ continue;
452
+ }
453
+ }
454
+ if ((tag & 7) === 4 || tag === 0) {
455
+ break;
456
+ }
457
+ reader.skip(tag & 7);
458
+ }
459
+ return message;
460
+ },
461
+ create(base) {
462
+ return TraceEvent_MetadataEntry.fromPartial(base ?? {});
463
+ },
464
+ fromPartial(object) {
465
+ const message = createBaseTraceEvent_MetadataEntry();
466
+ message.key = object.key ?? "";
467
+ message.value = object.value ?? "";
468
+ return message;
469
+ }
470
+ };
471
+ function createBaseBidTrace() {
472
+ return {
473
+ bidder: "",
474
+ cpm: 0,
475
+ currency: "",
476
+ width: 0,
477
+ height: 0,
478
+ dealId: "",
479
+ mediaType: "",
480
+ latencyMs: 0,
481
+ advertiserDomain: "",
482
+ creativeId: ""
483
+ };
484
+ }
485
+ var BidTrace = {
486
+ encode(message, writer = new BinaryWriter()) {
487
+ if (message.bidder !== void 0 && message.bidder !== "") {
488
+ writer.uint32(10).string(message.bidder);
489
+ }
490
+ if (message.cpm !== void 0 && message.cpm !== 0) {
491
+ writer.uint32(17).double(message.cpm);
492
+ }
493
+ if (message.currency !== void 0 && message.currency !== "") {
494
+ writer.uint32(26).string(message.currency);
495
+ }
496
+ if (message.width !== void 0 && message.width !== 0) {
497
+ writer.uint32(32).int32(message.width);
498
+ }
499
+ if (message.height !== void 0 && message.height !== 0) {
500
+ writer.uint32(40).int32(message.height);
501
+ }
502
+ if (message.dealId !== void 0 && message.dealId !== "") {
503
+ writer.uint32(50).string(message.dealId);
504
+ }
505
+ if (message.mediaType !== void 0 && message.mediaType !== "") {
506
+ writer.uint32(58).string(message.mediaType);
507
+ }
508
+ if (message.latencyMs !== void 0 && message.latencyMs !== 0) {
509
+ writer.uint32(65).double(message.latencyMs);
510
+ }
511
+ if (message.advertiserDomain !== void 0 && message.advertiserDomain !== "") {
512
+ writer.uint32(74).string(message.advertiserDomain);
513
+ }
514
+ if (message.creativeId !== void 0 && message.creativeId !== "") {
515
+ writer.uint32(82).string(message.creativeId);
516
+ }
517
+ return writer;
518
+ },
519
+ decode(input, length) {
520
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
521
+ const end = length === void 0 ? reader.len : reader.pos + length;
522
+ const message = createBaseBidTrace();
523
+ while (reader.pos < end) {
524
+ const tag = reader.uint32();
525
+ switch (tag >>> 3) {
526
+ case 1: {
527
+ if (tag !== 10) {
528
+ break;
529
+ }
530
+ message.bidder = reader.string();
531
+ continue;
532
+ }
533
+ case 2: {
534
+ if (tag !== 17) {
535
+ break;
536
+ }
537
+ message.cpm = reader.double();
538
+ continue;
539
+ }
540
+ case 3: {
541
+ if (tag !== 26) {
542
+ break;
543
+ }
544
+ message.currency = reader.string();
545
+ continue;
546
+ }
547
+ case 4: {
548
+ if (tag !== 32) {
549
+ break;
550
+ }
551
+ message.width = reader.int32();
552
+ continue;
553
+ }
554
+ case 5: {
555
+ if (tag !== 40) {
556
+ break;
557
+ }
558
+ message.height = reader.int32();
559
+ continue;
560
+ }
561
+ case 6: {
562
+ if (tag !== 50) {
563
+ break;
564
+ }
565
+ message.dealId = reader.string();
566
+ continue;
567
+ }
568
+ case 7: {
569
+ if (tag !== 58) {
570
+ break;
571
+ }
572
+ message.mediaType = reader.string();
573
+ continue;
574
+ }
575
+ case 8: {
576
+ if (tag !== 65) {
577
+ break;
578
+ }
579
+ message.latencyMs = reader.double();
580
+ continue;
581
+ }
582
+ case 9: {
583
+ if (tag !== 74) {
584
+ break;
585
+ }
586
+ message.advertiserDomain = reader.string();
587
+ continue;
588
+ }
589
+ case 10: {
590
+ if (tag !== 82) {
591
+ break;
592
+ }
593
+ message.creativeId = reader.string();
594
+ continue;
595
+ }
596
+ }
597
+ if ((tag & 7) === 4 || tag === 0) {
598
+ break;
599
+ }
600
+ reader.skip(tag & 7);
601
+ }
602
+ return message;
603
+ },
604
+ create(base) {
605
+ return BidTrace.fromPartial(base ?? {});
606
+ },
607
+ fromPartial(object) {
608
+ const message = createBaseBidTrace();
609
+ message.bidder = object.bidder ?? "";
610
+ message.cpm = object.cpm ?? 0;
611
+ message.currency = object.currency ?? "";
612
+ message.width = object.width ?? 0;
613
+ message.height = object.height ?? 0;
614
+ message.dealId = object.dealId ?? "";
615
+ message.mediaType = object.mediaType ?? "";
616
+ message.latencyMs = object.latencyMs ?? 0;
617
+ message.advertiserDomain = object.advertiserDomain ?? "";
618
+ message.creativeId = object.creativeId ?? "";
619
+ return message;
620
+ }
621
+ };
622
+
623
+ // src/prebid-analytics.ts
624
+ var BATCH_SIZE = 20;
625
+ var FLUSH_INTERVAL_MS = 1e4;
626
+ var MAX_ERRORS_PER_SESSION = 50;
627
+ var MAX_QUEUE_SIZE = 200;
628
+ var MAX_SEND_BACKOFF_MS = 5 * 60 * 1e3;
629
+ var MAX_CONSECUTIVE_SEND_FAILURES = 10;
630
+ var EVENT_NAME_TO_TYPE = {
631
+ auctionStart: TraceEventType.AUCTION_START,
632
+ auctionEnd: TraceEventType.AUCTION_END,
633
+ bidRequest: TraceEventType.BID_REQUEST,
634
+ bidResponse: TraceEventType.BID_RESPONSE,
635
+ bidTimeout: TraceEventType.BID_TIMEOUT,
636
+ bidWin: TraceEventType.BID_WIN,
637
+ noBid: TraceEventType.NO_BID,
638
+ adRenderFailed: TraceEventType.AD_RENDER_FAILED,
639
+ click: TraceEventType.CLICK,
640
+ impression: TraceEventType.IMPRESSION,
641
+ refresh: TraceEventType.REFRESH,
642
+ timeInView: TraceEventType.TIME_IN_VIEW,
643
+ viewable: TraceEventType.VIEWABLE
644
+ };
645
+ var SESSION_KEY = "_bidkernel_session";
646
+ var SESSION_TS_KEY = "_bidkernel_session_ts";
647
+ var THIRTY_MINUTES_MS = 30 * 60 * 1e3;
648
+ var inMemorySessionId = null;
649
+ var inMemorySessionTs = 0;
650
+ function generateUUID() {
651
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
652
+ return crypto.randomUUID();
653
+ }
654
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
655
+ const r = Math.random() * 16 | 0;
656
+ const v = c === "x" ? r : r & 3 | 8;
657
+ return v.toString(16);
658
+ });
659
+ }
660
+ function extendSession() {
661
+ const now = Date.now();
662
+ inMemorySessionTs = now;
663
+ try {
664
+ if (typeof localStorage !== "undefined") {
665
+ localStorage.setItem(SESSION_TS_KEY, now.toString());
666
+ }
667
+ } catch {
668
+ }
669
+ }
670
+ function getOrCreateSessionId() {
671
+ const now = Date.now();
672
+ try {
673
+ if (typeof localStorage !== "undefined") {
674
+ const storedId = localStorage.getItem(SESSION_KEY);
675
+ const tsStr = localStorage.getItem(SESSION_TS_KEY);
676
+ const storedTs = tsStr ? parseInt(tsStr, 10) || 0 : 0;
677
+ if (storedId && storedTs && now - storedTs <= THIRTY_MINUTES_MS) {
678
+ localStorage.setItem(SESSION_TS_KEY, now.toString());
679
+ return storedId;
680
+ }
681
+ const newId = generateUUID();
682
+ localStorage.setItem(SESSION_KEY, newId);
683
+ localStorage.setItem(SESSION_TS_KEY, now.toString());
684
+ return newId;
685
+ }
686
+ } catch {
687
+ }
688
+ if (inMemorySessionId && inMemorySessionTs && now - inMemorySessionTs <= THIRTY_MINUTES_MS) {
689
+ inMemorySessionTs = now;
690
+ return inMemorySessionId;
691
+ }
692
+ inMemorySessionId = generateUUID();
693
+ inMemorySessionTs = now;
694
+ return inMemorySessionId;
695
+ }
696
+ function getPrebidEventKey(eventName, data) {
697
+ switch (eventName) {
698
+ case "auctionInit":
699
+ return `auctionInit:${data?.auctionId || ""}`;
700
+ case "auctionEnd":
701
+ return `auctionEnd:${data?.auctionId || ""}`;
702
+ case "bidRequested":
703
+ return `bidRequested:${data?.auctionId || ""}:${data?.bidderCode || ""}:${Array.isArray(data?.bids) ? data.bids.map((b) => b?.bidId || b?.adUnitCode || "").join(",") : ""}`;
704
+ case "bidResponse":
705
+ return `bidResponse:${data?.auctionId || ""}:${data?.adUnitCode || ""}:${data?.bidderCode || data?.bidder || ""}:${data?.creativeId || data?.adId || data?.requestId || ""}:${data?.originalCpm ?? data?.cpm ?? ""}`;
706
+ case "bidTimeout":
707
+ if (Array.isArray(data)) {
708
+ return "bidTimeout:" + data.map(
709
+ (t) => `${t?.auctionId || ""}:${t?.bidder || t?.bidderCode || ""}:${t?.bidId || t?.adUnitCode || ""}`
710
+ ).join(",");
711
+ }
712
+ return `bidTimeout:${data?.auctionId || ""}:${data?.bidder || data?.bidderCode || ""}:${data?.bidId || data?.adUnitCode || ""}`;
713
+ case "bidWon":
714
+ return `bidWon:${data?.auctionId || ""}:${data?.adUnitCode || ""}:${data?.bidderCode || data?.bidder || ""}:${data?.creativeId || data?.adId || data?.requestId || ""}:${data?.originalCpm ?? data?.cpm ?? ""}`;
715
+ case "noBid":
716
+ return `noBid:${data?.auctionId || ""}:${data?.adUnitCode || ""}:${data?.bidderCode || data?.bidder || ""}:${data?.bidId || ""}`;
717
+ case "adRenderFailed":
718
+ return `adRenderFailed:${data?.bid?.auctionId || data?.auctionId || ""}:${data?.bid?.adUnitCode || data?.adUnitCode || ""}:${data?.bid?.bidderCode || data?.bid?.bidder || ""}:${data?.reason || ""}:${data?.message || ""}`;
719
+ case "adRenderSucceeded":
720
+ return `adRenderSucceeded:${data?.bid?.auctionId || data?.auctionId || ""}:${data?.bid?.adUnitCode || data?.adUnitCode || ""}:${data?.bid?.bidderCode || data?.bid?.bidder || ""}`;
721
+ case "setTargeting":
722
+ return `setTargeting:${Object.keys(data || {}).sort().join(",")}`;
723
+ case "auctionDebug":
724
+ return `auctionDebug:${data?.type || ""}:${String(data?.arguments?.[0] ?? "").slice(0, 50)}`;
725
+ default:
726
+ return "";
727
+ }
728
+ }
729
+ var PrebidEventDeduper = class {
730
+ seenObjects = /* @__PURE__ */ new WeakSet();
731
+ seenKeys = /* @__PURE__ */ new Set();
732
+ isDuplicate(eventName, data) {
733
+ if (!data) return false;
734
+ if (typeof data === "object") {
735
+ if (this.seenObjects.has(data)) return true;
736
+ this.seenObjects.add(data);
737
+ }
738
+ const key = getPrebidEventKey(eventName, data);
739
+ if (key) {
740
+ if (this.seenKeys.has(key)) return true;
741
+ if (this.seenKeys.size >= 1e3) {
742
+ const first = this.seenKeys.values().next().value;
743
+ if (first !== void 0) this.seenKeys.delete(first);
744
+ }
745
+ this.seenKeys.add(key);
746
+ }
747
+ return false;
748
+ }
749
+ };
750
+ function parseSize(raw) {
751
+ if (!raw) return { width: 0, height: 0 };
752
+ let cur = raw;
753
+ while (Array.isArray(cur) && cur.length > 0 && Array.isArray(cur[0])) {
754
+ cur = cur[0];
755
+ }
756
+ if (Array.isArray(cur) && cur.length >= 2) {
757
+ const w = Number(cur[0]);
758
+ const h = Number(cur[1]);
759
+ return {
760
+ width: Number.isFinite(w) ? w : 0,
761
+ height: Number.isFinite(h) ? h : 0
762
+ };
763
+ }
764
+ return { width: 0, height: 0 };
765
+ }
766
+ var BidkernelPrebidAnalytics = class {
767
+ config;
768
+ queue = [];
769
+ errorCount = 0;
770
+ flushTimer = null;
771
+ boundFlushBeacon;
772
+ boundVisibilityChange;
773
+ isEnabled = false;
774
+ boundPbjsHandlers = [];
775
+ // Captured at enable()/navigate() so events queued before an SPA route
776
+ // change flush with the page they occurred on, not the new URL.
777
+ pageUrl = "";
778
+ deduper = new PrebidEventDeduper();
779
+ consecutiveSendFailures = 0;
780
+ nextSendAllowedAt = 0;
781
+ constructor(config) {
782
+ this.config = {
783
+ endpoint: config.endpoint || "",
784
+ propertyId: config.propertyId || "",
785
+ pageviewId: config.pageviewId || generateUUID(),
786
+ sessionId: config.sessionId || getOrCreateSessionId(),
787
+ userId: config.userId || "",
788
+ deviceType: config.deviceType || "desktop",
789
+ country: config.country || "",
790
+ region: config.region || "",
791
+ auctionEnabled: config.auctionEnabled ?? true,
792
+ warningsEnabled: config.warningsEnabled ?? true,
793
+ errorsEnabled: config.errorsEnabled ?? true,
794
+ logLevel: config.logLevel || "INFO",
795
+ pbjsGlobalName: config.pbjsGlobalName || "pbjs",
796
+ attachPbjsListeners: config.attachPbjsListeners ?? true
797
+ };
798
+ this.boundFlushBeacon = () => this.flushBeacon();
799
+ this.boundVisibilityChange = () => this.handleVisibilityChange();
800
+ }
801
+ enable() {
802
+ if (this.isEnabled) return;
803
+ this.isEnabled = true;
804
+ if (!this.config.endpoint) {
805
+ this.log("WARN", "Endpoint is empty. Analytics events will not be transmitted.");
806
+ }
807
+ if (this.config.attachPbjsListeners) {
808
+ const win = typeof window !== "undefined" ? window : {};
809
+ const pbjs = win[this.config.pbjsGlobalName] || {};
810
+ if (typeof pbjs.onEvent === "function") {
811
+ this.log("DEBUG", "Attaching event listeners to pbjs");
812
+ const events = [
813
+ ["auctionInit", this.handleAuctionInit.bind(this)],
814
+ ["auctionEnd", this.handleAuctionEnd.bind(this)],
815
+ ["bidRequested", this.handleBidRequested.bind(this)],
816
+ ["bidResponse", this.handleBidResponse.bind(this)],
817
+ ["bidTimeout", this.handleBidTimeout.bind(this)],
818
+ ["bidWon", this.handleBidWon.bind(this)],
819
+ ["noBid", this.handleNoBid.bind(this)],
820
+ ["adRenderFailed", this.handleAdRenderFailed.bind(this)]
821
+ ];
822
+ for (const [name, fn] of events) {
823
+ pbjs.onEvent(name, fn);
824
+ this.boundPbjsHandlers.push({ event: name, handler: fn });
825
+ }
826
+ } else {
827
+ this.log("WARN", "pbjs.onEvent is not defined. Prebid analytics will not function.");
828
+ }
829
+ if (typeof pbjs.getEvents === "function") {
830
+ try {
831
+ const pastEvents = pbjs.getEvents();
832
+ if (Array.isArray(pastEvents)) {
833
+ this.log(
834
+ "DEBUG",
835
+ `Replaying ${pastEvents.length} historical events from pbjs.getEvents()`
836
+ );
837
+ const handlerMap = {
838
+ auctionInit: this.handleAuctionInit.bind(this),
839
+ auctionEnd: this.handleAuctionEnd.bind(this),
840
+ bidRequested: this.handleBidRequested.bind(this),
841
+ bidResponse: this.handleBidResponse.bind(this),
842
+ bidTimeout: this.handleBidTimeout.bind(this),
843
+ bidWon: this.handleBidWon.bind(this),
844
+ noBid: this.handleNoBid.bind(this),
845
+ adRenderFailed: this.handleAdRenderFailed.bind(this)
846
+ };
847
+ for (const ev of pastEvents) {
848
+ if (!ev) continue;
849
+ const eventType = ev.eventType || ev.event || ev.name;
850
+ const args = ev.args !== void 0 ? ev.args : ev.data !== void 0 ? ev.data : ev;
851
+ const handler = handlerMap[eventType];
852
+ if (handler) {
853
+ handler(args);
854
+ }
855
+ }
856
+ }
857
+ } catch (e) {
858
+ this.log("WARN", "Failed to replay historical events from pbjs.getEvents()", e);
859
+ }
860
+ }
861
+ }
862
+ if (typeof window !== "undefined") {
863
+ if (!this.pageUrl) {
864
+ try {
865
+ const u = new URL(window.location.href);
866
+ this.pageUrl = u.origin + u.pathname;
867
+ } catch {
868
+ this.pageUrl = window.location.href;
869
+ }
870
+ }
871
+ window.addEventListener("pagehide", this.boundFlushBeacon);
872
+ if (typeof document !== "undefined") {
873
+ document.addEventListener("visibilitychange", this.boundVisibilityChange);
874
+ }
875
+ this.flushTimer = setInterval(() => this.flush(), FLUSH_INTERVAL_MS);
876
+ }
877
+ }
878
+ disable() {
879
+ if (!this.isEnabled) return;
880
+ this.isEnabled = false;
881
+ if (this.flushTimer) {
882
+ clearInterval(this.flushTimer);
883
+ this.flushTimer = null;
884
+ }
885
+ if (typeof window !== "undefined") {
886
+ window.removeEventListener("pagehide", this.boundFlushBeacon);
887
+ if (typeof document !== "undefined") {
888
+ document.removeEventListener("visibilitychange", this.boundVisibilityChange);
889
+ }
890
+ }
891
+ if (this.boundPbjsHandlers.length > 0) {
892
+ const win = typeof window !== "undefined" ? window : {};
893
+ const pbjs = win[this.config.pbjsGlobalName] || {};
894
+ if (typeof pbjs.offEvent === "function") {
895
+ for (const { event, handler } of this.boundPbjsHandlers) {
896
+ pbjs.offEvent(event, handler);
897
+ }
898
+ }
899
+ this.boundPbjsHandlers = [];
900
+ }
901
+ this.flush();
902
+ }
903
+ handleVisibilityChange() {
904
+ if (typeof document !== "undefined" && document.visibilityState === "hidden") {
905
+ this.flushBeacon();
906
+ }
907
+ }
908
+ trackRawEvent(level, eventName, data) {
909
+ const eventType = EVENT_NAME_TO_TYPE[eventName] ?? (level === "ERROR" ? TraceEventType.ERROR : TraceEventType.TRACE_EVENT_TYPE_UNSPECIFIED);
910
+ this.enqueue(eventType, eventName, data, level);
911
+ }
912
+ setUserId(userId) {
913
+ this.config.userId = userId;
914
+ }
915
+ setSessionId(sessionId) {
916
+ this.config.sessionId = sessionId;
917
+ }
918
+ navigate(pageviewId, pageUrl) {
919
+ this.disable();
920
+ this.config.pageviewId = pageviewId || generateUUID();
921
+ if (pageUrl) {
922
+ try {
923
+ const u = new URL(pageUrl);
924
+ this.pageUrl = u.origin + u.pathname;
925
+ } catch {
926
+ this.pageUrl = pageUrl;
927
+ }
928
+ } else {
929
+ this.pageUrl = "";
930
+ }
931
+ extendSession();
932
+ this.enable();
933
+ }
934
+ handleAuctionInit(data) {
935
+ if (this.isDuplicate("auctionInit", data)) return;
936
+ this.log("DEBUG", "auctionInit", data);
937
+ this.enqueue(TraceEventType.AUCTION_START, "auctionStart", {
938
+ auctionId: data.auctionId || ""
939
+ });
940
+ }
941
+ handleAuctionEnd(data) {
942
+ if (this.isDuplicate("auctionEnd", data)) return;
943
+ this.log("DEBUG", "auctionEnd", data);
944
+ this.enqueue(TraceEventType.AUCTION_END, "auctionEnd", {
945
+ auctionId: data.auctionId || ""
946
+ });
947
+ }
948
+ handleBidRequested(data) {
949
+ if (this.isDuplicate("bidRequested", data)) return;
950
+ this.log("DEBUG", "bidRequested", data);
951
+ const auctionId = data.auctionId || "";
952
+ const bidder = data.bidderCode || "";
953
+ if (Array.isArray(data.bids)) {
954
+ data.bids.forEach((bid) => {
955
+ const mediaTypes = Object.keys(bid.mediaTypes || {});
956
+ const gpid = bid.ortb2Imp?.ext?.gpid || bid.gpid || data.gpid || "";
957
+ if (mediaTypes.length === 0) {
958
+ const mediaType = bid.mediaType || "banner";
959
+ const { width, height } = parseSize(bid.sizes || bid.playerSize);
960
+ this.enqueue(TraceEventType.BID_REQUEST, "bidRequest", {
961
+ auctionId,
962
+ adUnitCode: bid.adUnitCode || "",
963
+ gpid,
964
+ bid: {
965
+ bidder,
966
+ mediaType,
967
+ width,
968
+ height
969
+ }
970
+ });
971
+ return;
972
+ }
973
+ mediaTypes.forEach((mediaType) => {
974
+ let rawSize = null;
975
+ if (mediaType === "banner") {
976
+ rawSize = bid.mediaTypes?.banner?.sizes || bid.sizes;
977
+ } else if (mediaType === "video") {
978
+ rawSize = bid.mediaTypes?.video?.playerSize || bid.mediaTypes?.video?.sizes || bid.playerSize;
979
+ } else {
980
+ rawSize = bid.mediaTypes?.[mediaType]?.sizes;
981
+ }
982
+ const { width, height } = parseSize(rawSize);
983
+ this.enqueue(TraceEventType.BID_REQUEST, "bidRequest", {
984
+ auctionId,
985
+ adUnitCode: bid.adUnitCode || "",
986
+ gpid,
987
+ bid: {
988
+ bidder,
989
+ mediaType,
990
+ width,
991
+ height
992
+ }
993
+ });
994
+ });
995
+ });
996
+ }
997
+ }
998
+ handleBidResponse(data) {
999
+ if (this.isDuplicate("bidResponse", data)) return;
1000
+ this.log("DEBUG", "bidResponse", data);
1001
+ this.enqueue(TraceEventType.BID_RESPONSE, "bidResponse", {
1002
+ auctionId: data.auctionId || "",
1003
+ adUnitCode: data.adUnitCode || "",
1004
+ bid: {
1005
+ bidder: data.bidderCode || data.bidder || "",
1006
+ cpm: Number.isFinite(data.originalCpm) ? data.originalCpm : Number.isFinite(data.cpm) ? data.cpm : 0,
1007
+ currency: data.originalCurrency ?? data.currency ?? "USD",
1008
+ width: Number.isFinite(data.width) ? data.width : 0,
1009
+ height: Number.isFinite(data.height) ? data.height : 0,
1010
+ dealId: data.dealId || "",
1011
+ mediaType: data.mediaType || "banner",
1012
+ latencyMs: Number.isFinite(data.timeToRespond) ? data.timeToRespond : 0,
1013
+ advertiserDomain: data.meta?.advertiserDomains?.[0] || "",
1014
+ creativeId: data.creativeId || ""
1015
+ }
1016
+ });
1017
+ }
1018
+ handleBidTimeout(data) {
1019
+ if (this.isDuplicate("bidTimeout", data)) return;
1020
+ this.log("DEBUG", "bidTimeout", data);
1021
+ if (Array.isArray(data)) {
1022
+ data.forEach((t) => {
1023
+ this.enqueue(TraceEventType.BID_TIMEOUT, "bidTimeout", {
1024
+ auctionId: t.auctionId || "",
1025
+ adUnitCode: t.adUnitCode || "",
1026
+ bid: {
1027
+ bidder: t.bidder || ""
1028
+ }
1029
+ });
1030
+ });
1031
+ }
1032
+ }
1033
+ handleBidWon(data) {
1034
+ if (this.isDuplicate("bidWon", data)) return;
1035
+ this.log("DEBUG", "bidWon", data);
1036
+ this.enqueue(TraceEventType.BID_WIN, "bidWon", {
1037
+ auctionId: data.auctionId || "",
1038
+ adUnitCode: data.adUnitCode || "",
1039
+ bid: {
1040
+ bidder: data.bidderCode || data.bidder || "",
1041
+ cpm: Number.isFinite(data.originalCpm) ? data.originalCpm : Number.isFinite(data.cpm) ? data.cpm : 0,
1042
+ currency: data.originalCurrency ?? data.currency ?? "USD",
1043
+ width: Number.isFinite(data.width) ? data.width : 0,
1044
+ height: Number.isFinite(data.height) ? data.height : 0,
1045
+ dealId: data.dealId || "",
1046
+ mediaType: data.mediaType || "banner",
1047
+ latencyMs: Number.isFinite(data.timeToRespond) ? data.timeToRespond : 0,
1048
+ advertiserDomain: data.meta?.advertiserDomains?.[0] || "",
1049
+ creativeId: data.creativeId || ""
1050
+ }
1051
+ });
1052
+ }
1053
+ handleNoBid(data) {
1054
+ if (this.isDuplicate("noBid", data)) return;
1055
+ this.log("DEBUG", "noBid", data);
1056
+ this.enqueue(TraceEventType.NO_BID, "noBid", {
1057
+ auctionId: data.auctionId || "",
1058
+ adUnitCode: data.adUnitCode || "",
1059
+ bid: {
1060
+ bidder: data.bidderCode || data.bidder || ""
1061
+ }
1062
+ });
1063
+ }
1064
+ handleAdRenderFailed(data) {
1065
+ if (this.isDuplicate("adRenderFailed", data)) return;
1066
+ this.log("DEBUG", "adRenderFailed", data);
1067
+ this.enqueue(TraceEventType.AD_RENDER_FAILED, "adRenderFailed", {
1068
+ auctionId: data.bid?.auctionId || "",
1069
+ adUnitCode: data.bid?.adUnitCode || "",
1070
+ bid: {
1071
+ bidder: data.bid?.bidderCode || data.bid?.bidder || ""
1072
+ },
1073
+ metadata: {
1074
+ reason: String(data.reason || ""),
1075
+ message: String(data.message || "")
1076
+ }
1077
+ });
1078
+ }
1079
+ isDuplicate(eventName, data) {
1080
+ return this.deduper.isDuplicate(eventName, data);
1081
+ }
1082
+ enqueue(type, eventName, data, level) {
1083
+ if (!this.isEnabled) return;
1084
+ if (!this.shouldSample(type, level)) return;
1085
+ const protoEvent = {
1086
+ eventId: generateUUID(),
1087
+ timestampMs: Date.now(),
1088
+ type,
1089
+ eventName,
1090
+ auctionId: data.auctionId || "",
1091
+ transactionId: data.transactionId || "",
1092
+ adUnitCode: data.adUnitCode || data.elementId || "",
1093
+ namespace: data.ns || data.namespace || ""
1094
+ };
1095
+ if (data.bid) {
1096
+ protoEvent.bid = {
1097
+ bidder: data.bid.bidder || "",
1098
+ cpm: Number.isFinite(data.bid.cpm) ? data.bid.cpm : 0,
1099
+ currency: data.bid.currency || "USD",
1100
+ width: Number.isFinite(data.bid.width) ? data.bid.width : 0,
1101
+ height: Number.isFinite(data.bid.height) ? data.bid.height : 0,
1102
+ dealId: data.bid.dealId || "",
1103
+ mediaType: data.bid.mediaType || "banner",
1104
+ latencyMs: Number.isFinite(data.bid.latencyMs) ? data.bid.latencyMs : 0,
1105
+ advertiserDomain: data.bid.advertiserDomain || "",
1106
+ creativeId: data.bid.creativeId || ""
1107
+ };
1108
+ }
1109
+ if (data.viewableDurationMs !== void 0) {
1110
+ protoEvent.viewableDurationMs = Number.isFinite(data.viewableDurationMs) ? data.viewableDurationMs : 0;
1111
+ }
1112
+ const metadata = { ...data.metadata };
1113
+ if (data.error !== void 0 && data.error !== null) {
1114
+ metadata.error = typeof data.error === "object" && data.error.message ? String(data.error.message) : String(data.error);
1115
+ }
1116
+ if (data.gpid) {
1117
+ metadata.gpid = String(data.gpid);
1118
+ }
1119
+ if (Object.keys(metadata).length > 0) {
1120
+ protoEvent.metadata = metadata;
1121
+ }
1122
+ this.queue.push(protoEvent);
1123
+ if (this.queue.length > MAX_QUEUE_SIZE) {
1124
+ this.queue.splice(0, this.queue.length - MAX_QUEUE_SIZE);
1125
+ }
1126
+ if (this.queue.length >= BATCH_SIZE) {
1127
+ this.flush();
1128
+ }
1129
+ }
1130
+ shouldSample(type, level) {
1131
+ if (type === TraceEventType.ERROR) {
1132
+ this.errorCount++;
1133
+ if (this.errorCount > MAX_ERRORS_PER_SESSION) return false;
1134
+ return this.config.errorsEnabled;
1135
+ }
1136
+ if (level === "WARN") {
1137
+ return this.config.warningsEnabled;
1138
+ }
1139
+ return this.config.auctionEnabled;
1140
+ }
1141
+ requeue(events) {
1142
+ if (!events.length) return;
1143
+ this.queue = events.concat(this.queue);
1144
+ if (this.queue.length > MAX_QUEUE_SIZE) {
1145
+ this.queue.splice(0, this.queue.length - MAX_QUEUE_SIZE);
1146
+ }
1147
+ }
1148
+ // Drains the queue and returns the encoded batch plus target URL and event list,
1149
+ // or null if there is nothing to send. Shared by flush() and flushBeacon().
1150
+ drainBatch() {
1151
+ if (this.queue.length === 0 || !this.config.endpoint) return null;
1152
+ const events = this.queue;
1153
+ this.queue = [];
1154
+ const domain = typeof window !== "undefined" ? window.location.hostname : "";
1155
+ const batch = {
1156
+ propertyId: this.config.propertyId,
1157
+ pageviewId: this.config.pageviewId,
1158
+ sessionId: this.config.sessionId,
1159
+ pageUrl: this.pageUrl,
1160
+ country: this.config.country,
1161
+ region: this.config.region,
1162
+ deviceType: this.config.deviceType,
1163
+ userId: this.config.userId,
1164
+ domain,
1165
+ events
1166
+ };
1167
+ return {
1168
+ url: `${this.config.endpoint}/${this.config.propertyId}`,
1169
+ // protobufjs types finish() as Uint8Array<ArrayBufferLike>; the buffer is
1170
+ // always a plain ArrayBuffer, so narrow for fetch/Blob compatibility.
1171
+ encoded: TraceEventBatch.encode(batch).finish(),
1172
+ events
1173
+ };
1174
+ }
1175
+ sendFetch(payload) {
1176
+ fetch(payload.url, {
1177
+ method: "POST",
1178
+ headers: { "Content-Type": "application/x-protobuf" },
1179
+ body: payload.encoded,
1180
+ keepalive: true
1181
+ }).then((res) => {
1182
+ if (!res.ok) {
1183
+ this.log("WARN", `Failed to send batch: HTTP ${res.status}`);
1184
+ this.handleSendFailure(payload.events);
1185
+ } else {
1186
+ this.consecutiveSendFailures = 0;
1187
+ this.nextSendAllowedAt = 0;
1188
+ }
1189
+ }).catch((err) => {
1190
+ this.log("ERROR", "Failed to send batch", err);
1191
+ this.handleSendFailure(payload.events);
1192
+ });
1193
+ }
1194
+ handleSendFailure(events) {
1195
+ this.consecutiveSendFailures++;
1196
+ const backoff = Math.min(
1197
+ FLUSH_INTERVAL_MS * 2 ** (this.consecutiveSendFailures - 1),
1198
+ MAX_SEND_BACKOFF_MS
1199
+ );
1200
+ this.nextSendAllowedAt = Date.now() + backoff;
1201
+ if (this.consecutiveSendFailures <= MAX_CONSECUTIVE_SEND_FAILURES) {
1202
+ this.requeue(events);
1203
+ } else {
1204
+ this.log(
1205
+ "WARN",
1206
+ `Dropping ${events.length} events after ${this.consecutiveSendFailures} consecutive send failures`
1207
+ );
1208
+ }
1209
+ }
1210
+ flush() {
1211
+ if (Date.now() < this.nextSendAllowedAt) return;
1212
+ const payload = this.drainBatch();
1213
+ if (!payload) return;
1214
+ this.sendFetch(payload);
1215
+ }
1216
+ flushBeacon() {
1217
+ const payload = this.drainBatch();
1218
+ if (!payload) return;
1219
+ let sent = false;
1220
+ if (typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") {
1221
+ try {
1222
+ const blob = new Blob([payload.encoded], { type: "application/x-protobuf" });
1223
+ sent = navigator.sendBeacon(payload.url, blob);
1224
+ } catch {
1225
+ sent = false;
1226
+ }
1227
+ }
1228
+ if (!sent) {
1229
+ this.sendFetch(payload);
1230
+ }
1231
+ }
1232
+ log(level, msg, ...args) {
1233
+ const levels = { DEBUG: 10, INFO: 20, WARN: 30, ERROR: 40 };
1234
+ if (levels[level] < levels[this.config.logLevel]) return;
1235
+ const prefix = `[bidkernel][prebid-analytics][${level}]`;
1236
+ switch (level) {
1237
+ case "DEBUG":
1238
+ console.debug(prefix, msg, ...args);
1239
+ break;
1240
+ case "INFO":
1241
+ console.info(prefix, msg, ...args);
1242
+ break;
1243
+ case "WARN":
1244
+ console.warn(prefix, msg, ...args);
1245
+ break;
1246
+ case "ERROR":
1247
+ console.error(prefix, msg, ...args);
1248
+ break;
1249
+ }
1250
+ }
1251
+ };
1252
+ function extractAnalyticsOptions(config) {
1253
+ if (!config) return null;
1254
+ if (Array.isArray(config)) {
1255
+ const matched = config.find((item) => item?.provider === "bidkernel") ?? config.find((item) => item && typeof item === "object" && item.provider === void 0);
1256
+ return matched ? extractAnalyticsOptions(matched) : null;
1257
+ }
1258
+ if (typeof config === "object") {
1259
+ if (config.options && typeof config.options === "object") {
1260
+ return config.options;
1261
+ }
1262
+ if (config.config && typeof config.config === "object") {
1263
+ return config.config;
1264
+ }
1265
+ if (config.propertyId || config.endpoint) {
1266
+ return config;
1267
+ }
1268
+ }
1269
+ return null;
1270
+ }
1271
+ function getStashedConfig(win) {
1272
+ if (!win) return null;
1273
+ if (win._bidkernelAnalyticsConfig) {
1274
+ const extracted = extractAnalyticsOptions(win._bidkernelAnalyticsConfig);
1275
+ if (extracted) return extracted;
1276
+ }
1277
+ if (win.bidkernelPrebidAnalytics) {
1278
+ const bpa = win.bidkernelPrebidAnalytics;
1279
+ if (bpa.options) {
1280
+ const extracted = extractAnalyticsOptions(bpa.options);
1281
+ if (extracted) return extracted;
1282
+ }
1283
+ if (bpa.config) {
1284
+ const extracted = extractAnalyticsOptions(bpa.config);
1285
+ if (extracted) return extracted;
1286
+ }
1287
+ if (bpa.propertyId) {
1288
+ return extractAnalyticsOptions(bpa);
1289
+ }
1290
+ }
1291
+ return null;
1292
+ }
1293
+ function registerPrebidAnalytics(pbjsGlobalName = "pbjs", defaults) {
1294
+ const win = typeof window !== "undefined" ? window : {};
1295
+ win[pbjsGlobalName] = win[pbjsGlobalName] || {};
1296
+ const pbjs = win[pbjsGlobalName];
1297
+ const enableInstance = (options) => {
1298
+ if (win._bidkernelPrebidAnalytics) {
1299
+ try {
1300
+ win._bidkernelPrebidAnalytics.disable();
1301
+ } catch (e) {
1302
+ console.warn("[bidkernel] Failed to disable previous analytics instance:", e);
1303
+ }
1304
+ }
1305
+ const analytics = new BidkernelPrebidAnalytics({
1306
+ pbjsGlobalName,
1307
+ ...defaults,
1308
+ ...options
1309
+ });
1310
+ analytics.enable();
1311
+ win._bidkernelPrebidAnalytics = analytics;
1312
+ return analytics;
1313
+ };
1314
+ const doRegister = () => {
1315
+ try {
1316
+ if (pbjs.adapterManager && typeof pbjs.adapterManager.registerAnalyticsAdapter === "function") {
1317
+ pbjs.adapterManager.registerAnalyticsAdapter({
1318
+ adapter: {
1319
+ enableAnalytics: (config) => {
1320
+ const options = extractAnalyticsOptions(config);
1321
+ if (options) {
1322
+ enableInstance(options);
1323
+ }
1324
+ },
1325
+ disableAnalytics: () => {
1326
+ if (win._bidkernelPrebidAnalytics) {
1327
+ win._bidkernelPrebidAnalytics.disable();
1328
+ }
1329
+ }
1330
+ },
1331
+ code: "bidkernel"
1332
+ });
1333
+ }
1334
+ const stashed = getStashedConfig(win);
1335
+ if (stashed && (stashed.propertyId || defaults?.propertyId)) {
1336
+ enableInstance(stashed);
1337
+ }
1338
+ } catch (e) {
1339
+ console.warn("[bidkernel] Failed to register standard Prebid analytics adapter:", e);
1340
+ }
1341
+ };
1342
+ if (pbjs.adapterManager && typeof pbjs.adapterManager.registerAnalyticsAdapter === "function") {
1343
+ doRegister();
1344
+ } else {
1345
+ pbjs.que = pbjs.que || [];
1346
+ pbjs.que.push(doRegister);
1347
+ }
1348
+ }
1349
+
1350
+ // src/index.ts
1351
+ function getbidkernel(alias = "bidkernel") {
1352
+ if (typeof window === "undefined") {
1353
+ return { q: [] };
1354
+ }
1355
+ const win = window;
1356
+ win[alias] = win[alias] || { q: [] };
1357
+ return win[alias];
1358
+ }
1359
+ export {
1360
+ BidkernelPrebidAnalytics,
1361
+ PrebidEventDeduper,
1362
+ getPrebidEventKey,
1363
+ getbidkernel,
1364
+ registerPrebidAnalytics
1365
+ };