@bidkernel/analytics 0.11.0 → 0.16.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/analytics.global.js +1 -1
- package/dist/index.d.mts +73 -2
- package/dist/index.d.ts +73 -2
- package/dist/index.js +234 -78
- package/dist/index.mjs +233 -78
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1042,7 +1042,8 @@ var EVENT_NAME_TO_TYPE = {
|
|
|
1042
1042
|
timeInView: TraceEventType.TIME_IN_VIEW,
|
|
1043
1043
|
viewable: TraceEventType.VIEWABLE
|
|
1044
1044
|
};
|
|
1045
|
-
var
|
|
1045
|
+
var REVENUE_FLUSH_DELAY_MS = 3e3;
|
|
1046
|
+
var REVENUE_FLUSH_TYPES = /* @__PURE__ */ new Set([
|
|
1046
1047
|
TraceEventType.IMPRESSION,
|
|
1047
1048
|
TraceEventType.BID_WIN,
|
|
1048
1049
|
TraceEventType.CLICK
|
|
@@ -1051,11 +1052,13 @@ var CACHED_BID_TTL_MS = 30 * 60 * 1e3;
|
|
|
1051
1052
|
var MAX_CACHED_BID_KEYS = 200;
|
|
1052
1053
|
var MAX_IMPRESSION_KEYS = 1e3;
|
|
1053
1054
|
var MAX_TRACKED_AUCTIONS = 50;
|
|
1055
|
+
var CLICK_DEDUP_MS = 1e3;
|
|
1054
1056
|
var SESSION_KEY = "_bidkernel_session";
|
|
1055
1057
|
var SESSION_TS_KEY = "_bidkernel_session_ts";
|
|
1056
1058
|
var THIRTY_MINUTES_MS = 30 * 60 * 1e3;
|
|
1057
1059
|
var inMemorySessionId = null;
|
|
1058
1060
|
var inMemorySessionTs = 0;
|
|
1061
|
+
var storageAllowed = true;
|
|
1059
1062
|
function generateUUID() {
|
|
1060
1063
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
1061
1064
|
return crypto.randomUUID();
|
|
@@ -1125,6 +1128,7 @@ function sameEndpointOrigin(a, b) {
|
|
|
1125
1128
|
function extendSession() {
|
|
1126
1129
|
const now = Date.now();
|
|
1127
1130
|
inMemorySessionTs = now;
|
|
1131
|
+
if (!storageAllowed) return;
|
|
1128
1132
|
try {
|
|
1129
1133
|
if (typeof localStorage !== "undefined") {
|
|
1130
1134
|
localStorage.setItem(SESSION_TS_KEY, now.toString());
|
|
@@ -1134,18 +1138,23 @@ function extendSession() {
|
|
|
1134
1138
|
}
|
|
1135
1139
|
function getOrCreateSessionId() {
|
|
1136
1140
|
const now = Date.now();
|
|
1141
|
+
const memoryFresh = !!inMemorySessionId && !!inMemorySessionTs && now - inMemorySessionTs <= THIRTY_MINUTES_MS;
|
|
1137
1142
|
try {
|
|
1138
|
-
if (typeof localStorage !== "undefined") {
|
|
1143
|
+
if (storageAllowed && typeof localStorage !== "undefined") {
|
|
1139
1144
|
const storedId = localStorage.getItem(SESSION_KEY);
|
|
1140
1145
|
const tsStr = localStorage.getItem(SESSION_TS_KEY);
|
|
1141
1146
|
const storedTs = tsStr ? parseInt(tsStr, 10) || 0 : 0;
|
|
1142
1147
|
if (storedId && storedTs && now - storedTs <= THIRTY_MINUTES_MS) {
|
|
1143
1148
|
localStorage.setItem(SESSION_TS_KEY, now.toString());
|
|
1149
|
+
inMemorySessionId = storedId;
|
|
1150
|
+
inMemorySessionTs = now;
|
|
1144
1151
|
return storedId;
|
|
1145
1152
|
}
|
|
1146
|
-
const newId = generateUUID();
|
|
1153
|
+
const newId = memoryFresh ? inMemorySessionId : generateUUID();
|
|
1147
1154
|
localStorage.setItem(SESSION_KEY, newId);
|
|
1148
1155
|
localStorage.setItem(SESSION_TS_KEY, now.toString());
|
|
1156
|
+
inMemorySessionId = newId;
|
|
1157
|
+
inMemorySessionTs = now;
|
|
1149
1158
|
return newId;
|
|
1150
1159
|
}
|
|
1151
1160
|
} catch {
|
|
@@ -1511,6 +1520,17 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1511
1520
|
static initImaInterception() {
|
|
1512
1521
|
initImaInterception();
|
|
1513
1522
|
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Allows or forbids localStorage writes for every instance on the page.
|
|
1525
|
+
* Collection and delivery are unaffected: only the persisted session id,
|
|
1526
|
+
* its timestamp and exit batches are gated.
|
|
1527
|
+
*/
|
|
1528
|
+
static setStorageAllowed(allowed) {
|
|
1529
|
+
storageAllowed = allowed;
|
|
1530
|
+
}
|
|
1531
|
+
static isStorageAllowed() {
|
|
1532
|
+
return storageAllowed;
|
|
1533
|
+
}
|
|
1514
1534
|
config;
|
|
1515
1535
|
queue = [];
|
|
1516
1536
|
errorCount = 0;
|
|
@@ -1526,7 +1546,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1526
1546
|
consecutiveSendFailures = 0;
|
|
1527
1547
|
nextSendAllowedAt = 0;
|
|
1528
1548
|
replayedEventCount = 0;
|
|
1529
|
-
|
|
1549
|
+
revenueFlushTimer = null;
|
|
1530
1550
|
// localStorage keys of exit batches this instance persisted, so a page that
|
|
1531
1551
|
// survives its own pagehide/hidden (bfcache restore, tab re-focus) can
|
|
1532
1552
|
// remove them instead of leaving them for a duplicate resend.
|
|
@@ -1539,6 +1559,12 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1539
1559
|
slotRefreshIndices = /* @__PURE__ */ new Map();
|
|
1540
1560
|
slotLastAuctionIds = /* @__PURE__ */ new Map();
|
|
1541
1561
|
pendingThresholdListeners = /* @__PURE__ */ new Map();
|
|
1562
|
+
pendingViewableListeners = /* @__PURE__ */ new Map();
|
|
1563
|
+
// Element a subscriber named for a slot (a sticky bar or interstitial that
|
|
1564
|
+
// renders outside the slot element); wins over document.getElementById.
|
|
1565
|
+
slotElements = /* @__PURE__ */ new Map();
|
|
1566
|
+
clickDetachCleanups = /* @__PURE__ */ new Set();
|
|
1567
|
+
lastClickAt = /* @__PURE__ */ new Map();
|
|
1542
1568
|
// Impression deduplication per slot and refresh cycle (strictly 1 impression per cycle)
|
|
1543
1569
|
slotEmittedImpressionKeys = /* @__PURE__ */ new Set();
|
|
1544
1570
|
// Winning bid cache from bidWon to marry with subsequent render triggers (adRenderSucceeded, video, etc.)
|
|
@@ -1549,6 +1575,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1549
1575
|
auctionBidderOutcomes = /* @__PURE__ */ new Map();
|
|
1550
1576
|
logger;
|
|
1551
1577
|
constructor(config) {
|
|
1578
|
+
if (config.storageAllowed !== void 0) {
|
|
1579
|
+
_BidkernelPrebidAnalytics.setStorageAllowed(config.storageAllowed);
|
|
1580
|
+
}
|
|
1552
1581
|
const requestedEndpoint = config.endpoint || "";
|
|
1553
1582
|
const endpoint = !requestedEndpoint || isTrustedEndpoint(requestedEndpoint) ? requestedEndpoint : "";
|
|
1554
1583
|
this.config = {
|
|
@@ -1564,9 +1593,11 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1564
1593
|
warningsEnabled: config.warningsEnabled ?? true,
|
|
1565
1594
|
errorsEnabled: config.errorsEnabled ?? true,
|
|
1566
1595
|
viewabilityEnabled: config.viewabilityEnabled ?? true,
|
|
1596
|
+
storageAllowed: config.storageAllowed ?? true,
|
|
1567
1597
|
logLevel: config.logLevel || "INFO",
|
|
1568
1598
|
pbjsGlobalName: config.pbjsGlobalName || "pbjs",
|
|
1569
|
-
attachPbjsListeners: config.attachPbjsListeners ?? true
|
|
1599
|
+
attachPbjsListeners: config.attachPbjsListeners ?? true,
|
|
1600
|
+
revenueFlushDelayMs: Number.isFinite(config.revenueFlushDelayMs) && config.revenueFlushDelayMs >= 0 ? config.revenueFlushDelayMs : REVENUE_FLUSH_DELAY_MS
|
|
1570
1601
|
};
|
|
1571
1602
|
this.logger = createLogger({
|
|
1572
1603
|
prefix: "[bidkernel][prebid-analytics]",
|
|
@@ -1605,65 +1636,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1605
1636
|
}
|
|
1606
1637
|
}
|
|
1607
1638
|
if (this.config.attachPbjsListeners) {
|
|
1608
|
-
|
|
1609
|
-
const pbjs = win[this.config.pbjsGlobalName] || {};
|
|
1610
|
-
if (typeof pbjs.onEvent === "function") {
|
|
1611
|
-
this.log("DEBUG", "Attaching event listeners to pbjs");
|
|
1612
|
-
const events = [
|
|
1613
|
-
["auctionInit", this.handleAuctionInit.bind(this)],
|
|
1614
|
-
["auctionEnd", this.handleAuctionEnd.bind(this)],
|
|
1615
|
-
["bidRequested", this.handleBidRequested.bind(this)],
|
|
1616
|
-
["bidResponse", this.handleBidResponse.bind(this)],
|
|
1617
|
-
["bidTimeout", this.handleBidTimeout.bind(this)],
|
|
1618
|
-
["bidWon", this.handleBidWon.bind(this)],
|
|
1619
|
-
["noBid", this.handleNoBid.bind(this)],
|
|
1620
|
-
["adRenderFailed", this.handleAdRenderFailed.bind(this)],
|
|
1621
|
-
["adRenderSucceeded", this.handleAdRenderSucceeded.bind(this)]
|
|
1622
|
-
];
|
|
1623
|
-
for (const [name, fn] of events) {
|
|
1624
|
-
pbjs.onEvent(name, fn);
|
|
1625
|
-
this.boundPbjsHandlers.push({ event: name, handler: fn });
|
|
1626
|
-
}
|
|
1627
|
-
} else {
|
|
1628
|
-
this.log("WARN", "pbjs.onEvent is not defined. Prebid analytics will not function.");
|
|
1629
|
-
}
|
|
1630
|
-
if (typeof pbjs.getEvents === "function") {
|
|
1631
|
-
try {
|
|
1632
|
-
const pastEvents = pbjs.getEvents();
|
|
1633
|
-
if (Array.isArray(pastEvents)) {
|
|
1634
|
-
const newPastEvents = pastEvents.slice(this.replayedEventCount);
|
|
1635
|
-
this.replayedEventCount = pastEvents.length;
|
|
1636
|
-
if (newPastEvents.length > 0) {
|
|
1637
|
-
this.log(
|
|
1638
|
-
"DEBUG",
|
|
1639
|
-
`Replaying ${newPastEvents.length} historical events from pbjs.getEvents()`
|
|
1640
|
-
);
|
|
1641
|
-
const handlerMap = {
|
|
1642
|
-
auctionInit: this.handleAuctionInit.bind(this),
|
|
1643
|
-
auctionEnd: this.handleAuctionEnd.bind(this),
|
|
1644
|
-
bidRequested: this.handleBidRequested.bind(this),
|
|
1645
|
-
bidResponse: this.handleBidResponse.bind(this),
|
|
1646
|
-
bidTimeout: this.handleBidTimeout.bind(this),
|
|
1647
|
-
bidWon: this.handleBidWon.bind(this),
|
|
1648
|
-
noBid: this.handleNoBid.bind(this),
|
|
1649
|
-
adRenderFailed: this.handleAdRenderFailed.bind(this),
|
|
1650
|
-
adRenderSucceeded: this.handleAdRenderSucceeded.bind(this)
|
|
1651
|
-
};
|
|
1652
|
-
for (const ev of newPastEvents) {
|
|
1653
|
-
if (!ev) continue;
|
|
1654
|
-
const eventType = ev.eventType || ev.event || ev.name;
|
|
1655
|
-
const args = ev.args !== void 0 ? ev.args : ev.data !== void 0 ? ev.data : ev;
|
|
1656
|
-
const handler = handlerMap[eventType];
|
|
1657
|
-
if (handler) {
|
|
1658
|
-
handler(args);
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
} catch (e) {
|
|
1664
|
-
this.log("WARN", "Failed to replay historical events from pbjs.getEvents()", e);
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1639
|
+
this.attachPbjs();
|
|
1667
1640
|
}
|
|
1668
1641
|
if (typeof window !== "undefined") {
|
|
1669
1642
|
if (!this.pageUrl) {
|
|
@@ -1686,6 +1659,68 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1686
1659
|
}
|
|
1687
1660
|
}
|
|
1688
1661
|
}
|
|
1662
|
+
/**
|
|
1663
|
+
* Binds the Prebid event handlers on the configured global and replays
|
|
1664
|
+
* pbjs.getEvents() history. enable() calls this when attachPbjsListeners is
|
|
1665
|
+
* true. An integration that loads Prebid lazily constructs the instance with
|
|
1666
|
+
* attachPbjsListeners=false and calls this once pbjs exists; disable() (and
|
|
1667
|
+
* therefore navigate()) drops the handlers, so call it again after either.
|
|
1668
|
+
* Idempotent. Returns true when handlers are bound after the call, false
|
|
1669
|
+
* when the instance is disabled or pbjs.onEvent is not available yet.
|
|
1670
|
+
*/
|
|
1671
|
+
attachPbjs() {
|
|
1672
|
+
if (!this.isEnabled) return false;
|
|
1673
|
+
if (this.boundPbjsHandlers.length > 0) return true;
|
|
1674
|
+
const win = typeof window !== "undefined" ? window : {};
|
|
1675
|
+
const pbjs = win[this.config.pbjsGlobalName] || {};
|
|
1676
|
+
if (typeof pbjs.onEvent !== "function") {
|
|
1677
|
+
this.log("WARN", "pbjs.onEvent is not defined. Prebid analytics will not function.");
|
|
1678
|
+
return false;
|
|
1679
|
+
}
|
|
1680
|
+
this.log("DEBUG", "Attaching event listeners to pbjs");
|
|
1681
|
+
const handlerMap = {
|
|
1682
|
+
auctionInit: this.handleAuctionInit.bind(this),
|
|
1683
|
+
auctionEnd: this.handleAuctionEnd.bind(this),
|
|
1684
|
+
bidRequested: this.handleBidRequested.bind(this),
|
|
1685
|
+
bidResponse: this.handleBidResponse.bind(this),
|
|
1686
|
+
bidTimeout: this.handleBidTimeout.bind(this),
|
|
1687
|
+
bidWon: this.handleBidWon.bind(this),
|
|
1688
|
+
noBid: this.handleNoBid.bind(this),
|
|
1689
|
+
adRenderFailed: this.handleAdRenderFailed.bind(this),
|
|
1690
|
+
adRenderSucceeded: this.handleAdRenderSucceeded.bind(this)
|
|
1691
|
+
};
|
|
1692
|
+
for (const [name, fn] of Object.entries(handlerMap)) {
|
|
1693
|
+
pbjs.onEvent(name, fn);
|
|
1694
|
+
this.boundPbjsHandlers.push({ event: name, handler: fn });
|
|
1695
|
+
}
|
|
1696
|
+
if (typeof pbjs.getEvents === "function") {
|
|
1697
|
+
try {
|
|
1698
|
+
const pastEvents = pbjs.getEvents();
|
|
1699
|
+
if (Array.isArray(pastEvents)) {
|
|
1700
|
+
const newPastEvents = pastEvents.slice(this.replayedEventCount);
|
|
1701
|
+
this.replayedEventCount = pastEvents.length;
|
|
1702
|
+
if (newPastEvents.length > 0) {
|
|
1703
|
+
this.log(
|
|
1704
|
+
"DEBUG",
|
|
1705
|
+
`Replaying ${newPastEvents.length} historical events from pbjs.getEvents()`
|
|
1706
|
+
);
|
|
1707
|
+
for (const ev of newPastEvents) {
|
|
1708
|
+
if (!ev) continue;
|
|
1709
|
+
const eventType = ev.eventType || ev.event || ev.name;
|
|
1710
|
+
const args = ev.args !== void 0 ? ev.args : ev.data !== void 0 ? ev.data : ev;
|
|
1711
|
+
const handler = handlerMap[eventType];
|
|
1712
|
+
if (handler) {
|
|
1713
|
+
handler(args);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
} catch (e) {
|
|
1719
|
+
this.log("WARN", "Failed to replay historical events from pbjs.getEvents()", e);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
return true;
|
|
1723
|
+
}
|
|
1689
1724
|
disable() {
|
|
1690
1725
|
if (!this.isEnabled) return;
|
|
1691
1726
|
this.flushAllSlotsTimeInView();
|
|
@@ -1717,6 +1752,14 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1717
1752
|
}
|
|
1718
1753
|
}
|
|
1719
1754
|
this.videoDetachCleanups.clear();
|
|
1755
|
+
for (const cleanup of Array.from(this.clickDetachCleanups)) {
|
|
1756
|
+
try {
|
|
1757
|
+
cleanup();
|
|
1758
|
+
} catch {
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
this.clickDetachCleanups.clear();
|
|
1762
|
+
this.slotElements.clear();
|
|
1720
1763
|
this.cachedWinningBids.clear();
|
|
1721
1764
|
this.slotEmittedImpressionKeys.clear();
|
|
1722
1765
|
this.slotLastAuctionIds.clear();
|
|
@@ -1725,6 +1768,10 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1725
1768
|
clearInterval(this.flushTimer);
|
|
1726
1769
|
this.flushTimer = null;
|
|
1727
1770
|
}
|
|
1771
|
+
if (this.revenueFlushTimer) {
|
|
1772
|
+
clearTimeout(this.revenueFlushTimer);
|
|
1773
|
+
this.revenueFlushTimer = null;
|
|
1774
|
+
}
|
|
1728
1775
|
if (this.persistedCleanupTimer) {
|
|
1729
1776
|
clearTimeout(this.persistedCleanupTimer);
|
|
1730
1777
|
this.persistedCleanupTimer = null;
|
|
@@ -1874,6 +1921,105 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
1874
1921
|
}
|
|
1875
1922
|
});
|
|
1876
1923
|
}
|
|
1924
|
+
this.notifyViewable(record);
|
|
1925
|
+
}
|
|
1926
|
+
notifyViewable(record) {
|
|
1927
|
+
if (!record.viewableFired) return;
|
|
1928
|
+
for (const listener of record.viewableListeners) {
|
|
1929
|
+
if (listener.firedForIndex === record.refreshIndex) continue;
|
|
1930
|
+
listener.firedForIndex = record.refreshIndex;
|
|
1931
|
+
try {
|
|
1932
|
+
listener.callback(record.slotId);
|
|
1933
|
+
} catch (e) {
|
|
1934
|
+
this.log("ERROR", "Error in viewable listener callback", e);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* Calls back once per render cycle when the slot has met the IAB viewable
|
|
1940
|
+
* standard this adapter measures (immediately if it already has). Works
|
|
1941
|
+
* before the slot is observed: the listener waits for observeSlot. Returns
|
|
1942
|
+
* an unsubscribe function.
|
|
1943
|
+
*/
|
|
1944
|
+
/**
|
|
1945
|
+
* Names the element to measure for a slot when the creative renders
|
|
1946
|
+
* somewhere other than the slot element (a sticky bar, an interstitial).
|
|
1947
|
+
* Applies to the current cycle at once and to every later render.
|
|
1948
|
+
*/
|
|
1949
|
+
setSlotElement(slotId, element) {
|
|
1950
|
+
this.slotElements.set(slotId, element);
|
|
1951
|
+
const record = this.slotViewabilityRecords.get(slotId);
|
|
1952
|
+
if (record && record.element !== element) {
|
|
1953
|
+
this.observeSlot(element, slotId, {
|
|
1954
|
+
refreshIndex: record.refreshIndex,
|
|
1955
|
+
emitRefreshEvent: false
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* Records a click on the slot's current creative, attributed to the cached
|
|
1961
|
+
* winning bid. Repeats within one second are one click. Returns whether a
|
|
1962
|
+
* CLICK was recorded.
|
|
1963
|
+
*/
|
|
1964
|
+
recordClick(slotId, options) {
|
|
1965
|
+
if (!this.isEnabled || !slotId) return false;
|
|
1966
|
+
const now = Date.now();
|
|
1967
|
+
if (now - (this.lastClickAt.get(slotId) || 0) < CLICK_DEDUP_MS) return false;
|
|
1968
|
+
this.lastClickAt.set(slotId, now);
|
|
1969
|
+
const cached = this.getCachedBid(slotId);
|
|
1970
|
+
this.enqueue(TraceEventType.CLICK, "click", {
|
|
1971
|
+
auctionId: cached?.auctionId || "",
|
|
1972
|
+
transactionId: cached?.transactionId || "",
|
|
1973
|
+
adUnitCode: slotId,
|
|
1974
|
+
bid: cached?.bidTrace,
|
|
1975
|
+
metadata: {
|
|
1976
|
+
...options?.metadata,
|
|
1977
|
+
refresh_index: String(this.getRefreshIndex(slotId))
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
return true;
|
|
1981
|
+
}
|
|
1982
|
+
/**
|
|
1983
|
+
* Detects clicks into a cross-origin creative frame: a click inside an
|
|
1984
|
+
* iframe moves focus into it and blurs the window. Returns a detach
|
|
1985
|
+
* function; every tracker is detached on disable().
|
|
1986
|
+
*/
|
|
1987
|
+
attachClickTracker(element, slotId) {
|
|
1988
|
+
if (typeof window === "undefined") return () => {
|
|
1989
|
+
};
|
|
1990
|
+
const onBlur = () => {
|
|
1991
|
+
setTimeout(() => {
|
|
1992
|
+
const active = document.activeElement;
|
|
1993
|
+
if (active && (active === element || element.contains(active))) {
|
|
1994
|
+
this.recordClick(slotId, { metadata: { source: "blur" } });
|
|
1995
|
+
window.focus();
|
|
1996
|
+
}
|
|
1997
|
+
}, 0);
|
|
1998
|
+
};
|
|
1999
|
+
window.addEventListener("blur", onBlur);
|
|
2000
|
+
const cleanup = () => {
|
|
2001
|
+
window.removeEventListener("blur", onBlur);
|
|
2002
|
+
this.clickDetachCleanups.delete(cleanup);
|
|
2003
|
+
};
|
|
2004
|
+
this.clickDetachCleanups.add(cleanup);
|
|
2005
|
+
return cleanup;
|
|
2006
|
+
}
|
|
2007
|
+
onViewable(slotId, callback) {
|
|
2008
|
+
const listener = { callback, firedForIndex: -1 };
|
|
2009
|
+
const record = this.slotViewabilityRecords.get(slotId);
|
|
2010
|
+
if (record) {
|
|
2011
|
+
record.viewableListeners.add(listener);
|
|
2012
|
+
this.notifyViewable(record);
|
|
2013
|
+
} else {
|
|
2014
|
+
if (!this.pendingViewableListeners.has(slotId)) {
|
|
2015
|
+
this.pendingViewableListeners.set(slotId, /* @__PURE__ */ new Set());
|
|
2016
|
+
}
|
|
2017
|
+
this.pendingViewableListeners.get(slotId).add(listener);
|
|
2018
|
+
}
|
|
2019
|
+
return () => {
|
|
2020
|
+
this.slotViewabilityRecords.get(slotId)?.viewableListeners.delete(listener);
|
|
2021
|
+
this.pendingViewableListeners.get(slotId)?.delete(listener);
|
|
2022
|
+
};
|
|
1877
2023
|
}
|
|
1878
2024
|
scheduleThresholdTimers(record) {
|
|
1879
2025
|
if (!record.inView || typeof document !== "undefined" && document.visibilityState === "hidden") {
|
|
@@ -2063,6 +2209,8 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2063
2209
|
}
|
|
2064
2210
|
const listeners = this.pendingThresholdListeners.get(resolvedSlotId) || /* @__PURE__ */ new Set();
|
|
2065
2211
|
this.pendingThresholdListeners.delete(resolvedSlotId);
|
|
2212
|
+
const viewableListeners = this.pendingViewableListeners.get(resolvedSlotId) || /* @__PURE__ */ new Set();
|
|
2213
|
+
this.pendingViewableListeners.delete(resolvedSlotId);
|
|
2066
2214
|
const record = {
|
|
2067
2215
|
slotId: resolvedSlotId,
|
|
2068
2216
|
element: el,
|
|
@@ -2079,7 +2227,8 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2079
2227
|
viewableFired: false,
|
|
2080
2228
|
dwellTimer: null,
|
|
2081
2229
|
dwellStartedAt: null,
|
|
2082
|
-
thresholdListeners: listeners
|
|
2230
|
+
thresholdListeners: listeners,
|
|
2231
|
+
viewableListeners
|
|
2083
2232
|
};
|
|
2084
2233
|
this.slotViewabilityRecords.set(resolvedSlotId, record);
|
|
2085
2234
|
if (el) {
|
|
@@ -2104,6 +2253,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2104
2253
|
}
|
|
2105
2254
|
}
|
|
2106
2255
|
record.thresholdListeners = /* @__PURE__ */ new Set();
|
|
2256
|
+
record.viewableListeners = /* @__PURE__ */ new Set();
|
|
2107
2257
|
if (record.element && this.intersectionObserver) {
|
|
2108
2258
|
this.intersectionObserver.unobserve(record.element);
|
|
2109
2259
|
this.elementToSlotId.delete(record.element);
|
|
@@ -2118,6 +2268,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2118
2268
|
this.slotRefreshIndices.delete(slotId);
|
|
2119
2269
|
this.slotLastAuctionIds.delete(slotId);
|
|
2120
2270
|
this.pendingThresholdListeners.delete(slotId);
|
|
2271
|
+
this.pendingViewableListeners.delete(slotId);
|
|
2121
2272
|
const prefix = `${escapeKeyPart(slotId)}:`;
|
|
2122
2273
|
for (const key of Array.from(this.slotEmittedImpressionKeys)) {
|
|
2123
2274
|
if (key === slotId || key.startsWith(prefix)) {
|
|
@@ -2392,19 +2543,21 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2392
2543
|
if (!adsManager.__bidkernelAttachedInstances) {
|
|
2393
2544
|
try {
|
|
2394
2545
|
Object.defineProperty(adsManager, "__bidkernelAttachedInstances", {
|
|
2395
|
-
value: /* @__PURE__ */ new
|
|
2546
|
+
value: /* @__PURE__ */ new Map(),
|
|
2396
2547
|
configurable: true,
|
|
2397
2548
|
writable: true
|
|
2398
2549
|
});
|
|
2399
2550
|
} catch {
|
|
2400
|
-
adsManager.__bidkernelAttachedInstances = /* @__PURE__ */ new
|
|
2551
|
+
adsManager.__bidkernelAttachedInstances = /* @__PURE__ */ new Map();
|
|
2401
2552
|
}
|
|
2402
2553
|
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2554
|
+
const attached = adsManager.__bidkernelAttachedInstances;
|
|
2555
|
+
const previous = attached.get(this);
|
|
2556
|
+
if (previous) {
|
|
2557
|
+
if (!options) return () => {
|
|
2405
2558
|
};
|
|
2559
|
+
previous();
|
|
2406
2560
|
}
|
|
2407
|
-
adsManager.__bidkernelAttachedInstances.add(this);
|
|
2408
2561
|
const slotId = options?.slotId || options?.adUnitCode || "video";
|
|
2409
2562
|
const adUnitCode = options?.adUnitCode || slotId;
|
|
2410
2563
|
const auctionId = options?.auctionId || "";
|
|
@@ -2552,7 +2705,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2552
2705
|
}
|
|
2553
2706
|
}
|
|
2554
2707
|
const cleanup = () => {
|
|
2555
|
-
|
|
2708
|
+
attached.delete(this);
|
|
2556
2709
|
for (const { type, handler } of listeners) {
|
|
2557
2710
|
try {
|
|
2558
2711
|
adsManager.removeEventListener(type, handler);
|
|
@@ -2561,6 +2714,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
2561
2714
|
}
|
|
2562
2715
|
this.videoDetachCleanups.delete(cleanup);
|
|
2563
2716
|
};
|
|
2717
|
+
attached.set(this, cleanup);
|
|
2564
2718
|
this.videoDetachCleanups.add(cleanup);
|
|
2565
2719
|
return cleanup;
|
|
2566
2720
|
}
|
|
@@ -3188,9 +3342,9 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
3188
3342
|
);
|
|
3189
3343
|
}
|
|
3190
3344
|
if (this.config.viewabilityEnabled && typeof document !== "undefined") {
|
|
3191
|
-
let el = null;
|
|
3345
|
+
let el = adUnitCode && this.slotElements.get(adUnitCode) || null;
|
|
3192
3346
|
const targetId = adUnitCode || data.adId || bid.adId;
|
|
3193
|
-
if (targetId) {
|
|
3347
|
+
if (!el && targetId) {
|
|
3194
3348
|
el = document.getElementById(targetId);
|
|
3195
3349
|
}
|
|
3196
3350
|
if (!el && typeof window !== "undefined" && window.googletag?.pubads) {
|
|
@@ -3289,12 +3443,11 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
3289
3443
|
}
|
|
3290
3444
|
if (this.queue.length >= BATCH_SIZE) {
|
|
3291
3445
|
this.flush();
|
|
3292
|
-
} else if (
|
|
3293
|
-
this.
|
|
3294
|
-
|
|
3295
|
-
this.immediateFlushScheduled = false;
|
|
3446
|
+
} else if (REVENUE_FLUSH_TYPES.has(type) && this.revenueFlushTimer === null) {
|
|
3447
|
+
this.revenueFlushTimer = setTimeout(() => {
|
|
3448
|
+
this.revenueFlushTimer = null;
|
|
3296
3449
|
this.flush();
|
|
3297
|
-
},
|
|
3450
|
+
}, this.config.revenueFlushDelayMs);
|
|
3298
3451
|
}
|
|
3299
3452
|
}
|
|
3300
3453
|
shouldSample(type, level) {
|
|
@@ -3452,6 +3605,7 @@ var BidkernelPrebidAnalytics = class _BidkernelPrebidAnalytics {
|
|
|
3452
3605
|
return `${PENDING_BATCH_KEY_PREFIX}${encodeURIComponent(this.config.propertyId)}_`;
|
|
3453
3606
|
}
|
|
3454
3607
|
persistBatch(encoded) {
|
|
3608
|
+
if (!storageAllowed) return null;
|
|
3455
3609
|
try {
|
|
3456
3610
|
if (typeof localStorage === "undefined") return null;
|
|
3457
3611
|
if (!this.config.propertyId) return null;
|
|
@@ -3703,6 +3857,7 @@ function getbidkernel(alias = "bidkernel") {
|
|
|
3703
3857
|
export {
|
|
3704
3858
|
BidkernelPrebidAnalytics,
|
|
3705
3859
|
PrebidEventDeduper,
|
|
3860
|
+
getOrCreateSessionId,
|
|
3706
3861
|
getPrebidEventKey,
|
|
3707
3862
|
getbidkernel,
|
|
3708
3863
|
hookImaPrototype,
|
package/package.json
CHANGED