Skip to content

Commit

Permalink
AOL adapter: Fixed broken user matching in iframes (#2125)
Browse files Browse the repository at this point in the history
* Fixed broken user matching when creative is delivering like an iframe within a DFP iframe.

* Removed unnecessary import.
  • Loading branch information
vzhukovsky authored and matthewlane committed Feb 15, 2018
1 parent f4fd825 commit 45154a0
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 77 deletions.
137 changes: 70 additions & 67 deletions modules/aolBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
import { config } from 'src/config';
import constants from 'src/constants.json';
import { EVENTS } from 'src/constants.json';

const AOL_BIDDERS_CODES = {
AOL: 'aol',
Expand Down Expand Up @@ -180,55 +180,6 @@ function _buildOneMobileGetUrl(bid) {
return nexageApi;
}

function _parseBidResponse(response, bidRequest) {
let bidData;

try {
bidData = response.seatbid[0].bid[0];
} catch (e) {
return;
}

let cpm;

if (bidData.ext && bidData.ext.encp) {
cpm = bidData.ext.encp;
} else {
cpm = bidData.price;

if (cpm === null || isNaN(cpm)) {
utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bid);
return;
}
}

let ad = bidData.adm;
if (response.ext && response.ext.pixels) {
if (config.getConfig('aol.userSyncOn') !== constants.EVENTS.BID_RESPONSE) {
let formattedPixels = response.ext.pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, '');

ad += '<script>if(!parent.$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped){' +
'parent.$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped=true;' + formattedPixels +
'}</script>';
}
}

return {
bidderCode: bidRequest.bidderCode,
requestId: bidRequest.bidId,
ad: ad,
cpm: cpm,
width: bidData.w,
height: bidData.h,
creativeId: bidData.crid,
pubapiId: response.id,
currency: response.cur,
dealId: bidData.dealid,
netRevenue: true,
ttl: bidRequest.ttl
};
}

function _isMarketplaceBidder(bidder) {
return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY;
}
Expand Down Expand Up @@ -311,20 +262,6 @@ function formatBidRequest(endpointCode, bid) {
return bidRequest;
}

function interpretResponse({body}, bidRequest) {
showCpmAdjustmentWarning();

if (!body) {
utils.logError('Empty bid response', bidRequest.bidderCode, body);
} else {
let bid = _parseBidResponse(body, bidRequest);

if (bid) {
return bid;
}
}
}

export const spec = {
code: AOL_BIDDERS_CODES.AOL,
aliases: [AOL_BIDDERS_CODES.ONEMOBILE, AOL_BIDDERS_CODES.ONEDISPLAY],
Expand All @@ -340,12 +277,78 @@ export const spec = {
}
});
},
interpretResponse: interpretResponse,
interpretResponse: function ({body}, bidRequest) {
showCpmAdjustmentWarning();

if (!body) {
utils.logError('Empty bid response', bidRequest.bidderCode, body);
} else {
let bid = this._parseBidResponse(body, bidRequest);

if (bid) {
return bid;
}
}
},
_formatPixels: function (pixels) {
let formattedPixels = pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, '');

return '<script>var w=window,prebid;' +
'for(var i=0;i<10;i++){w = w.parent;prebid=w.$$PREBID_GLOBAL$$;' +
'if(prebid && prebid.aolGlobals && !prebid.aolGlobals.pixelsDropped){' +
'try{prebid.aolGlobals.pixelsDropped=true;' + formattedPixels + 'break;}' +
'catch(e){continue;}' +
'}}</script>';
},
_parseBidResponse: function (response, bidRequest) {
let bidData;

try {
bidData = response.seatbid[0].bid[0];
} catch (e) {
return;
}

let cpm;

if (bidData.ext && bidData.ext.encp) {
cpm = bidData.ext.encp;
} else {
cpm = bidData.price;

if (cpm === null || isNaN(cpm)) {
utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bid);
return;
}
}

let ad = bidData.adm;
if (response.ext && response.ext.pixels) {
if (config.getConfig('aol.userSyncOn') !== EVENTS.BID_RESPONSE) {
ad += this._formatPixels(response.ext.pixels);
}
}

