Skip to content

Commit

Permalink
appnexusBidAdapter 9.0 - remove transform bid params and create anPsp…
Browse files Browse the repository at this point in the history
…ParamsConverter module (#11583)

* appnexusBidAdapter 9.0 - move transformBidParams logic to module

* fix lint errors in test file

* rework logic that reads bidderRequests
  • Loading branch information
jsnellbaker authored May 30, 2024
1 parent 4cbb8d4 commit 7619d0a
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 141 deletions.
16 changes: 16 additions & 0 deletions libraries/appnexusUtils/anUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ export function convertCamelToUnderscore(value) {
}).replace(/^_/, '');
}

export const appnexusAliases = [
{ code: 'appnexusAst', gvlid: 32 },
{ code: 'emxdigital', gvlid: 183 },
{ code: 'emetriq', gvlid: 213 },
{ code: 'pagescience', gvlid: 32 },
{ code: 'gourmetads', gvlid: 32 },
{ code: 'matomy', gvlid: 32 },
{ code: 'featureforward', gvlid: 32 },
{ code: 'oftmedia', gvlid: 32 },
{ code: 'adasta', gvlid: 32 },
{ code: 'beintoo', gvlid: 618 },
{ code: 'projectagora', gvlid: 1032 },
{ code: 'uol', gvlid: 32 },
{ code: 'adzymic', gvlid: 723 },
];

/**
* Creates an array of n length and fills each item with the given value
*/
Expand Down
128 changes: 128 additions & 0 deletions modules/anPspParamsConverter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
- register a hook function on the makeBidRequests hook (after the main function ran)
- this hook function will:
1. verify s2sconfig is defined and we (or our aliases) are included to the config
2. filter bidRequests that match to our bidderName or any registered aliases
3. for each request, read the bidderRequests.bids[].params to modify the keys/values
a. in particular change the keywords structure, apply underscore casing for keys, adjust use_payment_rule name, and convert certain values' types
b. will import some functions from the anKeywords library, but ideally should be kept separate to avoid including this code when it's not needed (strict client-side setups) and avoid the rest of the appnexus adapter's need for inclusion for those strictly server-side setups.
*/

