From 438976897ed30fca08d2959b4a7ecac9761defb7 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Fri, 14 Jul 2023 05:42:39 -0700 Subject: [PATCH] userID: break out EID configuration to individual submodules (#10229) * move eids config to submodules * update EID logic * Fix tests --- modules/33acrossIdSystem.js | 9 + modules/admixerIdSystem.js | 6 + modules/adqueryIdSystem.js | 6 + modules/adtelligentIdSystem.js | 6 + modules/amxIdSystem.js | 6 + modules/britepoolIdSystem.js | 6 + modules/connectIdSystem.js | 6 + modules/criteoIdSystem.js | 6 + modules/czechAdIdSystem.js | 6 + modules/dacIdSystem.js | 6 + modules/deepintentDpesIdSystem.js | 9 +- modules/dmdIdSystem.js | 6 + modules/euidIdSystem.js | 9 + modules/fabrickIdSystem.js | 6 + modules/ftrackIdSystem.js | 16 + modules/gravitoIdSystem.js | 6 + modules/growthCodeIdSystem.js | 21 +- modules/hadronIdSystem.js | 6 + modules/id5IdSystem.js | 16 +- modules/identityLinkIdSystem.js | 6 + modules/idxIdSystem.js | 6 + modules/imuIdSystem.js | 10 + modules/intentIqIdSystem.js | 6 + modules/justIdSystem.js | 6 + modules/kinessoIdSystem.js | 9 +- modules/liveIntentIdSystem.js | 53 ++ modules/lotamePanoramaIdSystem.js | 6 + modules/merkleIdSystem.js | 24 + modules/mwOpenLinkIdSystem.js | 6 + modules/naveggIdSystem.js | 6 + modules/netIdSystem.js | 6 + modules/novatiqIdSystem.js | 12 + modules/oneKeyIdSystem.js | 26 + modules/pairIdSystem.js | 6 + modules/parrableIdSystem.js | 40 +- modules/publinkIdSystem.js | 8 +- modules/quantcastIdSystem.js | 6 + modules/sharedIdSystem.js | 6 + modules/tapadIdSystem.js | 6 + modules/tncIdSystem.js | 6 + modules/uid2IdSystem.js | 14 + modules/unifiedIdSystem.js | 11 + modules/userId/eids.js | 451 +---------- modules/userId/index.js | 60 +- modules/utiqSystem.js | 9 + modules/verizonMediaIdSystem.js | 6 + modules/zeotapIdPlusIdSystem.js | 6 + .../modules/freewheel-sspBidAdapter_spec.js | 10 +- test/spec/modules/ixBidAdapter_spec.js | 5 +- test/spec/modules/outbrainBidAdapter_spec.js | 8 +- .../modules/prebidServerBidAdapter_spec.js | 22 +- test/spec/modules/pubmaticBidAdapter_spec.js | 379 +-------- test/spec/modules/rubiconBidAdapter_spec.js | 200 ++++- test/spec/modules/smaatoBidAdapter_spec.js | 10 +- test/spec/modules/userId_spec.js | 123 ++- test/spec/modules/vrtcalBidAdapter_spec.js | 9 +- test/spec/modules/xeBidAdapter_spec.js | 734 +++++++++--------- test/spec/modules/yahoosspBidAdapter_spec.js | 23 +- 58 files changed, 1203 insertions(+), 1295 deletions(-) diff --git a/modules/33acrossIdSystem.js b/modules/33acrossIdSystem.js index 14cd8586d50..0f370237e21 100644 --- a/modules/33acrossIdSystem.js +++ b/modules/33acrossIdSystem.js @@ -126,6 +126,15 @@ export const thirthyThreeAcrossIdSubmodule = { }, calculateQueryStringParams(pid, gdprConsentData), { method: 'GET', withCredentials: true }); } }; + }, + eids: { + '33acrossId': { + source: '33across.com', + atype: 1, + getValue: function(data) { + return data.envelope; + } + }, } }; diff --git a/modules/admixerIdSystem.js b/modules/admixerIdSystem.js index 7fbebecfc12..0e3a56420a8 100644 --- a/modules/admixerIdSystem.js +++ b/modules/admixerIdSystem.js @@ -72,6 +72,12 @@ export const admixerIdSubmodule = { }; return { callback: resp }; + }, + eids: { + 'admixerId': { + source: 'admixer.net', + atype: 3 + }, } }; function retrieveVisitorId(url, callback) { diff --git a/modules/adqueryIdSystem.js b/modules/adqueryIdSystem.js index 5171802caba..82df787a2b4 100644 --- a/modules/adqueryIdSystem.js +++ b/modules/adqueryIdSystem.js @@ -98,6 +98,12 @@ export const adqueryIdSubmodule = { } }; return {callback: resp}; + }, + eids: { + 'qid': { + source: 'adquery.io', + atype: 1 + }, } }; diff --git a/modules/adtelligentIdSystem.js b/modules/adtelligentIdSystem.js index fb3b5f6fe2a..440ed9ade75 100644 --- a/modules/adtelligentIdSystem.js +++ b/modules/adtelligentIdSystem.js @@ -85,6 +85,12 @@ export const adtelligentIdModule = { } } + }, + eids: { + 'adtelligentId': { + source: 'adtelligent.com', + atype: 3 + }, } }; diff --git a/modules/amxIdSystem.js b/modules/amxIdSystem.js index 5deffa00dfe..184eff76c34 100644 --- a/modules/amxIdSystem.js +++ b/modules/amxIdSystem.js @@ -152,6 +152,12 @@ export const amxIdSubmodule = { return { callback }; }, + eids: { + amxId: { + source: 'amxdt.net', + atype: 1, + }, + } }; submodule('userId', amxIdSubmodule); diff --git a/modules/britepoolIdSystem.js b/modules/britepoolIdSystem.js index 2316fbb732d..b75fe9424b1 100644 --- a/modules/britepoolIdSystem.js +++ b/modules/britepoolIdSystem.js @@ -136,6 +136,12 @@ export const britepoolIdSubmodule = { } } return valueObj; + }, + eids: { + 'britepoolid': { + source: 'britepool.com', + atype: 3 + }, } }; diff --git a/modules/connectIdSystem.js b/modules/connectIdSystem.js index 1caff49199d..e1c5b427264 100644 --- a/modules/connectIdSystem.js +++ b/modules/connectIdSystem.js @@ -294,6 +294,12 @@ export const connectIdSubmodule = { */ getAjaxFn() { return ajax; + }, + eids: { + 'connectId': { + source: 'yahoo.com', + atype: 3 + }, } }; diff --git a/modules/criteoIdSystem.js b/modules/criteoIdSystem.js index b48612203f8..ee343d9b16a 100644 --- a/modules/criteoIdSystem.js +++ b/modules/criteoIdSystem.js @@ -216,6 +216,12 @@ export const criteoIdSubmodule = { id: localData.bidId ? { criteoId: localData.bidId } : undefined, callback: result } + }, + eids: { + 'criteoId': { + source: 'criteo.com', + atype: 1 + }, } }; diff --git a/modules/czechAdIdSystem.js b/modules/czechAdIdSystem.js index 957b3ed30bd..ae958aae198 100644 --- a/modules/czechAdIdSystem.js +++ b/modules/czechAdIdSystem.js @@ -42,6 +42,12 @@ export const czechAdIdSubmodule = { getId () { const id = readId() return id ? { id: id } : undefined + }, + eids: { + 'czechAdId': { + source: 'czechadid.cz', + atype: 1 + }, } } diff --git a/modules/dacIdSystem.js b/modules/dacIdSystem.js index 5adca074c87..ffdadef18e8 100644 --- a/modules/dacIdSystem.js +++ b/modules/dacIdSystem.js @@ -170,6 +170,12 @@ export const dacIdSystemSubmodule = { } return fetchAoneId(configParams.oid, cookie.fuuid); + }, + eids: { + 'dacId': { + source: 'impact-ad.jp', + atype: 1 + }, } }; diff --git a/modules/deepintentDpesIdSystem.js b/modules/deepintentDpesIdSystem.js index f2b50d535eb..4d685592c04 100644 --- a/modules/deepintentDpesIdSystem.js +++ b/modules/deepintentDpesIdSystem.js @@ -39,8 +39,13 @@ export const deepintentDpesSubmodule = { */ getId(config, consentData, cacheIdObj) { return cacheIdObj; - } - + }, + eids: { + 'deepintentId': { + source: 'deepintent.com', + atype: 3 + }, + }, }; submodule('userId', deepintentDpesSubmodule); diff --git a/modules/dmdIdSystem.js b/modules/dmdIdSystem.js index b42315d66ee..2f910a8bd92 100644 --- a/modules/dmdIdSystem.js +++ b/modules/dmdIdSystem.js @@ -85,6 +85,12 @@ export const dmdIdSubmodule = { }; return { callback: resp }; } + }, + eids: { + 'dmdId': { + source: 'hcn.health', + atype: 3 + }, } }; diff --git a/modules/euidIdSystem.js b/modules/euidIdSystem.js index c4e15b11d15..6a3a0869c0e 100644 --- a/modules/euidIdSystem.js +++ b/modules/euidIdSystem.js @@ -103,6 +103,15 @@ export const euidIdSubmodule = { _logInfo(`EUID getId returned`, result); return result; }, + eids: { + 'euid': { + source: 'euid.eu', + atype: 3, + getValue: function(data) { + return data.id; + } + }, + }, }; function decodeImpl(value) { diff --git a/modules/fabrickIdSystem.js b/modules/fabrickIdSystem.js index dfc2985b0db..bc9c30cb479 100644 --- a/modules/fabrickIdSystem.js +++ b/modules/fabrickIdSystem.js @@ -117,6 +117,12 @@ export const fabrickIdSubmodule = { } catch (e) { logError(`fabrickIdSystem encountered an error`, e); } + }, + eids: { + 'fabrickId': { + source: 'neustar.biz', + atype: 1 + }, } }; diff --git a/modules/ftrackIdSystem.js b/modules/ftrackIdSystem.js index 5f09a315b34..809f1311c42 100644 --- a/modules/ftrackIdSystem.js +++ b/modules/ftrackIdSystem.js @@ -221,6 +221,22 @@ export const ftrackIdSubmodule = { if (usPrivacyVersion == 1 && usPrivacyOptOutSale === 'Y') consentValue = false; return consentValue; + }, + eids: { + 'ftrackId': { + source: 'flashtalking.com', + atype: 1, + getValue: function(data) { + let value = ''; + if (data && data.ext && data.ext.DeviceID) { + value = data.ext.DeviceID; + } + return value; + }, + getUidExt: function(data) { + return data && data.ext; + } + }, } }; diff --git a/modules/gravitoIdSystem.js b/modules/gravitoIdSystem.js index aa25ea7db2c..70031ebd06e 100644 --- a/modules/gravitoIdSystem.js +++ b/modules/gravitoIdSystem.js @@ -53,6 +53,12 @@ export const gravitoIdSystemSubmodule = { } return undefined; }, + eids: { + 'gravitompId': { + source: 'gravito.net', + atype: 1 + }, + } } submodule('userId', gravitoIdSystemSubmodule); diff --git a/modules/growthCodeIdSystem.js b/modules/growthCodeIdSystem.js index fae022f1a56..aec49c64fa3 100644 --- a/modules/growthCodeIdSystem.js +++ b/modules/growthCodeIdSystem.js @@ -5,7 +5,7 @@ * @requires module:modules/userId */ -import {logError, logInfo, tryAppendQueryString} from '../src/utils.js'; +import {logError, logInfo, pick, tryAppendQueryString} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import { submodule } from '../src/hook.js' import {getStorageManager} from '../src/storageManager.js'; @@ -166,6 +166,25 @@ export const growthCodeIdSubmodule = { } }; return { callback: resp }; + }, + eids: { + 'growthCodeId': { + getValue: function(data) { + return data.gc_id + }, + source: 'growthcode.io', + atype: 1, + getUidExt: function(data) { + const extendedData = pick(data, [ + 'h1', + 'h2', + 'h3', + ]); + if (Object.keys(extendedData).length) { + return extendedData; + } + } + }, } }; diff --git a/modules/hadronIdSystem.js b/modules/hadronIdSystem.js index 596bf9611e6..c60f0f812a4 100644 --- a/modules/hadronIdSystem.js +++ b/modules/hadronIdSystem.js @@ -110,6 +110,12 @@ export const hadronIdSubmodule = { ajax(url, callbacks, undefined, {method: 'GET'}); }; return {callback: resp}; + }, + eids: { + 'hadronId': { + source: 'audigent.com', + atype: 1 + }, } }; diff --git a/modules/id5IdSystem.js b/modules/id5IdSystem.js index bb8a21264d0..eff1f136649 100644 --- a/modules/id5IdSystem.js +++ b/modules/id5IdSystem.js @@ -154,7 +154,21 @@ export const id5IdSubmodule = { logInfo(LOG_PREFIX + 'using cached ID', cacheIdObj); return cacheIdObj; - } + }, + eids: { + 'id5id': { + getValue: function(data) { + return data.uid + }, + source: 'id5-sync.com', + atype: 1, + getUidExt: function(data) { + if (data.ext) { + return data.ext; + } + } + }, + }, }; class IdFetchFlow { diff --git a/modules/identityLinkIdSystem.js b/modules/identityLinkIdSystem.js index ab10288f38f..e8cef34f41e 100644 --- a/modules/identityLinkIdSystem.js +++ b/modules/identityLinkIdSystem.js @@ -79,6 +79,12 @@ export const identityLinkSubmodule = { }; return { callback: resp }; + }, + eids: { + 'idl_env': { + source: 'liveramp.com', + atype: 3 + }, } }; // return envelope from third party endpoint diff --git a/modules/idxIdSystem.js b/modules/idxIdSystem.js index 3c00bbde34c..bf807f199a6 100644 --- a/modules/idxIdSystem.js +++ b/modules/idxIdSystem.js @@ -57,6 +57,12 @@ export const idxIdSubmodule = { } } return undefined; + }, + eids: { + 'idx': { + source: 'idx.lat', + atype: 1 + }, } }; submodule('userId', idxIdSubmodule); diff --git a/modules/imuIdSystem.js b/modules/imuIdSystem.js index 898f32b27b0..38870c9403b 100644 --- a/modules/imuIdSystem.js +++ b/modules/imuIdSystem.js @@ -160,6 +160,16 @@ export const imuIdSubmodule = { imppid: localData.ppid } }; + }, + eids: { + 'imppid': { + source: 'ppid.intimatemerger.com', + atype: 1 + }, + 'imuid': { + source: 'intimatemerger.com', + atype: 1 + }, } }; diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index 36454394841..5164080c317 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -193,6 +193,12 @@ export const intentIqIdSubmodule = { } }; return { callback: resp }; + }, + eids: { + 'intentIqId': { + source: 'intentiq.com', + atype: 1 + }, } }; diff --git a/modules/justIdSystem.js b/modules/justIdSystem.js index 15b1c90da4e..26e9275bbab 100644 --- a/modules/justIdSystem.js +++ b/modules/justIdSystem.js @@ -91,6 +91,12 @@ export const justIdSubmodule = { } } }; + }, + eids: { + 'justId': { + source: 'justtag.com', + atype: 1 + }, } }; diff --git a/modules/kinessoIdSystem.js b/modules/kinessoIdSystem.js index 632f3a669aa..c13ed3976d3 100644 --- a/modules/kinessoIdSystem.js +++ b/modules/kinessoIdSystem.js @@ -233,8 +233,13 @@ export const kinessoIdSubmodule = { const payloadString = JSON.stringify(kinessoIdPayload); ajax(kinessoSyncUrl(accountId, consentData), syncId(knnsoId), payloadString, {method: 'POST', withCredentials: true}); return {'id': knnsoId}; - } - + }, + eids: { + 'kpuid': { + source: 'kpuid.com', + atype: 3 + }, + }, }; // Register submodule for userId diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index 1c93427e3a9..33a702aa81f 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -242,6 +242,59 @@ export const liveIntentIdSubmodule = { } return { callback: result }; + }, + eids: { + 'lipb': { + getValue: function(data) { + return data.lipbid; + }, + source: 'liveintent.com', + atype: 3, + getEidExt: function(data) { + if (Array.isArray(data.segments) && data.segments.length) { + return { + segments: data.segments + }; + } + } + }, + 'bidswitch': { + source: 'bidswitch.net', + atype: 3, + getValue: function(data) { + return data.id; + }, + getUidExt: function(data) { + if (data.ext) { + return data.ext; + } + } + }, + 'medianet': { + source: 'media.net', + atype: 3, + getValue: function(data) { + return data.id; + }, + getUidExt: function(data) { + if (data.ext) { + return data.ext; + } + } + }, + 'magnite': { + source: 'rubiconproject.com', + atype: 3, + getValue: function(data) { + return data.id; + }, + getUidExt: function(data) { + if (data.ext) { + return data.ext; + } + } + }, + } }; diff --git a/modules/lotamePanoramaIdSystem.js b/modules/lotamePanoramaIdSystem.js index 02b01b8bd9d..808a67492b0 100644 --- a/modules/lotamePanoramaIdSystem.js +++ b/modules/lotamePanoramaIdSystem.js @@ -368,6 +368,12 @@ export const lotamePanoramaIdSubmodule = { return { callback: resolveIdFunction }; }, + eids: { + lotamePanoramaId: { + source: 'crwdcntrl.net', + atype: 1, + }, + }, }; submodule('userId', lotamePanoramaIdSubmodule); diff --git a/modules/merkleIdSystem.js b/modules/merkleIdSystem.js index c522d588970..fc77c7cc97d 100644 --- a/modules/merkleIdSystem.js +++ b/modules/merkleIdSystem.js @@ -196,6 +196,30 @@ export const merkleIdSubmodule = { logInfo('User ID - merkleId not refreshed'); return {id: storedId}; + }, + eids: { + 'merkleId': { + atype: 3, + getSource: function(data) { + if (data?.ext?.ssp) { + return `${data.ext.ssp}.merkleinc.com` + } + return 'merkleinc.com' + }, + getValue: function(data) { + return data.id; + }, + getUidExt: function(data) { + if (data.keyID) { + return { + keyID: data.keyID + } + } + if (data.ext) { + return data.ext; + } + } + }, } }; diff --git a/modules/mwOpenLinkIdSystem.js b/modules/mwOpenLinkIdSystem.js index 9b1035cbf18..ff23547224b 100644 --- a/modules/mwOpenLinkIdSystem.js +++ b/modules/mwOpenLinkIdSystem.js @@ -137,6 +137,12 @@ export const mwOpenLinkIdSubModule = { const submoduleConfigParams = (submoduleConfig && submoduleConfig.params) || {}; if (!isValidConfig(submoduleConfigParams)) return undefined; return setID(submoduleConfigParams); + }, + eids: { + 'mwOpenLinkId': { + source: 'mediawallahscript.com', + atype: 1 + }, } }; diff --git a/modules/naveggIdSystem.js b/modules/naveggIdSystem.js index 878ae7fadb2..8a472259873 100644 --- a/modules/naveggIdSystem.js +++ b/modules/naveggIdSystem.js @@ -107,6 +107,12 @@ export const naveggIdSubmodule = { } } return undefined; + }, + eids: { + 'naveggId': { + source: 'navegg.com', + atype: 1 + }, } }; submodule('userId', naveggIdSubmodule); diff --git a/modules/netIdSystem.js b/modules/netIdSystem.js index 90c8735c993..6f1ffe8b0e7 100644 --- a/modules/netIdSystem.js +++ b/modules/netIdSystem.js @@ -34,6 +34,12 @@ export const netIdSubmodule = { getId(config) { /* currently not possible */ return {}; + }, + eids: { + 'netId': { + source: 'netid.de', + atype: 1 + }, } }; diff --git a/modules/novatiqIdSystem.js b/modules/novatiqIdSystem.js index 7a801a945ae..7eced81d35e 100644 --- a/modules/novatiqIdSystem.js +++ b/modules/novatiqIdSystem.js @@ -259,6 +259,18 @@ export const novatiqIdSubmodule = { srcId = configParams.sourceid; } return srcId; + }, + eids: { + 'novatiq': { + getValue: function(data) { + if (data.snowflake.id === undefined) { + return data.snowflake; + } + + return data.snowflake.id; + }, + source: 'novatiq.com', + }, } }; submodule('userId', novatiqIdSubmodule); diff --git a/modules/oneKeyIdSystem.js b/modules/oneKeyIdSystem.js index 8d8d594b533..699a7a6ab95 100644 --- a/modules/oneKeyIdSystem.js +++ b/modules/oneKeyIdSystem.js @@ -72,6 +72,32 @@ export const oneKeyIdSubmodule = { return { callback: getIdsAndPreferences }; + }, + eids: { + 'oneKeyData': { + getValue: function(data) { + if (data && Array.isArray(data.identifiers) && data.identifiers[0]) { + return data.identifiers[0].value; + } + }, + source: 'paf', + atype: 1, + getEidExt: function(data) { + if (data && data.preferences) { + return {preferences: data.preferences}; + } + }, + getUidExt: function(data) { + if (data && Array.isArray(data.identifiers) && data.identifiers[0]) { + const id = data.identifiers[0]; + return { + version: id.version, + type: id.type, + source: id.source + }; + } + } + } } }; diff --git a/modules/pairIdSystem.js b/modules/pairIdSystem.js index f90e25fdd0f..489b97d02e3 100644 --- a/modules/pairIdSystem.js +++ b/modules/pairIdSystem.js @@ -78,6 +78,12 @@ export const pairIdSubmodule = { return undefined; } return {'id': ids}; + }, + eids: { + 'pairId': { + source: 'google.com', + atype: 571187 + }, } }; diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js index 01ffec3c249..3e3488f72f3 100644 --- a/modules/parrableIdSystem.js +++ b/modules/parrableIdSystem.js @@ -7,7 +7,17 @@ // ci trigger: 1 -import {contains, deepClone, inIframe, isEmpty, isPlainObject, logError, logWarn, timestamp} from '../src/utils.js'; +import { + contains, + deepClone, + inIframe, + isEmpty, + isPlainObject, + logError, + logWarn, + pick, + timestamp +} from '../src/utils.js'; import {find} from '../src/polyfill.js'; import {ajax} from '../src/ajax.js'; import {submodule} from '../src/hook.js'; @@ -368,7 +378,33 @@ export const parrableIdSubmodule = { getId(config, gdprConsentData, currentStoredId) { const configParams = (config && config.params) || {}; return fetchId(configParams, gdprConsentData); - } + }, + eids: { + 'parrableId': { + source: 'parrable.com', + atype: 1, + getValue: function(parrableId) { + if (parrableId.eid) { + return parrableId.eid; + } + if (parrableId.ccpaOptout) { + // If the EID was suppressed due to a non consenting ccpa optout then + // we still wish to provide this as a reason to the adapters + return ''; + } + return null; + }, + getUidExt: function(parrableId) { + const extendedData = pick(parrableId, [ + 'ibaOptout', + 'ccpaOptout' + ]); + if (Object.keys(extendedData).length) { + return extendedData; + } + } + }, + }, }; submodule('userId', parrableIdSubmodule); diff --git a/modules/publinkIdSystem.js b/modules/publinkIdSystem.js index 6a5504b5ba0..5b20dbb620a 100644 --- a/modules/publinkIdSystem.js +++ b/modules/publinkIdSystem.js @@ -140,6 +140,12 @@ export const publinkIdSubmodule = { if (!storedId) { return {callback: makeCallback(config, consentData)}; } - } + }, + eids: { + 'publinkId': { + source: 'epsilon.com', + atype: 3 + }, + }, }; submodule('userId', publinkIdSubmodule); diff --git a/modules/quantcastIdSystem.js b/modules/quantcastIdSystem.js index 6a07082b61c..2faf638fc0b 100644 --- a/modules/quantcastIdSystem.js +++ b/modules/quantcastIdSystem.js @@ -214,6 +214,12 @@ export const quantcastIdSubmodule = { } return { id: fpa ? { quantcastId: fpa } : undefined }; + }, + eids: { + 'quantcastId': { + source: 'quantcast.com', + atype: 1 + }, } }; diff --git a/modules/sharedIdSystem.js b/modules/sharedIdSystem.js index 26f6f75b7a0..9046d6a633d 100644 --- a/modules/sharedIdSystem.js +++ b/modules/sharedIdSystem.js @@ -174,6 +174,12 @@ export const sharedIdSystemSubmodule = { }, domainOverride: domainOverrideToRootDomain(storage, 'sharedId'), + eids: { + 'pubcid': { + source: 'pubcid.org', + atype: 1 + }, + } }; submodule('userId', sharedIdSystemSubmodule); diff --git a/modules/tapadIdSystem.js b/modules/tapadIdSystem.js index 149ba22eb92..2c24f062791 100644 --- a/modules/tapadIdSystem.js +++ b/modules/tapadIdSystem.js @@ -56,6 +56,12 @@ export const tapadIdSubmodule = { ); } } + }, + eids: { + 'tapadId': { + source: 'tapad.com', + atype: 1 + }, } } submodule('userId', tapadIdSubmodule); diff --git a/modules/tncIdSystem.js b/modules/tncIdSystem.js index 24e3c79d4df..59254a9430f 100644 --- a/modules/tncIdSystem.js +++ b/modules/tncIdSystem.js @@ -57,6 +57,12 @@ export const tncidSubModule = { return { callback: function (cb) { return tncCallback(cb); } } + }, + eids: { + 'tncid': { + source: 'thenewco.it', + atype: 3 + }, } } diff --git a/modules/uid2IdSystem.js b/modules/uid2IdSystem.js index f8178364e58..a36b24e3ae3 100644 --- a/modules/uid2IdSystem.js +++ b/modules/uid2IdSystem.js @@ -83,6 +83,20 @@ export const uid2IdSubmodule = { _logInfo(`UID2 getId returned`, result); return result; }, + eids: { + 'uid2': { + source: 'uidapi.com', + atype: 3, + getValue: function(data) { + return data.id; + }, + getUidExt: function(data) { + if (data.ext) { + return data.ext; + } + } + }, + }, }; function decodeImpl(value) { diff --git a/modules/unifiedIdSystem.js b/modules/unifiedIdSystem.js index 8ec5fcd3f90..5576c40d960 100644 --- a/modules/unifiedIdSystem.js +++ b/modules/unifiedIdSystem.js @@ -67,6 +67,17 @@ export const unifiedIdSubmodule = { ajax(url, callbacks, undefined, {method: 'GET', withCredentials: true}); }; return {callback: resp}; + }, + eids: { + 'tdid': { + source: 'adserver.org', + atype: 1, + getUidExt: function() { + return { + rtiPartner: 'TDID' + }; + } + }, } }; diff --git a/modules/userId/eids.js b/modules/userId/eids.js index cf2a0408246..dc362b41136 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -1,450 +1,10 @@ -import { pick, isFn, isStr, isPlainObject, deepAccess } from '../../src/utils.js'; +import {deepAccess, isFn, isPlainObject, isStr} from '../../src/utils.js'; -// Each user-id sub-module is expected to mention respective config here -export const USER_IDS_CONFIG = { - - // key-name : {config} - - // GrowthCode - 'growthCodeId': { - getValue: function(data) { - return data.gc_id - }, - source: 'growthcode.io', - atype: 1, - getUidExt: function(data) { - const extendedData = pick(data, [ - 'h1', - 'h2', - 'h3', - ]); - if (Object.keys(extendedData).length) { - return extendedData; - } - } - }, - - // utiq - 'utiq': { - source: 'utiq.com', - atype: 1, - getValue: function (data) { - return data; - }, - }, - - // intentIqId - 'intentIqId': { - source: 'intentiq.com', - atype: 1 - }, - - // naveggId - 'naveggId': { - source: 'navegg.com', - atype: 1 - }, - - // pairId - 'pairId': { - source: 'google.com', - atype: 571187 - }, - - // justId - 'justId': { - source: 'justtag.com', - atype: 1 - }, - - // pubCommonId - 'pubcid': { - source: 'pubcid.org', - atype: 1 - }, - - // unifiedId - 'tdid': { - source: 'adserver.org', - atype: 1, - getUidExt: function() { - return { - rtiPartner: 'TDID' - }; - } - }, - - // id5Id - 'id5id': { - getValue: function(data) { - return data.uid - }, - source: 'id5-sync.com', - atype: 1, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - - // ftrack - 'ftrackId': { - source: 'flashtalking.com', - atype: 1, - getValue: function(data) { - let value = ''; - if (data && data.ext && data.ext.DeviceID) { - value = data.ext.DeviceID; - } - return value; - }, - getUidExt: function(data) { - return data && data.ext; - } - }, - - // parrableId - 'parrableId': { - source: 'parrable.com', - atype: 1, - getValue: function(parrableId) { - if (parrableId.eid) { - return parrableId.eid; - } - if (parrableId.ccpaOptout) { - // If the EID was suppressed due to a non consenting ccpa optout then - // we still wish to provide this as a reason to the adapters - return ''; - } - return null; - }, - getUidExt: function(parrableId) { - const extendedData = pick(parrableId, [ - 'ibaOptout', - 'ccpaOptout' - ]); - if (Object.keys(extendedData).length) { - return extendedData; - } - } - }, - - // identityLink - 'idl_env': { - source: 'liveramp.com', - atype: 3 - }, - - // liveIntentId - 'lipb': { - getValue: function(data) { - return data.lipbid; - }, - source: 'liveintent.com', - atype: 3, - getEidExt: function(data) { - if (Array.isArray(data.segments) && data.segments.length) { - return { - segments: data.segments - }; - } - } - }, - - // bidswitchId - 'bidswitch': { - source: 'bidswitch.net', - atype: 3, - getValue: function(data) { - return data.id; - }, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - - // medianetId - 'medianet': { - source: 'media.net', - atype: 3, - getValue: function(data) { - return data.id; - }, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - - // magnite - 'magnite': { - source: 'rubiconproject.com', - atype: 3, - getValue: function(data) { - return data.id; - }, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - - // britepoolId - 'britepoolid': { - source: 'britepool.com', - atype: 3 - }, - - // dmdId - 'dmdId': { - source: 'hcn.health', - atype: 3 - }, - - // lotamePanoramaId - lotamePanoramaId: { - source: 'crwdcntrl.net', - atype: 1, - }, - - // criteo - 'criteoId': { - source: 'criteo.com', - atype: 1 - }, - - // merkleId - 'merkleId': { - atype: 3, - getSource: function(data) { - if (data?.ext?.ssp) { - return `${data.ext.ssp}.merkleinc.com` - } - return 'merkleinc.com' - }, - getValue: function(data) { - return data.id; - }, - getUidExt: function(data) { - if (data.keyID) { - return { - keyID: data.keyID - } - } - if (data.ext) { - return data.ext; - } - } - }, - - // NetId - 'netId': { - source: 'netid.de', - atype: 1 - }, - - // zeotapIdPlus - 'IDP': { - source: 'zeotap.com', - atype: 1 - }, - - // hadronId - 'hadronId': { - source: 'audigent.com', - atype: 1 - }, - - // quantcastId - 'quantcastId': { - source: 'quantcast.com', - atype: 1 - }, - - // IDx - 'idx': { - source: 'idx.lat', - atype: 1 - }, - - // Verizon Media ConnectID - 'connectid': { - source: 'verizonmedia.com', - atype: 3 - }, - - // Neustar Fabrick - 'fabrickId': { - source: 'neustar.biz', - atype: 1 - }, - - // MediaWallah OpenLink - 'mwOpenLinkId': { - source: 'mediawallahscript.com', - atype: 1 - }, - - 'tapadId': { - source: 'tapad.com', - atype: 1 - }, - - // Novatiq Snowflake - 'novatiq': { - getValue: function(data) { - if (data.snowflake.id === undefined) { - return data.snowflake; - } - - return data.snowflake.id; - }, - source: 'novatiq.com', - }, - - 'uid2': { - source: 'uidapi.com', - atype: 3, - getValue: function(data) { - return data.id; - }, - getUidExt: function(data) { - if (data.ext) { - return data.ext; - } - } - }, - - 'euid': { - source: 'euid.eu', - atype: 3, - getValue: function(data) { - return data.id; - } - }, - - 'deepintentId': { - source: 'deepintent.com', - atype: 3 - }, - - // Admixer Id - 'admixerId': { - source: 'admixer.net', - atype: 3 - }, - - // Adtelligent Id - 'adtelligentId': { - source: 'adtelligent.com', - atype: 3 - }, - - amxId: { - source: 'amxdt.net', - atype: 1, - }, - - 'publinkId': { - source: 'epsilon.com', - atype: 3 - }, - - 'kpuid': { - source: 'kpuid.com', - atype: 3 - }, - - 'imppid': { - source: 'ppid.intimatemerger.com', - atype: 1 - }, - - 'imuid': { - source: 'intimatemerger.com', - atype: 1 - }, - - // Yahoo ConnectID - 'connectId': { - source: 'yahoo.com', - atype: 3 - }, - - // Adquery ID - 'qid': { - source: 'adquery.io', - atype: 1 - }, - - // DAC ID - 'dacId': { - source: 'impact-ad.jp', - atype: 1 - }, - - // 33across ID - '33acrossId': { - source: '33across.com', - atype: 1, - getValue: function(data) { - return data.envelope; - } - }, - - // tncId - 'tncid': { - source: 'thenewco.it', - atype: 3 - }, - - // Gravito MP ID - 'gravitompId': { - source: 'gravito.net', - atype: 1 - }, - - // czechAdId - 'czechAdId': { - source: 'czechadid.cz', - atype: 1 - }, - - // OneKey Data - 'oneKeyData': { - getValue: function(data) { - if (data && Array.isArray(data.identifiers) && data.identifiers[0]) { - return data.identifiers[0].value; - } - }, - source: 'paf', - atype: 1, - getEidExt: function(data) { - if (data && data.preferences) { - return {preferences: data.preferences}; - } - }, - getUidExt: function(data) { - if (data && Array.isArray(data.identifiers) && data.identifiers[0]) { - const id = data.identifiers[0]; - return { - version: id.version, - type: id.type, - source: id.source - }; - } - } - } -}; +export const EID_CONFIG = new Map(); // this function will create an eid object for the given UserId sub-module function createEidObject(userIdData, subModuleKey) { - const conf = USER_IDS_CONFIG[subModuleKey]; + const conf = EID_CONFIG.get(subModuleKey); if (conf && userIdData) { let eid = {}; eid.source = isFn(conf['getSource']) ? conf['getSource'](userIdData) : conf['source']; @@ -510,11 +70,12 @@ export function buildEidPermissions(submodules) { submodules.filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length) .forEach(i => { Object.keys(i.idObj).forEach(key => { + const eidConf = EID_CONFIG.get(key) || {}; if (deepAccess(i, 'config.bidders') && Array.isArray(i.config.bidders) && - deepAccess(USER_IDS_CONFIG, key + '.source')) { + eidConf.source) { eidPermissions.push( { - source: USER_IDS_CONFIG[key].source, + source: eidConf.source, bidders: i.config.bidders } ); diff --git a/modules/userId/index.js b/modules/userId/index.js index 6d4ddf9aa9e..784ad7a7db1 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -133,7 +133,7 @@ import {getGlobal} from '../../src/prebidGlobal.js'; import adapterManager, {gdprDataHandler, gppDataHandler} from '../../src/adapterManager.js'; import CONSTANTS from '../../src/constants.json'; import {module, ready as hooksReady} from '../../src/hook.js'; -import {buildEidPermissions, createEidsArray, USER_IDS_CONFIG} from './eids.js'; +import {buildEidPermissions, createEidsArray, EID_CONFIG} from './eids.js'; import { getCoreStorageManager, getStorageManager, @@ -232,6 +232,7 @@ function submoduleMetrics(moduleName) { /** @param {Submodule[]} submodules */ export function setSubmoduleRegistry(submodules) { submoduleRegistry = submodules; + updateEIDConfig(submodules); } function cookieSetter(submodule, storageMgr) { @@ -465,7 +466,7 @@ function getSubmoduleId(submodules, sourceName) { const prioritisedIds = getPrioritizedCombinedSubmoduleIds(submodules); const eligibleIdName = Object.keys(prioritisedIds).find(idName => { - const config = USER_IDS_CONFIG[idName]; + const config = EID_CONFIG.get(idName); return config?.source === sourceName || (isFn(config?.getSource) && config.getSource() === sourceName); }); @@ -487,32 +488,33 @@ function getCombinedSubmoduleIdsForBidder(submodules, bidder) { return getPrioritizedCombinedSubmoduleIds(eligibleSubmodules); } +function collectByPriority(submodules, getIds, getName) { + return Object.fromEntries(Object.entries(submodules.reduce((carry, submod) => { + const ids = getIds(submod); + ids && Object.keys(ids).forEach(key => { + const maybeCurrentIdPriority = idPriority[key]?.indexOf(getName(submod)); + const currentIdPriority = isNumber(maybeCurrentIdPriority) ? maybeCurrentIdPriority : -1; + const currentIdState = {priority: currentIdPriority, value: ids[key]}; + if (carry[key]) { + const winnerIdState = currentIdState.priority > carry[key].priority ? currentIdState : carry[key]; + carry[key] = winnerIdState; + } else { + carry[key] = currentIdState; + } + }); + return carry; + }, {})).map(([k, v]) => [k, v.value])); +} + /** * @param {SubmoduleContainer[]} submodules */ function getPrioritizedCombinedSubmoduleIds(submodules) { - const combinedIdStates = submodules - .filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length) - .reduce((carry, i) => { - Object.keys(i.idObj).forEach(key => { - const maybeCurrentIdPriority = idPriority[key]?.indexOf(i.submodule.name); - const currentIdPriority = isNumber(maybeCurrentIdPriority) ? maybeCurrentIdPriority : -1; - const currentIdState = {priority: currentIdPriority, value: i.idObj[key]}; - if (carry[key]) { - const winnerIdState = currentIdState.priority > carry[key].priority ? currentIdState : carry[key]; - carry[key] = winnerIdState; - } else { - carry[key] = currentIdState; - } - }); - return carry; - }, {}); - - const result = {}; - Object.keys(combinedIdStates).forEach(key => { - result[key] = combinedIdStates[key].value - }); - return result; + return collectByPriority( + submodules.filter(i => isPlainObject(i.idObj) && Object.keys(i.idObj).length), + (submod) => submod.idObj, + (submod) => submod.submodule.name + ) } /** @@ -997,10 +999,20 @@ function canUseStorage(submodule) { return false; } +function updateEIDConfig(submodules) { + EID_CONFIG.clear(); + Object.entries(collectByPriority( + submodules, + (mod) => mod.eids, + (mod) => mod.name + )).forEach(([id, conf]) => EID_CONFIG.set(id, conf)); +} + /** * update submodules by validating against existing configs and storage types */ function updateSubmodules() { + updateEIDConfig(submoduleRegistry); const configs = getValidSubmoduleConfigs(configRegistry, submoduleRegistry); if (!configs.length) { return; diff --git a/modules/utiqSystem.js b/modules/utiqSystem.js index 441bba5660f..473dc5854a9 100644 --- a/modules/utiqSystem.js +++ b/modules/utiqSystem.js @@ -124,6 +124,15 @@ export const utiqSubmodule = { return { callback: result }; } }, + eids: { + 'utiq': { + source: 'utiq.com', + atype: 1, + getValue: function (data) { + return data; + }, + }, + } }; submodule('userId', utiqSubmodule); diff --git a/modules/verizonMediaIdSystem.js b/modules/verizonMediaIdSystem.js index 27577ad0de4..6b22538fdc7 100644 --- a/modules/verizonMediaIdSystem.js +++ b/modules/verizonMediaIdSystem.js @@ -99,6 +99,12 @@ export const verizonMediaIdSubmodule = { */ getAjaxFn() { return ajax; + }, + eids: { + 'connectid': { + source: 'verizonmedia.com', + atype: 3 + }, } }; diff --git a/modules/zeotapIdPlusIdSystem.js b/modules/zeotapIdPlusIdSystem.js index 4cb827cbdff..ab7bf7c237b 100644 --- a/modules/zeotapIdPlusIdSystem.js +++ b/modules/zeotapIdPlusIdSystem.js @@ -60,6 +60,12 @@ export const zeotapIdPlusSubmodule = { getId() { const id = readCookie() || readFromLocalStorage(); return id ? { id } : undefined; + }, + eids: { + 'IDP': { + source: 'zeotap.com', + atype: 1 + }, } }; submodule('userId', zeotapIdPlusSubmodule); diff --git a/test/spec/modules/freewheel-sspBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js index fe04a430ce6..c42c5e2528d 100644 --- a/test/spec/modules/freewheel-sspBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -135,11 +135,11 @@ describe('freewheelSSP BidAdapter Test', () => { it('should pass 3rd party IDs with the request when present', function () { const bidRequest = bidRequests[0]; - bidRequest.userIdAsEids = createEidsArray({ - tdid: 'TTD_ID_FROM_USER_ID_MODULE', - admixerId: 'admixerId_FROM_USER_ID_MODULE', - adtelligentId: 'adtelligentId_FROM_USER_ID_MODULE' - }); + bidRequest.userIdAsEids = [ + {source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]}, + {source: 'admixer.net', uids: [{id: 'admixerId_FROM_USER_ID_MODULE', atype: 3}]}, + {source: 'adtelligent.com', uids: [{id: 'adtelligentId_FROM_USER_ID_MODULE', atype: 3}]}, + ]; const request = spec.buildRequests(bidRequests); const payload = request[0].data; expect(payload._fw_prebid_3p_UID).to.deep.equal(JSON.stringify([ diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 36610db6aa6..3bfbf706d72 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -3,7 +3,6 @@ import { config } from 'src/config.js'; import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { spec, storage, ERROR_CODES, FEATURE_TOGGLES, LOCAL_STORAGE_FEATURE_TOGGLES_KEY, REQUESTED_FEATURE_TOGGLES, combineImps, bidToVideoImp, bidToNativeImp, deduplicateImpExtFields, removeSiteIDs } from '../../../modules/ixBidAdapter.js'; -import { createEidsArray } from 'modules/userId/eids.js'; import { deepAccess, deepClone } from '../../../src/utils.js'; describe('IndexexchangeAdapter', function () { @@ -763,8 +762,6 @@ describe('IndexexchangeAdapter', function () { '33acrossId': { envelope: 'v1.5fs.1000.fjdiosmclds' } }; - const DEFAULT_USERIDASEIDS_DATA = createEidsArray(DEFAULT_USERID_DATA); - const DEFAULT_USERID_PAYLOAD = [ { source: 'liveramp.com', @@ -824,6 +821,8 @@ describe('IndexexchangeAdapter', function () { } ]; + const DEFAULT_USERIDASEIDS_DATA = DEFAULT_USERID_PAYLOAD; + const DEFAULT_USERID_BID_DATA = { lotamePanoramaId: 'bd738d136bdaa841117fe9b331bb4' }; diff --git a/test/spec/modules/outbrainBidAdapter_spec.js b/test/spec/modules/outbrainBidAdapter_spec.js index ab72ff85ab0..d8690aeb6a5 100644 --- a/test/spec/modules/outbrainBidAdapter_spec.js +++ b/test/spec/modules/outbrainBidAdapter_spec.js @@ -2,8 +2,6 @@ import { expect } from 'chai'; import { spec } from 'modules/outbrainBidAdapter.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr'; -import { createEidsArray } from 'modules/userId/eids.js'; -import * as utils from 'src/utils.js'; describe('Outbrain Adapter', function () { describe('Bid request and response', function () { @@ -511,9 +509,9 @@ describe('Outbrain Adapter', function () { let bidRequest = { bidId: 'bidId', params: {}, - userIdAsEids: createEidsArray({ - idl_env: 'id-value', - }), + userIdAsEids: [ + { source: 'liveramp.com', uids: [{ id: 'id-value', atype: 3 }] } + ], ...commonBidRequest, }; diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 895c3754876..e4f06c8835f 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -2082,30 +2082,12 @@ describe('S2S Adapter', function () { } } }; - userIdBidRequest[0].bids[0].userIdAsEids = createEidsArray(userIdBidRequest[0].bids[0].userId); + userIdBidRequest[0].bids[0].userIdAsEids = [{id: 1}, {id: 2}]; adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax); let requestBid = JSON.parse(server.requests[0].requestBody); expect(typeof requestBid.user.ext.eids).is.equal('object'); - expect(Array.isArray(requestBid.user.ext.eids)).to.be.true; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'adserver.org')[0].uids[0].id).is.equal('abc123'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'criteo.com')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'criteo.com')[0].uids[0].id).is.equal('44VmRDeUE3ZGJ5MzRkRVJHU3BIUlJ6TlFPQUFU'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcid.org')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcid.org')[0].uids[0].id).is.equal('1234'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'parrable.com')[0].uids[0].id).is.equal('01.1563917337.test-eid'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].uids[0].id).is.equal('li-xyz'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments.length).is.equal(2); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments[0]).is.equal('segA'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveintent.com')[0].ext.segments[1]).is.equal('segB'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'id5-sync.com')).is.not.empty; - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'id5-sync.com')[0].uids[0].id).is.equal('11111'); - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'id5-sync.com')[0].uids[0].ext.linkType).is.equal('some-link-type'); - // LiveRamp should exist - expect(requestBid.user.ext.eids.filter(eid => eid.source === 'liveramp.com')[0].uids[0].id).is.equal('0000-1111-2222-3333'); + expect(requestBid.user.ext.eids).to.eql([{id: 1}, {id: 2}]); }); it('when config \'currency.adServerCurrency\' value is a string: ORTB has property \'cur\' value set to a single item array', function () { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 53f5e12aa6d..1ec9c36fac3 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -2160,7 +2160,7 @@ describe('PubMatic adapter', function () { sandbox.restore(); }); - describe('AdsrvrOrgId from userId module', function() { + describe('userIdAsEids', function() { let sandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); @@ -2170,13 +2170,10 @@ describe('PubMatic adapter', function () { sandbox.restore(); }); - it('Request should have AdsrvrOrgId config params', function() { + it('Request should have EIDs', function() { bidRequests[0].userId = {}; bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ + bidRequests[0].userIdAsEids = [{ 'source': 'adserver.org', 'uids': [{ 'id': 'TTD_ID_FROM_USER_ID_MODULE', @@ -2185,383 +2182,19 @@ describe('PubMatic adapter', function () { 'rtiPartner': 'TDID' } }] - }]); - }); - - it('Request should have adsrvrOrgId from UserId Module if config and userId module both have TTD ID', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID': 'TTD_ID_FROM_CONFIG', - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - } - }; - return config[key]; - }); - bidRequests[0].userId = {}; - bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'adserver.org', - 'uids': [{ - 'id': 'TTD_ID_FROM_USER_ID_MODULE', - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } - }] - }]); - }); - - it('Request should NOT have adsrvrOrgId params if userId is NOT object', function() { + }]; let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); + expect(data.user.eids).to.deep.equal(bidRequests[0].userIdAsEids); }); - it('Request should NOT have adsrvrOrgId params if userId.tdid is NOT string', function() { - bidRequests[0].userId = { - tdid: 1234 - }; + it('Request should NOT have EIDs userIdAsEids is NOT object', function() { let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal(undefined); }); }); - describe('UserIds from request', function() { - describe('pubcommon Id', function() { - it('send the pubcommon id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.pubcid = 'pub_common_user_id'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'pubcid.org', - 'uids': [{ - 'id': 'pub_common_user_id', - 'atype': 1 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.pubcid = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.pubcid = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.pubcid = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.pubcid = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('ID5 Id', function() { - it('send the id5 id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.id5id = { uid: 'id5-user-id' }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'id5-sync.com', - 'uids': [{ - 'id': 'id5-user-id', - 'atype': 1 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.id5id = { uid: 1 }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.id5id = { uid: [] }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.id5id = { uid: null }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.id5id = { uid: {} }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('Criteo Id', function() { - it('send the criteo id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.criteoId = 'criteo-user-id'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'criteo.com', - 'uids': [{ - 'id': 'criteo-user-id', - 'atype': 1 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.criteoId = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteoId = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteoId = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.criteoId = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('IdentityLink Id', function() { - it('send the identity-link id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.idl_env = 'identity-link-user-id'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'liveramp.com', - 'uids': [{ - 'id': 'identity-link-user-id', - 'atype': 3 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.idl_env = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.idl_env = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.idl_env = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.idl_env = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('LiveIntent Id', function() { - it('send the LiveIntent id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.lipb = { lipbid: 'live-intent-user-id' }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'liveintent.com', - 'uids': [{ - 'id': 'live-intent-user-id', - 'atype': 3 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.lipb = { lipbid: 1 }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.lipb.lipbid = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.lipb.lipbid = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.lipb.lipbid = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('Parrable Id', function() { - it('send the Parrable id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.parrableId = { eid: 'parrable-user-id' }; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'parrable.com', - 'uids': [{ - 'id': 'parrable-user-id', - 'atype': 1 - }] - }]); - }); - - it('do not pass if not object with eid key', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.parrableid = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.parrableid = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.parrableid = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.parrableid = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('Britepool Id', function() { - it('send the Britepool id if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.britepoolid = 'britepool-user-id'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'britepool.com', - 'uids': [{ - 'id': 'britepool-user-id', - 'atype': 3 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.britepoolid = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.britepoolid = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.britepoolid = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.britepoolid = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - - describe('NetId', function() { - it('send the NetId if it is present', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.netId = 'netid-user-id'; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'netid.de', - 'uids': [{ - 'id': 'netid-user-id', - 'atype': 1 - }] - }]); - }); - - it('do not pass if not string', function() { - bidRequests[0].userId = {}; - bidRequests[0].userId.netId = 1; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.netId = []; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.netId = null; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - bidRequests[0].userId.netId = {}; - bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); - request = spec.buildRequests(bidRequests, {}); - data = JSON.parse(request.data); - expect(data.user.eids).to.equal(undefined); - }); - }); - }); - it('should pass device.sua if present in bidderRequest fpd ortb2 object', function () { const suaObject = {'source': 2, 'platform': {'brand': 'macOS', 'version': ['12', '4', '0']}, 'browsers': [{'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']}], 'mobile': 0, 'model': '', 'bitness': '64', 'architecture': 'x86'}; let request = spec.buildRequests(multipleMediaRequests, { diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 1410e481d4e..317f03752f1 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -270,7 +270,81 @@ describe('the rubicon adapter', function () { }], criteoId: '1111', }; - bid.userIdAsEids = createEidsArray(bid.userId); + bid.userIdAsEids = [ + { + 'source': 'liveintent.com', + 'uids': [ + { + 'id': '0000-1111-2222-3333', + 'atype': 3 + } + ], + 'ext': { + 'segments': [ + 'segA', + 'segB' + ] + } + }, + { + 'source': 'liveramp.com', + 'uids': [ + { + 'id': '1111-2222-3333-4444', + 'atype': 3 + } + ] + }, + { + 'source': 'adserver.org', + 'uids': [ + { + 'id': '3000', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + } + ] + }, + { + 'source': 'pubcid.org', + 'uids': [ + { + 'id': '4000', + 'atype': 1 + } + ] + }, + { + 'source': 'example.com', + 'uids': [ + { + 'id': '333333', + 'ext': { + 'stype': 'ppuid' + } + } + ] + }, + { + 'source': 'id-partner.com', + 'uids': [ + { + 'id': '4444444' + } + ] + }, + { + 'source': 'criteo.com', + 'uids': [ + { + 'id': '1111', + 'atype': 1 + } + ] + } + ]; return bidderRequest; } @@ -1224,7 +1298,20 @@ describe('the rubicon adapter', function () { clonedBid.userId = { tdid: 'abcd-efgh-ijkl-mnop-1234' }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'adserver.org', + 'uids': [ + { + 'id': 'abcd-efgh-ijkl-mnop-1234', + 'atype': 1, + 'ext': { + 'rtiPartner': 'TDID' + } + } + ] + } + ]; let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1241,7 +1328,23 @@ describe('the rubicon adapter', function () { segments: ['segA', 'segB'] } }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'liveintent.com', + 'uids': [ + { + 'id': '0000-1111-2222-3333', + 'atype': 3 + } + ], + 'ext': { + 'segments': [ + 'segA', + 'segB' + ] + } + } + ]; let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1258,7 +1361,23 @@ describe('the rubicon adapter', function () { segments: ['segD', 'segE'] } }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'liveintent.com', + 'uids': [ + { + 'id': '1111-2222-3333-4444', + 'atype': 3 + } + ], + 'ext': { + 'segments': [ + 'segD', + 'segE' + ] + } + } + ] let [request] = spec.buildRequests([clonedBid], bidderRequest); const unescapedData = unescape(request.data); @@ -1273,7 +1392,17 @@ describe('the rubicon adapter', function () { clonedBid.userId = { idl_env: '1111-2222-3333-4444' }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'liveramp.com', + 'uids': [ + { + 'id': '1111-2222-3333-4444', + 'atype': 3 + } + ] + } + ] let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1287,7 +1416,17 @@ describe('the rubicon adapter', function () { clonedBid.userId = { pubcid: '1111' }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'pubcid.org', + 'uids': [ + { + 'id': '1111', + 'atype': 1 + } + ] + } + ] let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1301,7 +1440,17 @@ describe('the rubicon adapter', function () { clonedBid.userId = { criteoId: '1111' }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'criteo.com', + 'uids': [ + { + 'id': '1111', + 'atype': 1 + } + ] + } + ] let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1328,7 +1477,27 @@ describe('the rubicon adapter', function () { }] }] }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'example.com', + 'uids': [ + { + 'id': '11111', + 'ext': { + 'stype': 'ppuid' + } + } + ] + }, + { + 'source': 'id-partner.com', + 'uids': [ + { + 'id': '222222' + } + ] + } + ]; let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); @@ -1347,7 +1516,20 @@ describe('the rubicon adapter', function () { } } }; - clonedBid.userIdAsEids = createEidsArray(clonedBid.userId); + clonedBid.userIdAsEids = [ + { + 'source': 'id5-sync.com', + 'uids': [ + { + 'id': '11111', + 'atype': 1, + 'ext': { + 'linkType': '22222' + } + } + ] + } + ]; let [request] = spec.buildRequests([clonedBid], bidderRequest); let data = parseQuery(request.data); diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 61a877f329d..185dee2430f 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -1095,17 +1095,15 @@ describe('smaatoBidAdapterTest', () => { criteoId: '123456', tdid: '89145' }, - userIdAsEids: createEidsArray({ - criteoId: '123456', - tdid: '89145' - }) + userIdAsEids: [ + {id: 1}, {id: 2} + ] }; const reqs = spec.buildRequests([userIdBidRequest], defaultBidderRequest); const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.user.ext.eids).to.exist; - expect(req.user.ext.eids).to.have.length(2); + expect(req.user.ext.eids).to.eql(userIdBidRequest.userIdAsEids); }); }); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index b1908bdf085..acc016a903d 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -12,7 +12,7 @@ import { setSubmoduleRegistry, syncDelay, } from 'modules/userId/index.js'; -import {createEidsArray} from 'modules/userId/eids.js'; +import {createEidsArray, EID_CONFIG} from 'modules/userId/eids.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; import {getPrebidInternal} from 'src/utils.js'; @@ -86,7 +86,7 @@ describe('User ID', function () { } } - function createMockIdSubmodule(name, value, aliasName) { + function createMockIdSubmodule(name, value, aliasName, eids) { return { name, getId() { @@ -95,7 +95,8 @@ describe('User ID', function () { decode(v) { return v; }, - aliasName + aliasName, + eids } } @@ -594,6 +595,50 @@ describe('User ID', function () { }); }); + describe('EID updateConfig', () => { + function mockSubmod(name, eids) { + return createMockIdSubmodule(name, null, null, eids); + } + + it('does not choke if a submod does not provide an eids map', () => { + setSubmoduleRegistry([ + mockSubmod('mock1'), + mockSubmod('mock2') + ]); + expect(EID_CONFIG.size).to.equal(0); + }); + + it('should merge together submodules\' eid configs', () => { + setSubmoduleRegistry([ + mockSubmod('mock1', {mock1: {m: 1}}), + mockSubmod('mock2', {mock2: {m: 2}}) + ]); + expect(EID_CONFIG.get('mock1')).to.eql({m: 1}); + expect(EID_CONFIG.get('mock2')).to.eql({m: 2}); + }); + + it('should respect idPriority', () => { + config.setConfig({ + userSync: { + idPriority: { + m1: ['mod2', 'mod1'], + m2: ['mod1', 'mod2'] + }, + userIds: [ + { name: 'mod1' }, + { name: 'mod2' }, + ] + } + }); + setSubmoduleRegistry([ + mockSubmod('mod1', {m1: {i: 1}, m2: {i: 2}}), + mockSubmod('mod2', {m1: {i: 3}, m2: {i: 4}}) + ]); + expect(EID_CONFIG.get('m1')).to.eql({i: 3}); + expect(EID_CONFIG.get('m2')).to.eql({i: 2}); + }); + }) + it('should set googletag ppid correctly', function () { let adUnits = [getAdUnitMock()]; init(config); @@ -626,7 +671,25 @@ describe('User ID', function () { // some of the ids are padded to have length >= 32 characters createMockIdSubmodule('mockId1Module', {id: {uid2: {id: 'uid2_value_7ac66c0f148de9519b8bd264312c4d64'}}}), createMockIdSubmodule('mockId2Module', {id: {pubcid: 'pubcid_value_7ac66c0f148de9519b8bd264312c4d64', lipb: {lipbid: 'lipbid_value_from_mockId2Module_7ac66c0f148de9519b8bd264312c4d64'}}}), - createMockIdSubmodule('mockId3Module', {id: {uid2: {id: 'uid2_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64'}, pubcid: 'pubcid_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64', lipb: {lipbid: 'lipbid_value_7ac66c0f148de9519b8bd264312c4d64'}, merkleId: {id: 'merkleId_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64'}}}), + createMockIdSubmodule('mockId3Module', { + id: { + uid2: { + id: 'uid2_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64' + }, + pubcid: 'pubcid_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64', + lipb: { + lipbid: 'lipbid_value_7ac66c0f148de9519b8bd264312c4d64' + }, + merkleId: { + id: 'merkleId_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64' + } + } + }, null, { + uid2: { + source: 'uidapi.com', + getValue(data) { return data.id } + } + }), createMockIdSubmodule('mockId4Module', {id: {merkleId: {id: 'merkleId_value_7ac66c0f148de9519b8bd264312c4d64'}}}) ]); @@ -717,6 +780,11 @@ describe('User ID', function () { }, decode(d) { return d + }, + eids: { + pubcid: { + source: 'pubcid.org', + } } }]); config.setConfig({ @@ -808,7 +876,25 @@ describe('User ID', function () { // some of the ids are padded to have length >= 32 characters createMockIdSubmodule('mockId1Module', {id: {uid2: {id: 'uid2_value_7ac66c0f148de9519b8bd264312c4d64'}}}), createMockIdSubmodule('mockId2Module', {id: {pubcid: 'pubcid_value_7ac66c0f148de9519b8bd264312c4d64', lipb: {lipbid: 'lipbid_value_from_mockId2Module_7ac66c0f148de9519b8bd264312c4d64'}}}), - createMockIdSubmodule('mockId3Module', {id: {uid2: {id: 'uid2_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64'}, pubcid: 'pubcid_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64', lipb: {lipbid: 'lipbid_value_7ac66c0f148de9519b8bd264312c4d64'}, merkleId: {id: 'merkleId_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64'}}}), + createMockIdSubmodule('mockId3Module', { + id: { + uid2: { + id: 'uid2_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64' + }, + pubcid: 'pubcid_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64', + lipb: { + lipbid: 'lipbid_value_7ac66c0f148de9519b8bd264312c4d64' + }, + merkleId: { + id: 'merkleId_value_from_mockId3Module_7ac66c0f148de9519b8bd264312c4d64' + } + } + }, null, { + uid2: { + source: 'uidapi.com', + getValue(data) { return data.id } + } + }), createMockIdSubmodule('mockId4Module', {id: {merkleId: {id: 'merkleId_value_7ac66c0f148de9519b8bd264312c4d64'}}}) ]); @@ -3259,8 +3345,31 @@ describe('User ID', function () { setSubmoduleRegistry([ createMockIdSubmodule('mockId1Module', {id: {uid2: {id: 'uid2_value'}}}), createMockIdSubmodule('mockId2Module', {id: {pubcid: 'pubcid_value', lipb: {lipbid: 'lipbid_value_from_mockId2Module'}}}), - createMockIdSubmodule('mockId3Module', {id: {uid2: {id: 'uid2_value_from_mockId3Module'}, pubcid: 'pubcid_value_from_mockId3Module', lipb: {lipbid: 'lipbid_value'}, merkleId: {id: 'merkleId_value_from_mockId3Module'}}}), - createMockIdSubmodule('mockId4Module', {id: {merkleId: {id: 'merkleId_value'}}}) + createMockIdSubmodule('mockId3Module', {id: {uid2: {id: 'uid2_value_from_mockId3Module'}, pubcid: 'pubcid_value_from_mockId3Module', lipb: {lipbid: 'lipbid_value'}, merkleId: {id: 'merkleId_value_from_mockId3Module'}}}, null, { + uid2: { + source: 'uidapi.com', + getValue(data) { + return data.id + } + }, + pubcid: { + source: 'pubcid.org', + }, + lipb: { + source: 'liveintent.com', + getValue(data) { + return data.lipbid + } + } + }), + createMockIdSubmodule('mockId4Module', {id: {merkleId: {id: 'merkleId_value'}}}, null, { + merkleId: { + source: 'merkleinc.com', + getValue(data) { + return data.id + } + } + }) ]); config.setConfig({ userSync: { diff --git a/test/spec/modules/vrtcalBidAdapter_spec.js b/test/spec/modules/vrtcalBidAdapter_spec.js index 764db3fa4f0..609d5d0a5f7 100644 --- a/test/spec/modules/vrtcalBidAdapter_spec.js +++ b/test/spec/modules/vrtcalBidAdapter_spec.js @@ -79,9 +79,12 @@ describe('vrtcalBidAdapter', function () { }); it('pass 3rd party IDs with the request when present', function () { - bidRequests[0].userIdAsEids = createEidsArray({ - tdid: 'TTD_ID_FROM_USER_ID_MODULE' - }); + bidRequests[0].userIdAsEids = [ + { + source: 'adserver.org', + uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}] + } + ]; request = spec.buildRequests(bidRequests); expect(request[0].data).to.include(JSON.stringify({ext: {consent: 'gdpr-consent-string', eids: [{source: 'adserver.org', uids: [{id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: {rtiPartner: 'TDID'}}]}]}})); diff --git a/test/spec/modules/xeBidAdapter_spec.js b/test/spec/modules/xeBidAdapter_spec.js index 38b334c32c5..914b0cacd71 100644 --- a/test/spec/modules/xeBidAdapter_spec.js +++ b/test/spec/modules/xeBidAdapter_spec.js @@ -41,414 +41,412 @@ defaultRequestVideo.mediaTypes = { skipppable: true } }; +describe('xeBidAdapter', () => { + describe('isBidRequestValid', function () { + it('should return false when request params is missing', function () { + const invalidRequest = deepClone(defaultRequest); + delete invalidRequest.params; + expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); + }); -describe('isBidRequestValid', function () { - it('should return false when request params is missing', function () { - const invalidRequest = deepClone(defaultRequest); - delete invalidRequest.params; - expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); - }); - - it('should return false when required env param is missing', function () { - const invalidRequest = deepClone(defaultRequest); - delete invalidRequest.params.env; - expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); - }); + it('should return false when required env param is missing', function () { + const invalidRequest = deepClone(defaultRequest); + delete invalidRequest.params.env; + expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); + }); - it('should return false when required placement param is missing', function () { - const invalidRequest = deepClone(defaultRequest); - delete invalidRequest.params.placement; - expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); - }); + it('should return false when required placement param is missing', function () { + const invalidRequest = deepClone(defaultRequest); + delete invalidRequest.params.placement; + expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); + }); - it('should return false when video.playerSize is missing', function () { - const invalidRequest = deepClone(defaultRequestVideo); - delete invalidRequest.mediaTypes.video.playerSize; - expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); - }); + it('should return false when video.playerSize is missing', function () { + const invalidRequest = deepClone(defaultRequestVideo); + delete invalidRequest.mediaTypes.video.playerSize; + expect(spec.isBidRequestValid(invalidRequest)).to.equal(false); + }); - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(defaultRequest)).to.equal(true); + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(defaultRequest)).to.equal(true); + }); }); -}); -describe('buildRequests', function () { - beforeEach(function () { - config.resetConfig(); - }); + describe('buildRequests', function () { + beforeEach(function () { + config.resetConfig(); + }); - it('should send request with correct structure', function () { - const request = spec.buildRequests([defaultRequest], {}); - expect(request.method).to.equal('POST'); - expect(request.url).to.equal(ENDPOINT); - expect(request.options).to.have.property('contentType').and.to.equal('application/json'); - expect(request).to.have.property('data'); - }); + it('should send request with correct structure', function () { + const request = spec.buildRequests([defaultRequest], {}); + expect(request.method).to.equal('POST'); + expect(request.url).to.equal(ENDPOINT); + expect(request.options).to.have.property('contentType').and.to.equal('application/json'); + expect(request).to.have.property('data'); + }); - it('should build basic request structure', function () { - const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0]; - expect(request).to.have.property('bidId').and.to.equal(defaultRequest.bidId); - expect(request).to.have.property('auctionId').and.to.equal(defaultRequest.auctionId); - expect(request).to.have.property('transactionId').and.to.equal(defaultRequest.ortb2Imp.ext.tid); - expect(request).to.have.property('tz').and.to.equal(new Date().getTimezoneOffset()); - expect(request).to.have.property('bc').and.to.equal(1); - expect(request).to.have.property('floor').and.to.equal(null); - expect(request).to.have.property('banner').and.to.deep.equal({ sizes: [[300, 250], [300, 200]] }); - expect(request).to.have.property('gdprApplies').and.to.equal(0); - expect(request).to.have.property('consentString').and.to.equal(''); - expect(request).to.have.property('userEids').and.to.deep.equal([]); - expect(request).to.have.property('usPrivacy').and.to.equal(''); - expect(request).to.have.property('coppa').and.to.equal(0); - expect(request).to.have.property('sizes').and.to.deep.equal(['300x250', '300x200']); - expect(request).to.have.property('ext').and.to.deep.equal({}); - expect(request).to.have.property('env').and.to.deep.equal({ - env: 'xe', - placement: 'test-banner' - }); - expect(request).to.have.property('device').and.to.deep.equal({ - ua: navigator.userAgent, - lang: navigator.language + it('should build basic request structure', function () { + const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0]; + expect(request).to.have.property('bidId').and.to.equal(defaultRequest.bidId); + expect(request).to.have.property('auctionId').and.to.equal(defaultRequest.auctionId); + expect(request).to.have.property('transactionId').and.to.equal(defaultRequest.ortb2Imp.ext.tid); + expect(request).to.have.property('tz').and.to.equal(new Date().getTimezoneOffset()); + expect(request).to.have.property('bc').and.to.equal(1); + expect(request).to.have.property('floor').and.to.equal(null); + expect(request).to.have.property('banner').and.to.deep.equal({ sizes: [[300, 250], [300, 200]] }); + expect(request).to.have.property('gdprApplies').and.to.equal(0); + expect(request).to.have.property('consentString').and.to.equal(''); + expect(request).to.have.property('userEids').and.to.deep.equal([]); + expect(request).to.have.property('usPrivacy').and.to.equal(''); + expect(request).to.have.property('coppa').and.to.equal(0); + expect(request).to.have.property('sizes').and.to.deep.equal(['300x250', '300x200']); + expect(request).to.have.property('ext').and.to.deep.equal({}); + expect(request).to.have.property('env').and.to.deep.equal({ + env: 'xe', + placement: 'test-banner' + }); + expect(request).to.have.property('device').and.to.deep.equal({ + ua: navigator.userAgent, + lang: navigator.language + }); }); - }); - it('should build request with schain', function () { - const schainRequest = deepClone(defaultRequest); - schainRequest.schain = { - validation: 'strict', - config: { - ver: '1.0' - } - }; - const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; - expect(request).to.have.property('schain').and.to.deep.equal({ - validation: 'strict', - config: { - ver: '1.0' - } + it('should build request with schain', function () { + const schainRequest = deepClone(defaultRequest); + schainRequest.schain = { + validation: 'strict', + config: { + ver: '1.0' + } + }; + const request = JSON.parse(spec.buildRequests([schainRequest], {}).data)[0]; + expect(request).to.have.property('schain').and.to.deep.equal({ + validation: 'strict', + config: { + ver: '1.0' + } + }); }); - }); - it('should build request with location', function () { - const bidderRequest = { - refererInfo: { - page: 'page', - location: 'location', - domain: 'domain', - ref: 'ref', - isAmp: false - } - }; - const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; - expect(request).to.have.property('location'); - const location = request.location; - expect(location).to.have.property('page').and.to.equal('page'); - expect(location).to.have.property('location').and.to.equal('location'); - expect(location).to.have.property('domain').and.to.equal('domain'); - expect(location).to.have.property('ref').and.to.equal('ref'); - expect(location).to.have.property('isAmp').and.to.equal(false); - }); + it('should build request with location', function () { + const bidderRequest = { + refererInfo: { + page: 'page', + location: 'location', + domain: 'domain', + ref: 'ref', + isAmp: false + } + }; + const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; + expect(request).to.have.property('location'); + const location = request.location; + expect(location).to.have.property('page').and.to.equal('page'); + expect(location).to.have.property('location').and.to.equal('location'); + expect(location).to.have.property('domain').and.to.equal('domain'); + expect(location).to.have.property('ref').and.to.equal('ref'); + expect(location).to.have.property('isAmp').and.to.equal(false); + }); - it('should build request with ortb2 info', function () { - const ortb2Request = deepClone(defaultRequest); - ortb2Request.ortb2 = { - site: { - name: 'name' - } - }; - const request = JSON.parse(spec.buildRequests([ortb2Request], {}).data)[0]; - expect(request).to.have.property('ortb2').and.to.deep.equal({ - site: { - name: 'name' - } + it('should build request with ortb2 info', function () { + const ortb2Request = deepClone(defaultRequest); + ortb2Request.ortb2 = { + site: { + name: 'name' + } + }; + const request = JSON.parse(spec.buildRequests([ortb2Request], {}).data)[0]; + expect(request).to.have.property('ortb2').and.to.deep.equal({ + site: { + name: 'name' + } + }); }); - }); - it('should build request with ortb2Imp info', function () { - const ortb2ImpRequest = deepClone(defaultRequest); - ortb2ImpRequest.ortb2Imp = { - ext: { - data: { - pbadslot: 'home1', - adUnitSpecificAttribute: '1' + it('should build request with ortb2Imp info', function () { + const ortb2ImpRequest = deepClone(defaultRequest); + ortb2ImpRequest.ortb2Imp = { + ext: { + data: { + pbadslot: 'home1', + adUnitSpecificAttribute: '1' + } } - } - }; - const request = JSON.parse(spec.buildRequests([ortb2ImpRequest], {}).data)[0]; - expect(request).to.have.property('ortb2Imp').and.to.deep.equal({ - ext: { - data: { - pbadslot: 'home1', - adUnitSpecificAttribute: '1' + }; + const request = JSON.parse(spec.buildRequests([ortb2ImpRequest], {}).data)[0]; + expect(request).to.have.property('ortb2Imp').and.to.deep.equal({ + ext: { + data: { + pbadslot: 'home1', + adUnitSpecificAttribute: '1' + } } - } + }); }); - }); - it('should build request with valid bidfloor', function () { - const bfRequest = deepClone(defaultRequest); - bfRequest.getFloor = () => ({ floor: 5, currency: 'USD' }); - const request = JSON.parse(spec.buildRequests([bfRequest], {}).data)[0]; - expect(request).to.have.property('floor').and.to.equal(5); - }); + it('should build request with valid bidfloor', function () { + const bfRequest = deepClone(defaultRequest); + bfRequest.getFloor = () => ({ floor: 5, currency: 'USD' }); + const request = JSON.parse(spec.buildRequests([bfRequest], {}).data)[0]; + expect(request).to.have.property('floor').and.to.equal(5); + }); - it('should build request with gdpr consent data if applies', function () { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'qwerty' - } - }; - const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; - expect(request).to.have.property('gdprApplies').and.equals(1); - expect(request).to.have.property('consentString').and.equals('qwerty'); - }); + it('should build request with gdpr consent data if applies', function () { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'qwerty' + } + }; + const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; + expect(request).to.have.property('gdprApplies').and.equals(1); + expect(request).to.have.property('consentString').and.equals('qwerty'); + }); - it('should build request with usp consent data if applies', function () { - const bidderRequest = { - uspConsent: '1YA-' - }; - const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; - expect(request).to.have.property('usPrivacy').and.equals('1YA-'); - }); + it('should build request with usp consent data if applies', function () { + const bidderRequest = { + uspConsent: '1YA-' + }; + const request = JSON.parse(spec.buildRequests([defaultRequest], bidderRequest).data)[0]; + expect(request).to.have.property('usPrivacy').and.equals('1YA-'); + }); - it('should build request with coppa 1', function () { - config.setConfig({ - coppa: true + it('should build request with coppa 1', function () { + config.setConfig({ + coppa: true + }); + const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0]; + expect(request).to.have.property('coppa').and.equals(1); }); - const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0]; - expect(request).to.have.property('coppa').and.equals(1); - }); - it('should build request with extended ids', function () { - const idRequest = deepClone(defaultRequest); - idRequest.userIdAsEids = createEidsArray({ - tdid: 'TTD_ID_FROM_USER_ID_MODULE', - pubcid: 'pubCommonId_FROM_USER_ID_MODULE' - }); - const request = JSON.parse(spec.buildRequests([idRequest], {}).data)[0]; - expect(request).to.have.property('userEids').and.deep.equal([ - { source: 'adserver.org', uids: [ { id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: { rtiPartner: 'TDID' } } ] }, - { source: 'pubcid.org', uids: [ { id: 'pubCommonId_FROM_USER_ID_MODULE', atype: 1 } ] } - ]); - }); + it('should build request with extended ids', function () { + const idRequest = deepClone(defaultRequest); + idRequest.userIdAsEids = [ + { source: 'adserver.org', uids: [ { id: 'TTD_ID_FROM_USER_ID_MODULE', atype: 1, ext: { rtiPartner: 'TDID' } } ] }, + { source: 'pubcid.org', uids: [ { id: 'pubCommonId_FROM_USER_ID_MODULE', atype: 1 } ] } + ]; + const request = JSON.parse(spec.buildRequests([idRequest], {}).data)[0]; + expect(request).to.have.property('userEids').and.deep.equal(idRequest.userIdAsEids); + }); - it('should build request with video', function () { - const request = JSON.parse(spec.buildRequests([defaultRequestVideo], {}).data)[0]; - expect(request).to.have.property('video').and.to.deep.equal({ - playerSize: [640, 480], - context: 'instream', - skipppable: true + it('should build request with video', function () { + const request = JSON.parse(spec.buildRequests([defaultRequestVideo], {}).data)[0]; + expect(request).to.have.property('video').and.to.deep.equal({ + playerSize: [640, 480], + context: 'instream', + skipppable: true + }); + expect(request).to.have.property('sizes').and.to.deep.equal(['640x480']); }); - expect(request).to.have.property('sizes').and.to.deep.equal(['640x480']); - }); -}); - -describe('interpretResponse', function () { - it('should return empty bids', function () { - const serverResponse = { - body: { - data: null - } - }; - - const invalidResponse = spec.interpretResponse(serverResponse, {}); - expect(invalidResponse).to.be.an('array').that.is.empty; }); - it('should interpret valid response', function () { - const serverResponse = { - body: { - data: [{ - requestId: 'qwerty', - cpm: 1, - currency: 'USD', - width: 300, - height: 250, - ttl: 600, - meta: { - advertiserDomains: ['xe.works'] - }, - ext: { - pixels: [ - [ 'iframe', 'surl1' ], - [ 'image', 'surl2' ], - ] - } - }] - } - }; - - const validResponse = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequest }); - const bid = validResponse[0]; - expect(validResponse).to.be.an('array').that.is.not.empty; - expect(bid.requestId).to.equal('qwerty'); - expect(bid.cpm).to.equal(1); - expect(bid.currency).to.equal('USD'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.ttl).to.equal(600); - expect(bid.meta).to.deep.equal({ advertiserDomains: ['xe.works'] }); - }); + describe('interpretResponse', function () { + it('should return empty bids', function () { + const serverResponse = { + body: { + data: null + } + }; - it('should interpret valid banner response', function () { - const serverResponse = { - body: { - data: [{ - requestId: 'qwerty', - cpm: 1, - currency: 'USD', - width: 300, - height: 250, - ttl: 600, - mediaType: 'banner', - creativeId: 'xe-demo-banner', - ad: 'ad', - meta: {} - }] - } - }; - - const validResponseBanner = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequest }); - const bid = validResponseBanner[0]; - expect(validResponseBanner).to.be.an('array').that.is.not.empty; - expect(bid.mediaType).to.equal('banner'); - expect(bid.creativeId).to.equal('xe-demo-banner'); - expect(bid.ad).to.equal('ad'); - }); + const invalidResponse = spec.interpretResponse(serverResponse, {}); + expect(invalidResponse).to.be.an('array').that.is.empty; + }); - it('should interpret valid video response', function () { - const serverResponse = { - body: { - data: [{ - requestId: 'qwerty', - cpm: 1, - currency: 'USD', - width: 600, - height: 480, - ttl: 600, - mediaType: 'video', - creativeId: 'xe-demo-video', - ad: 'vast-xml', - meta: {} - }] - } - }; - - const validResponseBanner = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequestVideo }); - const bid = validResponseBanner[0]; - expect(validResponseBanner).to.be.an('array').that.is.not.empty; - expect(bid.mediaType).to.equal('video'); - expect(bid.creativeId).to.equal('xe-demo-video'); - expect(bid.ad).to.equal('vast-xml'); - }); -}); + it('should interpret valid response', function () { + const serverResponse = { + body: { + data: [{ + requestId: 'qwerty', + cpm: 1, + currency: 'USD', + width: 300, + height: 250, + ttl: 600, + meta: { + advertiserDomains: ['xe.works'] + }, + ext: { + pixels: [ + [ 'iframe', 'surl1' ], + [ 'image', 'surl2' ], + ] + } + }] + } + }; + + const validResponse = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequest }); + const bid = validResponse[0]; + expect(validResponse).to.be.an('array').that.is.not.empty; + expect(bid.requestId).to.equal('qwerty'); + expect(bid.cpm).to.equal(1); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.ttl).to.equal(600); + expect(bid.meta).to.deep.equal({ advertiserDomains: ['xe.works'] }); + }); -describe('getUserSyncs', function () { - it('shoukd handle no params', function () { - const opts = spec.getUserSyncs({}, []); - expect(opts).to.be.an('array').that.is.empty; - }); + it('should interpret valid banner response', function () { + const serverResponse = { + body: { + data: [{ + requestId: 'qwerty', + cpm: 1, + currency: 'USD', + width: 300, + height: 250, + ttl: 600, + mediaType: 'banner', + creativeId: 'xe-demo-banner', + ad: 'ad', + meta: {} + }] + } + }; + + const validResponseBanner = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequest }); + const bid = validResponseBanner[0]; + expect(validResponseBanner).to.be.an('array').that.is.not.empty; + expect(bid.mediaType).to.equal('banner'); + expect(bid.creativeId).to.equal('xe-demo-banner'); + expect(bid.ad).to.equal('ad'); + }); - it('should return empty if sync is not allowed', function () { - const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}); - expect(opts).to.be.an('array').that.is.empty; + it('should interpret valid video response', function () { + const serverResponse = { + body: { + data: [{ + requestId: 'qwerty', + cpm: 1, + currency: 'USD', + width: 600, + height: 480, + ttl: 600, + mediaType: 'video', + creativeId: 'xe-demo-video', + ad: 'vast-xml', + meta: {} + }] + } + }; + + const validResponseBanner = spec.interpretResponse(serverResponse, { bidderRequest: defaultRequestVideo }); + const bid = validResponseBanner[0]; + expect(validResponseBanner).to.be.an('array').that.is.not.empty; + expect(bid.mediaType).to.equal('video'); + expect(bid.creativeId).to.equal('xe-demo-video'); + expect(bid.ad).to.equal('vast-xml'); + }); }); - it('should allow iframe sync', function () { - const opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [{ - body: { - data: [{ - requestId: 'qwerty', - ext: { - pixels: [ - [ 'iframe', 'surl1?a=b' ], - [ 'image', 'surl2?a=b' ], - ] - } - }] - } - }]); - expect(opts.length).to.equal(1); - expect(opts[0].type).to.equal('iframe'); - expect(opts[0].url).to.equal('surl1?a=b&us_privacy=&gdpr=0&gdpr_consent='); - }); + describe('getUserSyncs', function () { + it('shoukd handle no params', function () { + const opts = spec.getUserSyncs({}, []); + expect(opts).to.be.an('array').that.is.empty; + }); - it('should allow pixel sync', function () { - const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{ - body: { - data: [{ - requestId: 'qwerty', - ext: { - pixels: [ - [ 'iframe', 'surl1?a=b' ], - [ 'image', 'surl2?a=b' ], - ] - } - }] - } - }]); - expect(opts.length).to.equal(1); - expect(opts[0].type).to.equal('image'); - expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=0&gdpr_consent='); - }); + it('should return empty if sync is not allowed', function () { + const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}); + expect(opts).to.be.an('array').that.is.empty; + }); - it('should allow pixel sync and parse consent params', function () { - const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{ - body: { - data: [{ - requestId: 'qwerty', - ext: { - pixels: [ - [ 'iframe', 'surl1?a=b' ], - [ 'image', 'surl2?a=b' ], - ] - } - }] - } - }], { - gdprApplies: 1, - consentString: '1YA-' - }); - expect(opts.length).to.equal(1); - expect(opts[0].type).to.equal('image'); - expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=1&gdpr_consent=1YA-'); - }); -}); + it('should allow iframe sync', function () { + const opts = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: false}, [{ + body: { + data: [{ + requestId: 'qwerty', + ext: { + pixels: [ + [ 'iframe', 'surl1?a=b' ], + [ 'image', 'surl2?a=b' ], + ] + } + }] + } + }]); + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('iframe'); + expect(opts[0].url).to.equal('surl1?a=b&us_privacy=&gdpr=0&gdpr_consent='); + }); -describe('getBidFloor', function () { - it('should return null when getFloor is not a function', () => { - const bid = { getFloor: 2 }; - const result = getBidFloor(bid); - expect(result).to.be.null; - }); + it('should allow pixel sync', function () { + const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{ + body: { + data: [{ + requestId: 'qwerty', + ext: { + pixels: [ + [ 'iframe', 'surl1?a=b' ], + [ 'image', 'surl2?a=b' ], + ] + } + }] + } + }]); + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('image'); + expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=0&gdpr_consent='); + }); - it('should return null when getFloor doesnt return an object', () => { - const bid = { getFloor: () => 2 }; - const result = getBidFloor(bid); - expect(result).to.be.null; + it('should allow pixel sync and parse consent params', function () { + const opts = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{ + body: { + data: [{ + requestId: 'qwerty', + ext: { + pixels: [ + [ 'iframe', 'surl1?a=b' ], + [ 'image', 'surl2?a=b' ], + ] + } + }] + } + }], { + gdprApplies: 1, + consentString: '1YA-' + }); + expect(opts.length).to.equal(1); + expect(opts[0].type).to.equal('image'); + expect(opts[0].url).to.equal('surl2?a=b&us_privacy=&gdpr=1&gdpr_consent=1YA-'); + }); }); - it('should return null when floor is not a number', () => { - const bid = { - getFloor: () => ({ floor: 'string', currency: 'USD' }) - }; - const result = getBidFloor(bid); - expect(result).to.be.null; - }); + describe('getBidFloor', function () { + it('should return null when getFloor is not a function', () => { + const bid = { getFloor: 2 }; + const result = getBidFloor(bid); + expect(result).to.be.null; + }); - it('should return null when currency is not USD', () => { - const bid = { - getFloor: () => ({ floor: 5, currency: 'EUR' }) - }; - const result = getBidFloor(bid); - expect(result).to.be.null; - }); + it('should return null when getFloor doesnt return an object', () => { + const bid = { getFloor: () => 2 }; + const result = getBidFloor(bid); + expect(result).to.be.null; + }); - it('should return floor value when everything is correct', () => { - const bid = { - getFloor: () => ({ floor: 5, currency: 'USD' }) - }; - const result = getBidFloor(bid); - expect(result).to.equal(5); + it('should return null when floor is not a number', () => { + const bid = { + getFloor: () => ({ floor: 'string', currency: 'USD' }) + }; + const result = getBidFloor(bid); + expect(result).to.be.null; + }); + + it('should return null when currency is not USD', () => { + const bid = { + getFloor: () => ({ floor: 5, currency: 'EUR' }) + }; + const result = getBidFloor(bid); + expect(result).to.be.null; + }); + + it('should return floor value when everything is correct', () => { + const bid = { + getFloor: () => ({ floor: 5, currency: 'USD' }) + }; + const result = getBidFloor(bid); + expect(result).to.equal(5); + }); }); -}); +}) diff --git a/test/spec/modules/yahoosspBidAdapter_spec.js b/test/spec/modules/yahoosspBidAdapter_spec.js index c0584173082..40dc2b3c63b 100644 --- a/test/spec/modules/yahoosspBidAdapter_spec.js +++ b/test/spec/modules/yahoosspBidAdapter_spec.js @@ -969,23 +969,7 @@ describe('Yahoo Advertising Bid Adapter:', () => { describe('User data', () => { it('should set the allowed sources user eids', () => { const { validBidRequests, bidderRequest } = generateBuildRequestMock({}); - validBidRequests[0].userIdAsEids = createEidsArray({ - connectId: 'connectId_FROM_USER_ID_MODULE', - admixerId: 'admixerId_FROM_USER_ID_MODULE', - adtelligentId: 'adtelligentId_FROM_USER_ID_MODULE', - amxId: 'amxId_FROM_USER_ID_MODULE', - britepoolid: 'britepoolid_FROM_USER_ID_MODULE', - deepintentId: 'deepintentId_FROM_USER_ID_MODULE', - publinkId: 'publinkId_FROM_USER_ID_MODULE', - intentIqId: 'intentIqId_FROM_USER_ID_MODULE', - idl_env: 'idl_env_FROM_USER_ID_MODULE', - imuid: 'imuid_FROM_USER_ID_MODULE', - criteoId: 'criteoId_FROM_USER_ID_MODULE', - fabrickId: 'fabrickId_FROM_USER_ID_MODULE', - }); - const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; - - expect(data.user.ext.eids).to.deep.equal([ + validBidRequests[0].userIdAsEids = [ {source: 'yahoo.com', uids: [{id: 'connectId_FROM_USER_ID_MODULE', atype: 3}]}, {source: 'admixer.net', uids: [{id: 'admixerId_FROM_USER_ID_MODULE', atype: 3}]}, {source: 'adtelligent.com', uids: [{id: 'adtelligentId_FROM_USER_ID_MODULE', atype: 3}]}, @@ -998,7 +982,10 @@ describe('Yahoo Advertising Bid Adapter:', () => { {source: 'intimatemerger.com', uids: [{id: 'imuid_FROM_USER_ID_MODULE', atype: 1}]}, {source: 'criteo.com', uids: [{id: 'criteoId_FROM_USER_ID_MODULE', atype: 1}]}, {source: 'neustar.biz', uids: [{id: 'fabrickId_FROM_USER_ID_MODULE', atype: 1}]} - ]); + ]; + const data = spec.buildRequests(validBidRequests, bidderRequest)[0].data; + + expect(data.user.ext.eids).to.deep.equal(validBidRequests[0].userIdAsEids); }); it('should not set not allowed user eids sources', () => {