From 7bf3be104c01c463ff245a11f892bf54810720bd Mon Sep 17 00:00:00 2001 From: sa1omon Date: Wed, 23 Jan 2019 23:26:26 +0200 Subject: [PATCH 1/6] Add support for multi-format ad units. Add favoredMediaType property to params. --- modules/gamoshiBidAdapter.js | 103 +++++++++++++++++++---------------- modules/gamoshiBidAdapter.md | 46 +++++++++++++++- 2 files changed, 100 insertions(+), 49 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index fa6632f9abb..80aebd3b548 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -1,10 +1,15 @@ import * as utils from '../src/utils'; -import { registerBidder } from '../src/adapters/bidderFactory'; -import { config } from '../src/config'; -import { Renderer } from '../src/Renderer'; +import {registerBidder} from '../src/adapters/bidderFactory'; +import {config} from '../src/config'; +import {Renderer} from '../src/Renderer'; + +const ENDPOINTS = { + 'cleanmedia': 'https://bidder.cleanmediaads.com', + 'gamoshi': 'https://rtb.gamoshi.io', + 'gambid': 'https://rtb.gamoshi.io', +}; export const helper = { - getTopFrame: function () { try { return window.top === window ? 1 : 0; @@ -12,30 +17,14 @@ export const helper = { } return 0; }, - startsWith: function (str, search) { return str.substr(0, search.length) === search; }, - getTopWindowDomain: function (url) { const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); - }, - - getTopWindowReferer: function () { - try { - return window.top.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining top window\'s referrer: ', e); - try { - return window.document.referrer; - } catch (e) { - utils.logMessage('Failed obtaining current window\'s referrer: ', e); - } - } - return ''; } -} +}; export const spec = { code: 'gamoshi', @@ -43,7 +32,8 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!bid.params.supplyPartnerId && typeof bid.params.supplyPartnerId === 'string' && + return !!bid.params.supplyPartnerId && + typeof bid.params.supplyPartnerId === 'string' && (typeof bid.params['rtbEndpoint'] === 'undefined' || typeof bid.params['rtbEndpoint'] === 'string') && (typeof bid.params.bidfloor === 'undefined' || typeof bid.params.bidfloor === 'number') && (typeof bid.params['adpos'] === 'undefined' || typeof bid.params['adpos'] === 'number') && @@ -54,17 +44,16 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; - const baseEndpoint = params['rtbEndpoint'] || 'https://rtb.gamoshi.io'; + const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS[bidRequest.bidder] || ENDPOINTS['gamoshi']; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); - let referer = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer; - let url = config.getConfig('pageUrl') || referer || utils.getTopWindowUrl(); + let url = config.getConfig('pageUrl') || bidderRequest.refererInfo.referer; const rtbBidRequest = { 'id': auctionId, 'site': { 'domain': helper.getTopWindowDomain(url), 'page': url, - 'ref': helper.getTopWindowReferer() + 'ref': bidderRequest.refererInfo.referer }, 'device': { 'ua': navigator.userAgent @@ -72,7 +61,8 @@ export const spec = { 'imp': [], 'ext': {} }; - if (bidderRequest && bidderRequest.gdprConsent) { + + if (bidderRequest.gdprConsent) { rtbBidRequest.ext.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies @@ -88,25 +78,44 @@ export const spec = { 'secure': helper.startsWith(utils.getTopWindowUrl().toLowerCase(), 'http://') ? 0 : 1 }; - if (!mediaTypes || mediaTypes.banner) { - imp.banner = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else if (mediaTypes.video) { - imp.video = { - w: sizes.length ? sizes[0][0] : 300, - h: sizes.length ? sizes[0][1] : 250, - protocols: params.protocols || [1, 2, 3, 4, 5, 6], - pos: params.pos || 0, - topframe: helper.getTopFrame() - }; - } else { + const hasFavoredMediaType = + params.favoredMediaType && this.supportedMediaTypes.includes(params.favoredMediaType); + + if ((!mediaTypes || mediaTypes.banner)) { + if (!hasFavoredMediaType || params.favoredMediaType === 'banner') { + const bannerImp = Object.assign({}, imp, { + banner: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + pos: params.pos || 0, + topframe: helper.getTopFrame() + } + }); + rtbBidRequest.imp.push(bannerImp); + } + } + + if (mediaTypes && mediaTypes.video) { + if (!hasFavoredMediaType || params.favoredMediaType === 'video') { + const videoImp = Object.assign({}, imp, { + video: { + w: sizes.length ? sizes[0][0] : 300, + h: sizes.length ? sizes[0][1] : 250, + protocols: params.protocols || [1, 2, 3, 4, 5, 6], + pos: params.pos || 0, + ext: { + context: mediaTypes.video.context + } + } + }); + rtbBidRequest.imp.push(videoImp); + } + } + + if (rtbBidRequest.imp.length === 0) { return; } - rtbBidRequest.imp.push(imp); + return {method: 'POST', url: rtbEndpoint, data: rtbBidRequest, bidRequest}; }); }, @@ -120,6 +129,7 @@ export const spec = { const bids = response.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); const outBids = []; + bids.forEach(bid => { const outBid = { requestId: bidRequest.bidRequest.bidId, @@ -129,7 +139,8 @@ export const spec = { ttl: 60 * 10, creativeId: bid.crid, netRevenue: true, - currency: bid.cur || response.cur + currency: bid.cur || response.cur, + adUnitCode: bidRequest.bidRequest.adUnitCode }; if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); @@ -181,7 +192,7 @@ export const spec = { function newRenderer(bidRequest, bid, rendererOptions = {}) { const renderer = Renderer.install({ - url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.gamoshi.io/video/latest/renderer.js', + url: (bidRequest.params && bidRequest.params.rendererUrl) || (bid.ext && bid.ext.renderer_url) || '//s.wlplayer.com/video/latest/renderer.js', config: rendererOptions, loaded: false, }); diff --git a/modules/gamoshiBidAdapter.md b/modules/gamoshiBidAdapter.md index f88248ef668..6e930375059 100644 --- a/modules/gamoshiBidAdapter.md +++ b/modules/gamoshiBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Gamoshi Bid Adapter Module Type: Bidder Adapter -Maintainer: moses@gamoshi.com +Maintainer: salomon@gamoshi.com ``` # Description @@ -47,7 +47,6 @@ var adUnits = [ // Video outstream adUnit { code: 'video-outstream', - sizes: [[300, 250]], mediaTypes: { video: { context: 'outstream', @@ -76,6 +75,47 @@ var adUnits = [ //instl: 0 } }] - } + }, + + // Multi-Format adUnit + { + code: 'banner-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [300, 250] + }, + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'gamoshi', + params: { + + // ID of the supply partner you created in the Gamoshi dashboard + supplyPartnerId: '1253', + + // OPTIONAL: if you have a whitelabel account on Gamoshi, specify it here + //rtbEndpoint: 'https://my.custom-whitelabel-domain.io', + + // OPTIONAL: custom bid floor + bidfloor: 0.01, + + // OPTIONAL: if you know the ad position on the page, specify it here + // (this corresponds to "Ad Position" in OpenRTB 2.3, section 5.4) + //adpos: 1, + + // OPTIONAL: whether this is an interstitial placement (0 or 1) + // (see "instl" property in "Imp" object in the OpenRTB 2.3, section 3.2.2) + //instl: 0, + + // OPTIONAL: enable enforcement bids of a specific media type (video, banner) + // in this ad placement + // query: 'key1=value1&k2=value2', + // favoredMediaType: 'video', + } + }] + }, ]; ``` From fed69e9ea81236cc0307eeb58fb3b64ea35f1e40 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Wed, 23 Jan 2019 23:27:58 +0200 Subject: [PATCH 2/6] Add tests for gdpr consent. --- test/spec/modules/gamoshiBidAdapter_spec.js | 136 +++++++++++++++++--- 1 file changed, 118 insertions(+), 18 deletions(-) diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 26d67b70f78..a8e9d49cf07 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -4,6 +4,7 @@ import {helper} from 'modules/gamoshiBidAdapter'; import * as utils from 'src/utils'; import {newBidder} from '../../../src/adapters/bidderFactory'; import {deepClone} from 'src/utils'; + const supplyPartnerId = '123'; const adapter = newBidder(spec); describe('GamoshiAdapter', function () { @@ -79,42 +80,47 @@ describe('GamoshiAdapter', function () { }, 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', - refererInfo: {referer: 'http://examplereferer.com'} + refererInfo: {referer: 'http://examplereferer.com'}, + gdprConsent: { + consentString: 'some string', + gdprApplies: true + } }; it('returns an array', function () { let response; response = spec.buildRequests([]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); - response = spec.buildRequests([bidRequest]); + response = spec.buildRequests([bidRequest], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'a'}); const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), {auctionId: '1', adUnitCode: 'b'}); - response = spec.buildRequests([adUnit1, adUnit2]); + response = spec.buildRequests([adUnit1, adUnit2], bidRequest); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); }); it('targets correct endpoint', function () { let response; - response = spec.buildRequests([bidRequest])[0]; + response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://rtb\\.gamoshi\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); expect(response.data.id).to.equal(bidRequest.auctionId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gamoshi.io/a12'; - response = spec.buildRequests([bidRequestWithEndpoint])[0]; + response = spec.buildRequests([bidRequestWithEndpoint], bidRequest)[0]; expect(response.url).to.match(new RegExp(`^https://rtb2\\.gamoshi\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); it('builds request correctly', function () { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); - let response; - response = spec.buildRequests([bidRequest])[0]; + let bidRequest2 = deepClone(bidRequest); + bidRequest2.refererInfo.referer = 'http://www.test.com/page.html'; + let response = spec.buildRequests([bidRequest], bidRequest2)[0]; expect(response.data.site.domain).to.equal('www.test.com'); expect(response.data.site.page).to.equal('http://www.test.com/page.html'); - expect(response.data.site.ref).to.equal(''); + expect(response.data.site.ref).to.equal('http://www.test.com/page.html'); expect(response.data.imp.length).to.equal(1); expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); expect(response.data.imp[0].instl).to.equal(0); @@ -123,15 +129,15 @@ describe('GamoshiAdapter', function () { expect(response.data.imp[0].bidfloorcur).to.equal('USD'); const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); bidRequestWithInstlEquals1.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals1])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals1], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals1.params.instl); const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); bidRequestWithInstlEquals0.params.instl = 1; - response = spec.buildRequests([bidRequestWithInstlEquals0])[0]; + response = spec.buildRequests([bidRequestWithInstlEquals0], bidRequest2)[0]; expect(response.data.imp[0].instl).to.equal(bidRequestWithInstlEquals0.params.instl); const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); bidRequestWithBidfloorEquals1.params.bidfloor = 1; - response = spec.buildRequests([bidRequestWithBidfloorEquals1])[0]; + response = spec.buildRequests([bidRequestWithBidfloorEquals1], bidRequest2)[0]; expect(response.data.imp[0].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); stub.restore(); }); @@ -144,14 +150,14 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithBanner])[0]; + response = spec.buildRequests([bidRequestWithBanner], bidRequest)[0]; expect(response.data.imp[0].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][0]); expect(response.data.imp[0].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[0][1]); expect(response.data.imp[0].banner.pos).to.equal(0); expect(response.data.imp[0].banner.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); @@ -163,16 +169,45 @@ describe('GamoshiAdapter', function () { sizes: [[300, 250], [120, 600]] } }; - response = spec.buildRequests([bidRequestWithVideo])[0]; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; expect(response.data.imp[0].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][0]); expect(response.data.imp[0].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[0][1]); expect(response.data.imp[0].video.pos).to.equal(0); - expect(response.data.imp[0].video.topframe).to.equal(0); const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); bidRequestWithPosEquals1.params.pos = 1; - response = spec.buildRequests([bidRequestWithPosEquals1])[0]; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; expect(response.data.imp[0].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); + + it('builds request video object correctly with context', function () { + let response; + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + context: 'instream' + } + }; + response = spec.buildRequests([bidRequestWithVideo], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('instream'); + bidRequestWithVideo.mediaTypes.video.context = 'outstream'; + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.mediaTypes.video.context = 'outstream'; + response = spec.buildRequests([bidRequestWithPosEquals1], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal('outstream'); + + const bidRequestWithPosEquals2 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals2.mediaTypes.video.context = null; + response = spec.buildRequests([bidRequestWithPosEquals2], bidRequest)[0]; + expect(response.data.imp[0].video.ext.context).to.equal(null); + }); + + it('builds request with gdpr consent', function () { + let response = spec.buildRequests([bidRequest], bidRequest)[0]; + expect(response.data.ext).to.have.property('gdpr_consent'); + expect(response.data.ext.gdpr_consent.consent_string).to.equal('some string'); + expect(response.data.ext.gdpr_consent.consent_required).to.equal(true); + }); }); describe('interpretResponse', function () { @@ -188,7 +223,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const videoBidRequest = { @@ -203,7 +238,7 @@ describe('GamoshiAdapter', function () { 'sizes': [[300, 250], [300, 600]], 'transactionId': 'a123456789', 'bidId': '111', - refererInfo: { referer: 'http://examplereferer.com' } + refererInfo: {referer: 'http://examplereferer.com'} }; const rtbResponse = { @@ -402,5 +437,70 @@ describe('GamoshiAdapter', function () { const result = spec.interpretResponse({body: videoResponse}, {bidRequest: videoRequest}); expect(result[0].renderer).to.not.equal(undefined); }); + + it('validates in/existing of gdpr consent', function () { + let videoResponse = { + 'id': '64f32497-b2f7-48ec-9205-35fc39894d44', + 'bidid': 'imp_5c24924de4b0d106447af333', + 'cur': 'USD', + 'seatbid': [ + { + 'seat': '3668', + 'group': 0, + 'bid': [ + { + 'id': 'gb_1', + 'impid': 'afbb5852-7cea-4a81-aa9a-a41aab505c23', + 'price': 5.0, + 'adid': '1274', + 'nurl': 'https://rtb.gamoshi.io/pix/1275/win_notice/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&p=${AUCTION_PRICE}', + 'adomain': [], + 'adm': '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'cid': '3668', + 'crid': '1274', + 'cat': [], + 'attr': [], + 'h': 250, + 'w': 300, + 'ext': { + 'vast_url': 'https://rtb.gamoshi.io/pix/1275/vast_o/imp_5c24924de4b0d106447af333/im.xml?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1&w=300&h=250&vatu=aHR0cHM6Ly9zdGF0aWMuZ2FtYmlkLmlvL2RlbW8vdmFzdC54bWw&vwarv', + 'imptrackers': [ + 'https://rtb.gamoshi.io/pix/1275/imp/imp_5c24924de4b0d106447af333/im.gif?r=imp_5c24924de4b0d106447af333&i=afbb5852-7cea-4a81-aa9a-a41aab505c23&a=1274&b=gb_1'] + } + } + ] + } + ], + 'ext': { + 'utrk': [{ + 'type': 'image', + 'url': 'https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675' + }] + } + }; + let gdprConsent = { + gdprApplies: true, + consentString: 'consent string' + }; + let result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=consent%20string'); + + gdprConsent.gdprApplies = false; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?cb=1545900621675&gc=missing'); + + videoResponse.ext.utrk[0].url = 'https://rtb.gamoshi.io/pix/1275/scm'; + result = spec.getUserSyncs({}, [{body: videoResponse}], gdprConsent); + expect(result).to.be.an('array'); + expect(result.length).to.equal(1); + expect(result[0].type).to.equal('image'); + expect(result[0].url).to.equal('https://rtb.gamoshi.io/pix/1275/scm?gc=missing'); + }); }); }); From a3b285040204bfb6ea1a36b0f74b0a9f9a13491b Mon Sep 17 00:00:00 2001 From: sa1omon Date: Thu, 24 Jan 2019 17:49:43 +0200 Subject: [PATCH 3/6] Add adId to outbids --- modules/gamoshiBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 80aebd3b548..2f7864d5570 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -128,10 +128,11 @@ export const spec = { } const bids = response.seatbid.reduce((acc, seatBid) => acc.concat(seatBid.bid), []); - const outBids = []; + let outBids = []; bids.forEach(bid => { const outBid = { + adId: bidRequest.bidRequest.adUnitCode, requestId: bidRequest.bidRequest.bidId, cpm: bid.price, width: bid.w, From c53757a0daafe2ef235c2d0780d41e5d1f0c44b8 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Sun, 27 Jan 2019 20:28:04 +0200 Subject: [PATCH 4/6] Modify media type resolving --- modules/gamoshiBidAdapter.js | 39 ++++++++++++------ test/spec/modules/gamoshiBidAdapter_spec.js | 44 ++++++--------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 2f7864d5570..1a5b115907d 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -23,6 +23,19 @@ export const helper = { getTopWindowDomain: function (url) { const domainStart = url.indexOf('://') + '://'.length; return url.substring(domainStart, url.indexOf('/', domainStart) < 0 ? url.length : url.indexOf('/', domainStart)); + }, + + getMediaType: function (bid) { + if (bid.ext) { + if (bid.ext.media_type) { + return bid.ext.media_type; + } else if (bid.ext.vast_url) { + return 'video'; + } else { + return 'banner'; + } + } + return 'banner'; } }; @@ -141,18 +154,22 @@ export const spec = { creativeId: bid.crid, netRevenue: true, currency: bid.cur || response.cur, - adUnitCode: bidRequest.bidRequest.adUnitCode + adUnitCode: bidRequest.bidRequest.adUnitCode, + mediaType: helper.getMediaType(bid) + }; - if (!bidRequest.bidRequest.mediaTypes || bidRequest.bidRequest.mediaTypes.banner) { - outBids.push(Object.assign({}, outBid, {mediaType: 'banner', ad: bid.adm})); - } else if (bidRequest.bidRequest.mediaTypes.video) { - const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); - outBids.push(Object.assign({}, outBid, { - mediaType: 'video', - vastUrl: bid.ext.vast_url, - vastXml: bid.adm, - renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined - })); + + if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { + if (outBid.mediaType === 'banner') { + outBids.push(Object.assign({}, outBid, {ad: bid.adm})); + } else if (outBid.mediaType === 'video') { + const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); + outBids.push(Object.assign({}, outBid, { + vastUrl: bid.ext.vast_url, + vastXml: bid.adm, + renderer: context === 'outstream' ? newRenderer(bidRequest.bidRequest, bid) : undefined + })); + } } }); return outBids; diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index a8e9d49cf07..148a8857f69 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -262,7 +262,7 @@ describe('GamoshiAdapter', function () { 'price': 2.016, 'adid': '579ef31bfa788b9d2000d562', 'nurl': 'https://rtb.gamoshi.io/pix/monitoring/win_notice/imp_5b05b9fde4b09084267a556f/im.gif?r=imp_5b05b9fde4b09084267a556f&i=1&a=579ef31bfa788b9d2000d562&b=0&p=${AUCTION_PRICE}', - 'adm': ' ', + 'adm': '', 'adomain': ['aaa.com'], 'cid': '579ef268fa788b9d2000d55c', 'crid': '579ef31bfa788b9d2000d562', @@ -321,38 +321,28 @@ describe('GamoshiAdapter', function () { it('aggregates banner bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: bannerBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); const ad0 = response[0], ad1 = response[1]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); - expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); - expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); - expect(ad0.height).to.equal(rtbResponse.seatbid[0].bid[0].h); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[1].bid[0].h); expect(ad0.ttl).to.equal(60 * 10); - expect(ad0.creativeId).to.equal(rtbResponse.seatbid[0].bid[0].crid); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); expect(ad0.netRevenue).to.equal(true); - expect(ad0.currency).to.equal(rtbResponse.seatbid[0].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad0.ad).to.equal(rtbResponse.seatbid[0].bid[0].adm); + expect(ad0.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); expect(ad0.vastXml).to.be.an('undefined'); - - expect(ad1.requestId).to.equal(bannerBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastXml).to.be.an('undefined'); + expect(ad0.vastUrl).to.be.an('undefined'); }); it('aggregates video bids from all seat bids', function () { const response = spec.interpretResponse({body: rtbResponse}, {bidRequest: videoBidRequest}); expect(Array.isArray(response)).to.equal(true); - expect(response.length).to.equal(2); + expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(videoBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[0].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[0].bid[0].w); @@ -364,18 +354,6 @@ describe('GamoshiAdapter', function () { expect(ad0.ad).to.be.an('undefined'); expect(ad0.vastXml).to.equal(rtbResponse.seatbid[0].bid[0].adm); expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[0].bid[0].ext.vast_url); - - expect(ad1.requestId).to.equal(videoBidRequest.bidId); - expect(ad1.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); - expect(ad1.width).to.equal(rtbResponse.seatbid[1].bid[0].w); - expect(ad1.height).to.equal(rtbResponse.seatbid[1].bid[0].h); - expect(ad1.ttl).to.equal(60 * 10); - expect(ad1.creativeId).to.equal(rtbResponse.seatbid[1].bid[0].crid); - expect(ad1.netRevenue).to.equal(true); - expect(ad1.currency).to.equal(rtbResponse.seatbid[1].bid[0].cur || rtbResponse.cur || 'USD'); - expect(ad1.ad).to.be.an('undefined'); - expect(ad1.vastXml).to.equal(rtbResponse.seatbid[1].bid[0].adm); - expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[1].bid[0].ext.vast_url); }); it('aggregates user-sync pixels', function () { From 65cbdd8796ad15c6cdc7ce1dcdd5845caf515df0 Mon Sep 17 00:00:00 2001 From: sa1omon Date: Mon, 28 Jan 2019 12:06:36 +0200 Subject: [PATCH 5/6] Refactor multi-format ad units handler. --- modules/gamoshiBidAdapter.js | 13 +++++++------ test/spec/modules/gamoshiBidAdapter_spec.js | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 1a5b115907d..4ff304af867 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {Renderer} from '../src/Renderer'; +import {BANNER, VIDEO} from "../src/mediaTypes"; const ENDPOINTS = { 'cleanmedia': 'https://bidder.cleanmediaads.com', @@ -28,14 +29,14 @@ export const helper = { getMediaType: function (bid) { if (bid.ext) { if (bid.ext.media_type) { - return bid.ext.media_type; + return bid.ext.media_type.toLowerCase(); } else if (bid.ext.vast_url) { - return 'video'; + return VIDEO; } else { - return 'banner'; + return BANNER; } } - return 'banner'; + return BANNER; } }; @@ -160,9 +161,9 @@ export const spec = { }; if (utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.' + outBid.mediaType)) { - if (outBid.mediaType === 'banner') { + if (outBid.mediaType === BANNER) { outBids.push(Object.assign({}, outBid, {ad: bid.adm})); - } else if (outBid.mediaType === 'video') { + } else if (outBid.mediaType === VIDEO) { const context = utils.deepAccess(bidRequest.bidRequest, 'mediaTypes.video.context'); outBids.push(Object.assign({}, outBid, { vastUrl: bid.ext.vast_url, diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 148a8857f69..896271be4d3 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -323,7 +323,7 @@ describe('GamoshiAdapter', function () { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(1); - const ad0 = response[0], ad1 = response[1]; + const ad0 = response[0]; expect(ad0.requestId).to.equal(bannerBidRequest.bidId); expect(ad0.cpm).to.equal(rtbResponse.seatbid[1].bid[0].price); expect(ad0.width).to.equal(rtbResponse.seatbid[1].bid[0].w); From 1b33591ed3e83b048b0d2df859031628e8dd046b Mon Sep 17 00:00:00 2001 From: sa1omon Date: Mon, 4 Feb 2019 11:33:47 +0200 Subject: [PATCH 6/6] Modify gdpr consent existence. Add viewdeos bidder code. --- modules/gamoshiBidAdapter.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 4ff304af867..307f2d8bc91 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -2,9 +2,10 @@ import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; import {config} from '../src/config'; import {Renderer} from '../src/Renderer'; -import {BANNER, VIDEO} from "../src/mediaTypes"; +import {BANNER, VIDEO} from '../src/mediaTypes'; const ENDPOINTS = { + 'viewdeos': 'https://rtb.viewdeos.com', 'cleanmedia': 'https://bidder.cleanmediaads.com', 'gamoshi': 'https://rtb.gamoshi.io', 'gambid': 'https://rtb.gamoshi.io', @@ -42,7 +43,7 @@ export const helper = { export const spec = { code: 'gamoshi', - aliases: ['gambid', 'cleanmedia'], + aliases: ['gambid', 'cleanmedia', 'viewdeos'], supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { @@ -76,7 +77,9 @@ export const spec = { 'ext': {} }; - if (bidderRequest.gdprConsent) { + if (bidderRequest.gdprConsent && + bidderRequest.gdprConsent.consentString && + bidderRequest.gdprConsent.gdprApplies) { rtbBidRequest.ext.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies @@ -96,7 +99,7 @@ export const spec = { params.favoredMediaType && this.supportedMediaTypes.includes(params.favoredMediaType); if ((!mediaTypes || mediaTypes.banner)) { - if (!hasFavoredMediaType || params.favoredMediaType === 'banner') { + if (!hasFavoredMediaType || params.favoredMediaType === BANNER) { const bannerImp = Object.assign({}, imp, { banner: { w: sizes.length ? sizes[0][0] : 300, @@ -110,7 +113,7 @@ export const spec = { } if (mediaTypes && mediaTypes.video) { - if (!hasFavoredMediaType || params.favoredMediaType === 'video') { + if (!hasFavoredMediaType || params.favoredMediaType === VIDEO) { const videoImp = Object.assign({}, imp, { video: { w: sizes.length ? sizes[0][0] : 300,