Skip to content

Commit

Permalink
appnexus bid adapter - update logic of native viewability script (pre…
Browse files Browse the repository at this point in the history
  • Loading branch information
jsnellbaker authored and JacobKlein26 committed Feb 8, 2023
1 parent 4e2f66d commit 3aa1714
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 93 deletions.
106 changes: 13 additions & 93 deletions modules/appnexusBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
getMaxValueFromArray,
getMinValueFromArray,
getParameterByName,
getUniqueIdentifierStr,
isArray,
isArrayOfNums,
isEmpty,
Expand Down Expand Up @@ -444,16 +445,6 @@ export const spec = {
}

return params;
},

/**
* Add element selector to javascript tracker to improve native viewability
* @param {Bid} bid
*/
onBidWon: function (bid) {
if (FEATURES.NATIVE && bid.native) {
reloadViewabilityScriptWithCorrectParameters(bid);
}
}
};

Expand All @@ -467,58 +458,9 @@ function deleteValues(keyPairObj) {
}
}

function reloadViewabilityScriptWithCorrectParameters(bid) {
let viewJsPayload = getAppnexusViewabilityScriptFromJsTrackers(bid.native.javascriptTrackers);

if (viewJsPayload) {
let prebidParams = 'pbjs_adid=' + bid.adId + ';pbjs_auc=' + bid.adUnitCode;

let jsTrackerSrc = getViewabilityScriptUrlFromPayload(viewJsPayload);

let newJsTrackerSrc = jsTrackerSrc.replace('dom_id=%native_dom_id%', prebidParams);

// find iframe containing script tag
let frameArray = document.getElementsByTagName('iframe');

// boolean var to modify only one script. That way if there are muliple scripts,
// they won't all point to the same creative.
let modifiedAScript = false;

// first, loop on all ifames
for (let i = 0; i < frameArray.length && !modifiedAScript; i++) {
let currentFrame = frameArray[i];
try {
// IE-compatible, see https://stackoverflow.com/a/3999191/2112089
let nestedDoc = currentFrame.contentDocument || currentFrame.contentWindow.document;

if (nestedDoc) {
// if the doc is present, we look for our jstracker
let scriptArray = nestedDoc.getElementsByTagName('script');
for (let j = 0; j < scriptArray.length && !modifiedAScript; j++) {
let currentScript = scriptArray[j];
if (currentScript.getAttribute('data-src') == jsTrackerSrc) {
currentScript.setAttribute('src', newJsTrackerSrc);
currentScript.setAttribute('data-src', '');
if (currentScript.removeAttribute) {
currentScript.removeAttribute('data-src');
}
modifiedAScript = true;
}
}
}
} catch (exception) {
// trying to access a cross-domain iframe raises a SecurityError
// this is expected and ignored
if (!(exception instanceof DOMException && exception.name === 'SecurityError')) {
// all other cases are raised again to be treated by the calling function
throw exception;
}
}
}
}
}

function strIsAppnexusViewabilityScript(str) {
if (!str || str === '') return false;

let regexMatchUrlStart = str.match(VIEWABILITY_URL_START);
let viewUrlStartInStr = regexMatchUrlStart != null && regexMatchUrlStart.length >= 1;

Expand All @@ -528,30 +470,6 @@ function strIsAppnexusViewabilityScript(str) {
return str.startsWith(SCRIPT_TAG_START) && fileNameInStr && viewUrlStartInStr;
}

function getAppnexusViewabilityScriptFromJsTrackers(jsTrackerArray) {
let viewJsPayload;
if (isStr(jsTrackerArray) && strIsAppnexusViewabilityScript(jsTrackerArray)) {
viewJsPayload = jsTrackerArray;
} else if (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 = [];
let options = {
Expand Down Expand Up @@ -633,7 +551,9 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) {
*/
function newBid(serverBid, rtbBid, bidderRequest) {
const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]);
const adId = getUniqueIdentifierStr();
const bid = {
adId: adId,
requestId: serverBid.uuid,
cpm: rtbBid.cpm,
creativeId: rtbBid.creative_id,
Expand Down Expand Up @@ -721,20 +641,20 @@ function newBid(serverBid, rtbBid, bidderRequest) {
}
} else if (FEATURES.NATIVE && rtbBid.rtb[NATIVE]) {
const nativeAd = rtbBid.rtb[NATIVE];
let viewScript;

// 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=');
if (strIsAppnexusViewabilityScript(rtbBid.viewability.config)) {
let prebidParams = 'pbjs_adid=' + adId + ';pbjs_auc=' + bidRequest.adUnitCode;
viewScript = rtbBid.viewability.config.replace('dom_id=%native_dom_id%', prebidParams);
}

let jsTrackers = nativeAd.javascript_trackers;

if (jsTrackers == undefined) {
jsTrackers = jsTrackerDisarmed;
jsTrackers = viewScript;
} else if (isStr(jsTrackers)) {
jsTrackers = [jsTrackers, jsTrackerDisarmed];
jsTrackers = [jsTrackers, viewScript];
} else {
jsTrackers.push(jsTrackerDisarmed);
jsTrackers.push(viewScript);
}

bid[NATIVE] = {
Expand Down
1 change: 1 addition & 0 deletions test/spec/modules/appnexusBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,7 @@ describe('AppNexusAdapter', function () {
it('should get correct bid response', function () {
let expectedResponse = [
{
'adId': '3a1f23123e',
'requestId': '3db3773286ee59',
'cpm': 0.5,
'creativeId': 29681110,
Expand Down
1 change: 1 addition & 0 deletions test/spec/modules/big-richmediaBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ describe('bigRichMediaAdapterTests', function () {
it('should get correct bid response', function () {
const expectedResponse = [
{
'adId': '3a1f23123e',
'requestId': '3db3773286ee59',
'cpm': 0.5,
'creativeId': 29681110,
Expand Down

0 comments on commit 3aa1714

Please sign in to comment.