Skip to content

Commit d055668

Browse files
committed
Extract eids from bid requests
1 parent ed74a03 commit d055668

File tree

3 files changed

+109
-24
lines changed

3 files changed

+109
-24
lines changed

modules/adnuntiusBidAdapter.js

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { registerBidder } from '../src/adapters/bidderFactory.js';
22
import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js';
3-
import {isStr, isEmpty, deepAccess, getUnixTimestampFromNow, convertObjectToArray, getWindowTop, deepClone, getWinDimensions} from '../src/utils.js';
3+
import {isStr, isEmpty, deepAccess, isArray, getUnixTimestampFromNow, convertObjectToArray, getWindowTop, deepClone, getWinDimensions, isPlainObjectWithKeys, _map} from '../src/utils.js';
44
import { config } from '../src/config.js';
55
import { getStorageManager } from '../src/storageManager.js';
66
import {toLegacyResponse, toOrtbNativeRequest} from '../src/native.js';
@@ -154,28 +154,66 @@ const storageTool = (function () {
154154
storage.setDataInLocalStorage(METADATA_KEY, JSON.stringify(metaDataForSaving));
155155
};
156156

157-
const getUsi = function (meta, ortb2, bidParams) {
158-
// Fetch user id from parameters.
159-
for (let i = 0; i < bidParams.length; i++) {
160-
const bidParam = bidParams[i];
161-
if (bidParam.userId) {
162-
return bidParam.userId;
163-
}
157+
const getFirstValidValueFromArray = function(arr, param) {
158+
const example = (arr || []).find((b) => {
159+
return deepAccess(b, param);
160+
});
161+
return example ? deepAccess(example, param) : undefined;
162+
};
163+
164+
const normaliseLegacyIds = function(obj) {
165+
const result = {};
166+
if (!isPlainObjectWithKeys(obj)) {
167+
return result;
164168
}
165-
if (ortb2 && ortb2.user && ortb2.user.id) {
166-
return ortb2.user.id
169+
for (const [key, value] of Object.entries(obj)) {
170+
if (isPlainObjectWithKeys(value)) {
171+
const theId = value[Object.keys(value)[0]];
172+
if (isStr(theId)) {
173+
result[key] = theId;
174+
}
175+
} else if (isStr(value)) {
176+
result[key] = value;
177+
}
167178
}
168-
return (meta && meta.usi) ? meta.usi : false
169-
}
179+
180+
return result;
181+
};
170182

171183
return {
172-
refreshStorage: function (bidderRequest) {
173-
const ortb2 = bidderRequest.ortb2 || {};
184+
refreshStorage: function (validBidRequests, bidderRequest) {
174185
const bidParams = (bidderRequest.bids || []).map((b) => {
175186
return b.params ? b.params : {};
176187
});
177188
metaInternal = getMetaDataFromLocalStorage(bidParams).reduce((a, entry) => ({ ...a, [entry.key]: entry.value }), {});
178-
metaInternal.usi = getUsi(metaInternal, ortb2, bidParams);
189+
const bidParamUserId = getFirstValidValueFromArray(bidParams, 'userId');
190+
const ortb2 = bidderRequest.ortb2 || {};
191+
192+
if (isStr(bidParamUserId)) {
193+
metaInternal.usi = bidParamUserId;
194+
} else if (isStr(ortb2?.user?.id)) {
195+
metaInternal.usi = ortb2.user.id;
196+
} else {
197+
const unvettedOrtb2Eids = deepAccess(ortb2, 'user.ext.eids');
198+
const vettedOrtb2Eids = isArray(unvettedOrtb2Eids) && unvettedOrtb2Eids.length > 0 ? unvettedOrtb2Eids : false;
199+
const unvettedBidRequestEids = getFirstValidValueFromArray(validBidRequests, 'userIdAsEids') || bidderRequest?.userIdAsEids;
200+
const vettedBidRequestEids = isArray(unvettedBidRequestEids) && unvettedBidRequestEids.length > 0 ? unvettedBidRequestEids : false;
201+
const bidRequestUserId = getFirstValidValueFromArray(validBidRequests, 'userId') || bidderRequest?.userId;
202+
203+
if (vettedOrtb2Eids) {
204+
metaInternal.eids = vettedOrtb2Eids;
205+
} else if (vettedBidRequestEids) {
206+
metaInternal.eids = vettedBidRequestEids;
207+
} else if (isPlainObjectWithKeys(bidRequestUserId)) {
208+
const normalisedLegacyIds = normaliseLegacyIds(bidRequestUserId);
209+
if (isPlainObjectWithKeys(normalisedLegacyIds)) {
210+
metaInternal.eids = _map(normalisedLegacyIds, function(v, k) {
211+
return {source: k, uids: [{id: v}]}
212+
});
213+
}
214+
}
215+
}
216+
179217
if (!metaInternal.usi) {
180218
delete metaInternal.usi;
181219
}
@@ -190,8 +228,8 @@ const storageTool = (function () {
190228
},
191229
getUrlRelatedData: function () {
192230
// getting the URL information is theoretically not network-specific
193-
const { usi, voidAuIdsArray } = metaInternal;
194-
return { usi, voidAuIdsArray };
231+
const { usi, voidAuIdsArray, eids } = metaInternal;
232+
return { usi, voidAuIdsArray, eids };
195233
},
196234
getPayloadRelatedData: function (network) {
197235
// getting the payload data should be network-specific
@@ -301,12 +339,13 @@ export const spec = {
301339
queryParamsAndValues.push('so=' + searchParams.get('script-override'));
302340
}
303341

304-
storageTool.refreshStorage(bidderRequest);
342+
storageTool.refreshStorage(validBidRequests, bidderRequest);
305343

306344
const urlRelatedMetaData = storageTool.getUrlRelatedData();
307345
targetingTool.addSegmentsToUrlData(validBidRequests, bidderRequest, urlRelatedMetaData);
308346
if (urlRelatedMetaData.segments.length > 0) queryParamsAndValues.push('segments=' + urlRelatedMetaData.segments.join(','));
309347
if (urlRelatedMetaData.usi) queryParamsAndValues.push('userId=' + urlRelatedMetaData.usi);
348+
if (isArray(urlRelatedMetaData.eids) && urlRelatedMetaData.eids.length > 0) queryParamsAndValues.push('eids=' + encodeURIComponent(JSON.stringify(urlRelatedMetaData.eids)));
310349

311350
const bidderConfig = config.getConfig();
312351
if (bidderConfig.useCookie === false) queryParamsAndValues.push('noCookies=true');
@@ -323,7 +362,7 @@ export const spec = {
323362
continue;
324363
}
325364

326-
let network = bid.params.network || 'network';
365+
const network = bid.params.network || 'network';
327366
bidRequests[network] = bidRequests[network] || [];
328367
bidRequests[network].push(bid);
329368

src/utils.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,15 @@ export function isPlainObject(object) {
406406
return isA(object, tObject);
407407
}
408408

409+
/**
410+
* Returns true if value is an object created via {} or new Object() and the object has keys, so {} fails but {a: 'b'} passes
411+
* @param object
412+
* @returns {Boolean}
413+
*/
414+
export function isPlainObjectWithKeys(object) {
415+
return isA(object, tObject) && Object.keys(object).length > 0;
416+
}
417+
409418
export function isBoolean(object) {
410419
return isA(object, tBoolean);
411420
}

test/spec/modules/adnuntiusBidAdapter_spec.js

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {config, newConfig} from 'src/config.js';
66
import * as utils from 'src/utils.js';
77
import { getStorageManager } from 'src/storageManager.js';
88
import { getGlobal } from '../../../src/prebidGlobal';
9-
import {getUnixTimestampFromNow, getWindowTop} from 'src/utils.js';
9+
import {deepClone, getUnixTimestampFromNow, getWindowTop} from 'src/utils.js';
1010
import { getWinDimensions } from '../../../src/utils';
1111

1212
describe('adnuntiusBidAdapter', function () {
@@ -1252,18 +1252,55 @@ describe('adnuntiusBidAdapter', function () {
12521252
config.setBidderConfig({
12531253
bidders: ['adnuntius'],
12541254
});
1255+
12551256
const req = [
12561257
{
12571258
bidId: 'adn-000000000008b6bc',
12581259
bidder: 'adnuntius',
12591260
params: {
12601261
auId: '000000000008b6bc',
1261-
network: 'adnuntius',
1262-
userId: 'different_user_id'
1262+
network: 'adnuntius'
12631263
}
12641264
}
1265-
]
1266-
const request = config.runWithBidder('adnuntius', () => spec.buildRequests(req, { bids: req }));
1265+
];
1266+
1267+
const validReqs = deepClone(req);
1268+
let request = config.runWithBidder('adnuntius', () => spec.buildRequests(req, { bids: req }));
1269+
expect(request.length).to.equal(1);
1270+
expect(request[0]).to.have.property('url')
1271+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=${usi}`);
1272+
1273+
validReqs[0].userId = {fred: 'fredId', george: {georgekey: 'georgeid'}, skip: [], skipAgain: 2, skipAnother: {anotherSkip: {nestedFred: 'blah'}}};
1274+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(validReqs, { bids: req }));
1275+
expect(request.length).to.equal(1);
1276+
expect(request[0]).to.have.property('url')
1277+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=${usi}&eids=%5B%7B%22source%22%3A%22fred%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22fredId%22%7D%5D%7D%2C%7B%22source%22%3A%22george%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22georgeid%22%7D%5D%7D%5D`);
1278+
1279+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(validReqs, { bids: req, userIdAsEids: [{source: 'a2', uids: [{id: '1232', atype: 1}]}, {source: 'b2', uids: [{id: '4562', atype: 3, ext: {some: '1'}}]}] }));
1280+
expect(request.length).to.equal(1);
1281+
expect(request[0]).to.have.property('url')
1282+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=${usi}&eids=%5B%7B%22source%22%3A%22a2%22%2C%22uids%22%3A%5B%7B%22id%22%3A%221232%22%2C%22atype%22%3A1%7D%5D%7D%2C%7B%22source%22%3A%22b2%22%2C%22uids%22%3A%5B%7B%22id%22%3A%224562%22%2C%22atype%22%3A3%2C%22ext%22%3A%7B%22some%22%3A%221%22%7D%7D%5D%7D%5D`);
1283+
1284+
validReqs[0].userIdAsEids = [{source: 'a3', uids: [{id: '12323', atype: 1}]}, {source: 'b3', uids: [{id: '45623', atype: 3, ext: {some: '1'}}]}];
1285+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(validReqs, { bids: req }));
1286+
expect(request.length).to.equal(1);
1287+
expect(request[0]).to.have.property('url')
1288+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=${usi}&eids=%5B%7B%22source%22%3A%22a3%22%2C%22uids%22%3A%5B%7B%22id%22%3A%2212323%22%2C%22atype%22%3A1%7D%5D%7D%2C%7B%22source%22%3A%22b3%22%2C%22uids%22%3A%5B%7B%22id%22%3A%2245623%22%2C%22atype%22%3A3%2C%22ext%22%3A%7B%22some%22%3A%221%22%7D%7D%5D%7D%5D`);
1289+
1290+
const ortb2 = {user: {ext: {eids: [{source: 'a', uids: [{id: '123', atype: 1}]}, {source: 'b', uids: [{id: '456', atype: 3, ext: {some: '1'}}]}]}}};
1291+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(validReqs, { bids: req, ortb2: ortb2 }));
1292+
expect(request.length).to.equal(1);
1293+
expect(request[0]).to.have.property('url')
1294+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=${usi}&eids=%5B%7B%22source%22%3A%22a%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22123%22%2C%22atype%22%3A1%7D%5D%7D%2C%7B%22source%22%3A%22b%22%2C%22uids%22%3A%5B%7B%22id%22%3A%22456%22%2C%22atype%22%3A3%2C%22ext%22%3A%7B%22some%22%3A%221%22%7D%7D%5D%7D%5D`);
1295+
1296+
ortb2.user.id = "ortb2userid"
1297+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(validReqs, { bids: req, ortb2: ortb2 }));
1298+
expect(request.length).to.equal(1);
1299+
expect(request[0]).to.have.property('url')
1300+
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=ortb2userid`);
1301+
1302+
req[0].params.userId = 'different_user_id';
1303+
request = config.runWithBidder('adnuntius', () => spec.buildRequests(req, { bids: req }));
12671304
expect(request.length).to.equal(1);
12681305
expect(request[0]).to.have.property('url')
12691306
expect(request[0].url).to.equal(`${ENDPOINT_URL_BASE}&userId=different_user_id`);

0 commit comments

Comments
 (0)