From e603156fba59a32e47168b2e69cc7511bad0b473 Mon Sep 17 00:00:00 2001 From: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Date: Tue, 30 Jul 2019 15:29:38 -0400 Subject: [PATCH] Appnexus native view tracker (#4022) * First pass: adding viewability script to rtbBid * Added viewability scrit in the right place * Clean up * Corrected script position, added a workaround to get the adId after the bid's creation and fixed tests * Removed debugging logs * More cleanup * Opted to append rtbBid.viewability.config to the existing (nativeAd.javascript_trackers) in the bidAdapter's newBid function * Removed AnalyticsAdaper code and added bidAdapter.onBidWon to check for our jstracker and update their src attributes. * Added a way to differentiate scripts and clean up * Changed newBid to disarm jstracker before it's ready and changed onBidWon to arm it. This prevents the tracker from being loaded twice. * Making the code more robust * Grouped code in a function. Also changed parameters to reflect that finding the element will now fall be a view_js responsability. * Changed parameter pbjs_iframeid name to pbjs_auc so its not misleading * Variable name change to better reflect its nature * Fixing URL parameters (; separated and replacing completely the useless one) * undo changes to appnexus Analytics adapter * update regex variable * update regex again --- modules/appnexusBidAdapter.js | 116 ++++++++++++++++++- src/native.js | 1 - test/spec/modules/appnexusBidAdapter_spec.js | 12 +- test/spec/unit/pbjs_api_spec.js | 12 +- 4 files changed, 134 insertions(+), 7 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 67388848815..d0f4774185e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -33,6 +33,9 @@ const NATIVE_MAPPING = { const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; const mappingFileUrl = '//acdn.adnxs.com/prebid/appnexus-mapping/mappings.json'; +const SCRIPT_TAG_START = '= 1; + + let regexMatchFileName = str.match(VIEWABILITY_FILE_NAME); + let fileNameInStr = regexMatchFileName != null && regexMatchFileName.length >= 1; + + return str.startsWith(SCRIPT_TAG_START) && fileNameInStr && viewUrlStartInStr; +} + +function getAppnexusViewabilityScriptFromJsTrackers(jsTrackerArray) { + let viewJsPayload; + if (utils.isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) { + viewJsPayload = jsTrackerArray; + } else if (utils.isArray(jsTrackerArray)) { + for (let i = 0; i < jsTrackerArray.length; i++) { + let currentJsTracker = jsTrackerArray[i]; + if (strIsAppnexusViewabilityScript(currentJsTracker)) { + viewJsPayload = currentJsTracker; + } + } + } + return viewJsPayload; +} + +function getViewabilityScriptUrlFromPayload(viewJsPayload) { + // extracting the content of the src attribute + // -> substring between src=" and " + let indexOfFirstQuote = viewJsPayload.indexOf('src="') + 5; // offset of 5: the length of 'src=' + 1 + let indexOfSecondQuote = viewJsPayload.indexOf('"', indexOfFirstQuote); + let jsTrackerSrc = viewJsPayload.substring(indexOfFirstQuote, indexOfSecondQuote); + return jsTrackerSrc; +} + function formatRequest(payload, bidderRequest) { let request = []; @@ -415,6 +513,22 @@ function newBid(serverBid, rtbBid, bidderRequest) { } } else if (rtbBid.rtb[NATIVE]) { const nativeAd = rtbBid.rtb[NATIVE]; + + // setting up the jsTracker: + // we put it as a data-src attribute so that the tracker isn't called + // until we have the adId (see onBidWon) + let jsTrackerDisarmed = rtbBid.viewability.config.replace('src=', 'data-src='); + + let jsTrackers = nativeAd.javascript_trackers; + + if (jsTrackers == undefined) { + jsTrackers = jsTrackerDisarmed; + } else if (utils.isStr(jsTrackers)) { + jsTrackers = [jsTrackers, jsTrackerDisarmed]; + } else { + jsTrackers.push(jsTrackerDisarmed); + } + bid[NATIVE] = { title: nativeAd.title, body: nativeAd.desc, @@ -433,7 +547,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { displayUrl: nativeAd.displayurl, clickTrackers: nativeAd.link.click_trackers, impressionTrackers: nativeAd.impression_trackers, - javascriptTrackers: nativeAd.javascript_trackers + javascriptTrackers: jsTrackers }; if (nativeAd.main_img) { bid['native'].image = { diff --git a/src/native.js b/src/native.js index c9a67ca7541..6252eb133b3 100644 --- a/src/native.js +++ b/src/native.js @@ -132,7 +132,6 @@ export function nativeBidIsValid(bid, bidRequests) { */ export function fireNativeTrackers(message, adObject) { let trackers; - if (message.action === 'click') { trackers = adObject['native'] && adObject['native'].clickTrackers; } else { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 30d2dc08159..e1cca8c05ff 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -665,6 +665,9 @@ describe('AppNexusAdapter', function () { 'cpm_publisher_currency': 0.5, 'publisher_currency_code': '$', 'client_initiated_ad_counting': true, + 'viewability': { + 'config': '' + }, 'rtb': { 'banner': { 'content': '', @@ -744,7 +747,8 @@ describe('AppNexusAdapter', function () { 'video': { 'content': '' } - } + }, + 'javascriptTrackers': '' }] }] }; @@ -775,6 +779,9 @@ describe('AppNexusAdapter', function () { 'content': '', 'duration_ms': 30000, } + }, + 'viewability': { + 'config': '' } }] }] @@ -831,7 +838,8 @@ describe('AppNexusAdapter', function () { 'saleprice': 'FREE', 'phone': '1234567890', 'address': '28 W 23rd St, New York, NY 10010', - 'privacy_link': 'http://appnexus.com/?url=privacy_url' + 'privacy_link': 'http://appnexus.com/?url=privacy_url', + 'javascriptTrackers': '' }; let bidderRequest = { bids: [{ diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index d4daec0c266..c73604cac82 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -434,7 +434,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -574,7 +576,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] }; @@ -606,7 +610,9 @@ describe('Unit: Prebid Module', function () { 'trackers': [{ 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] - } + }, + 'viewability': { + 'config': ''} }] }] };