Skip to content

Commit

Permalink
Digitrust support in PBS bid adapter and Rubicon bid adapter (#3935)
Browse files Browse the repository at this point in the history
* Add microadBidAdapter

* Remove unnecessary encodeURIComponent from microadBidAdapter

* Submit Advangelists Prebid Adapter

* Submit Advangelists Prebid Adapter 1.1

* Correct procudtion endpoint for prebid

* - Get digitrust data from bid request
- Send UnifiedID and PubCommon data to OpenRTB

* - Replace lodash with Prebid util functions
- Updated pubcommon id location when sending to OpenRTB

* Remove pref property when sending DigiTrust to OpenRTB

* Updated tests to check new user external id locations in request

* Remove use of array find from unit test
  • Loading branch information
msm0504 authored and Isaac Dettman committed Jun 21, 2019
1 parent ce095e0 commit bbd73ce
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 100 deletions.
64 changes: 36 additions & 28 deletions modules/prebidServerBidAdapter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,24 @@ function doClientSideSyncs(bidders) {
});
}

function _getDigiTrustQueryParams() {
function getDigiTrustId() {
let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'}));
function _getDigiTrustQueryParams(bidRequest = {}) {
function getDigiTrustId(bidRequest) {
const bidRequestDigitrust = utils.deepAccess(bidRequest, 'bids.0.userId.digitrustid.data');
if (bidRequestDigitrust) {
return bidRequestDigitrust;
}

const digiTrustUser = config.getConfig('digiTrustId');
return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null;
}
let digiTrustId = getDigiTrustId();
let digiTrustId = getDigiTrustId(bidRequest);
// Verify there is an ID and this user has not opted out
if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) {
return null;
}
return {
id: digiTrustId.id,
keyv: digiTrustId.keyv,
pref: 0
keyv: digiTrustId.keyv
};
}

Expand Down Expand Up @@ -334,7 +338,7 @@ const LEGACY_PROTOCOL = {

_appendSiteAppDevice(request);

let digiTrust = _getDigiTrustQueryParams();
let digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]);
if (digiTrust) {
request.digiTrust = digiTrust;
}
Expand Down Expand Up @@ -521,26 +525,39 @@ const OPEN_RTB_PROTOCOL = {

_appendSiteAppDevice(request);

const digiTrust = _getDigiTrustQueryParams();
const digiTrust = _getDigiTrustQueryParams(bidRequests && bidRequests[0]);
if (digiTrust) {
request.user = { ext: { digitrust: digiTrust } };
utils.deepSetValue(request, 'user.ext.digitrust', digiTrust);
}

if (!utils.isEmpty(aliases)) {
request.ext.prebid.aliases = aliases;
}

if (bidRequests && bidRequests[0].userId && typeof bidRequests[0].userId === 'object') {
if (!request.user) {
request.user = {};
}
if (!request.user.ext) {
request.user.ext = {}
const bidUserId = utils.deepAccess(bidRequests, '0.bids.0.userId');
if (bidUserId && typeof bidUserId === 'object' && (bidUserId.tdid || bidUserId.pubcid)) {
utils.deepSetValue(request, 'user.ext.eids', []);

if (bidUserId.tdid) {
request.user.ext.eids.push({
source: 'adserver.org',
uids: [{
id: bidUserId.tdid,
ext: {
rtiPartner: 'TDID'
}
}]
});
}
if (!request.user.ext.tpid) {
request.user.ext.tpid = {}

if (bidUserId.pubcid) {
request.user.ext.eids.push({
source: 'pubcommon',
uids: [{
id: bidUserId.pubcid,
}]
});
}
Object.assign(request.user.ext.tpid, bidRequests[0].userId);
}

if (bidRequests && bidRequests[0].gdprConsent) {
Expand All @@ -560,16 +577,7 @@ const OPEN_RTB_PROTOCOL = {
request.regs = { ext: { gdpr: gdprApplies } };
}

let consentString = bidRequests[0].gdprConsent.consentString;
if (request.user) {
if (request.user.ext) {
request.user.ext.consent = consentString;
} else {
request.user.ext = { consent: consentString };
}
} else {
request.user = { ext: { consent: consentString } };
}
utils.deepSetValue(request, 'user.ext.consent', bidRequests[0].gdprConsent.consentString);
}

return request;
Expand Down
107 changes: 63 additions & 44 deletions modules/rubiconBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ export const FASTLANE_ENDPOINT = '//fastlane.rubiconproject.com/a/api/fastlane.j
export const VIDEO_ENDPOINT = '//prebid-server.rubiconproject.com/openrtb2/auction';
export const SYNC_ENDPOINT = 'https://eus.rubiconproject.com/usync.html';

const DIGITRUST_PROP_NAMES = {
FASTLANE: {
id: 'dt.id',
keyv: 'dt.keyv',
pref: 'dt.pref'
},
PREBID_SERVER: {
id: 'id',
keyv: 'keyv'
}
};

var sizeMap = {
1: '468x60',
2: '728x90',
Expand Down Expand Up @@ -170,13 +182,9 @@ export const spec = {

addVideoParameters(data, bidRequest);

const digiTrust = getDigiTrustQueryParams();
const digiTrust = _getDigiTrustQueryParams(bidRequest, 'PREBID_SERVER');
if (digiTrust) {
data.user = {
ext: {
digitrust: digiTrust
}
};
utils.deepSetValue(data, 'user.ext.digitrust', digiTrust);
}

if (bidderRequest.gdprConsent) {
Expand All @@ -196,15 +204,32 @@ export const spec = {
data.regs = {ext: {gdpr: gdprApplies}};
}

const consentString = bidderRequest.gdprConsent.consentString;
if (data.user) {
if (data.user.ext) {
data.user.ext.consent = consentString;
} else {
data.user.ext = {consent: consentString};
}
} else {
data.user = {ext: {consent: consentString}};
utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
}

if (bidRequest.userId && typeof bidRequest.userId === 'object' &&
(bidRequest.userId.tdid || bidRequest.userId.pubcid)) {
utils.deepSetValue(data, 'user.ext.eids', []);

if (bidRequest.userId.tdid) {
data.user.ext.eids.push({
source: 'adserver.org',
uids: [{
id: bidRequest.userId.tdid,
ext: {
rtiPartner: 'TDID'
}
}]
});
}

if (bidRequest.userId.pubcid) {
data.user.ext.eids.push({
source: 'pubcommon',
uids: [{
id: bidRequest.userId.pubcid,
}]
});
}
}

Expand Down Expand Up @@ -406,10 +431,8 @@ export const spec = {
}

// digitrust properties
const digitrustParams = _getDigiTrustQueryParams();
Object.keys(digitrustParams).forEach(paramKey => {
data[paramKey] = digitrustParams[paramKey];
});
const digitrustParams = _getDigiTrustQueryParams(bidRequest, 'FASTLANE');
Object.assign(data, digitrustParams);

return data;
},
Expand Down Expand Up @@ -600,22 +623,36 @@ function _getScreenResolution() {
return [window.screen.width, window.screen.height].join('x');
}

function _getDigiTrustQueryParams() {
function _getDigiTrustQueryParams(bidRequest = {}, endpointName) {
if (!endpointName || !DIGITRUST_PROP_NAMES[endpointName]) {
return null;
}
const propNames = DIGITRUST_PROP_NAMES[endpointName];

function getDigiTrustId() {
let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'}));
const bidRequestDigitrust = utils.deepAccess(bidRequest, 'userId.digitrustid.data');
if (bidRequestDigitrust) {
return bidRequestDigitrust;
}

let digiTrustUser = (window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'})));
return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null;
}

let digiTrustId = getDigiTrustId();
// Verify there is an ID and this user has not opted out
if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) {
return [];
return null;
}
return {
'dt.id': digiTrustId.id,
'dt.keyv': digiTrustId.keyv,
'dt.pref': 0

const digiTrustQueryParams = {
[propNames.id]: digiTrustId.id,
[propNames.keyv]: digiTrustId.keyv
};
if (propNames.pref) {
digiTrustQueryParams[propNames.pref] = 0;
}
return digiTrustQueryParams;
}

/**
Expand Down Expand Up @@ -677,24 +714,6 @@ function parseSizes(bid, mediaType) {
return masSizeOrdering(sizes);
}

function getDigiTrustQueryParams() {
function getDigiTrustId() {
let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: 'T9QSFKPDN9'}));
return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null;
}

let digiTrustId = getDigiTrustId();
// Verify there is an ID and this user has not opted out
if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) {
return null;
}
return {
id: digiTrustId.id,
keyv: digiTrustId.keyv,
pref: 0
};
}

/**
* @param {Object} data
* @param bidRequest
Expand Down
17 changes: 17 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,23 @@ export function deepAccess(obj, path) {
return obj;
}

/**
* @param {Object} obj The object to set a deep property value in
* @param {(string|Array.<string>)} path Object path to the value you would like ot set.
* @param {*} value The value you would like to set
*/
export function deepSetValue(obj, path, value) {
let i;
path = path.split('.');
for (i = 0; i < path.length - 1; i++) {
if (i !== path.length - 1 && typeof obj[path[i]] === 'undefined') {
obj[path[i]] = {};
}
obj = obj[path[i]];
}
obj[path[i]] = value;
}

/**
* Returns content for a friendly iframe to execute a URL in script tag
* @param {string} url URL to be executed in a script tag in a friendly iframe
Expand Down
58 changes: 30 additions & 28 deletions test/spec/modules/prebidServerBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,38 +513,37 @@ describe('S2S Adapter', function () {
});

it('adds digitrust id is present and user is not optout', function () {
let ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';

let consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);

let digiTrustObj = {
success: true,
identity: {
privacy: {
optout: false
},
id: 'testId',
keyv: 'testKeyV'
}
privacy: {
optout: false
},
id: 'testId',
keyv: 'testKeyV'
};

window.DigiTrust = {
getUser: () => digiTrustObj
};
let digiTrustBidRequest = utils.deepClone(BID_REQUESTS);
digiTrustBidRequest[0].bids[0].userId = { digitrustid: { data: digiTrustObj } };

adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax);
adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax);
let requestBid = JSON.parse(requests[0].requestBody);

expect(requestBid.digiTrust).to.deep.equal({
id: digiTrustObj.identity.id,
keyv: digiTrustObj.identity.keyv,
pref: 0
expect(requestBid.user.ext.digitrust).to.deep.equal({
id: digiTrustObj.id,
keyv: digiTrustObj.keyv
});

digiTrustObj.identity.privacy.optout = true;
digiTrustObj.privacy.optout = true;

adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax);
adapter.callBids(REQUEST, digiTrustBidRequest, addBidResponse, done, ajax);
requestBid = JSON.parse(requests[1].requestBody);

expect(requestBid.digiTrust).to.not.exist;

delete window.DigiTrust;
expect(requestBid.user && request.user.ext && requestBid.user.ext.digitrust).to.not.exist;
});

it('adds device and app objects to request', function () {
Expand Down Expand Up @@ -813,22 +812,25 @@ describe('S2S Adapter', function () {

it('when userId is defined on bids, it\'s properties should be copied to user.ext.tpid properties', function () {
let ortb2Config = utils.deepClone(CONFIG);
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'
ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction';

let consentConfig = { s2sConfig: ortb2Config };
config.setConfig(consentConfig);

let userIdBidRequest = utils.deepClone(BID_REQUESTS);
userIdBidRequest[0].userId = {
foo: 'abc123',
unifiedid: '1234'
userIdBidRequest[0].bids[0].userId = {
tdid: 'abc123',
pubcid: '1234'
};

adapter.callBids(REQUEST, userIdBidRequest, addBidResponse, done, ajax);
let requestBid = JSON.parse(requests[0].requestBody);
expect(typeof requestBid.user.ext.tpid).is.equal('object');
expect(requestBid.user.ext.tpid.foo).is.equal('abc123');
expect(requestBid.user.ext.tpid.unifiedid).is.equal('1234');
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 === 'pubcommon')).is.not.empty; ;
expect(requestBid.user.ext.eids.filter(eid => eid.source === 'pubcommon')[0].uids[0].id).is.equal('1234');
})

it('always add ext.prebid.targeting.includebidderkeys: false for ORTB', function () {
Expand Down

0 comments on commit bbd73ce

Please sign in to comment.