return {
bidderCode: bidRequest.bidderCode,
requestId: bidRequest.bidId,
ad: ad,
cpm: cpm,
width: bidData.w,
height: bidData.h,
creativeId: bidData.crid,
pubapiId: response.id,
currency: response.cur,
dealId: bidData.dealid,
netRevenue: true,
ttl: bidRequest.ttl
};
},
getUserSyncs: function(options, bidResponses) {
let bidResponse = bidResponses[0];

if (config.getConfig('aol.userSyncOn') === constants.EVENTS.BID_RESPONSE) {
if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse && bidResponse.ext && bidResponse.ext.pixels) {
if (config.getConfig('aol.userSyncOn') === EVENTS.BID_RESPONSE) {
if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) {
$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true;

return parsePixelItems(bidResponse.ext.pixels);
Expand Down
37 changes: 27 additions & 10 deletions test/spec/modules/aolBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as utils from 'src/utils';
import {spec} from 'modules/aolBidAdapter';
import {config} from 'src/config';

const DEFAULT_AD_CONTENT = '<script>logInfo(\'ad\');</script>';

let getDefaultBidResponse = () => {
return {
id: '245730051428950632',
Expand All @@ -12,7 +14,7 @@ let getDefaultBidResponse = () => {
id: 1,
impid: '245730051428950632',
price: 0.09,
adm: '<script>logInfo(\'ad\');</script>',
adm: DEFAULT_AD_CONTENT,
crid: 'creative-id',
h: 90,
w: 728,
Expand Down Expand Up @@ -95,6 +97,7 @@ describe('AolAdapter', () => {
let bidResponse;
let bidRequest;
let logWarnSpy;
let formatPixelsStub;

beforeEach(() => {
bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings;
Expand All @@ -107,19 +110,21 @@ describe('AolAdapter', () => {
body: getDefaultBidResponse()
};
logWarnSpy = sinon.spy(utils, 'logWarn');
formatPixelsStub = sinon.stub(spec, '_formatPixels');
});

afterEach(() => {
$$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup;
logWarnSpy.restore();
formatPixelsStub.restore();
});

it('should return formatted bid response with required properties', () => {
let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest);
expect(formattedBidResponse).to.deep.equal({
bidderCode: bidRequest.bidderCode,
requestId: 'bid-id',
ad: '<script>logInfo(\'ad\');</script>',
ad: DEFAULT_AD_CONTENT,
cpm: 0.09,
width: 728,
height: 90,
Expand All @@ -132,19 +137,15 @@ describe('AolAdapter', () => {
});
});

it('should return formatted bid response including pixels', () => {
it('should add pixels to ad content when pixels are present in the response', () => {
bidResponse.body.ext = {
pixels: '<script>document.write(\'<img src="pixel.gif">\');</script>'
pixels: 'pixels-content'
};

formatPixelsStub.returns('pixels-content');
let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest);

expect(formattedBidResponse.ad).to.equal(
'<script>logInfo(\'ad\');</script>' +
'<script>if(!parent.$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped){' +
'parent.$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped=true;' +
'document.write(\'<img src="pixel.gif">\');}</script>'
);
expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + 'pixels-content');
});

it('should show warning in the console', function() {
Expand Down Expand Up @@ -532,4 +533,20 @@ describe('AolAdapter', () => {
expect(userSyncs).to.deep.equal([]);
});
});

describe('_formatPixels()', () => {
it('should return pixels wrapped for dropping them once and within nested frames ', () => {
let pixels = '<script>document.write(\'<pixels-dom-elements/>\');</script>';
let formattedPixels = spec._formatPixels(pixels);

expect(formattedPixels).to.equal(
'<script>var w=window,prebid;' +
'for(var i=0;i<10;i++){w = w.parent;prebid=w.$$PREBID_GLOBAL$$;' +
'if(prebid && prebid.aolGlobals && !prebid.aolGlobals.pixelsDropped){' +
'try{prebid.aolGlobals.pixelsDropped=true;' +
'document.write(\'<pixels-dom-elements/>\');break;}' +
'catch(e){continue;}' +
'}}</script>');
});
})
});

0 comments on commit 45154a0

Please sign in to comment.