• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prebid / Prebid.js / 22148703734

18 Feb 2026 04:41PM UTC coverage: 96.218% (+0.01%) from 96.205%
22148703734

Pull #14488

github

ff15b7
patmmccann
Docs: require TypeScript for new src/modules/libraries files
Pull Request #14488: Prebid 11: document TypeScript-first policy for new source files

54237 of 66588 branches covered (81.45%)

208182 of 216366 relevant lines covered (96.22%)

69.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.87
/modules/invisiblyAnalyticsAdapter.js
1
/**
1✔
2
 * invisiblyAdapterAdapter.js - analytics adapter for Invisibly
3
 */
4
import { ajaxBuilder } from '../src/ajax.js';
5
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
6
import adapterManager from '../src/adapterManager.js';
7

8
import { deepClone, hasNonSerializableProperty, generateUUID, logInfo } from '../src/utils.js';
9
import { EVENTS } from '../src/constants.js';
10
import { getViewportSize } from '../libraries/viewport/viewport.js';
11

12
const DEFAULT_EVENT_URL = 'https://api.pymx5.com/v1/' + 'sites/events';
1✔
13
const analyticsType = 'endpoint';
1✔
14
const analyticsName = 'Invisibly Analytics Adapter:';
1✔
15
const ajax = ajaxBuilder(0);
1✔
16

17
// Events needed
18
const {
19
  AUCTION_INIT,
20
  AUCTION_END,
21
  BID_ADJUSTMENT,
22
  BID_TIMEOUT,
23
  BID_REQUESTED,
24
  BID_RESPONSE,
25
  NO_BID,
26
  BID_WON,
27
  BIDDER_DONE,
28
  SET_TARGETING,
29
  REQUEST_BIDS,
30
  AD_RENDER_FAILED,
31
} = EVENTS;
1✔
32

33
const _VERSION = 1;
1✔
34
const _pageViewId = generateUUID();
1✔
35
let initOptions = null;
1✔
36
let _startAuction = 0;
1✔
37
let _bidRequestTimeout = 0;
1✔
38
let flushInterval;
39
let invisiblyAnalyticsEnabled = false;
1✔
40

41
const { width: x, height: y } = getViewportSize();
1✔
42

43
const _pageView = {
1✔
44
  eventType: 'pageView',
45
  userAgent: window.navigator.userAgent,
46
  timestamp: Date.now(),
47
  timezoneOffset: new Date().getTimezoneOffset(),
48
  language: window.navigator.language,
49
  vendor: window.navigator.vendor,
50
  screenWidth: x,
51
  screenHeight: y,
52
};
53

54
// pass only 1% of events & fail the rest 99%
55
const weightedFilter = { filter: Math.random() > 0.99 };
1✔
56

57
const _eventQueue = [_pageView];
1✔
58

59
const invisiblyAdapter = Object.assign(
1✔
60
  adapter({ url: DEFAULT_EVENT_URL, analyticsType }),
61
  {
62
    track({ eventType, args }) {
35✔
63
      handleEvent(eventType, args);
35✔
64
    },
65
    sendEvent,
66
    weightedFilter,
67
  }
68
);
69

70
invisiblyAdapter.originEnableAnalytics = invisiblyAdapter.enableAnalytics;
1✔
71
invisiblyAdapter.enableAnalytics = function (config) {
1✔
72
  initOptions = config.options || {};
18!
73
  initOptions.url = initOptions.url || DEFAULT_EVENT_URL;
18✔
74
  if (initOptions.url && initOptions.account && weightedFilter.filter) {
18✔
75
    invisiblyAnalyticsEnabled = true;
16✔
76
    invisiblyAdapter.originEnableAnalytics(config);
16✔
77
  } else {
78
    invisiblyAnalyticsEnabled = false;
2✔
79
    invisiblyAdapter.originDisableAnalytics();
2✔
80
  }
81
  flushInterval = setInterval(flush, 1000);
18✔
82
};
83

84
invisiblyAdapter.originDisableAnalytics = invisiblyAdapter.disableAnalytics;
1✔
85
invisiblyAdapter.disableAnalytics = function () {
1✔
86
  if (!invisiblyAnalyticsEnabled) {
18✔
87
    return;
2✔
88
  }
89
  flush();
16✔
90
  clearInterval(flushInterval);
16✔
91
  invisiblyAdapter.originDisableAnalytics();
16✔
92
};
93

