diff --git a/adapters.json b/adapters.json index 6fad373286b..06a353e6541 100644 --- a/adapters.json +++ b/adapters.json @@ -12,6 +12,7 @@ "conversant", "districtmDMX", "getintent", + "gumgum", "hiromedia", "indexExchange", "kruxlink", diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index 456f1ce09cb..4c5fd87798d 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -319,6 +319,12 @@ params: { tagid: 007, // REQUIRED int. To get one, contact http://www.memeglobal.com } + }, + { + bidder: 'gumgum', + params: { + inScreen: 'ggumtest' // REQUIRED str Tracking Id + } } ] } diff --git a/src/adapters/gumgum.js b/src/adapters/gumgum.js new file mode 100644 index 00000000000..36b53c4e060 --- /dev/null +++ b/src/adapters/gumgum.js @@ -0,0 +1,114 @@ +const bidfactory = require('../bidfactory'); +const bidmanager = require('../bidmanager'); +const utils = require('../utils'); +const adloader = require('../adloader'); + +const BIDDER_CODE = 'gumgum'; +const CALLBACKS = {}; + +const GumgumAdapter = function GumgumAdapter() { + + const bidEndpoint = `https://g2.gumgum.com/hbid/imp`; + + const WINDOW = global.top; + const SCREEN = WINDOW.screen; + + function _callBids({ bids }) { + const browserParams = { + vw: WINDOW.innerWidth, + vh: WINDOW.innerHeight, + sw: SCREEN.width, + sh: SCREEN.height, + pu: WINDOW.location.href, + dpr: WINDOW.devicePixelRatio || 1 + }; + utils._each(bids, bidRequest => { + const { bidId + , params = {} + , placementCode + } = bidRequest; + const trackingId = params.inScreen; + const nativeId = params.native; + const slotId = params.inSlot; + const bid = {}; + + /* slot/native ads need the placement id */ + switch (true) { + case !!(params.inImage): bid.pi = 1; break; + case !!(params.inScreen): bid.pi = 2; break; + case !!(params.inSlot): bid.pi = 3; break; + case !!(params.native): bid.pi = 5; break; + default: return utils.logWarn( + `[GumGum] No product selected for the placement ${placementCode}` + + ', please check your implementation.' + ); + } + /* tracking id is required for in-image and in-screen */ + if (trackingId) bid.t = trackingId; + /* native ads require a native placement id */ + if (nativeId) bid.ni = nativeId; + /* slot ads require a slot id */ + if (slotId) bid.si = slotId; + + const cachedBid = Object.assign({ + placementCode, + id: bidId + }, bid); + + const callback = { jsonp: `$$PREBID_GLOBAL$$.handleGumGumCB['${ bidId }']` }; + CALLBACKS[bidId] = _handleGumGumResponse(cachedBid); + const query = Object.assign(callback, browserParams, bid); + const bidCall = `${bidEndpoint}?${utils.parseQueryStringParameters(query)}`; + adloader.loadScript(bidCall); + }); + } + + const _handleGumGumResponse = cachedBidRequest => bidResponse => { + const ad = bidResponse && bidResponse.ad; + if (ad && ad.id) { + const bid = bidfactory.createBid(1); + const { t: trackingId + , pi: productId + , placementCode + } = cachedBidRequest; + bidResponse.placementCode = placementCode; + const encodedResponse = encodeURIComponent(JSON.stringify(bidResponse)); + const gumgumAdLoader = ``; + Object.assign(bid, { + cpm: ad.price, + ad: gumgumAdLoader, + width: ad.width, + height: ad.height, + bidderCode: BIDDER_CODE + }); + bidmanager.addBidResponse(cachedBidRequest.placementCode, bid); + } else { + const noBid = bidfactory.createBid(2); + noBid.bidderCode = BIDDER_CODE; + bidmanager.addBidResponse(cachedBidRequest.placementCode, noBid); + } + delete CALLBACKS[cachedBidRequest.id]; + }; + + window.$$PREBID_GLOBAL$$.handleGumGumCB = CALLBACKS; + + return { + callBids: _callBids + }; + +}; + +module.exports = GumgumAdapter; diff --git a/test/spec/adapters/gumgum_spec.js b/test/spec/adapters/gumgum_spec.js new file mode 100644 index 00000000000..1c4f8a329f7 --- /dev/null +++ b/test/spec/adapters/gumgum_spec.js @@ -0,0 +1,201 @@ +import {expect} from 'chai'; +import Adapter from '../../../src/adapters/gumgum'; +import bidManager from '../../../src/bidmanager'; +import adLoader from '../../../src/adloader'; +import { STATUS } from '../../../src/constants'; + +describe('gumgum adapter', () => { + 'use strict'; + + let adapter; + let sandbox; + + const TEST = { + PUBLISHER_IDENTITY: 'ggumtest', + BIDDER_CODE: 'gumgum', + PLACEMENT: 'placementId', + CPM: 2 + }; + const bidderRequest = { + bidderCode: TEST.BIDDER_CODE, + bids: [{ // in-screen + bidId: 'InScreenBidId', + bidder: TEST.BIDDER_CODE, + placementCode: TEST.PLACEMENT, + sizes: [ [728, 90] ], + params: { + inScreen: TEST.PUBLISHER_IDENTITY + } + }, { // in-image + bidId: 'InImageBidId', + bidder: TEST.BIDDER_CODE, + placementCode: TEST.PLACEMENT, + sizes: [ [728, 90] ], + params: { + inImage: TEST.PUBLISHER_IDENTITY + } + }, { // native + bidId: 'NativeBidId', + bidder: TEST.BIDDER_CODE, + placementCode: TEST.PLACEMENT, + sizes: [ [728, 90] ], + params: { + native: 10 + } + }, { // slot + bidId: 'InSlotBidId', + bidder: TEST.BIDDER_CODE, + placementCode: TEST.PLACEMENT, + sizes: [ [728, 90] ], + params: { + inSlot: 10 + } + }, { // no identity + bidId: 'NoIdentityBidId', + bidder: TEST.BIDDER_CODE, + placementCode: TEST.PLACEMENT, + sizes: [ [728, 90] ] + }] + }; + const bidderResponse = { + "ad": { + "id": 1, + "width": 728, + "height": 90, + "markup": "