Skip to content

Commit

Permalink
add support for non-purpose1 consent domains to appnexus and PBS bid …
Browse files Browse the repository at this point in the history
…adapters (#6484)

* add support for non-purpose1 consent domains

* fix logic and consentdata to clientSideSyncs

* update openx vendor config
  • Loading branch information
jsnellbaker authored and idettman committed May 21, 2021
1 parent c21af77 commit 733cd7c
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 65 deletions.
2 changes: 1 addition & 1 deletion integrationExamples/gpt/prebidServer_example.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
s2sConfig : {
accountId : '1',
enabled : true, //default value set to false
defaultVendor: 'appnexus',
bidders : ['appnexus'],
timeout : 1000, //default value is 1000
adapter : 'prebidServer', //if we have any other s2s adapter, default value is s2s
endpoint : 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction'
}
});

Expand Down
19 changes: 10 additions & 9 deletions modules/appnexusBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getStorageManager } from '../src/storageManager.js';

const BIDDER_CODE = 'appnexus';
const URL = 'https://ib.adnxs.com/ut/v3/prebid';
const URL_SIMPLE = 'https://ib.adnxs-simple.com/ut/v3/prebid';
const VIDEO_TARGETING = ['id', 'minduration', 'maxduration',
'skippable', 'playback_method', 'frameworks', 'context', 'skipoffset'];
const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language'];
Expand Down Expand Up @@ -53,9 +54,9 @@ const NATIVE_MAPPING = {
};
const SOURCE = 'pbjs';
const MAX_IMPS_PER_REQUEST = 15;
const mappingFileUrl = 'https://acdn.adnxs.com/prebid/appnexus-mapping/mappings.json';
const mappingFileUrl = 'https://acdn.adnxs-simple.com/prebid/appnexus-mapping/mappings.json';
const SCRIPT_TAG_START = '<script';
const VIEWABILITY_URL_START = /\/\/cdn\.adnxs\.com\/v/;
const VIEWABILITY_URL_START = /\/\/cdn\.adnxs\.com\/v|\/\/cdn\.adnxs\-simple\.com\/v/;
const VIEWABILITY_FILE_NAME = 'trk.js';
const GVLID = 32;
const storage = getStorageManager(GVLID, BIDDER_CODE);
Expand Down Expand Up @@ -326,8 +327,8 @@ export const spec = {
}
},

