diff --git a/adapters.json b/adapters.json index 06a353e6541..fdf892be5ad 100644 --- a/adapters.json +++ b/adapters.json @@ -11,6 +11,7 @@ "appnexusAst", "conversant", "districtmDMX", + "fidelity", "getintent", "gumgum", "hiromedia", diff --git a/src/adapters/fidelity.js b/src/adapters/fidelity.js new file mode 100644 index 00000000000..66550219561 --- /dev/null +++ b/src/adapters/fidelity.js @@ -0,0 +1,100 @@ +var utils = require('../utils.js'); +var bidfactory = require('../bidfactory.js'); +var bidmanager = require('../bidmanager.js'); +var adloader = require('../adloader'); +var STATUS = require('../constants').STATUS; + +var FidelityAdapter = function FidelityAdapter() { + var FIDELITY_BIDDER_NAME = 'fidelity'; + var FIDELITY_SERVER_NAME = 'x.fidelity-media.com'; + + function _callBids(params) { + var bids = params.bids || []; + bids.forEach(function (currentBid) { + var server = currentBid.params.server || FIDELITY_SERVER_NAME; + var m3_u = window.location.protocol + '//'+server+'/delivery/hb.php?'; + m3_u += 'callback=window.$$PREBID_GLOBAL$$.fidelityResponse'; + m3_u += '&requestid='+utils.getUniqueIdentifierStr(); + m3_u += '&impid='+currentBid.bidId; + m3_u += '&zoneid='+currentBid.params.zoneid; + m3_u += '&cb='+Math.floor(Math.random()*99999999999); + m3_u += document.charset ? '&charset='+document.charset : (document.characterSet ? '&charset='+document.characterSet : ''); + + var loc; + try { + loc = window.top !== window ? document.referrer : window.location.href; + } catch (e) { + loc = document.referrer; + } + loc = currentBid.params.loc || loc; + m3_u += '&loc=' + encodeURIComponent(loc); + + var subid = currentBid.params.subid || 'hb'; + m3_u += '&subid=' + subid; + if (document.referrer) m3_u += '&referer=' + encodeURIComponent(document.referrer); + if (currentBid.params.click) m3_u += '&ct0=' + encodeURIComponent(currentBid.params.click); + m3_u += '&flashver=' + encodeURIComponent(getFlashVersion()); + + adloader.loadScript(m3_u); + }); + } + + function getFlashVersion(){ + var plugins, plugin, result; + + if (navigator.plugins && navigator.plugins.length > 0) { + plugins = navigator.plugins; + for (var i = 0; i < plugins.length && !result; i++) { + plugin = plugins[i]; + if (plugin.name.indexOf("Shockwave Flash") > -1) { + result = plugin.description.split("Shockwave Flash ")[1]; + } + } + } + return result ? result : ""; + } + + function addBlankBidResponses(placementsWithBidsBack) { + var allFidelityBidRequests = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === FIDELITY_BIDDER_NAME); + + if (allFidelityBidRequests && allFidelityBidRequests.bids){ + utils._each(allFidelityBidRequests.bids, function (fidelityBid) { + if (!utils.contains(placementsWithBidsBack, fidelityBid.placementCode)) { + // Add a no-bid response for this placement. + var bid = bidfactory.createBid(STATUS.NO_BID, fidelityBid); + bid.bidderCode = FIDELITY_BIDDER_NAME; + bidmanager.addBidResponse(fidelityBid.placementCode, bid); + } + }); + } + } + + $$PREBID_GLOBAL$$.fidelityResponse = function(responseObj) { + + if (!responseObj || !responseObj.seatbid || responseObj.seatbid.length === 0 || !responseObj.seatbid[0].bid || responseObj.seatbid[0].bid.length === 0) { + addBlankBidResponses([]); + return; + } + + var bid = responseObj.seatbid[0].bid[0]; + var status = bid.adm ? STATUS.GOOD : STATUS.NO_BID; + var requestObj = utils.getBidRequest(bid.impid); + + var bidResponse = bidfactory.createBid(status); + bidResponse.bidderCode = FIDELITY_BIDDER_NAME; + if (status === STATUS.GOOD) { + bidResponse.cpm = parseFloat(bid.price); + bidResponse.ad = bid.adm; + bidResponse.width = parseInt(bid.width); + bidResponse.height = parseInt(bid.height); + } + var placementCode = requestObj && requestObj.placementCode; + bidmanager.addBidResponse(placementCode, bidResponse); + }; + + return { + callBids: _callBids + }; +}; + +module.exports = FidelityAdapter; \ No newline at end of file diff --git a/test/spec/adapters/fidelity_spec.js b/test/spec/adapters/fidelity_spec.js new file mode 100644 index 00000000000..31ae9378574 --- /dev/null +++ b/test/spec/adapters/fidelity_spec.js @@ -0,0 +1,197 @@ +describe('fidelity adapter tests', function() { + const expect = require('chai').expect; + const adapter = require('src/adapters/fidelity'); + const adLoader = require('src/adloader'); + const bidmanager = require('src/bidmanager'); + const STATUS = require('src/constants').STATUS; + var urlParse = require('url-parse'); + var querystringify = require('querystringify'); + + describe('creation of bid url', function () { + + it('should be called', function () { + var stubLoadScript; + stubLoadScript = sinon.stub(adLoader, 'loadScript'); + + var bidderRequest = { + bidderCode: 'fidelity', + bids: [ + { + bidId: 'bidId-123456-1', + bidder: 'fidelity', + params: { + zoneid: '37' + }, + placementCode: 'div-gpt-ad-123456-1' + }, + ] + }; + + adapter().callBids(bidderRequest); + sinon.assert.called(stubLoadScript); + + stubLoadScript.restore(); + }); + + it('should populate required parameters', function () { + var stubLoadScript; + stubLoadScript = sinon.stub(adLoader, 'loadScript'); + + var bidderRequest = { + bidderCode: 'fidelity', + bids: [ + { + bidId: 'bidId-123456-1', + bidder: 'fidelity', + params: { + zoneid: '37', + }, + placementCode: 'div-gpt-ad-123456-1' + }, + ] + }; + + adapter().callBids(bidderRequest); + + stubLoadScript.restore(); + }); + + it('should populate required and optional parameters', function () { + var stubLoadScript; + stubLoadScript = sinon.stub(adLoader, 'loadScript'); + + var bidderRequest = { + bidderCode: 'fidelity', + bids: [ + { + bidId: 'bidId-123456-1', + bidder: 'fidelity', + params: { + zoneid: '37', + server: 't.fidelity-media.com', + loc: 'http://locurl', + click: 'http://clickurl', + subid: '000' + }, + placementCode: 'div-gpt-ad-123456-1' + }, + ] + }; + + adapter().callBids(bidderRequest); + + var requestURI = stubLoadScript.getCall(0).args[0]; + var parsedBidUrl = urlParse(requestURI); + var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); + + expect(parsedBidUrl.hostname).to.equal('t.fidelity-media.com'); + + expect(parsedBidUrlQueryString).to.have.property('zoneid').and.to.equal('37'); + expect(parsedBidUrlQueryString).to.have.property('impid').and.to.equal('bidId-123456-1'); + expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal('window.$$PREBID_GLOBAL$$.fidelityResponse'); + expect(parsedBidUrlQueryString).to.have.property('loc').and.to.equal('http://locurl'); + expect(parsedBidUrlQueryString).to.have.property('ct0').and.to.equal('http://clickurl'); + expect(parsedBidUrlQueryString).to.have.property('subid').and.to.equal('000'); + + stubLoadScript.restore(); + }); + }); + + describe('fidelityResponse', function () { + + it('should exist and be a function', function () { + expect(pbjs.fidelityResponse).to.exist.and.to.be.a('function'); + }); + + it('should add empty bid response if no bids returned', function () { + var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); + + var bidderRequest = { + bidderCode: 'fidelity', + bids: [ + { + bidId: 'bidId-123456-1', + bidder: 'fidelity', + params: { + zoneid: '37' + }, + placementCode: 'div-gpt-ad-123456-1' + }, + ] + }; + + // no bids returned in the response. + var response = { + "id": "543210", + "seatbid": [] + }; + + pbjs._bidsRequested.push(bidderRequest); + // adapter needs to be called, in order for the stub to register. + adapter() + + pbjs.fidelityResponse(response); + + var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; + var bidObject1 = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode1).to.equal('div-gpt-ad-123456-1'); + expect(bidObject1.getStatusCode()).to.equal(2); + expect(bidObject1.bidderCode).to.equal('fidelity'); + + stubAddBidResponse.restore(); + }); + + it('should add a bid response for bid returned', function () { + var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); + + var bidderRequest = { + bidderCode: 'fidelity', + bids: [ + { + bidId: 'bidId-123456-1', + bidder: 'fidelity', + params: { + zoneid: '37' + }, + placementCode: 'div-gpt-ad-123456-1' + }, + ] + }; + + // Returning a single bid in the response. + var response = { + "id": "543210", + "seatbid": [ { + "bid" : [ { + "id" : "1111111", + "impid" : "bidId-123456-1", + "price" : 0.09, + "adm" : "<>", + "height" : 90, + "width" : 728 + } ] + } ] + }; + + pbjs._bidsRequested.push(bidderRequest); + // adapter needs to be called, in order for the stub to register. + adapter() + + pbjs.fidelityResponse(response); + + var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; + var bidObject1 = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode1).to.equal('div-gpt-ad-123456-1'); + expect(bidObject1.getStatusCode()).to.equal(1); + expect(bidObject1.bidderCode).to.equal('fidelity'); + expect(bidObject1.cpm).to.equal(0.09); + expect(bidObject1.height).to.equal(90); + expect(bidObject1.width).to.equal(728); + expect(bidObject1.ad).to.equal('<>'); + + stubAddBidResponse.restore(); + }); + }); +}); \ No newline at end of file