Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for non-purpose1 consent domains to appnexus and PBS bid adapters #6484

Merged
merged 4 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsnellbaker This looks good. One question on this piece though. Should this work the same for both client and s2s. It seems to me that the PBS Bid Adapter runs doClientSideSyncs() which in turn calls registerSyncs([]) not passing in any GDPR data when GDPR exists on the bidderRequests. I just want to understand if this is expected or not. The reason being that testing the s2s, the following always returns true since the gdprConsent value is undefined and therefore, the sync iframe runs.

if (syncOptions.iframeEnabled && hasPurpose1Consent({gdprConsent}))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmoschovas Thanks for raising this concern.

I did some digging and found that the behavior within the doClientSideSyncs function wasn't properly working with the gdprEnforcement module. It was consistently returning this warning: WARNING: User sync not allowed for null because we were not properly permitting the bidder to run this code within the special control logic that was added to the src/config.js (see runWithBidder).

I'm about to push a commit that should address the lack of consent data on this registerSync call and grant the permissions. Please take a look

CC @snapwich to take a look at the change, to ensure it's formatted properly with the config bidder permission logic (which I believe he helped design).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsnellbaker your update looks good and it does look like the server -> client syncs call not passing consent data was an oversight (possibly was added before we had standardized on the user sync call). good callout @mmoschovas

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
20 changes: 16 additions & 4 deletions modules/prebidServerBidAdapter/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@ 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
}
}
43 changes: 34 additions & 9 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 @@ -208,7 +220,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 @@ -966,6 +978,20 @@ 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;
}

/**
* Bidder adapter for Prebid Server
*/
Expand All @@ -975,6 +1001,11 @@ 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;
if (Array.isArray(bidRequests) && bidRequests.length > 0) {
gdprConsent = bidRequests[0].gdprConsent;
uspConsent = bidRequests[0].uspConsent;
}

// 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 @@ -988,13 +1019,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 @@ -1007,7 +1032,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 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