From d10339a4ee5c09c9d2c6b03bff13f5583daaae8c Mon Sep 17 00:00:00 2001 From: Drilon Kastrati Date: Mon, 10 Aug 2020 16:54:04 +0200 Subject: [PATCH 1/3] added adapters for gjirafa and malltv --- modules/gjirafaBidAdapter.js | 89 +++++++++++++ modules/gjirafaBidAdapter.md | 69 ++++++---- modules/malltvBidAdapter.js | 89 +++++++++++++ modules/malltvBidAdapter.md | 51 +++++++ test/spec/modules/gjirafaBidAdapter_spec.js | 140 ++++++++++++++++++++ test/spec/modules/malltvBidAdapter_spec.js | 140 ++++++++++++++++++++ 6 files changed, 551 insertions(+), 27 deletions(-) create mode 100644 modules/gjirafaBidAdapter.js create mode 100644 modules/malltvBidAdapter.js create mode 100644 modules/malltvBidAdapter.md create mode 100644 test/spec/modules/gjirafaBidAdapter_spec.js create mode 100644 test/spec/modules/malltvBidAdapter_spec.js diff --git a/modules/gjirafaBidAdapter.js b/modules/gjirafaBidAdapter.js new file mode 100644 index 00000000000..44e2dd8cfa0 --- /dev/null +++ b/modules/gjirafaBidAdapter.js @@ -0,0 +1,89 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; + +const BIDDER_CODE = 'gjirafa'; +const ENDPOINT_URL = 'https://central.gjirafa.com/bid'; +const DIMENSION_SEPARATOR = 'x'; +const SIZE_SEPARATOR = ';'; + +export const spec = { + code: BIDDER_CODE, + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + return !!(bid.params.propertyId && bid.params.placementId); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + let response = validBidRequests.map(bidRequest => { + let sizes = generateSizeParam(bidRequest.sizes); + let propertyId = bidRequest.params.propertyId; + let placementId = bidRequest.params.placementId; + let adUnitId = bidRequest.adUnitCode; + let pageViewGuid = bidRequest.params.pageViewGuid || ''; + let contents = bidRequest.params.contents || []; + const body = { + sizes: sizes, + adUnitId: adUnitId, + placementId: placementId, + propertyId: propertyId, + pageViewGuid: pageViewGuid, + url: bidderRequest ? bidderRequest.refererInfo.referer : '', + requestid: bidRequest.bidderRequestId, + bidid: bidRequest.bidId, + contents: contents + }; + return { + method: 'POST', + url: ENDPOINT_URL, + data: body + }; + }); + return response + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + window.adnResponse = serverResponse; + const serverBody = serverResponse.body; + const bidResponses = []; + const bidResponse = { + requestId: bidRequest.data.bidid, + cpm: serverBody.CPM, + width: serverBody.Width, + height: serverBody.Height, + creativeId: serverBody.CreativeId, + currency: serverBody.Currency, + netRevenue: serverBody.NetRevenue, + ttl: serverBody.TTL, + referrer: serverBody.Referrer, + ad: serverBody.Ad + }; + bidResponses.push(bidResponse); + return bidResponses; + } +} + +/** +* Generate size param for bid request using sizes array +* +* @param {Array} sizes Possible sizes for the ad unit. +* @return {string} Processed sizes param to be used for the bid request. +*/ +function generateSizeParam(sizes) { + return sizes.map(size => size.join(DIMENSION_SEPARATOR)).join(SIZE_SEPARATOR); +} + +registerBidder(spec); diff --git a/modules/gjirafaBidAdapter.md b/modules/gjirafaBidAdapter.md index 1ec8222d8de..53d3a76c5ed 100644 --- a/modules/gjirafaBidAdapter.md +++ b/modules/gjirafaBidAdapter.md @@ -1,36 +1,51 @@ # Overview Module Name: Gjirafa Bidder Adapter Module Type: Bidder Adapter -Maintainer: agonq@gjirafa.com +Maintainer: drilon@gjirafa.com # Description Gjirafa Bidder Adapter for Prebid.js. # Test Parameters var adUnits = [ -{ - code: 'test-div', - sizes: [[728, 90]], // leaderboard - bids: [ - { - bidder: 'gjirafa', - params: { - placementId: '71-3' - } - } - ] -},{ - code: 'test-div', - sizes: [[300, 250]], // mobile rectangle - bids: [ - { - bidder: 'gjirafa', - params: { - minCPM: 0.0001, - minCPC: 0.001, - explicit: true - } - } - ] -} -]; \ No newline at end of file + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bids: [ + { + bidder: 'gjirafa', + params: { + propertyId: '105227', + placementId: '846841' + } + } + ] + }, + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [ + { + bidder: 'gjirafa', + params: { + propertyId: '105227', + placementId: '846848', + contents: [ //optional + { + type: 'article', + id: '123' + } + ] + } + } + ] + } +]; diff --git a/modules/malltvBidAdapter.js b/modules/malltvBidAdapter.js new file mode 100644 index 00000000000..ffb410f82b4 --- /dev/null +++ b/modules/malltvBidAdapter.js @@ -0,0 +1,89 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; + +const BIDDER_CODE = 'malltv'; +const ENDPOINT_URL = 'https://central.mall.tv/bid'; +const DIMENSION_SEPARATOR = 'x'; +const SIZE_SEPARATOR = ';'; + +export const spec = { + code: BIDDER_CODE, + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + return !!(bid.params.propertyId && bid.params.placementId); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + let response = validBidRequests.map(bidRequest => { + let sizes = generateSizeParam(bidRequest.sizes); + let propertyId = bidRequest.params.propertyId; + let placementId = bidRequest.params.placementId; + let adUnitId = bidRequest.adUnitCode; + let pageViewGuid = bidRequest.params.pageViewGuid || ''; + let contents = bidRequest.params.contents || []; + const body = { + sizes: sizes, + adUnitId: adUnitId, + placementId: placementId, + propertyId: propertyId, + pageViewGuid: pageViewGuid, + url: bidderRequest ? bidderRequest.refererInfo.referer : '', + requestid: bidRequest.bidderRequestId, + bidid: bidRequest.bidId, + contents: contents + }; + return { + method: 'POST', + url: ENDPOINT_URL, + data: body + }; + }); + return response + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + window.adnResponse = serverResponse; + const serverBody = serverResponse.body; + const bidResponses = []; + const bidResponse = { + requestId: bidRequest.data.bidid, + cpm: serverBody.CPM, + width: serverBody.Width, + height: serverBody.Height, + creativeId: serverBody.CreativeId, + currency: serverBody.Currency, + netRevenue: serverBody.NetRevenue, + ttl: serverBody.TTL, + referrer: serverBody.Referrer, + ad: serverBody.Ad + }; + bidResponses.push(bidResponse); + return bidResponses; + } +} + +/** +* Generate size param for bid request using sizes array +* +* @param {Array} sizes Possible sizes for the ad unit. +* @return {string} Processed sizes param to be used for the bid request. +*/ +function generateSizeParam(sizes) { + return sizes.map(size => size.join(DIMENSION_SEPARATOR)).join(SIZE_SEPARATOR); +} + +registerBidder(spec); diff --git a/modules/malltvBidAdapter.md b/modules/malltvBidAdapter.md new file mode 100644 index 00000000000..2e8f55eab93 --- /dev/null +++ b/modules/malltvBidAdapter.md @@ -0,0 +1,51 @@ +# Overview +Module Name: MallTV Bidder Adapter Module +Type: Bidder Adapter +Maintainer: drilon@gjirafa.com + +# Description +MallTV Bidder Adapter for Prebid.js. + +# Test Parameters +var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 300]] + } + }, + bids: [ + { + bidder: 'malltv', + params: { + propertyId: '105135', + placementId: '846835' + } + } + ] + }, + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 300]] + } + }, + bids: [ + { + bidder: 'malltv', + params: { + propertyId: '105135', + placementId: '846835', + contents: [ //optional + { + type: 'video', + id: '123' + } + ] + } + } + ] + } +]; diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js new file mode 100644 index 00000000000..566b1243f62 --- /dev/null +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -0,0 +1,140 @@ +import { expect } from 'chai'; +import { spec } from 'modules/gjirafaBidAdapter'; + +describe('gjirafaAdapterTest', () => { + describe('bidRequestValidity', () => { + it('bidRequest with propertyId and placementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + propertyId: '{propertyId}', + placementId: '{placementId}' + } + })).to.equal(true); + }); + + it('bidRequest without propertyId', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + placementId: '{placementId}' + } + })).to.equal(false); + }); + + it('bidRequest without placementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + propertyId: '{propertyId}', + } + })).to.equal(false); + }); + + it('bidRequest without propertyId orplacementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'gjirafa', + params: { + propertyId: '{propertyId}', + } + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'gjirafa', + 'params': { + 'propertyId': '{propertyId}', + 'placementId': '{placementId}' + }, + 'adUnitCode': 'hb-leaderboard', + 'transactionId': 'b6b889bb-776c-48fd-bc7b-d11a1cf0425e', + 'sizes': [[728, 90]], + 'bidId': '10bdc36fe0b48c8', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + }]; + + it('bidRequest HTTP method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.method).to.equal('POST'); + }); + }); + + it('bidRequest url', () => { + const endpointUrl = 'https://central.gjirafa.com/bid'; + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.url).to.match(new RegExp(`${endpointUrl}`)); + }); + }); + + it('bidRequest data', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.data).to.exist; + }); + }); + + it('bidRequest sizes', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.sizes).to.equal('728x90'); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = { + 'method': 'POST', + 'url': 'https://central.gjirafa.com/bid', + 'data': { + 'sizes': '728x90', + 'adUnitId': 'hb-leaderboard', + 'placementId': '{placementId}', + 'propertyId': '{propertyId}', + 'pageViewGuid': '{pageViewGuid}', + 'url': 'http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true', + 'requestid': '26ee8fe87940da7', + 'bidid': '2962dbedc4768bf' + } + }; + + const bidResponse = { + body: [{ + 'CPM': 1, + 'Width': 728, + 'Height': 90, + 'Referrer': 'http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true', + 'Ad': '
Test ad
', + 'CreativeId': '123abc', + 'NetRevenue': false, + 'Currency': 'EUR', + 'TTL': 360 + }], + headers: {} + }; + + it('all keys present', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + let keys = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'creativeId', + 'currency', + 'netRevenue', + 'ttl', + 'referrer', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + resultKeys.forEach(function (key) { + expect(keys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); +}); diff --git a/test/spec/modules/malltvBidAdapter_spec.js b/test/spec/modules/malltvBidAdapter_spec.js new file mode 100644 index 00000000000..10161b319c5 --- /dev/null +++ b/test/spec/modules/malltvBidAdapter_spec.js @@ -0,0 +1,140 @@ +import { expect } from 'chai'; +import { spec } from 'modules/malltvBidAdapter'; + +describe('malltvAdapterTest', () => { + describe('bidRequestValidity', () => { + it('bidRequest with propertyId and placementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'malltv', + params: { + propertyId: '{propertyId}', + placementId: '{placementId}' + } + })).to.equal(true); + }); + + it('bidRequest without propertyId', () => { + expect(spec.isBidRequestValid({ + bidder: 'malltv', + params: { + placementId: '{placementId}' + } + })).to.equal(false); + }); + + it('bidRequest without placementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'malltv', + params: { + propertyId: '{propertyId}', + } + })).to.equal(false); + }); + + it('bidRequest without propertyId or placementId', () => { + expect(spec.isBidRequestValid({ + bidder: 'malltv', + params: { + propertyId: '{propertyId}', + } + })).to.equal(false); + }); + }); + + describe('bidRequest', () => { + const bidRequests = [{ + 'bidder': 'malltv', + 'params': { + 'propertyId': '{propertyId}', + 'placementId': '{placementId}' + }, + 'adUnitCode': 'hb-leaderboard', + 'transactionId': 'b6b889bb-776c-48fd-bc7b-d11a1cf0425e', + 'sizes': [[300, 250]], + 'bidId': '10bdc36fe0b48c8', + 'bidderRequestId': '70deaff71c281d', + 'auctionId': 'f9012acc-b6b7-4748-9098-97252914f9dc' + }]; + + it('bidRequest HTTP method', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.method).to.equal('POST'); + }); + }); + + it('bidRequest url', () => { + const endpointUrl = 'https://central.mall.tv/bid'; + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.url).to.match(new RegExp(`${endpointUrl}`)); + }); + }); + + it('bidRequest data', () => { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function (requestItem) { + expect(requestItem.data).to.exist; + }); + }); + + it('bidRequest sizes', () => { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].data.sizes).to.equal('300x250'); + }); + }); + + describe('interpretResponse', () => { + const bidRequest = { + 'method': 'POST', + 'url': 'https://central.mall.tv/bid', + 'data': { + 'sizes': '300x250', + 'adUnitId': 'rectangle', + 'placementId': '{placementId}', + 'propertyId': '{propertyId}', + 'pageViewGuid': '{pageViewGuid}', + 'url': 'http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true', + 'requestid': '26ee8fe87940da7', + 'bidid': '2962dbedc4768bf' + } + }; + + const bidResponse = { + body: [{ + 'CPM': 1, + 'Width': 300, + 'Height': 250, + 'Referrer': 'http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true', + 'Ad': '
Test ad
', + 'CreativeId': '123abc', + 'NetRevenue': false, + 'Currency': 'EUR', + 'TTL': 360 + }], + headers: {} + }; + + it('all keys present', () => { + const result = spec.interpretResponse(bidResponse, bidRequest); + + let keys = [ + 'requestId', + 'cpm', + 'width', + 'height', + 'creativeId', + 'currency', + 'netRevenue', + 'ttl', + 'referrer', + 'ad' + ]; + + let resultKeys = Object.keys(result[0]); + resultKeys.forEach(function (key) { + expect(keys.indexOf(key) !== -1).to.equal(true); + }); + }) + }); +}); From aeb706f278bc2fdd6bb5a054dfdba7e905231f5d Mon Sep 17 00:00:00 2001 From: Drilon Kastrati Date: Tue, 1 Sep 2020 10:18:30 +0200 Subject: [PATCH 2/3] interpretResponse fix for empty result --- modules/gjirafaBidAdapter.js | 30 ++++++++++++++++-------------- modules/malltvBidAdapter.js | 30 ++++++++++++++++-------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/modules/gjirafaBidAdapter.js b/modules/gjirafaBidAdapter.js index 44e2dd8cfa0..ca7fb4af32d 100644 --- a/modules/gjirafaBidAdapter.js +++ b/modules/gjirafaBidAdapter.js @@ -57,21 +57,23 @@ export const spec = { */ interpretResponse: function (serverResponse, bidRequest) { window.adnResponse = serverResponse; - const serverBody = serverResponse.body; + const responses = serverResponse.body; const bidResponses = []; - const bidResponse = { - requestId: bidRequest.data.bidid, - cpm: serverBody.CPM, - width: serverBody.Width, - height: serverBody.Height, - creativeId: serverBody.CreativeId, - currency: serverBody.Currency, - netRevenue: serverBody.NetRevenue, - ttl: serverBody.TTL, - referrer: serverBody.Referrer, - ad: serverBody.Ad - }; - bidResponses.push(bidResponse); + for (var i = 0; i < responses.length; i++) { + const bidResponse = { + requestId: bidRequest.data.bidid, + cpm: responses[i].CPM, + width: responses[i].Width, + height: responses[i].Height, + creativeId: responses[i].CreativeId, + currency: responses[i].Currency, + netRevenue: responses[i].NetRevenue, + ttl: responses[i].TTL, + referrer: responses[i].Referrer, + ad: responses[i].Ad + }; + bidResponses.push(bidResponse); + } return bidResponses; } } diff --git a/modules/malltvBidAdapter.js b/modules/malltvBidAdapter.js index ffb410f82b4..4cdb5d45328 100644 --- a/modules/malltvBidAdapter.js +++ b/modules/malltvBidAdapter.js @@ -57,21 +57,23 @@ export const spec = { */ interpretResponse: function (serverResponse, bidRequest) { window.adnResponse = serverResponse; - const serverBody = serverResponse.body; + const responses = serverResponse.body; const bidResponses = []; - const bidResponse = { - requestId: bidRequest.data.bidid, - cpm: serverBody.CPM, - width: serverBody.Width, - height: serverBody.Height, - creativeId: serverBody.CreativeId, - currency: serverBody.Currency, - netRevenue: serverBody.NetRevenue, - ttl: serverBody.TTL, - referrer: serverBody.Referrer, - ad: serverBody.Ad - }; - bidResponses.push(bidResponse); + for (var i = 0; i < responses.length; i++) { + const bidResponse = { + requestId: bidRequest.data.bidid, + cpm: responses[i].CPM, + width: responses[i].Width, + height: responses[i].Height, + creativeId: responses[i].CreativeId, + currency: responses[i].Currency, + netRevenue: responses[i].NetRevenue, + ttl: responses[i].TTL, + referrer: responses[i].Referrer, + ad: responses[i].Ad + }; + bidResponses.push(bidResponse); + } return bidResponses; } } From 3ee81a76e81aec9b7a132a07313184792d251185 Mon Sep 17 00:00:00 2001 From: Drilon Kastrati Date: Wed, 2 Sep 2020 09:18:50 +0200 Subject: [PATCH 3/3] updated testing propertyId and placementId --- modules/malltvBidAdapter.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/malltvBidAdapter.md b/modules/malltvBidAdapter.md index 2e8f55eab93..72db0cef6c7 100644 --- a/modules/malltvBidAdapter.md +++ b/modules/malltvBidAdapter.md @@ -19,8 +19,8 @@ var adUnits = [ { bidder: 'malltv', params: { - propertyId: '105135', - placementId: '846835' + propertyId: '105134', + placementId: '846832' } } ] @@ -36,8 +36,8 @@ var adUnits = [ { bidder: 'malltv', params: { - propertyId: '105135', - placementId: '846835', + propertyId: '105134', + placementId: '846832', contents: [ //optional { type: 'video',