diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 7dac4b8b182..01f45d30413 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -11,6 +11,8 @@ const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']; const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately +const AST_DEBUG_URL = ['ast_debug', 'ast_dongle', 'ast_debug_member', 'ast_debug_timeout'] +const AST_DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout'] const NATIVE_MAPPING = { body: 'description', cta: 'ctatext', @@ -77,6 +79,38 @@ export const spec = { }; } + let debugObj = {}; + const debugObjParams = find(bidRequests, hasDebug); + if (debugObjParams && debugObjParams.debug) { + Object.keys(debugObjParams.debug) + .filter(param => includes(AST_DEBUG_PARAMS, param)) + .forEach(param => { + debugObj['debug'] = debugObj['debug'] || {}; + debugObj.debug[param] = debugObjParams.debug[param] + }); + } + + const debugUrlParams = getURLparams(); + if (debugUrlParams && debugUrlParams.params) { + Object.keys(debugUrlParams.params) + .filter(param => includes(AST_DEBUG_URL, param)) + .forEach(param => { + debugObj['debug'] = debugObj['debug'] || {}; + if (param == 'ast_debug') { + debugObj['debug']['enabled'] = (debugUrlParams.params[param] === 'true'); + } + if (param == 'ast_dongle') { + debugObj['debug']['dongle'] = debugUrlParams.params[param]; + } + if (param == 'ast_debug_member') { + debugObj['debug']['member_id'] = parseInt(debugUrlParams.params[param], 10); + } + if (param == 'ast_debug_timeout') { + debugObj['debug']['debug_timeout'] = parseInt(debugUrlParams.params[param], 10); + } + }); + } + const memberIdBid = find(bidRequests, hasMemberId); const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; @@ -99,6 +133,10 @@ export const spec = { payload.app = appIdObj; } + if (debugObj && debugObj.debug) { + payload.debug = debugObj.debug + } + if (bidderRequest && bidderRequest.gdprConsent) { // note - objects for impbus use underscore instead of camelCase payload.gdpr_consent = { @@ -144,6 +182,21 @@ export const spec = { } }); } + + if (serverResponse.debug && serverResponse.debug.debug_info) { + let debugHeader = 'AppNexus Debug Auction for Prebid\n\n' + let debugText = debugHeader + serverResponse.debug.debug_info + debugText = debugText + .replace(/(|)/gm, '\t') // Tables + .replace(/(<\/td>|<\/th>)/gm, '\n') // Tables + .replace(/^
/gm, '') // Remove leading
+ .replace(/(
\n|
)/gm, '\n') //
+ .replace(/

(.*)<\/h1>/gm, '\n\n===== $1 =====\n\n') // Header H1 + .replace(/(.*)<\/h[2-6]>/gm, '\n\n*** $1 ***\n\n') // Headers + .replace(/(<([^>]+)>)/igm, ''); // Remove any other tags + utils.logMessage(debugText); + } + return bids; }, @@ -419,6 +472,23 @@ function hasAppId(bid) { return !!bid.params.app } +function hasDebug(bid) { + return !!bid.debug +} + +function getURLparams() { + let obj = {}; + if (utils.getTopWindowLocation() && utils.getTopWindowLocation().search) { + obj['params'] = {}; + utils.getTopWindowLocation().search.substr(1).split('&').forEach(keyvalue => { + let key = keyvalue.split('=')[0]; + let val = keyvalue.split('=')[1]; + obj['params'][key] = val + }); + } + return obj +} + function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); } diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index b65988e3ec1..111d5ad91dd 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -370,6 +370,32 @@ describe('AppNexusAdapter', () => { lng: -75.3009142 }); }); + + it('sends a debug auction', () => { + let debugRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394' + }, + debug: { + enabled: true, + dongle: 'QWERTY', + member_id: 958, + debug_timeout: 1000 + } + } + ); + const request = spec.buildRequests([debugRequest]); + const payload = JSON.parse(request.data); + expect(payload.debug).to.exist; + expect(payload.debug).to.deep.equal({ + enabled: true, + dongle: 'QWERTY', + member_id: 958, + debug_timeout: 1000 + }); + }); }) describe('interpretResponse', () => {