getUserSyncs: function (syncOptions) {
if (syncOptions.iframeEnabled) {
getUserSyncs: function (syncOptions, responses, gdprConsent) {
if (syncOptions.iframeEnabled && hasPurpose1Consent({gdprConsent})) {
return [{
type: 'iframe',
url: 'https://acdn.adnxs.com/dmp/async_usersync.html'
Expand Down Expand Up @@ -483,10 +484,10 @@ function hasPurpose1Consent(bidderRequest) {
function formatRequest(payload, bidderRequest) {
let request = [];
let options = {};
let endpointUrl = URL;

if (!hasPurpose1Consent(bidderRequest)) {
options = {
withCredentials: false
}
endpointUrl = URL_SIMPLE;
}

if (utils.getParameterByName('apn_test').toUpperCase() === 'TRUE' || config.getConfig('apn_test') === true) {
Expand All @@ -503,7 +504,7 @@ function formatRequest(payload, bidderRequest) {
const payloadString = JSON.stringify(clonedPayload);
request.push({
method: 'POST',
url: URL,
url: endpointUrl,
data: payloadString,
bidderRequest,
options
Expand All @@ -513,7 +514,7 @@ function formatRequest(payload, bidderRequest) {
const payloadString = JSON.stringify(payload);
request = {
method: 'POST',
url: URL,
url: endpointUrl,
data: payloadString,
bidderRequest,
options
Expand Down
30 changes: 24 additions & 6 deletions modules/prebidServerBidAdapter/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,40 @@ export const S2S_VENDORS = {
'appnexus': {
adapter: 'prebidServer',
enabled: true,
endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction',
syncEndpoint: 'https://prebid.adnxs.com/pbs/v1/cookie_sync',
endpoint: {
p1Consent: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction',
noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/openrtb2/auction'
},
syncEndpoint: {
p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync',
noP1Consent: 'https://prebid.adnxs-simple.com/pbs/v1/cookie_sync'
},
timeout: 1000
},
'rubicon': {
adapter: 'prebidServer',
enabled: true,
endpoint: 'https://prebid-server.rubiconproject.com/openrtb2/auction',
syncEndpoint: 'https://prebid-server.rubiconproject.com/cookie_sync',
endpoint: {
p1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction',
noP1Consent: 'https://prebid-server.rubiconproject.com/openrtb2/auction',
},
syncEndpoint: {
p1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync',
noP1Consent: 'https://prebid-server.rubiconproject.com/cookie_sync',
},
timeout: 500
},
'openx': {
adapter: 'prebidServer',
enabled: true,
endpoint: 'https://prebid.openx.net/openrtb2/auction',
syncEndpoint: 'https://prebid.openx.net/cookie_sync',
endpoint: {
p1Consent: 'https://prebid.openx.net/openrtb2/auction',
noP1Consent: 'https://prebid.openx.net/openrtb2/auction'
},
syncEndpoint: {
p1Consent: 'https://prebid.openx.net/cookie_sync',
noP1Consent: 'https://prebid.openx.net/cookie_sync'
},
timeout: 1000
}
}
64 changes: 52 additions & 12 deletions modules/prebidServerBidAdapter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ function validateConfigRequiredProps(option) {
}
}

// temporary change to modify the s2sConfig for new format used for endpoint URLs;
// could be removed later as part of a major release, if we decide to not support the old format
function formatUrlParams(option) {
['endpoint', 'syncEndpoint'].forEach((prop) => {
if (utils.isStr(option[prop])) {
let temp = option[prop];
option[prop] = { p1Consent: temp, noP1Consent: temp };
}
});
}

/**
* @param {(S2SConfig[]|S2SConfig)} options
*/
Expand All @@ -135,6 +146,7 @@ function setS2sConfig(options) {

const activeBidders = [];
const optionsValid = normalizedOptions.every((option, i, array) => {
formatUrlParams(options);
const updateSuccess = updateConfigDefaultVendor(option);
if (updateSuccess !== false) {
const valid = validateConfigRequiredProps(option);
Expand Down Expand Up @@ -205,7 +217,7 @@ function queueSync(bidderCodes, gdprConsent, uspConsent, s2sConfig) {
}

const jsonPayload = JSON.stringify(payload);
ajax(s2sConfig.syncEndpoint,
ajax(getMatchingConsentUrl(s2sConfig.syncEndpoint, gdprConsent),
(response) => {
try {
response = JSON.parse(response);
Expand Down Expand Up @@ -285,11 +297,20 @@ function doBidderSync(type, url, bidder, done) {
*
* @param {Array} bidders a list of bidder names
*/
function doClientSideSyncs(bidders) {
function doClientSideSyncs(bidders, gdprConsent, uspConsent) {
bidders.forEach(bidder => {
let clientAdapter = adapterManager.getBidAdapter(bidder);
if (clientAdapter && clientAdapter.registerSyncs) {
clientAdapter.registerSyncs([]);
config.runWithBidder(
bidder,
utils.bind.call(
clientAdapter.registerSyncs,
clientAdapter,
[],
gdprConsent,
uspConsent
)
);
}
});
}
Expand Down Expand Up @@ -980,6 +1001,29 @@ function bidWonHandler(bid) {
}
}

function hasPurpose1Consent(gdprConsent) {
let result = true;
if (gdprConsent) {
if (gdprConsent.gdprApplies && gdprConsent.apiVersion === 2) {
result = !!(utils.deepAccess(gdprConsent, 'vendorData.purpose.consents.1') === true);
}
}
return result;
}

function getMatchingConsentUrl(urlProp, gdprConsent) {
return hasPurpose1Consent(gdprConsent) ? urlProp.p1Consent : urlProp.noP1Consent;
}

function getConsentData(bidRequests) {
let gdprConsent, uspConsent;
if (Array.isArray(bidRequests) && bidRequests.length > 0) {
gdprConsent = bidRequests[0].gdprConsent;
uspConsent = bidRequests[0].uspConsent;
}
return { gdprConsent, uspConsent };
}

/**
* Bidder adapter for Prebid Server
*/
Expand All @@ -989,6 +1033,7 @@ export function PrebidServer() {
/* Prebid executes this function when the page asks to send out bid requests */
baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) {
const adUnits = utils.deepClone(s2sBidRequest.ad_units);
let { gdprConsent, uspConsent } = getConsentData(bidRequests);

// at this point ad units should have a size array either directly or mapped so filter for that
const validAdUnits = adUnits.filter(unit =>
Expand All @@ -1002,13 +1047,7 @@ export function PrebidServer() {
.filter(utils.uniques);

if (Array.isArray(_s2sConfigs)) {
if (s2sBidRequest.s2sConfig && s2sBidRequest.s2sConfig.syncEndpoint) {
let gdprConsent, uspConsent;
if (Array.isArray(bidRequests) && bidRequests.length > 0) {
gdprConsent = bidRequests[0].gdprConsent;
uspConsent = bidRequests[0].uspConsent;
}

if (s2sBidRequest.s2sConfig && s2sBidRequest.s2sConfig.syncEndpoint && getMatchingConsentUrl(s2sBidRequest.s2sConfig.syncEndpoint, gdprConsent)) {
let syncBidders = s2sBidRequest.s2sConfig.bidders
.map(bidder => adapterManager.aliasRegistry[bidder] || bidder)
.filter((bidder, index, array) => (array.indexOf(bidder) === index));
Expand All @@ -1021,7 +1060,7 @@ export function PrebidServer() {
utils.logInfo('BidRequest: ' + requestJson);
if (request && requestJson) {
ajax(
s2sBidRequest.s2sConfig.endpoint,
getMatchingConsentUrl(s2sBidRequest.s2sConfig.endpoint, gdprConsent),
{
success: response => handleResponse(response, requestedBidders, bidRequests, addBidResponse, done, s2sBidRequest.s2sConfig),
error: done
Expand All @@ -1037,6 +1076,7 @@ export function PrebidServer() {
function handleResponse(response, requestedBidders, bidderRequests, addBidResponse, done, s2sConfig) {
let result;
let bids = [];
let { gdprConsent, uspConsent } = getConsentData(bidderRequests);

try {
result = JSON.parse(response);
Expand All @@ -1063,7 +1103,7 @@ export function PrebidServer() {
}

done();
doClientSideSyncs(requestedBidders);
doClientSideSyncs(requestedBidders, gdprConsent, uspConsent);
}

// Listen for bid won to call wurl
Expand Down
4 changes: 2 additions & 2 deletions test/spec/modules/appnexusBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ describe('AppNexusAdapter', function () {
config.getConfig.restore();
});

it('should set withCredentials to false if purpose 1 consent is not given', function () {
it('should set simple domain variant if purpose 1 consent is not given', function () {
let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==';
let bidderRequest = {
'bidderCode': 'appnexus',
Expand All @@ -819,7 +819,7 @@ describe('AppNexusAdapter', function () {
bidderRequest.bids = bidRequests;

const request = spec.buildRequests(bidRequests, bidderRequest);
expect(request.options).to.deep.equal({withCredentials: false});
expect(request.url).to.equal('https://ib.adnxs-simple.com/ut/v3/prebid');
});

it('should populate eids when supported userIds are available', function () {
Expand Down
Loading

0 comments on commit 733cd7c

Please sign in to comment.