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

prebid / Prebid.js / #304

24 Jun 2025 05:14PM UTC coverage: 90.422% (+0.02%) from 90.403%
#304

push

travis-ci

prebidjs-release
Prebid 9.51.0 release

43346 of 54399 branches covered (79.68%)

64092 of 70881 relevant lines covered (90.42%)

174.66 hits per line

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

98.82
/libraries/liveIntentId/idSystem.js
1
/**
2
 * This module adds LiveIntentId to the User ID module.
3
 * The {@link module:modules/userId} module is required.
4
 * @module modules/idSystem
5
 * @requires module:modules/userId
6
 */
7
import { triggerPixel, logError } from '../../src/utils.js';
8
import { ajaxBuilder } from '../../src/ajax.js';
9
import { gdprDataHandler, uspDataHandler, gppDataHandler } from '../../src/adapterManager.js';
10
import { submodule } from '../../src/hook.js';
11
import { LiveConnect } from 'live-connect-js'; // eslint-disable-line prebid/validate-imports
12
import { getStorageManager } from '../../src/storageManager.js';
13
import { MODULE_TYPE_UID } from '../../src/activities/modules.js';
14
import { DEFAULT_AJAX_TIMEOUT, MODULE_NAME, composeResult, eids, GVLID, DEFAULT_DELAY, PRIMARY_IDS, parseRequestedAttributes, makeSourceEventToSend, setUpTreatment } from './shared.js'
15

16
/**
17
 * @typedef {import('../modules/userId/index.js').Submodule} Submodule
18
 * @typedef {import('../modules/userId/index.js').SubmoduleConfig} SubmoduleConfig
19
 * @typedef {import('../modules/userId/index.js').IdResponse} IdResponse
20
 */
21

22
const EVENTS_TOPIC = 'pre_lips';
1✔
23

24
export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
1✔
25
const calls = {
1✔
26
  ajaxGet: (url, onSuccess, onError, timeout, headers) => {
27
    ajaxBuilder(timeout)(
41✔
28
      url,
29
      {
30
        success: onSuccess,
31
        error: onError
32
      },
33
      undefined,
34
      {
35
        method: 'GET',
36
        withCredentials: true,
37
        customHeaders: headers
38
      }
39
    )
40
  },
41
  pixelGet: (url, onload) => triggerPixel(url, onload)
5✔
42
}
43

44
let eventFired = false;
1✔
45
let liveConnect = null;
1✔
46

47
/**
48
 * This function is used in tests.
49
 */
50
export function reset() {
51
  if (window && window.liQ_instances) {
119✔
52
    window.liQ_instances.forEach(i => i.eventBus.off(EVENTS_TOPIC, setEventFiredFlag));
118✔
53
    window.liQ_instances = [];
118✔
54
  }
55
  liveIntentIdSubmodule.setModuleMode(null);
119✔
56
  eventFired = false;
119✔
57
  liveConnect = null;
119✔
58
}
59

60
/**
61
 * This function is used in tests.
62
 */
63
export function setEventFiredFlag() {
64
  eventFired = true;
86✔
65
}
66

67
function parseLiveIntentCollectorConfig(collectConfig) {
68
  const config = {};
90✔
69
  collectConfig = collectConfig || {};
90✔
70
  collectConfig.appId && (config.appId = collectConfig.appId);
90✔
71
  collectConfig.fpiStorageStrategy && (config.storageStrategy = collectConfig.fpiStorageStrategy);
90!
72
  collectConfig.fpiExpirationDays && (config.expirationDays = collectConfig.fpiExpirationDays);
90!
73
  collectConfig.collectorUrl && (config.collectorUrl = collectConfig.collectorUrl);
90✔
74
  config.ajaxTimeout = collectConfig.ajaxTimeout || DEFAULT_AJAX_TIMEOUT;
90✔
75
  return config;
90✔
76
}
77

78
/**
79
 * Create requestedAttributes array to pass to LiveConnect.
80
 * @function
81
 * @param {Object} overrides - object with boolean values that will override defaults { 'foo': true, 'bar': false }
82
 * @returns {Array}
83
 */
84

