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

prebid / Prebid.js / #289

27 Mar 2025 06:27PM UTC coverage: 90.449% (-0.04%) from 90.491%
#289

push

travis-ci

prebidjs-release
Prebid 9.37.0 release

42704 of 53507 branches covered (79.81%)

63450 of 70150 relevant lines covered (90.45%)

227.65 hits per line

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

98.88
/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)(
42✔
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) {
122✔
52
    window.liQ_instances.forEach(i => i.eventBus.off(EVENTS_TOPIC, setEventFiredFlag));
121✔
53
    window.liQ_instances = [];
121✔
54
  }
55
  liveIntentIdSubmodule.setModuleMode(null);
122✔
56
  eventFired = false;
122✔
57
  liveConnect = null;
122✔
58
}
59

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

67
function parseLiveIntentCollectorConfig(collectConfig) {
68
  const config = {};
94✔
69
  collectConfig = collectConfig || {};
94✔
70
  collectConfig.appId && (config.appId = collectConfig.appId);
94✔
71
  collectConfig.fpiStorageStrategy && (config.storageStrategy = collectConfig.fpiStorageStrategy);
94!
72
  collectConfig.fpiExpirationDays && (config.expirationDays = collectConfig.fpiExpirationDays);
94!
73
  collectConfig.collectorUrl && (config.collectorUrl = collectConfig.collectorUrl);
94✔
74
  config.ajaxTimeout = collectConfig.ajaxTimeout || DEFAULT_AJAX_TIMEOUT;
94✔
75
  return config;
94✔
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) {
96✔
87
    return liveConnect;
2✔
88
  }
89

90
  configParams = configParams || {};
94!
91
  const fpidConfig = configParams.fpid || {};
94✔
92

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

106
  identityResolutionConfig.ajaxTimeout = configParams.ajaxTimeout || DEFAULT_AJAX_TIMEOUT;
94✔
107

108
  const liveConnectConfig = parseLiveIntentCollectorConfig(configParams.liCollectConfig);
94✔
109

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

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

123
  liveConnectConfig.idCookie = {};
94✔
124
  liveConnectConfig.idCookie.name = fpidConfig.name;
94✔
125
  liveConnectConfig.idCookie.strategy = fpidConfig.strategy == 'html5' ? 'localStorage' : fpidConfig.strategy;
94!
126

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

145
  const sourceEvent = makeSourceEventToSend(configParams)
94✔
146
  if (sourceEvent != null) {
94✔
147
    liveConnect.push(sourceEvent);
3✔
148
  }
149
  return liveConnect;
94✔
150
}
151

152
function tryFireEvent() {
153
  if (!eventFired && liveConnect) {
101!
154
    const eventDelay = liveConnect.config.fireEventDelay || DEFAULT_DELAY;
101✔
155
    setTimeout(() => {
101✔
156
      const instances = window.liQ_instances;
101✔
157
      instances.forEach(i => i.eventBus.once(EVENTS_TOPIC, setEventFiredFlag));
101✔
158
      if (!eventFired && liveConnect) {
101✔
159
        liveConnect.fire();
10✔
160
      }
161
    }, eventDelay);
162
  }
163
}
164

165
/** @type {Submodule} */
166
export const liveIntentIdSubmodule = {
1✔
167
  moduleMode: '$$LIVE_INTENT_MODULE_MODE$$',
168
  /**
169
   * Used to link submodule with config.
170
   * @type {string}
171
   */
172
  name: MODULE_NAME,
173
  gvlid: GVLID,
174
  setModuleMode(mode) {
175
    this.moduleMode = mode;
276✔
176
  },
177
  getInitializer() {
178
    return (liveConnectConfig, storage, calls) => LiveConnect(liveConnectConfig, storage, calls, this.moduleMode);
94✔
179
  },
180

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

196
    if (!liveConnect) {
61✔
197
      initializeLiveConnect(configParams);
56✔
198
    }
199
    tryFireEvent();
61✔
200

201
    return composeResult(value, configParams);
61✔
202
  },
203

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

214
    const liveConnect = initializeLiveConnect(configParams);
40✔
215
    if (!liveConnect) {
40!
216
      return;
×
217
    }
218
    tryFireEvent();
40✔
219
    const result = function(callback) {
40✔
220
      liveConnect.resolve(
31✔
221
        response => {
222
          callback(response);
21✔
223
        },
224
        error => {
225
          logError(`${MODULE_NAME}: ID fetch encountered an error: `, error);
2✔
226
          callback();
2✔
227
        }
228
      )
229
    }
230

231
    return { callback: result };
40✔
232
  },
233
  primaryIds: PRIMARY_IDS,
234
  eids
235
};
236

237
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