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

appnexusBidAdapter 9.0 - remove transform bid params and create anPspParamsConverter module #11583

Merged
merged 4 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
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