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

prebid / Prebid.js / 19143166793

06 Nov 2025 04:48PM UTC coverage: 96.228%. Remained the same
19143166793

push

github

web-flow
feat: wallet profiling (#14067)

52795 of 64670 branches covered (81.64%)

164 of 167 new or added lines in 2 files covered. (98.2%)

31 existing lines in 11 files now uncovered.

201947 of 209864 relevant lines covered (96.23%)

124.84 hits per line

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

83.97
/modules/pubwiseAnalyticsAdapter.js
1
import { getParameterByName, logInfo, generateUUID, debugTurnedOn } from '../src/utils.js';
1✔
2
import {ajax} from '../src/ajax.js';
3
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
4
import adapterManager from '../src/adapterManager.js';
5
import { EVENTS } from '../src/constants.js';
6
import {getStorageManager} from '../src/storageManager.js';
7
import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js';
8
const MODULE_CODE = 'pubwise';
1✔
9
const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_CODE});
1✔
10

11
/****
12
 * PubWise.io Analytics
13
 * Contact: support@pubwise.io
14
 * Developer: Stephen Johnston
15
 *
16
 * For testing:
17
 *
18
 pbjs.enableAnalytics({
19
  provider: 'pubwise',
20
  options: {
21
    site: 'b1ccf317-a6fc-428d-ba69-0c9c208aa61c'
22
  }
23
 });
24

25
Changes in 4.0 Version
26
4.0.1 - Initial Version for Prebid 4.x, adds activationId, adds additiona testing, removes prebid global in favor of a prebid.version const
27
4.0.2 - Updates to include dedicated default site to keep everything from getting rate limited
28

29
*/
30

31
const analyticsType = 'endpoint';
1✔
32
const analyticsName = 'PubWise:';
1✔
33
const prebidVersion = '$prebid.version$';
1✔
34
const pubwiseVersion = '4.0.1';
1✔
35
let configOptions = {site: '', endpoint: 'https://api.pubwise.io/api/v5/event/add/', debug: null};
1✔
36
let pwAnalyticsEnabled = false;
1✔
37
const utmKeys = {utm_source: '', utm_medium: '', utm_campaign: '', utm_term: '', utm_content: ''};
1✔
38
const sessionData = {sessionId: '', activationId: ''};
1✔
39
const pwNamespace = 'pubwise';
1✔
40
const pwEvents = [];
1✔
41
let metaData = {};
1✔
42
const auctionEnded = false;
1✔
43
const sessTimeout = 60 * 30 * 1000; // 30 minutes, G Analytics default session length
1✔
44
const sessName = 'sess_id';
1✔
45
const sessTimeoutName = 'sess_timeout';
1✔
46

47
function enrichWithSessionInfo(dataBag) {
48
  try {
12✔
49
    // console.log(sessionData);
50
    dataBag['session_id'] = sessionData.sessionId;
12✔
51
    dataBag['activation_id'] = sessionData.activationId;
12✔
52
  } catch (e) {
53
    dataBag['error_sess'] = 1;
×
54
  }
55

56
  return dataBag;
12✔
57
}
58

59
function enrichWithMetrics(dataBag) {
60
  try {
12✔
61
    if (window.PREBID_TIMEOUT) {
12!
62
      dataBag['target_timeout'] = window.PREBID_TIMEOUT;
×
63
    } else {
64
      dataBag['target_timeout'] = 'NA';
12✔
65
    }
66
    dataBag['pw_version'] = pubwiseVersion;
12✔
67
    dataBag['pbjs_version'] = prebidVersion;
12✔
68
    dataBag['debug'] = configOptions.debug;
12✔
69
  } catch (e) {
70
    dataBag['error_metric'] = 1;
×
71
  }
72

73
  return dataBag;
12✔
74
}
75

76
function enrichWithUTM(dataBag) {
77
  let newUtm = false;
12✔
78
  try {
12✔
79
    for (const prop in utmKeys) {
12✔
80
      utmKeys[prop] = getParameterByName(prop);
60✔
81
      if (utmKeys[prop]) {
60!
82
        newUtm = true;
×
83
        dataBag[prop] = utmKeys[prop];
×
84
      }
85
    }
86

87
    if (newUtm === false) {
12!
88
      for (const prop in utmKeys) {
12✔
89
        const itemValue = storage.getDataFromLocalStorage(setNamespace(prop));
60✔
90
        if (itemValue !== null && typeof itemValue !== 'undefined' && itemValue.length !== 0) {
60!
91
          dataBag[prop] = itemValue;
×
92
        }
93
      }
94
    } else {
95
      for (const prop in utmKeys) {
×
96
        storage.setDataInLocalStorage(setNamespace(prop), utmKeys[prop]);
×
97
      }
98
    }
99
  } catch (e) {
100
    pwInfo(`Error`, e);
×
101
    dataBag['error_utm'] = 1;
×
102
  }
103
  return dataBag;
12✔
104
}
105

