diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 8f8288011e6..ebd3a271ffd 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -5,7 +5,7 @@ import { VIDEO, BANNER } from 'src/mediaTypes'; import find from 'core-js/library/fn/array/find'; import includes from 'core-js/library/fn/array/includes'; -const ADAPTER_VERSION = '1.1'; +const ADAPTER_VERSION = '1.2'; const ADAPTER_NAME = 'BFIO_PREBID'; const OUTSTREAM = 'outstream'; @@ -16,6 +16,8 @@ export const OUTSTREAM_SRC = '//player-cdn.beachfrontmedia.com/playerapi/loader/ export const VIDEO_TARGETING = ['mimes']; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; +let appId = ''; + export const spec = { code: 'beachfront', supportedMediaTypes: [ VIDEO, BANNER ], @@ -29,14 +31,16 @@ export const spec = { let videoBids = bids.filter(bid => isVideoBidValid(bid)); let bannerBids = bids.filter(bid => isBannerBidValid(bid)); videoBids.forEach(bid => { + appId = getVideoBidParam(bid, 'appId'); requests.push({ method: 'POST', - url: VIDEO_ENDPOINT + getVideoBidParam(bid, 'appId'), + url: VIDEO_ENDPOINT + appId, data: createVideoRequestData(bid, bidderRequest), bidRequest: bid }); }); if (bannerBids.length) { + appId = getBannerBidParam(bannerBids[0], 'appId'); requests.push({ method: 'POST', url: BANNER_ENDPOINT, @@ -77,23 +81,56 @@ export const spec = { utils.logWarn(`No valid banner bids from ${spec.code} bidder`); return []; } - return response.map((bid) => { - let request = find(bidRequest, req => req.adUnitCode === bid.slot); - return { - requestId: request.bidId, - bidderCode: spec.code, - ad: bid.adm, - creativeId: bid.crid, - cpm: bid.price, - width: bid.w, - height: bid.h, - mediaType: BANNER, - currency: 'USD', - netRevenue: true, - ttl: 300 - }; + return response + .filter(bid => bid.adm) + .map((bid) => { + let request = find(bidRequest, req => req.adUnitCode === bid.slot); + return { + requestId: request.bidId, + bidderCode: spec.code, + ad: bid.adm, + creativeId: bid.crid, + cpm: bid.price, + width: bid.w, + height: bid.h, + mediaType: BANNER, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; + }); + } + }, + + getUserSyncs(syncOptions, serverResponses = [], gdprConsent = {}) { + let syncs = []; + let { gdprApplies, consentString } = gdprConsent; + let bannerResponse = find(serverResponses, (res) => utils.isArray(res.body)); + + if (bannerResponse) { + if (syncOptions.iframeEnabled) { + bannerResponse.body + .filter(bid => bid.sync) + .forEach(bid => { + syncs.push({ + type: 'iframe', + url: bid.sync + }); + }); + } + } else if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: `//sync.bfmio.com/sync_iframe?ifg=1&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` + }); + } else if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: `//sync.bfmio.com/syncb?pid=144&id=${appId}&gdpr=${gdprApplies ? 1 : 0}&gc=${consentString || ''}&gce=1` }); } + + return syncs; } }; diff --git a/modules/beachfrontBidAdapter.md b/modules/beachfrontBidAdapter.md index 90c726633b8..5defb358f7b 100644 --- a/modules/beachfrontBidAdapter.md +++ b/modules/beachfrontBidAdapter.md @@ -60,7 +60,7 @@ Module that connects to Beachfront's demand sources code: 'test-video-banner', mediaTypes: { video: { - context: 'instream', + context: 'outstream', playerSize: [ 640, 360 ] }, banner: { diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index a3ecccba6cb..8f2e210694d 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -554,4 +554,119 @@ describe('BeachfrontAdapter', () => { }); }); }); + + describe('spec.getUserSyncs', () => { + describe('for video bids', () => { + let bidResponse; + + beforeEach(() => { + bidResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + }); + + it('should return an iframe user sync if iframes are enabled', () => { + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs.length).to.equal(1); + expect(userSyncs[0].type).to.equal('iframe'); + }); + + it('should return an image user sync if iframes are disabled', () => { + const syncOptions = { + iframeEnabled: false, + pixelEnabled: true + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs.length).to.equal(1); + expect(userSyncs[0].type).to.equal('image'); + }); + + it('should not return user syncs if none are enabled', () => { + const syncOptions = { + iframeEnabled: false, + pixelEnabled: false + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + }); + + describe('for banner bids', () => { + let bidResponse; + + beforeEach(() => { + bidResponse = { + slot: bidRequests[0].adUnitCode, + adm: '
', + crid: 'crid_1', + price: 3.02, + w: 728, + h: 90 + }; + }); + + it('should return user syncs defined the bid response', () => { + const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + { sync: syncUrl }, + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([ + { type: 'iframe', url: syncUrl } + ]); + }); + + it('should not return user syncs if iframes are disabled', () => { + const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncOptions = { + iframeEnabled: false, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + { sync: syncUrl }, + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + + it('should not return user syncs if there are none in the bid response', () => { + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + }); + }); });