diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index ccf565df5da..94136839e74 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -13,10 +13,10 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: ['banner'], /** - * Determines whether or not the given bid request is valid. - * @param {object} bid, bid to validate - * @return boolean, true if valid, otherwise false - */ + * Determines whether or not the given bid request is valid. + * @param {object} bid, bid to validate + * @return boolean, true if valid, otherwise false + */ isBidRequestValid: function(bid) { return !!(bid && bid.adUnitCode && bid.bidId); }, @@ -41,13 +41,19 @@ export const spec = { h: localWindow.innerHeight, userConsent: JSON.stringify({ // case of undefined, stringify will remove param - gdprApplies: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : undefined, - cmp: bidderRequest && bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : undefined + gdprApplies: + bidderRequest && bidderRequest.gdprConsent + ? bidderRequest.gdprConsent.gdprApplies + : undefined, + cmp: + bidderRequest && bidderRequest.gdprConsent + ? bidderRequest.gdprConsent.consentString + : undefined }), - us_privacy: bidderRequest && bidderRequest.us_privacy, + us_privacy: bidderRequest && bidderRequest.us_privacy }; - bidRequests.forEach((request) => { + bidRequests.forEach(request => { serverRequest.p.push(addPlacement(request)); const pubcid = getId(request, 'pubcid'); if (pubcid) { @@ -61,6 +67,10 @@ export const spec = { if (tdid) { serverRequest.tdid = tdid; } + const criteoId = getId(request, 'criteoId'); + if (criteoId) { + serverRequest.cri_prebid = criteoId; + } if (request.schain) { serverRequest.schain = JSON.stringify(request.schain); } @@ -70,7 +80,7 @@ export const spec = { method: 'GET', url: SERVER_ENDPOINT, data: serverRequest - } + }; }, /** * Makes Yieldmo Ad Server response compatible to Prebid specs @@ -81,7 +91,7 @@ export const spec = { let bids = []; let data = serverResponse.body; if (data.length > 0) { - data.forEach((response) => { + data.forEach(response => { if (response.cpm && response.cpm > 0) { bids.push(createNewBid(response)); } @@ -91,15 +101,17 @@ export const spec = { }, getUserSync: function(syncOptions) { if (trackingEnabled(syncOptions)) { - return [{ - type: 'iframe', - url: SYNC_ENDPOINT + utils.getOrigin() - }]; + return [ + { + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin() + } + ]; } else { return []; } } -} +}; registerBidder(spec); /*************************************** @@ -115,7 +127,7 @@ function addPlacement(request) { placement_id: request.adUnitCode, callback_id: request.bidId, sizes: request.mediaTypes.banner.sizes - } + }; if (request.params) { if (request.params.placementId) { placementInfo.ym_placement_id = request.params.placementId; @@ -128,9 +140,9 @@ function addPlacement(request) { } /** - * creates a new bid with response information - * @param response server response - */ + * creates a new bid with response information + * @param response server response + */ function createNewBid(response) { return { requestId: response['callback_id'], @@ -150,23 +162,25 @@ function createNewBid(response) { * @returns false if dnt or if not iframe/pixel enabled */ function trackingEnabled(options) { - return (isIOS() && !getDNT() && options.iframeEnabled); + return isIOS() && !getDNT() && options.iframeEnabled; } /** - * Detects whether we're in iOS - * @returns true if in iOS - */ + * Detects whether we're in iOS + * @returns true if in iOS + */ function isIOS() { return /iPhone|iPad|iPod/i.test(window.navigator.userAgent); } /** - * Detects whether dnt is true - * @returns true if user enabled dnt - */ + * Detects whether dnt is true + * @returns true if user enabled dnt + */ function getDNT() { - return window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false; + return ( + window.doNotTrack === '1' || window.navigator.doNotTrack === '1' || false + ); } /** @@ -174,7 +188,9 @@ function getDNT() { */ function getPageDescription() { if (document.querySelector('meta[name="description"]')) { - return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + return document + .querySelector('meta[name="description"]') + .getAttribute('content'); // Value of the description metadata from the publisher's page. } else { return ''; } @@ -200,9 +216,9 @@ function getPageDescription() { */ /** - * Detects what environment we're in - * @returns Environment kind - */ + * Detects what environment we're in + * @returns Environment kind + */ function getEnvironment() { if (isSuperSandboxedIframe()) { return 89; @@ -228,28 +244,31 @@ function getEnvironment() { } /** - * @returns true if we are running on the top window at dispatch time - */ + * @returns true if we are running on the top window at dispatch time + */ function isCodeOnPage() { return window === window.parent; } /** - * @returns true if the environment is both DFP and AMP - */ + * @returns true if the environment is both DFP and AMP + */ function isDfpInAmp() { return isDfp() && isAmp(); } /** - * @returns true if the window is in an iframe whose id and parent element id match DFP - */ + * @returns true if the window is in an iframe whose id and parent element id match DFP + */ function isDfp() { try { const frameElement = window.frameElement; const parentElement = window.frameElement.parentNode; if (frameElement && parentElement) { - return frameElement.id.indexOf('google_ads_iframe') > -1 && parentElement.id.indexOf('google_ads_iframe') > -1; + return ( + frameElement.id.indexOf('google_ads_iframe') > -1 && + parentElement.id.indexOf('google_ads_iframe') > -1 + ); } return false; } catch (e) { @@ -258,8 +277,8 @@ function isDfp() { } /** -* @returns true if there is an AMP context object -*/ + * @returns true if there is an AMP context object + */ function isAmp() { try { const ampContext = window.context || window.parent.context; @@ -285,7 +304,11 @@ function isSafeFrame() { function isDFPSafeFrame() { if (window.location && window.location.href) { const href = window.location.href; - return isSafeFrame() && href.indexOf('google') !== -1 && href.indexOf('safeframe') !== -1; + return ( + isSafeFrame() && + href.indexOf('google') !== -1 && + href.indexOf('safeframe') !== -1 + ); } return false; } @@ -318,7 +341,7 @@ function isSuperSandboxedIframe() { * @returns true if the window has the attribute identifying MRAID */ function isMraid() { - return !!(window.mraid); + return !!window.mraid; } /** @@ -329,7 +352,12 @@ function isMraid() { */ function getId(request, idType) { let id; - if (request && request.userId && request.userId[idType] && typeof request.userId === 'object') { + if ( + request && + request.userId && + request.userId[idType] && + typeof request.userId === 'object' + ) { id = request.userId[idType]; } return id; diff --git a/modules/yieldmoBidAdapter.md b/modules/yieldmoBidAdapter.md index ef5f07a4eb9..0f86d2507d1 100644 --- a/modules/yieldmoBidAdapter.md +++ b/modules/yieldmoBidAdapter.md @@ -4,6 +4,7 @@ Module Name: Yieldmo Bid Adapter Module Type: Bidder Adapter Maintainer: opensource@yieldmo.com +Note: Our ads will only render in mobile ``` # Description diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index 6a4a142975f..4e962e7a2af 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -8,44 +8,48 @@ describe('YieldmoAdapter', function () { const ENDPOINT = 'https://ads.yieldmo.com/exchange/prebid'; let tdid = '8d146286-91d4-4958-aff4-7e489dd1abd6'; + let criteoId = 'aff4'; let bid = { bidder: 'yieldmo', params: { - bidFloor: 0.1 + bidFloor: 0.1, }, adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', crumbs: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da', }, userId: { tdid, - } + }, }; let bidArray = [bid]; let bidderRequest = { - 'bidderCode': 'yieldmo', - 'auctionId': 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', - 'bidderRequestId': '14c4ede8c693f', - 'bids': bidArray, - 'auctionStart': 1520001292880, - 'timeout': 3000, - 'start': 1520001292884, - 'doneCbCallCount': 0, - 'refererInfo': { - 'numIframes': 1, - 'reachedTop': true, - 'referer': 'yieldmo.com' - } - } + bidderCode: 'yieldmo', + auctionId: 'e3a336ad-2761-4a1c-b421-ecc7c5294a34', + bidderRequestId: '14c4ede8c693f', + bids: bidArray, + auctionStart: 1520001292880, + timeout: 3000, + start: 1520001292884, + doneCbCallCount: 0, + refererInfo: { + numIframes: 1, + reachedTop: true, + referer: 'yieldmo.com', + }, + }; describe('isBidRequestValid', function () { it('should return true when necessary information is found', function () { @@ -77,38 +81,44 @@ describe('YieldmoAdapter', function () { }); it('should not blow up if crumbs is undefined', function () { - let bidArray = [ - { ...bid, crumbs: undefined } - ] - expect(function () { spec.buildRequests(bidArray, bidderRequest) }).not.to.throw() - }) + let bidArray = [{ ...bid, crumbs: undefined }]; + expect(function () { + spec.buildRequests(bidArray, bidderRequest); + }).not.to.throw(); + }); it('should place bid information into the p parameter of data', function () { let placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]'); + expect(placementInfo).to.equal( + '[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1}]' + ); bidArray.push({ bidder: 'yieldmo', params: { - bidFloor: 0.2 + bidFloor: 0.2, }, adUnitCode: 'adunit-code-1', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '123456789', bidderRequestId: '987654321', auctionId: '0246810', crumbs: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da' - } - + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da', + }, }); // multiple placements placementInfo = spec.buildRequests(bidArray, bidderRequest).data.p; - expect(placementInfo).to.equal('[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]'); + expect(placementInfo).to.equal( + '[{"placement_id":"adunit-code","callback_id":"30b31c1838de1e","sizes":[[300,250],[300,600]],"bidFloor":0.1},{"placement_id":"adunit-code-1","callback_id":"123456789","sizes":[[300,250],[300,600]],"bidFloor":0.2}]' + ); }); it('should add placement id if given', function () { @@ -145,18 +155,23 @@ describe('YieldmoAdapter', function () { adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: { - pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' - } + pubcid: 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2', + }, }; const data = spec.buildRequests([pubcidBid], bidderRequest).data; - expect(data.pubcid).to.deep.equal('c604130c-0144-4b63-9bf2-c2bd8c8d86da2'); + expect(data.pubcid).to.deep.equal( + 'c604130c-0144-4b63-9bf2-c2bd8c8d86da2' + ); }); it('should add unified id as parameter of request', function () { @@ -166,31 +181,60 @@ describe('YieldmoAdapter', function () { adUnitCode: 'adunit-code', mediaTypes: { banner: { - sizes: [[300, 250], [300, 600]] - } + sizes: [ + [300, 250], + [300, 600], + ], + }, }, bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', auctionId: '1d1a030790a475', userId: { tdid, - } + }, }; const data = spec.buildRequests([unifiedIdBid], bidderRequest).data; expect(data.tdid).to.deep.equal(tdid); }); + it('should add CRITEO RTUS id as parameter of request', function () { + const criteoIdBid = { + bidder: 'yieldmo', + params: {}, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600], + ], + }, + }, + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + userId: { + criteoId, + }, + }; + const data = spec.buildRequests([criteoIdBid], bidderRequest).data; + expect(data.cri_prebid).to.deep.equal(criteoId); + }); + it('should add gdpr information to request if available', () => { bidderRequest.gdprConsent = { - 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', - 'vendorData': {'blerp': 1}, - 'gdprApplies': true - } + consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + vendorData: { blerp: 1 }, + gdprApplies: true, + }; const data = spec.buildRequests(bidArray, bidderRequest).data; - expect(data.userConsent).equal(JSON.stringify({ - 'gdprApplies': true, - 'cmp': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==' - })); + expect(data.userConsent).equal( + JSON.stringify({ + gdprApplies: true, + cmp: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + }) + ); }); it('should add ccpa information to request if available', () => { @@ -201,11 +245,15 @@ describe('YieldmoAdapter', function () { }); it('should add schain if it is in the bidRequest', () => { - const schain = {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'indirectseller.com', 'sid': '00001', 'hp': 1}]}; + const schain = { + ver: '1.0', + complete: 1, + nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }], + }; bidArray[0].schain = schain; const request = spec.buildRequests([bidArray[0]], bidderRequest); expect(request.data.schain).equal(JSON.stringify(schain)); - }) + }); }); describe('interpretResponse', function () { @@ -213,17 +261,20 @@ describe('YieldmoAdapter', function () { beforeEach(function () { serverResponse = { - body: [{ - callback_id: '21989fdbef550a', - cpm: 3.45455, - width: 300, - height: 250, - ad: '
', - creative_id: '9874652394875' - }], - header: 'header?' + body: [ + { + callback_id: '21989fdbef550a', + cpm: 3.45455, + width: 300, + height: 250, + ad: + '
', + creative_id: '9874652394875', + }, + ], + header: 'header?', }; - }) + }); it('should correctly reorder the server response', function () { const newResponse = spec.interpretResponse(serverResponse); @@ -237,7 +288,8 @@ describe('YieldmoAdapter', function () { currency: 'USD', netRevenue: true, ttl: 300, - ad: '
' + ad: + '
', }); }); @@ -248,7 +300,7 @@ describe('YieldmoAdapter', function () { serverResponse.body[0].cpm = null; response = spec.interpretResponse(serverResponse); - expect(response).to.deep.equal([]) + expect(response).to.deep.equal([]); }); }); @@ -256,15 +308,17 @@ describe('YieldmoAdapter', function () { const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; let options = { iframeEnabled: true, - pixelEnabled: true + pixelEnabled: true, }; it('should return a tracker with type and url as parameters', function () { if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { - expect(spec.getUserSync(options)).to.deep.equal([{ - type: 'iframe', - url: SYNC_ENDPOINT + utils.getOrigin() - }]); + expect(spec.getUserSync(options)).to.deep.equal([ + { + type: 'iframe', + url: SYNC_ENDPOINT + utils.getOrigin(), + }, + ]); options.iframeEnabled = false; expect(spec.getUserSync(options)).to.deep.equal([]);