106
function expireUtmData() {
UNCOV
107
  pwInfo(`Session Expiring UTM Data`);
×
UNCOV
108
  for (const prop in utmKeys) {
×
UNCOV
109
    storage.removeDataFromLocalStorage(setNamespace(prop));
×
110
  }
111
}
112

113
function enrichWithCustomSegments(dataBag) {
114
  // c_script_type: '', c_slot1: '', c_slot2: '', c_slot3: '', c_slot4: ''
115
  if (configOptions.custom) {
12✔
116
    if (configOptions.custom.c_script_type) {
12✔
117
      dataBag['c_script_type'] = configOptions.custom.c_script_type;
12✔
118
    }
119

120
    if (configOptions.custom.c_host) {
12✔
121
      dataBag['c_host'] = configOptions.custom.c_host;
12✔
122
    }
123

124
    if (configOptions.custom.c_slot1) {
12✔
125
      dataBag['c_slot1'] = configOptions.custom.c_slot1;
12✔
126
    }
127

128
    if (configOptions.custom.c_slot2) {
12✔
129
      dataBag['c_slot2'] = configOptions.custom.c_slot2;
12✔
130
    }
131

132
    if (configOptions.custom.c_slot3) {
12✔
133
      dataBag['c_slot3'] = configOptions.custom.c_slot3;
12✔
134
    }
135

136
    if (configOptions.custom.c_slot4) {
12✔
137
      dataBag['c_slot4'] = configOptions.custom.c_slot4;
12✔
138
    }
139
  }
140

141
  return dataBag;
12✔
142
}
143

144
function setNamespace(itemText) {
145
  return pwNamespace.concat('_' + itemText);
69✔
146
}
147

148
function localStorageSessTimeoutName() {
149
  return setNamespace(sessTimeoutName);
6✔
150
}
151

152
function localStorageSessName() {
153
  return setNamespace(sessName);
3✔
154
}
155

156
function extendUserSessionTimeout() {
157
  storage.setDataInLocalStorage(localStorageSessTimeoutName(), Date.now().toString());
3✔
158
}
159

160
function userSessionID() {
161
  return storage.getDataFromLocalStorage(localStorageSessName()) || '';
3!
162
}
163

164
function sessionExpired() {
165
  const sessLastTime = storage.getDataFromLocalStorage(localStorageSessTimeoutName());
3✔
166
  return (Date.now() - parseInt(sessLastTime)) > sessTimeout;
3✔
167
}
168

169
function flushEvents() {
170
  if (pwEvents.length > 0) {
13✔
171
    const dataBag = {metaData: metaData, eventList: pwEvents.splice(0)}; // put all the events together with the metadata and send
4✔
172
    ajax(configOptions.endpoint, (result) => pwInfo(`Result`, result), JSON.stringify(dataBag));
4✔
173
  }
174
}
175

176
function isIngestedEvent(eventType) {
177
  const ingested = [
13✔
178
    EVENTS.AUCTION_INIT,
179
    EVENTS.BID_REQUESTED,
180
    EVENTS.BID_RESPONSE,
181
    EVENTS.BID_WON,
182
    EVENTS.BID_TIMEOUT,
183
    EVENTS.AD_RENDER_FAILED,
184
    EVENTS.TCF2_ENFORCEMENT
185
  ];
186
  return ingested.indexOf(eventType) !== -1;
13✔
187
}
188

189
function markEnabled() {
190
  pwInfo(`Enabled`, configOptions);
3✔
191
  pwAnalyticsEnabled = true;
3✔
192
  setInterval(flushEvents, 100);
3✔
193
}
194

195
function pwInfo(info, context) {
196
  logInfo(`${analyticsName} ` + info, context);
16✔
197
}
198

199
function filterBidResponse(data) {
200
  const modified = Object.assign({}, data);
2✔
201
  // clean up some properties we don't track in public version
202
  if (typeof modified.ad !== 'undefined') {
2!
203
    modified.ad = '';
×
204
  }
205
  if (typeof modified.adUrl !== 'undefined') {
2!
206
    modified.adUrl = '';
×
207
  }
208
  if (typeof modified.adserverTargeting !== 'undefined') {
2!
209
    modified.adserverTargeting = '';
×
210
  }
211
  if (typeof modified.ts !== 'undefined') {
2!
212
    modified.ts = '';
×
213
  }
214
  // clean up a property to make simpler
215
  if (typeof modified.statusMessage !== 'undefined' && modified.statusMessage === 'Bid returned empty or error response') {
2!
216
    modified.statusMessage = 'eoe';
×
217
  }
218
  modified.auctionEnded = auctionEnded;
2✔
219
  return modified;
2✔
220
}
221

