Skip to content

Commit bdb661f

Browse files
li-ranixranliamykwyang
authored
IndexExchange Bid Adapter: Added support for netID, ID+ and FabrickId userId (prebid#6286)
* added more userID partner support for IX adapter - TDID, LI, NetID, Neustar, Zeotap * removed liveintent and adsrvr.org [DNA-5040] * updated neustar id * fixed fabrickid * frabrickId instead of id * added more userID partner support for IX adapter - NetID, Neustar, Zeotap (#1) * added more userID partner support for IX adapter - TDID, LI, NetID, Neustar, Zeotap * added tests * added tests for new userinfo modules * missed a few checks * Dna 5040 ix userid support (prebid#2) * added more userID partner support for IX adapter - TDID, LI, NetID, Neustar, Zeotap * removed liveintent and adsrvr.org [DNA-5040] * updated neustar id * fixed fabrickid * frabrickId instead of id * added tests * added tests for new userinfo modules * missed a few checks Co-authored-by: Ran Li <[email protected]> * added few missing checks in IX adapter * Use userIdAsEids instead of userId (prebid#3) * use eids, revert package-lock * test update Co-authored-by: Ran Li <[email protected]> Co-authored-by: amykwyang <[email protected]>
1 parent dc83f3b commit bdb661f

File tree

2 files changed

+116
-52
lines changed

2 files changed

+116
-52
lines changed

modules/ixBidAdapter.js

+33-45
Original file line numberDiff line numberDiff line change
@@ -212,36 +212,35 @@ function getBidRequest(id, impressions) {
212212
}
213213

214214
/**
215-
* Adds a User ID module's response into user Eids array.
216-
*
217-
* @param {array} userEids An array of objects containing user ids,
218-
* will be attached to bid request later.
219-
* @param {object} seenIdPartners An object with Identity partners names already added,
220-
* updated with new partner name.
221-
* @param {*} id The id obtained from User ID module.
222-
* @param {string} source The URL of the User ID module.
223-
* @param {string} ixlPartnerName The name of the Identity Partner in IX Library.
224-
* @param {string} rtiPartner The name of the User ID provider in Prebid.
225-
* @return {boolean} True if successfully added the ID to the userEids, false otherwise.
215+
* From the userIdAsEids array, filter for the ones our adserver can use, and modify them
216+
* for our purposes, e.g. add rtiPartner
217+
* @param {array} allEids userIdAsEids passed in by prebid
218+
* @return {object} contains toSend (eids to send to the adserver) and seenSources (used to filter
219+
* identity info from IX Library)
226220
*/
227-
function addUserEids(userEids, seenIdPartners, id, source, ixlPartnerName, rtiPartner) {
228-
if (id) {
229-
// mark the partnername that IX RTI uses
230-
seenIdPartners[ixlPartnerName] = 1;
231-
userEids.push({
232-
source: source,
233-
uids: [{
234-
id: id,
235-
ext: {
236-
rtiPartner: rtiPartner
237-
}
238-
}]
239-
});
240-
return true;
221+
function getEidInfo(allEids) {
222+
// determines which eids we send and the rtiPartner field in ext
223+
var sourceRTIMapping = {
224+
'liveramp.com': 'idl',
225+
'netid.de': 'NETID',
226+
'neustar.biz': 'fabrickId',
227+
'zeotap.com': 'zeotapIdPlus'
228+
};
229+
var toSend = [];
230+
var seenSources = {};
231+
if (utils.isArray(allEids)) {
232+
for (var i = 0; i < allEids.length; i++) {
233+
if (sourceRTIMapping[allEids[i].source] && utils.deepAccess(allEids[i], 'uids.0')) {
234+
seenSources[allEids[i].source] = 1;
235+
allEids[i].uids[0].ext = {
236+
rtiPartner: sourceRTIMapping[allEids[i].source]
237+
};
238+
delete allEids[i].uids[0].atype;
239+
toSend.push(allEids[i]);
240+
}
241+
}
241242
}
242-
243-
utils.logWarn('Tried to add a user ID from Prebid, the ID received was null');
244-
return false;
243+
return { toSend: toSend, seenSources: seenSources };
245244
}
246245

247246
/**
@@ -255,21 +254,12 @@ function addUserEids(userEids, seenIdPartners, id, source, ixlPartnerName, rtiPa
255254
*
256255
*/
257256
function buildRequest(validBidRequests, bidderRequest, impressions, version) {
258-
const userEids = [];
259-
260257
// Always use secure HTTPS protocol.
261258
let baseUrl = SECURE_BID_URL;
262259

263-
// Dict for identity partners already populated from prebid
264-
let seenIdPartners = {};
265-
266260
// Get ids from Prebid User ID Modules
267-
const userId = validBidRequests[0].userId;
268-
if (userId && typeof userId === 'object') {
269-
if (userId.idl_env) {
270-
addUserEids(userEids, seenIdPartners, userId.idl_env, 'liveramp.com', 'LiveRampIp', 'idl');
271-
}
272-
}
261+
var eidInfo = getEidInfo(utils.deepAccess(validBidRequests, '0.userIdAsEids'));
262+
var userEids = eidInfo.toSend;
273263

274264
// RTI ids will be included in the bid request if the function getIdentityInfo() is loaded
275265
// and if the data for the partner exist
@@ -278,12 +268,10 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
278268
if (identityInfo && typeof identityInfo === 'object') {
279269
for (const partnerName in identityInfo) {
280270
if (identityInfo.hasOwnProperty(partnerName)) {
281-
// check if not already populated by prebid cache
282-
if (!seenIdPartners.hasOwnProperty(partnerName)) {
283-
let response = identityInfo[partnerName];
284-
if (!response.responsePending && response.data && typeof response.data === 'object' && Object.keys(response.data).length) {
285-
userEids.push(response.data);
286-
}
271+
let response = identityInfo[partnerName];
272+
if (!response.responsePending && response.data && typeof response.data === 'object' &&
273+
Object.keys(response.data).length && !eidInfo.seenSources[response.data.source]) {
274+
userEids.push(response.data);
287275
}
288276
}
289277
}

test/spec/modules/ixBidAdapter_spec.js

+83-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { config } from 'src/config.js';
33
import { expect } from 'chai';
44
import { newBidder } from 'src/adapters/bidderFactory.js';
55
import { spec } from 'modules/ixBidAdapter.js';
6+
import { createEidsArray } from 'modules/userId/eids.js';
67

78
describe('IndexexchangeAdapter', function () {
89
const IX_SECURE_ENDPOINT = 'https://htlb.casalemedia.com/cygnus';
@@ -351,8 +352,13 @@ describe('IndexexchangeAdapter', function () {
351352

352353
const DEFAULT_USERID_DATA = {
353354
idl_env: '1234-5678-9012-3456', // Liveramp
355+
netId: 'testnetid123', // NetId
356+
IDP: 'userIDP000', // IDP
357+
fabrickId: 'fabrickId9000', // FabrickId
354358
};
355359

360+
const DEFAULT_USERIDASEIDS_DATA = createEidsArray(DEFAULT_USERID_DATA);
361+
356362
const DEFAULT_USERID_PAYLOAD = [
357363
{
358364
source: 'liveramp.com',
@@ -362,6 +368,30 @@ describe('IndexexchangeAdapter', function () {
362368
rtiPartner: 'idl'
363369
}
364370
}]
371+
}, {
372+
source: 'netid.de',
373+
uids: [{
374+
id: DEFAULT_USERID_DATA.netId,
375+
ext: {
376+
rtiPartner: 'NETID'
377+
}
378+
}]
379+
}, {
380+
source: 'neustar.biz',
381+
uids: [{
382+
id: DEFAULT_USERID_DATA.fabrickId,
383+
ext: {
384+
rtiPartner: 'fabrickId'
385+
}
386+
}]
387+
}, {
388+
source: 'zeotap.com',
389+
uids: [{
390+
id: DEFAULT_USERID_DATA.IDP,
391+
ext: {
392+
rtiPartner: 'zeotapIdPlus'
393+
}
394+
}]
365395
}
366396
];
367397

@@ -761,14 +791,18 @@ describe('IndexexchangeAdapter', function () {
761791
delete window.headertag;
762792
});
763793

764-
it('IX adapter reads LiveRamp IDL envelope from Prebid and adds it to Video', function () {
794+
it('IX adapter reads supported user modules from Prebid and adds it to Video', function () {
765795
const cloneValidBid = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
766-
cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA);
796+
// cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA);
797+
cloneValidBid[0].userIdAsEids = utils.deepClone(DEFAULT_USERIDASEIDS_DATA);
767798
const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
768799
const payload = JSON.parse(request.data.r);
769800

770-
expect(payload.user.eids).to.have.lengthOf(1);
801+
expect(payload.user.eids).to.have.lengthOf(4);
771802
expect(payload.user.eids).to.deep.include(DEFAULT_USERID_PAYLOAD[0]);
803+
expect(payload.user.eids).to.deep.include(DEFAULT_USERID_PAYLOAD[1]);
804+
expect(payload.user.eids).to.deep.include(DEFAULT_USERID_PAYLOAD[2]);
805+
expect(payload.user.eids).to.deep.include(DEFAULT_USERID_PAYLOAD[3]);
772806
});
773807

774808
it('We continue to send in IXL identity info and Prebid takes precedence over IXL', function () {
@@ -822,11 +856,45 @@ describe('IndexexchangeAdapter', function () {
822856
}
823857
}
824858
]
859+
},
860+
NetIdIp: {
861+
source: 'netid.de',
862+
uids: [
863+
{
864+
id: 'testnetid',
865+
ext: {
866+
rtiPartner: 'NETID'
867+
}
868+
}
869+
]
870+
},
871+
NeustarIp: {
872+
source: 'neustar.biz',
873+
uids: [
874+
{
875+
id: 'testfabrick',
876+
ext: {
877+
rtiPartner: 'fabrickId'
878+
}
879+
}
880+
]
881+
},
882+
ZeotapIp: {
883+
source: 'zeotap.com',
884+
uids: [
885+
{
886+
id: 'testzeotap',
887+
ext: {
888+
rtiPartner: 'zeotapIdPlus'
889+
}
890+
}
891+
]
825892
}
826893
};
827894

828895
const cloneValidBid = utils.deepClone(DEFAULT_BANNER_VALID_BID);
829-
cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA)
896+
// cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA);
897+
cloneValidBid[0].userIdAsEids = utils.deepClone(DEFAULT_USERIDASEIDS_DATA);
830898

831899
const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
832900
const payload = JSON.parse(request.data.r);
@@ -867,10 +935,14 @@ describe('IndexexchangeAdapter', function () {
867935
})
868936

869937
expect(payload.user).to.exist;
870-
expect(payload.user.eids).to.have.lengthOf(3);
938+
expect(payload.user.eids).to.have.lengthOf(6);
939+
871940
expect(payload.user.eids).to.deep.include(validUserIdPayload[0]);
872941
expect(payload.user.eids).to.deep.include(validUserIdPayload[1]);
873942
expect(payload.user.eids).to.deep.include(validUserIdPayload[2]);
943+
expect(payload.user.eids).to.deep.include(validUserIdPayload[3]);
944+
expect(payload.user.eids).to.deep.include(validUserIdPayload[4]);
945+
expect(payload.user.eids).to.deep.include(validUserIdPayload[5]);
874946
});
875947

876948
it('IXL and Prebid are mutually exclusive', function () {
@@ -892,7 +964,8 @@ describe('IndexexchangeAdapter', function () {
892964
};
893965

894966
const cloneValidBid = utils.deepClone(DEFAULT_VIDEO_VALID_BID);
895-
cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA);
967+
// cloneValidBid[0].userId = utils.deepClone(DEFAULT_USERID_DATA);
968+
cloneValidBid[0].userIdAsEids = utils.deepClone(DEFAULT_USERIDASEIDS_DATA);
896969

897970
const request = spec.buildRequests(cloneValidBid, DEFAULT_OPTION)[0];
898971

@@ -910,9 +983,12 @@ describe('IndexexchangeAdapter', function () {
910983
});
911984

912985
const payload = JSON.parse(request.data.r);
913-
expect(payload.user.eids).to.have.lengthOf(2);
986+
expect(payload.user.eids).to.have.lengthOf(5);
914987
expect(payload.user.eids).to.deep.include(validUserIdPayload[0]);
915988
expect(payload.user.eids).to.deep.include(validUserIdPayload[1]);
989+
expect(payload.user.eids).to.deep.include(validUserIdPayload[2]);
990+
expect(payload.user.eids).to.deep.include(validUserIdPayload[3]);
991+
expect(payload.user.eids).to.deep.include(validUserIdPayload[4]);
916992
});
917993
});
918994

0 commit comments

Comments
 (0)