From f169a8514d0ae8b3fe70030c82ef545eaa17cac2 Mon Sep 17 00:00:00 2001 From: Cameron Hotchkies Date: Wed, 28 Feb 2018 15:25:00 -0800 Subject: [PATCH] RockYou Adapter: Update for multiple ad unit support (#2198) * RockYou Adapter: Added RockYou Adapter supporting Prebid 1.0 * RockYou Adapter: Removed extraneous imports, replaced a for loop w/ forEach for variable scoping. * RockYou Adapter: Updated the size handling to allow for multiple size definitions to be handled successfully * RockYou Adapter: Ad Size / Multiple Ad Unit update (#1) RockYou Adapter: * Updated to support size coming from the mediaTypes object, multiple AdUnit support * RockYou Adapter: Readme updates * RockYou Adapter: explicitly pass request.bidId in the response object * RockYou Adapter: Updated sync URL --- modules/rockyouBidAdapter.js | 107 +++++++++++--------- modules/rockyouBidAdapter.md | 17 ++-- test/spec/modules/rockyouBidAdapter_spec.js | 87 +++++++++++----- 3 files changed, 129 insertions(+), 82 deletions(-) diff --git a/modules/rockyouBidAdapter.js b/modules/rockyouBidAdapter.js index 975756d18bc..0748d6842a6 100644 --- a/modules/rockyouBidAdapter.js +++ b/modules/rockyouBidAdapter.js @@ -6,9 +6,9 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'rockyou'; const BASE_REQUEST_PATH = 'https://tas.rockyou.net/servlet/rotator/'; -const IFRAME_SYNC_URL = 'https://prebid.tex-sync.rockyou.net/usersync2/tas'; +const IFRAME_SYNC_URL = 'https://prebid.tas-sync.rockyou.net/usersync2/prebid'; const VAST_PLAYER_LOCATION = 'https://rya-static.rockyou.com/rya/js/PreBidPlayer.js'; -export const ROTATION_ZONE = 'openrtbprod'; +export const ROTATION_ZONE = 'prod'; let isBidRequestValid = (bid) => { return !!bid.params && !!bid.params.placementId; @@ -52,17 +52,27 @@ let extractValidSize = (bidRequest) => { let width = null; let height = null; - if (!utils.isEmpty(bidRequest.sizes)) { - // Ensure the size array is normalized - let conformingSize = utils.parseSizesInput(bidRequest.sizes); + let requestedSizes = []; + let mediaTypes = bidRequest.mediaTypes; + if (mediaTypes && ((mediaTypes.banner && mediaTypes.banner.sizes) || (mediaTypes.video && mediaTypes.video.playerSize))) { + if (mediaTypes.banner) { + requestedSizes = mediaTypes.banner.sizes; + } else { + requestedSizes = [mediaTypes.video.playerSize]; + } + } else if (!utils.isEmpty(bidRequest.sizes)) { + requestedSizes = bidRequest.sizes + } - if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { - // Currently only the first size is utilized - let splitSizes = conformingSize[0].split('x'); + // Ensure the size array is normalized + let conformingSize = utils.parseSizesInput(requestedSizes); - width = parseInt(splitSizes[0]); - height = parseInt(splitSizes[1]); - } + if (!utils.isEmpty(conformingSize) && conformingSize[0] != null) { + // Currently only the first size is utilized + let splitSizes = conformingSize[0].split('x'); + + width = parseInt(splitSizes[0]); + height = parseInt(splitSizes[1]); } return { @@ -109,22 +119,14 @@ let generateImpBody = (bidRequest) => { }; } -let generatePayload = (bidRequests) => { +let generatePayload = (bidRequest) => { // Generate the expected OpenRTB payload - let rootBidRequest = bidRequests[0]; - - let index = 1; - bidRequests.forEach((bidRequest) => { - bidRequest.index = index; - index += 1; - }) - let payload = { - id: determineOptimalRequestId(rootBidRequest), - site: buildSiteComponent(rootBidRequest), - device: buildDeviceComponent(rootBidRequest), - imp: bidRequests.map(generateImpBody) + id: determineOptimalRequestId(bidRequest), + site: buildSiteComponent(bidRequest), + device: buildDeviceComponent(bidRequest), + imp: [generateImpBody(bidRequest)] }; return JSON.stringify(payload); @@ -165,37 +167,42 @@ let buildRequests = (validBidRequests, requestRoot) => { let adUnitCode = null; let rendererOverride = null; + let results = []; // Due to the nature of how URLs are generated, there must // be at least one bid request present for this to function // correctly if (!utils.isEmpty(validBidRequests)) { - let headBidRequest = validBidRequests[0]; - - let serverLocations = overridableProperties(headBidRequest); - - // requestUrl is the full endpoint w/ relevant adspot paramters - let placementId = determineOptimalPlacementId(headBidRequest); - requestUrl = `${serverLocations.baseRequestPath}${placementId}/0/vo?z=${serverLocations.rotationZone}`; - - // requestPayload is the POST body JSON for the OpenRtb request - requestPayload = generatePayload(validBidRequests); - - mediaTypes = headBidRequest.mediaTypes; - adUnitCode = headBidRequest.adUnitCode; - rendererOverride = headBidRequest.rendererOverride; + results = validBidRequests.map( + bidRequest => { + let serverLocations = overridableProperties(bidRequest); + + // requestUrl is the full endpoint w/ relevant adspot paramters + let placementId = determineOptimalPlacementId(bidRequest); + requestUrl = `${serverLocations.baseRequestPath}${placementId}/0/vo?z=${serverLocations.rotationZone}`; + + // requestPayload is the POST body JSON for the OpenRtb request + requestPayload = generatePayload(bidRequest); + + mediaTypes = bidRequest.mediaTypes; + adUnitCode = bidRequest.adUnitCode; + rendererOverride = bidRequest.rendererOverride; + + return { + method: requestType, + type: requestType, + url: requestUrl, + data: requestPayload, + mediaTypes, + requestId: requestRoot.bidderRequestId, + bidId: bidRequest.bidId, + adUnitCode, + rendererOverride + }; + } + ); } - const result = { - method: requestType, - type: requestType, - url: requestUrl, - data: requestPayload, - mediaTypes, - requestId: requestRoot.bidderRequestId, - adUnitCode, - rendererOverride - }; - return result; + return results; }; let outstreamRender = (bid) => { @@ -308,7 +315,7 @@ let interpretResponse = (serverResponse, request) => { } let response = { - requestId: responseBody.id, + requestId: request.bidId, cpm: bid.price, width: bidWidth, height: bidHeight, diff --git a/modules/rockyouBidAdapter.md b/modules/rockyouBidAdapter.md index 8cc9ba371d7..1c6d2708b99 100644 --- a/modules/rockyouBidAdapter.md +++ b/modules/rockyouBidAdapter.md @@ -24,13 +24,16 @@ var adUnits = [ // Banner adUnit { code: 'banner-div', - sizes: [[720, 480]], + mediaTypes: { + banner: { + sizes: [[720, 480]] + } + }, - // Replace this object to test a new Adapter! bids: [{ bidder: 'rockyou', params: { - placementId: '4322' + placementId: '4954' } }] }, @@ -38,18 +41,16 @@ var adUnits = [ // Video (outstream) { code: 'video-outstream', - sizes: [[720, 480]], - - mediaType: 'video', mediaTypes: { video: { - context: 'outstream' + context: 'outstream', + playerSize: [720, 480] } }, bids: [{ bidder: 'rockyou', params: { - placementId: '4307' + placementId: '4957' } }] } diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index 8b38a333bca..7c06c41485c 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -33,9 +33,14 @@ describe('RockYouAdapter', () => { }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'sizes': [[320, 50], [300, 250], [300, 600]], + 'sizes': [[999, 888]], 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757' + 'auctionId': '18fd8b8b0bd757', + 'mediaTypes': { + banner: { + 'sizes': [[320, 50], [300, 250], [300, 600]] + } + } }; it('successfully generates a URL', () => { @@ -49,9 +54,10 @@ describe('RockYouAdapter', () => { } ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); expect(result.url).to.not.be.undefined; expect(result.url).to.not.be.null; @@ -66,9 +72,10 @@ describe('RockYouAdapter', () => { sampleBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -82,9 +89,10 @@ describe('RockYouAdapter', () => { sampleBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -95,33 +103,57 @@ describe('RockYouAdapter', () => { expect(userData).to.not.be.null; }); - it('generates multiple imp bodies', () => { + it('generates multiple requests with single imp bodies', () => { + const SECOND_PLACEMENT_ID = 'YYYPLACEMENTIDYYY'; + let firstBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + let secondBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); + secondBidRequest.params.placementId = SECOND_PLACEMENT_ID; + let bidRequests = [ - sampleBidRequest, - sampleBidRequest + firstBidRequest, + secondBidRequest ]; - let result = spec.buildRequests(bidRequests, { + let results = spec.buildRequests(bidRequests, { bidderRequestId: 'sample' }); + expect(results instanceof Array).to.be.true; + expect(results.length).to.equal(2); + + let firstRequest = results[0]; + // Double encoded JSON - let payload = JSON.parse(result.data); + let firstPayload = JSON.parse(firstRequest.data); - expect(payload).to.not.be.null; - expect(payload.imp).to.not.be.null; - expect(payload.imp.length).to.equal(2); + expect(firstPayload).to.not.be.null; + expect(firstPayload.imp).to.not.be.null; + expect(firstPayload.imp.length).to.equal(1); + + expect(firstRequest.url).to.not.be.null; + expect(firstRequest.url.indexOf('ZZZPLACEMENTZZZ')).to.be.gt(0); + + let secondRequest = results[1]; + + // Double encoded JSON + let secondPayload = JSON.parse(secondRequest.data); + + expect(secondPayload).to.not.be.null; + expect(secondPayload.imp).to.not.be.null; + expect(secondPayload.imp.length).to.equal(1); + + expect(secondRequest.url).to.not.be.null; + expect(secondRequest.url.indexOf(SECOND_PLACEMENT_ID)).to.be.gt(0); }); it('generates a banner request as expected', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); - localBidRequest.mediaTypes = { banner: {} }; - - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -146,9 +178,10 @@ describe('RockYouAdapter', () => { localBidRequest.sizes = [320, 50]; localBidRequest.mediaTypes = { banner: {} }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -171,11 +204,13 @@ describe('RockYouAdapter', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = ['x', 'w']; - localBidRequest.mediaTypes = { banner: {} }; - let result = spec.buildRequests([localBidRequest], { + localBidRequest.mediaTypes = { banner: { sizes: ['y', 'z']} }; + + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -198,11 +233,14 @@ describe('RockYouAdapter', () => { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); - localBidRequest.mediaTypes = { video: {} }; + localBidRequest.mediaTypes = { video: { + playerSize: [326, 56] + } }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); // Double encoded JSON let payload = JSON.parse(result.data); @@ -217,8 +255,8 @@ describe('RockYouAdapter', () => { let videoData = firstImp.video; - expect(videoData.w).to.equal(320); - expect(videoData.h).to.equal(50); + expect(videoData.w).to.equal(326); + expect(videoData.h).to.equal(56); }); it('propagates the mediaTypes object in the built request', () => { @@ -226,9 +264,10 @@ describe('RockYouAdapter', () => { localBidRequest.mediaTypes = { video: {} }; - let result = spec.buildRequests([localBidRequest], { + let results = spec.buildRequests([localBidRequest], { bidderRequestId: 'sample' }); + let result = results.pop(); let mediaTypes = result.mediaTypes;