85
function initializeLiveConnect(configParams) {
86
  if (liveConnect) {
92✔
87
    return liveConnect;
2✔
88
  }
89

90
  configParams = configParams || {};
90!
91

92
  const publisherId = configParams.publisherId || 'any';
90✔
93
  const identityResolutionConfig = {
90✔
94
    publisherId: publisherId,
95
    requestedAttributes: parseRequestedAttributes(configParams.requestedAttributesOverrides),
96
    extraAttributes: {
97
      ipv4: configParams.ipv4,
98
      ipv6: configParams.ipv6
99
    }
100
  };
101
  if (configParams.url) {
90✔
102
    identityResolutionConfig.url = configParams.url;
5✔
103
  };
104

105
  identityResolutionConfig.ajaxTimeout = configParams.ajaxTimeout || DEFAULT_AJAX_TIMEOUT;
90✔
106

107
  const liveConnectConfig = parseLiveIntentCollectorConfig(configParams.liCollectConfig);
90✔
108

109
  if (!liveConnectConfig.appId && configParams.distributorId) {
90✔
110
    liveConnectConfig.distributorId = configParams.distributorId;
3✔
111
    identityResolutionConfig.source = configParams.distributorId;
3✔
112
  } else {
113
    identityResolutionConfig.source = configParams.partner || 'prebid';
87✔
114
  }
115

116
  liveConnectConfig.wrapperName = 'prebid';
90✔
117
  liveConnectConfig.trackerVersion = '$prebid.version$';
90✔
118
  liveConnectConfig.identityResolutionConfig = identityResolutionConfig;
90✔
119
  liveConnectConfig.identifiersToResolve = configParams.identifiersToResolve || [];
90✔
120
  liveConnectConfig.fireEventDelay = configParams.fireEventDelay;
90✔
121

122
  const usPrivacyString = uspDataHandler.getConsentData();
90✔
123
  if (usPrivacyString) {
90✔
124
    liveConnectConfig.usPrivacyString = usPrivacyString;
4✔
125
  }
126
  const gdprConsent = gdprDataHandler.getConsentData();
90✔
127
  if (gdprConsent) {
90✔
128
    liveConnectConfig.gdprApplies = gdprConsent.gdprApplies;
4✔
129
    liveConnectConfig.gdprConsent = gdprConsent.consentString;
4✔
130
  }
131
  const gppConsent = gppDataHandler.getConsentData();
90✔
132
  if (gppConsent) {
90✔
133
    liveConnectConfig.gppString = gppConsent.gppString;
3✔
134
    liveConnectConfig.gppApplicableSections = gppConsent.applicableSections;
3✔
135
  }
136
  // The second param is the storage object, LS & Cookie manipulation uses PBJS.
137
  // The third param is the ajax and pixel object, the AJAX and pixel use PBJS.
138
  liveConnect = liveIntentIdSubmodule.getInitializer()(liveConnectConfig, storage, calls);
90✔
139

140
  const sourceEvent = makeSourceEventToSend(configParams)
90✔
141
  if (sourceEvent != null) {
90✔
142
    liveConnect.push(sourceEvent);
3✔
143
  }
144
  return liveConnect;
90✔
145
}
146

147
function tryFireEvent() {
148
  if (!eventFired && liveConnect) {
96!
149
    const eventDelay = liveConnect.config.fireEventDelay || DEFAULT_DELAY;
96✔
150
    setTimeout(() => {
96✔
151
      const instances = window.liQ_instances;
96✔
152
      instances.forEach(i => i.eventBus.once(EVENTS_TOPIC, setEventFiredFlag));
96✔
153
      if (!eventFired && liveConnect) {
96✔
154
        liveConnect.fire();
10✔
155
      }
156
    }, eventDelay);
157
  }
158
}
159

160
/** @type {Submodule} */
161
export const liveIntentIdSubmodule = {
1✔
162
  moduleMode: '$$LIVE_INTENT_MODULE_MODE$$',
163
  /**
164
   * Used to link submodule with config.
165
   * @type {string}
166
   */
167
  name: MODULE_NAME,
168
  gvlid: GVLID,
169
  setModuleMode(mode) {
170
    this.moduleMode = mode;
269✔
171
  },
172
  getInitializer() {
173
    return (liveConnectConfig, storage, calls) => LiveConnect(liveConnectConfig, storage, calls, this.moduleMode);
90✔
174
  },
175

176
  /**
177
   * Decode the stored id value for passing to bid requests.
178
   * Note that lipb object is a wrapper for everything, and
179
   * internally it could contain more data other than `lipbid`
180
   * (e.g. `segments`) depending on the `partner` and `publisherId`
181
   * params.
182
   * @function
183
   * @param {{unifiedId:string}} value
184
   * @param {SubmoduleConfig|undefined} config
185
   * @returns {{lipb:Object}}
186
   */
187
  decode(value, config) {
188
    const configParams = (config && config.params) || {};
57✔
189
    setUpTreatment(configParams);
57✔
190

191
    if (!liveConnect) {
57✔
192
      initializeLiveConnect(configParams);
53✔
193
    }
194
    tryFireEvent();
57✔
195

196
    return composeResult(value, configParams);
57✔
197
  },
198

199
  /**
200
   * Performs action to obtain id and return a value in the callback's response argument.
201
   * @function
202
   * @param {SubmoduleConfig} [config]
203
   * @returns {IdResponse|undefined}
204
   */
205
  getId(config) {
206
    const configParams = (config && config.params) || {};
39!
207
    setUpTreatment(configParams);
39✔
208

209
    const liveConnect = initializeLiveConnect(configParams);
39✔
210
    if (!liveConnect) {
39!
211
      return;
×
212
    }
213
    tryFireEvent();
39✔
214
    const result = function(callback) {
39✔
215
      liveConnect.resolve(
30✔
216
        response => {
217
          callback(response);
20✔
218
        },
219
        error => {
220
          logError(`${MODULE_NAME}: ID fetch encountered an error: `, error);
2✔
221
          callback();
2✔
222
        }
223
      )
224
    }
225

226
    return { callback: result };
39✔
227
  },
228
  primaryIds: PRIMARY_IDS,
229
  eids
230
};
231

232
submodule('userId', liveIntentIdSubmodule);
1✔
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