// import { CONSTANTS } from '../src/cons tants.js';
import {isArray, isPlainObject, isStr} from '../src/utils.js';
import {getHook} from '../src/hook.js';
import {config} from '../src/config.js';
import {convertCamelToUnderscore, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js';
import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js';
import adapterManager from '../src/adapterManager.js';

// keywords: { 'genre': ['rock', 'pop'], 'pets': ['dog'] } goes to 'genre=rock,genre=pop,pets=dog'
function convertKeywordsToString(keywords) {
let result = '';
Object.keys(keywords).forEach(key => {
// if 'text' or ''
if (isStr(keywords[key])) {
if (keywords[key] !== '') {
result += `${key}=${keywords[key]},`
} else {
result += `${key},`;
}
} else if (isArray(keywords[key])) {
if (keywords[key][0] === '') {
result += `${key},`
} else {
keywords[key].forEach(val => {
result += `${key}=${val},`
});
}
}
});

// remove last trailing comma
result = result.substring(0, result.length - 1);
return result;
}

function digForAppNexusBidder(s2sConfig) {
let result = false;
// check for plain setup
if (s2sConfig?.bidders?.includes('appnexus')) result = true;

// registered aliases
const aliasList = appnexusAliases.map(aliasObj => (aliasObj.code));
if (!result && s2sConfig?.bidders?.filter(s2sBidder => aliasList.includes(s2sBidder)).length > 0) result = true;

// pbjs.aliasBidder
if (!result) {
result = !!(s2sConfig?.bidders?.find(bidder => (adapterManager.resolveAlias(bidder) === 'appnexus')));
}

return result;
}

// need a separate check b/c we're checking a specific bidRequest to see if we modify it, not just that we have a server-side bidder somewhere in prebid.js
// function isThisOurBidderInDisguise(tarBidder, s2sConfig) {
// if (tarBidder === 'appnexus') return true;

// if (isPlainObject(s2sConfig?.extPrebid?.aliases) && !!(Object.entries(s2sConfig?.extPrebid?.aliases).find((pair) => (pair[0] === tarBidder && pair[1] === 'appnexus')))) return true;

// if (appnexusAliases.map(aliasObj => (aliasObj.code)).includes(tarBidder)) return true;

// if (adapterManager.resolveAlias(tarBidder) === 'appnexus') return true;

// return false;
// }

export function convertAnParams(next, bidderRequests) {
// check s2sconfig
const s2sConfig = config.getConfig('s2sConfig');
let proceed = false;

if (isPlainObject(s2sConfig)) {
proceed = digForAppNexusBidder(s2sConfig);
} else if (isArray(s2sConfig)) {
s2sConfig.forEach(s2sCfg => {
proceed = digForAppNexusBidder(s2sCfg);
});
}

if (proceed) {
bidderRequests
.flatMap(br => br.bids)
.filter(bid => bid.src === 's2s' && adapterManager.resolveAlias(bid.bidder) === 'appnexus')
.forEach((bid) => {
transformBidParams(bid);
});
}

next(bidderRequests);
}

function transformBidParams(bid) {
let params = bid.params;
if (params) {
params = convertTypes({
'member': 'string',
'invCode': 'string',
'placementId': 'number',
'keywords': convertKeywordsToString,
'publisherId': 'number'
}, params);

Object.keys(params).forEach(paramKey => {
let convertedKey = convertCamelToUnderscore(paramKey);
if (convertedKey !== paramKey) {
params[convertedKey] = params[paramKey];
delete params[paramKey];
}
});

params.use_pmt_rule = (typeof params.use_payment_rule === 'boolean') ? params.use_payment_rule : false;
if (params.use_payment_rule) {
delete params.use_payment_rule;
}
}
}

getHook('makeBidRequests').after(convertAnParams, 9);
10 changes: 10 additions & 0 deletions modules/anPspParamsConverter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Quick Summary

This module is a temporary measure for publishers running Prebid.js 9.0+ and using the AppNexus PSP endpoint through their Prebid.js setup. Please ensure to include this module in your builds of Prebid.js 9.0+, otherwise requests to PSP may not complete successfully.

## Module's purpose

This module replicates certain functionality that was previously stored in the appnexusBidAdapter.js file within a function named transformBidParams.

This transformBidParams was a standard function in all adapters, which helped to change/modify the params and their values to a format that matched the bidder's request structure on the server-side endpoint. In Prebid.js 9.0, this standard function was removed in all adapter files, so that the whole client-side file (eg appnexusBidAdapter.js) wouldn't have to be included in a prebid.js build file that was meant for server-side bidders.

93 changes: 3 additions & 90 deletions modules/appnexusBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ import {APPNEXUS_CATEGORY_MAPPING} from '../libraries/categoryTranslationMapping
import {
convertKeywordStringToANMap,
getANKewyordParamFromMaps,
getANKeywordParam,
transformBidderParamKeywords
getANKeywordParam
} from '../libraries/appnexusUtils/anKeywords.js';
import {convertCamelToUnderscore, fill} from '../libraries/appnexusUtils/anUtils.js';
import {convertCamelToUnderscore, fill, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js';
import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js';
import {chunk} from '../libraries/chunk/chunk.js';

Expand Down Expand Up @@ -108,21 +107,7 @@ const storage = getStorageManager({bidderCode: BIDDER_CODE});
export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
aliases: [
{ code: 'appnexusAst', gvlid: 32 },
{ code: 'emxdigital', gvlid: 183 },
{ code: 'emetriq', gvlid: 213 },
{ code: 'pagescience', gvlid: 32 },
{ code: 'gourmetads', gvlid: 32 },
{ code: 'matomy', gvlid: 32 },
{ code: 'featureforward', gvlid: 32 },
{ code: 'oftmedia', gvlid: 32 },
{ code: 'adasta', gvlid: 32 },
{ code: 'beintoo', gvlid: 618 },
{ code: 'projectagora', gvlid: 1032 },
{ code: 'uol', gvlid: 32 },
{ code: 'adzymic', gvlid: 723 },
],
aliases: appnexusAliases,
supportedMediaTypes: [BANNER, VIDEO, NATIVE],

/**
Expand Down Expand Up @@ -449,51 +434,6 @@ export const spec = {
url: 'https://acdn.adnxs.com/dmp/async_usersync.html'
}];
}
},

transformBidParams: function (params, isOpenRtb, adUnit, bidRequests) {
let conversionFn = transformBidderParamKeywords;
if (isOpenRtb === true) {
let s2sEndpointUrl = null;
let s2sConfig = config.getConfig('s2sConfig');

if (isPlainObject(s2sConfig)) {
s2sEndpointUrl = deepAccess(s2sConfig, 'endpoint.p1Consent');
} else if (isArray(s2sConfig)) {
s2sConfig.forEach(s2sCfg => {
if (includes(s2sCfg.bidders, adUnit.bids[0].bidder)) {
s2sEndpointUrl = deepAccess(s2sCfg, 'endpoint.p1Consent');
}
});
}

if (s2sEndpointUrl && s2sEndpointUrl.match('/openrtb2/prebid')) {
conversionFn = convertKeywordsToString;
}
}

params = convertTypes({
'member': 'string',
'invCode': 'string',
'placementId': 'number',
'keywords': conversionFn,
'publisherId': 'number'
}, params);

if (isOpenRtb) {
Object.keys(params).forEach(paramKey => {
let convertedKey = convertCamelToUnderscore(paramKey);
if (convertedKey !== paramKey) {
params[convertedKey] = params[paramKey];
delete params[paramKey];
}
});

params.use_pmt_rule = (typeof params.use_payment_rule === 'boolean') ? params.use_payment_rule : false;
if (params.use_payment_rule) { delete params.use_payment_rule; }
}

return params;
}
};

Expand Down Expand Up @@ -1256,31 +1196,4 @@ function getBidFloor(bid) {
return null;
}

// keywords: { 'genre': ['rock', 'pop'], 'pets': ['dog'] } goes to 'genre=rock,genre=pop,pets=dog'
function convertKeywordsToString(keywords) {
let result = '';
Object.keys(keywords).forEach(key => {
// if 'text' or ''
if (isStr(keywords[key])) {
if (keywords[key] !== '') {
result += `${key}=${keywords[key]},`
} else {
result += `${key},`;
}
} else if (isArray(keywords[key])) {
if (keywords[key][0] === '') {
result += `${key},`
} else {
keywords[key].forEach(val => {
result += `${key}=${val},`
});
}
}
});

// remove last trailing comma
result = result.substring(0, result.length - 1);
return result;
}

registerBidder(spec);
Loading

0 comments on commit 7619d0a

Please sign in to comment.