94
function flush() {
95
  if (!invisiblyAnalyticsEnabled) {
34✔
96
    return;
2✔
97
  }
98

99
  if (_eventQueue.length > 0) {
32✔
100
    while (_eventQueue.length) {
16✔
101
      const eventFromQue = _eventQueue.shift();
30✔
102
      const eventtype = 'PREBID_' + eventFromQue.eventType;
30✔
103
      delete eventFromQue.eventType;
30✔
104

105
      const data = {
30✔
106
        pageViewId: _pageViewId,
107
        ver: _VERSION,
108
        bundleId: initOptions.bundleId,
109
        ...eventFromQue,
110
      };
111

112
      const payload = {
30✔
113
        event_type: eventtype,
114
        event_data: { ...data },
115
      };
116
      ajax(
30✔
117
        initOptions.url,
118
        () => logInfo(`${analyticsName} sent events batch`),
×
119
        JSON.stringify(payload),
120
        {
121
          contentType: 'application/json',
122
          method: 'POST',
123
          withCredentials: true,
124
        }
125
      );
126
    }
127
  }
128
}
129

130
function handleEvent(eventType, eventArgs) {
131
  if (eventArgs) {
35!
132
    eventArgs = hasNonSerializableProperty(eventArgs) ? eventArgs : deepClone(eventArgs)
35✔
133
  } else {
134
    eventArgs = {}
×
135
  }
136

137
  let invisiblyEvent = {};
35✔
138

139
  switch (eventType) {
35✔
140
    case AUCTION_INIT: {
141
      invisiblyEvent = eventArgs;
3✔
142
      _startAuction = invisiblyEvent.timestamp;
3✔
143
      _bidRequestTimeout = invisiblyEvent.timeout;
3✔
144
      break;
3✔
145
    }
146
    case AUCTION_END: {
147
      invisiblyEvent = eventArgs;
3✔
148
      invisiblyEvent.start = _startAuction;
3✔
149
      invisiblyEvent.end = Date.now();
3✔
150
      break;
3✔
151
    }
152
    case BID_ADJUSTMENT: {
153
      invisiblyEvent.bidders = eventArgs;
2✔
154
      break;
2✔
155
    }
156
    case BID_TIMEOUT: {
157
      invisiblyEvent.bidders = eventArgs;
2✔
158
      invisiblyEvent.duration = _bidRequestTimeout;
2✔
159
      break;
2✔
160
    }
161
    case BID_REQUESTED: {
162
      invisiblyEvent = eventArgs;
3✔
163
      break;
3✔
164
    }
165
    case BID_RESPONSE: {
166
      invisiblyEvent = eventArgs;
3✔
167
      break;
3✔
168
    }
169
    case NO_BID: {
170
      invisiblyEvent.noBid = eventArgs;
2✔
171
      break;
2✔
172
    }
173
    case BID_WON: {
174
      invisiblyEvent = eventArgs;
3✔
175
      break;
3✔
176
    }
177
    case BIDDER_DONE: {
178
      invisiblyEvent = eventArgs;
2✔
179
      break;
2✔
180
    }
181
    case SET_TARGETING: {
182
      invisiblyEvent.targetings = eventArgs;
2✔
183
      break;
2✔
184
    }
185
    case REQUEST_BIDS: {
186
      invisiblyEvent = eventArgs;
2✔
187
      break;
2✔
188
    }
189
    case AD_RENDER_FAILED: {
190
      invisiblyEvent = eventArgs;
2✔
191
      break;
2✔
192
    }
193
    default:
194
      return;
6✔
195
  }
196
  invisiblyEvent.eventType = eventType;
29✔
197
  invisiblyEvent.timestamp = invisiblyEvent.timestamp || Date.now();
29✔
198
  sendEvent(invisiblyEvent);
29✔
199
}
200

201
function sendEvent(event) {
202
  _eventQueue.push(event);
29✔
203
  logInfo(`${analyticsName}Event ${event.eventType}:`, event);
29✔
204

205
  if (event.eventType === AUCTION_END) {
29✔
206
    flush();
3✔
207
    clearInterval(flushInterval);
3✔
208
  }
209
}
210

211
adapterManager.registerAnalyticsAdapter({
1✔
212
  adapter: invisiblyAdapter,
213
  code: 'invisiblyAnalytics',
214
});
215

216
invisiblyAdapter.getOptions = function () {
1✔
217
  return initOptions;
1✔
218
};
219

220
invisiblyAdapter.flush = flush;
1✔
221

222
export default invisiblyAdapter;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc