Skip to content

Commit

Permalink
UserID: merge EIDs with first party data (#12110)
Browse files Browse the repository at this point in the history
* ortbConverter: do not override EIDS provided as first party data

* update tests

* Allow bidder-specific FPD enrichments

* Refactor eid generation, add primaryIds

* EIDs as FPD

* Fix tests

* PBS tests, fix multiple hook registration

* Fix more test cleanup

* remove eidPermissions

* refactor oderByPriority

* refactor initializedSubmodules

* fix lint

* update id5 primaryIds

* simplify eid source filtering

* clean up PBS userId logic

* Revert "Allow bidder-specific FPD enrichments"

This reverts commit 2fb7452.

* undo bidder-specific enrichments

* use startAuction instead of requestBids

* add test on userIdAsEids

* Fix lint
  • Loading branch information
dgirardi authored Aug 20, 2024
1 parent 0f3a853 commit 9e2c63e
Show file tree
Hide file tree
Showing 24 changed files with 651 additions and 516 deletions.
1 change: 1 addition & 0 deletions modules/id5IdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ export const id5IdSubmodule = {
}
return cacheIdObj;
},
primaryIds: ['id5id', 'trueLinkId'],
eids: {
'id5id': {
getValue: function (data) {
Expand Down
1 change: 1 addition & 0 deletions modules/imuIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const imuIdSubmodule = {
}
};
},
primaryIds: ['imppid', 'imuid'],
eids: {
'imppid': {
source: 'ppid.intimatemerger.com',
Expand Down
1 change: 1 addition & 0 deletions modules/liveIntentIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ export const liveIntentIdSubmodule = {

return { callback: result };
},
primaryIds: ['libp'],
eids: {
...UID1_EIDS,
...UID2_EIDS,
Expand Down
17 changes: 2 additions & 15 deletions modules/prebidServerBidAdapter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
deepClone,
flatten,
generateUUID,
getPrebidInternal,
insertUserSyncIframe,
isNumber,
isPlainObject,
Expand All @@ -16,7 +15,7 @@ import {
triggerPixel,
uniques,
} from '../../src/utils.js';
import { EVENTS, REJECTION_REASON, S2S } from '../../src/constants.js';
import {EVENTS, REJECTION_REASON, S2S} from '../../src/constants.js';
import adapterManager, {s2sActivityParams} from '../../src/adapterManager.js';
import {config} from '../../src/config.js';
import {addPaapiConfig, isValid} from '../../src/adapters/bidderFactory.js';
Expand All @@ -37,8 +36,6 @@ const TYPE = S2S.SRC;
let _syncCount = 0;
let _s2sConfigs;

let eidPermissions;

/**
* @typedef {Object} AdapterOptions
* @summary s2sConfig parameter that adds arguments to resulting OpenRTB payload that goes to Prebid Server
Expand Down Expand Up @@ -553,7 +550,7 @@ export const processPBSRequest = hook('sync', function (s2sBidRequest, bidReques
.reduce(flatten, [])
.filter(uniques);

const request = s2sBidRequest.metrics.measureTime('buildRequests', () => buildPBSRequest(s2sBidRequest, bidRequests, adUnits, requestedBidders, eidPermissions));
const request = s2sBidRequest.metrics.measureTime('buildRequests', () => buildPBSRequest(s2sBidRequest, bidRequests, adUnits, requestedBidders));
const requestJson = request && JSON.stringify(request);
logInfo('BidRequest: ' + requestJson);
const endpointUrl = getMatchingConsentUrl(s2sBidRequest.s2sConfig.endpoint, gdprConsent);
Expand Down Expand Up @@ -605,14 +602,4 @@ function shouldEmitNonbids(s2sConfig, response) {
return s2sConfig?.extPrebid?.returnallbidstatus && response?.ext?.seatnonbid;
}

/**
* Global setter that sets eids permissions for bidders
* This setter is to be used by userId module when included
* @param {Array} newEidPermissions
*/
function setEidPermissions(newEidPermissions) {
eidPermissions = newEidPermissions;
}
getPrebidInternal().setEidPermissions = setEidPermissions;

adapterManager.registerBidAdapter(new PrebidServer(), 'prebidServer');
30 changes: 4 additions & 26 deletions modules/prebidServerBidAdapter/ortbConverter.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import {ortbConverter} from '../../libraries/ortbConverter/converter.js';
import {
deepAccess,
deepSetValue,
getBidRequest,
getDefinedParams,
isArray,
logError,
logWarn,
mergeDeep,
timestamp
} from '../../src/utils.js';
import {deepAccess, deepSetValue, getBidRequest, logError, logWarn, mergeDeep, timestamp} from '../../src/utils.js';
import {config} from '../../src/config.js';
import { STATUS, S2S } from '../../src/constants.js';
import {S2S, STATUS} from '../../src/constants.js';
import {createBid} from '../../src/bidfactory.js';
import {pbsExtensions} from '../../libraries/pbsExtensions/pbsExtensions.js';
import {setImpBidParams} from '../../libraries/pbsExtensions/processors/params.js';
Expand Down Expand Up @@ -55,7 +45,7 @@ const PBS_CONVERTER = ortbConverter({
if (!imps.length) {
logError('Request to Prebid Server rejected due to invalid media type(s) in adUnit.');
} else {
let {s2sBidRequest, requestedBidders, eidPermissions} = context;
let {s2sBidRequest} = context;
const request = buildRequest(imps, proxyBidderRequest, context);

request.tmax = s2sBidRequest.s2sConfig.timeout ?? Math.min(s2sBidRequest.requestBidsTimeout * 0.75, s2sBidRequest.s2sConfig.maxTimeout ?? s2sDefaultConfig.maxTimeout);
Expand All @@ -67,16 +57,6 @@ const PBS_CONVERTER = ortbConverter({
}
})

if (isArray(eidPermissions) && eidPermissions.length > 0) {
if (requestedBidders && isArray(requestedBidders)) {
eidPermissions = eidPermissions.map(p => ({
...p,
bidders: p.bidders.filter(bidder => requestedBidders.includes(bidder))
}))
}
deepSetValue(request, 'ext.prebid.data.eidpermissions', eidPermissions);
}

if (!context.transmitTids) {
deepSetValue(request, 'ext.prebid.createtids', false);
}
Expand Down Expand Up @@ -253,7 +233,7 @@ const PBS_CONVERTER = ortbConverter({
},
});

export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requestedBidders, eidPermissions) {
export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requestedBidders) {
const requestTimestamp = timestamp();
const impIds = new Set();
const proxyBidRequests = [];
Expand Down Expand Up @@ -295,7 +275,6 @@ export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requeste
proxyBidRequests.push({
...adUnit,
adUnitCode: adUnit.code,
...getDefinedParams(actualBidRequests.values().next().value || {}, ['userId', 'userIdAsEids', 'schain']),
pbsData: {impId, actualBidRequests, adUnit},
});
});
Expand All @@ -317,7 +296,6 @@ export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requeste
s2sBidRequest,
requestedBidders,
actualBidderRequests: bidderRequests,
eidPermissions,
nativeRequest: s2sBidRequest.s2sConfig.ortbNative,
getRedactor,
transmitTids: isActivityAllowed(ACTIVITY_TRANSMIT_TID, s2sParams),
Expand Down
56 changes: 24 additions & 32 deletions modules/userId/eids.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
import {deepAccess, deepClone, isFn, isPlainObject, isStr} from '../../src/utils.js';
import {deepClone, isFn, isStr} from '../../src/utils.js';
/*
* @typedef {import('../modules/userId/index.js').SubmoduleContainer} SubmoduleContainer
*/

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 = EID_CONFIG.get(subModuleKey);
if (conf && userIdData) {
function createEidObject(userIdData, subModuleKey, eidConf) {
if (eidConf && userIdData) {
let eid = {};
eid.source = isFn(conf['getSource']) ? conf['getSource'](userIdData) : conf['source'];
const value = isFn(conf['getValue']) ? conf['getValue'](userIdData) : userIdData;
eid.source = isFn(eidConf['getSource']) ? eidConf['getSource'](userIdData) : eidConf['source'];
const value = isFn(eidConf['getValue']) ? eidConf['getValue'](userIdData) : userIdData;
if (isStr(value)) {
const uid = { id: value, atype: conf['atype'] };
const uid = { id: value, atype: eidConf['atype'] };
// getUidExt
if (isFn(conf['getUidExt'])) {
const uidExt = conf['getUidExt'](userIdData);
if (isFn(eidConf['getUidExt'])) {
const uidExt = eidConf['getUidExt'](userIdData);
if (uidExt) {
uid.ext = uidExt;
}
}
eid.uids = [uid];
// getEidExt
if (isFn(conf['getEidExt'])) {
const eidExt = conf['getEidExt'](userIdData);
if (isFn(eidConf['getEidExt'])) {
const eidExt = eidConf['getEidExt'](userIdData);
if (eidExt) {
eid.ext = eidExt;
}
Expand All @@ -35,7 +34,7 @@ function createEidObject(userIdData, subModuleKey) {
return null;
}

export function createEidsArray(bidRequestUserId) {
export function createEidsArray(bidRequestUserId, eidConfigs = EID_CONFIG) {
const allEids = {};
function collect(eid) {
const key = JSON.stringify([eid.source?.toLowerCase(), eid.ext]);
Expand All @@ -48,31 +47,24 @@ export function createEidsArray(bidRequestUserId) {

Object.entries(bidRequestUserId).forEach(([name, values]) => {
values = Array.isArray(values) ? values : [values];
const eids = name === 'pubProvidedId' ? deepClone(values) : values.map(value => createEidObject(value, name));
const eids = name === 'pubProvidedId' ? deepClone(values) : values.map(value => createEidObject(value, name, eidConfigs.get(name)));
eids.filter(eid => eid != null).forEach(collect);
})
return Object.values(allEids);
}

/**
* @param {SubmoduleContainer[]} submodules
* @param {SubmodulePriorityMap} priorityMap
*/
export function buildEidPermissions(submodules) {
let eidPermissions = [];
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) &&
eidConf.source) {
eidPermissions.push(
{
source: eidConf.source,
bidders: i.config.bidders
}
);
}
});
});
return eidPermissions;
export function getEids(priorityMap) {
const eidConfigs = new Map();
const idValues = {};
Object.entries(priorityMap).forEach(([key, submodules]) => {
const submodule = submodules.find(mod => mod.idObj?.[key] != null);
if (submodule) {
idValues[key] = submodule.idObj[key];
eidConfigs.set(key, submodule.submodule.eids?.[key])
}
})
return createEidsArray(idValues, eidConfigs);
}
Loading

0 comments on commit 9e2c63e

Please sign in to comment.