222
function filterAuctionInit(data) {
223
  const modified = Object.assign({}, data);
3✔
224

225
  modified.refererInfo = {};
3✔
226
  // handle clean referrer, we only need one
227
  if (typeof modified.bidderRequests !== 'undefined' && typeof modified.bidderRequests[0] !== 'undefined' && typeof modified.bidderRequests[0].refererInfo !== 'undefined') {
3!
228
    // TODO: please do not send internal data structures over the network
229
    modified.refererInfo = modified.bidderRequests[0].refererInfo.legacy;
×
230
  }
231

232
  if (typeof modified.adUnitCodes !== 'undefined') {
3✔
233
    delete modified.adUnitCodes;
1✔
234
  }
235
  if (typeof modified.adUnits !== 'undefined') {
3✔
236
    delete modified.adUnits;
1✔
237
  }
238
  if (typeof modified.bidderRequests !== 'undefined') {
3✔
239
    delete modified.bidderRequests;
1✔
240
  }
241
  if (typeof modified.bidsReceived !== 'undefined') {
3✔
242
    delete modified.bidsReceived;
1✔
243
  }
244
  if (typeof modified.config !== 'undefined') {
3✔
245
    delete modified.config;
1✔
246
  }
247
  if (typeof modified.noBids !== 'undefined') {
3✔
248
    delete modified.noBids;
1✔
249
  }
250
  if (typeof modified.winningBids !== 'undefined') {
3✔
251
    delete modified.winningBids;
1✔
252
  }
253

254
  return modified;
3✔
255
}
256

257
const pubwiseAnalytics = Object.assign(adapter({analyticsType}), {
1✔
258
  // Override AnalyticsAdapter functions by supplying custom methods
259
  track({eventType, args}) {
13✔
260
    this.handleEvent(eventType, args);
13✔
261
  }
262
});
263

264
pubwiseAnalytics.handleEvent = function(eventType, data) {
1✔
265
  // we log most events, but some are information
266
  if (isIngestedEvent(eventType)) {
13✔
267
    pwInfo(`Emitting Event ${eventType} ${pwAnalyticsEnabled}`, data);
12✔
268

269
    // record metadata
270
    metaData = {
12✔
271
      target_site: configOptions.site,
272
      debug: configOptions.debug ? 1 : 0,
12!
273
    };
274
    metaData = enrichWithSessionInfo(metaData);
12✔
275
    metaData = enrichWithMetrics(metaData);
12✔
276
    metaData = enrichWithUTM(metaData);
12✔
277
    metaData = enrichWithCustomSegments(metaData);
12✔
278

279
    // add data on init to the metadata container
280
    if (eventType === EVENTS.AUCTION_INIT) {
12✔
281
      data = filterAuctionInit(data);
3✔
282
    } else if (eventType === EVENTS.BID_RESPONSE) {
9✔
283
      data = filterBidResponse(data);
2✔
284
    }
285

286
    // add all ingested events
287
    pwEvents.push({
12✔
288
      eventType: eventType,
289
      args: data
290
    });
291
  } else {
292
    pwInfo(`Skipping Event ${eventType} ${pwAnalyticsEnabled}`, data);
1✔
293
  }
294

295
  // once the auction ends, or the event is a bid won send events
296
  if (eventType === EVENTS.AUCTION_END || eventType === EVENTS.BID_WON) {
13✔
297
    flushEvents();
3✔
298
  }
299
};
300

301
pubwiseAnalytics.storeSessionID = function (userSessID) {
1✔
UNCOV
302
  storage.setDataInLocalStorage(localStorageSessName(), userSessID);
×
UNCOV
303
  pwInfo(`New Session Generated`, userSessID);
×
304
};
305

306
// ensure a session exists, if not make one, always store it
307
pubwiseAnalytics.ensureSession = function () {
1✔
308
  const sessionId = userSessionID();
3✔
309
  if (sessionExpired() === true || sessionId === null || sessionId === '') {
3!
UNCOV
310
    const generatedId = generateUUID();
×
UNCOV
311
    expireUtmData();
×
UNCOV
312
    this.storeSessionID(generatedId);
×
UNCOV
313
    sessionData.sessionId = generatedId;
×
314
  } else if (sessionId != null) {
3✔
315
    sessionData.sessionId = sessionId;
3✔
316
  }
317

318
  // console.log('ensured session');
319
  extendUserSessionTimeout();
3✔
320
};
321

322
pubwiseAnalytics.adapterEnableAnalytics = pubwiseAnalytics.enableAnalytics;
1✔
323

324
pubwiseAnalytics.enableAnalytics = function (config) {
1✔
325
  configOptions = Object.assign(configOptions, config.options);
3✔
326
  // take the PBJS debug for our debug setting if no PW debug is defined
327
  if (configOptions.debug === null) {
3✔
328
    configOptions.debug = debugTurnedOn();
1✔
329
  }
330
  markEnabled();
3✔
331
  sessionData.activationId = generateUUID();
3✔
332
  this.ensureSession();
3✔
333
  pubwiseAnalytics.adapterEnableAnalytics(config);
3✔
334
};
335

336
adapterManager.registerAnalyticsAdapter({
1✔
337
  adapter: pubwiseAnalytics,
338
  code: MODULE_CODE,
339
  gvlid: 842
340
});
341

342
export default pubwiseAnalytics;
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