diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 4f1eb298794..5d6227dd69d 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,7 +1,9 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER } from 'src/mediaTypes'; -import { REPO_AND_VERSION } from 'src/constants'; +import * as utils from 'src/utils' +import { registerBidder } from 'src/adapters/bidderFactory' +import { BANNER } from 'src/mediaTypes' +import { REPO_AND_VERSION } from 'src/constants' +import { ajax } from 'src/ajax' +const errorUrl = 'https://pcb.aws.lijit.com/collect' export const spec = { code: 'sovrn', @@ -22,48 +24,59 @@ export const spec = { * @return object of parameters for Prebid AJAX request */ buildRequests: function(bidReqs, bidderRequest) { - const loc = utils.getTopWindowLocation(); - let sovrnImps = []; - let iv; - utils._each(bidReqs, function (bid) { - iv = iv || utils.getBidIdParameter('iv', bid.params); - sovrnImps.push({ - id: bid.bidId, - banner: { w: 1, h: 1 }, - tagid: String(utils.getBidIdParameter('tagid', bid.params)), - bidfloor: utils.getBidIdParameter('bidfloor', bid.params) + try { + const loc = utils.getTopWindowLocation(); + let sovrnImps = []; + let iv; + utils._each(bidReqs, function (bid) { + iv = iv || utils.getBidIdParameter('iv', bid.params); + bid.sizes = ((utils.isArray(bid.sizes) && utils.isArray(bid.sizes[0])) ? bid.sizes : [bid.sizes]) + bid.sizes = bid.sizes.filter(size => utils.isArray(size)) + const processedSizes = bid.sizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) + sovrnImps.push({ + id: bid.bidId, + banner: { + format: processedSizes, + w: 1, + h: 1, + }, + tagid: String(utils.getBidIdParameter('tagid', bid.params)), + bidfloor: utils.getBidIdParameter('bidfloor', bid.params) + }); }); - }); - const sovrnBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: sovrnImps, - site: { - domain: loc.host, - page: loc.host + loc.pathname + loc.search + loc.hash - } - }; + const sovrnBidReq = { + id: utils.getUniqueIdentifierStr(), + imp: sovrnImps, + site: { + domain: loc.host, + page: loc.host + loc.pathname + loc.search + loc.hash + } + }; - if (bidderRequest && bidderRequest.gdprConsent) { - sovrnBidReq.regs = { - ext: { - gdpr: +bidderRequest.gdprConsent.gdprApplies - }}; - sovrnBidReq.user = { - ext: { - consent: bidderRequest.gdprConsent.consentString - }}; - } + if (bidderRequest && bidderRequest.gdprConsent) { + sovrnBidReq.regs = { + ext: { + gdpr: +bidderRequest.gdprConsent.gdprApplies + }}; + sovrnBidReq.user = { + ext: { + consent: bidderRequest.gdprConsent.consentString + }}; + } - let url = `//ap.lijit.com/rtb/bid?` + - `src=${REPO_AND_VERSION}`; - if (iv) url += `&iv=${iv}`; + let url = `//ap.lijit.com/rtb/bid?` + + `src=${REPO_AND_VERSION}`; + if (iv) url += `&iv=${iv}`; - return { - method: 'POST', - url: url, - data: JSON.stringify(sovrnBidReq), - options: {contentType: 'text/plain'} - }; + return { + method: 'POST', + url: url, + data: JSON.stringify(sovrnBidReq), + options: {contentType: 'text/plain'} + } + } catch (e) { + new LogError(e, {bidReqs, bidderRequest}).send() + } }, /** @@ -72,48 +85,83 @@ export const spec = { * @return {Bid[]} An array of formatted bids. */ interpretResponse: function({ body: {id, seatbid} }) { - let sovrnBidResponses = []; - if (id && - seatbid && - seatbid.length > 0 && - seatbid[0].bid && - seatbid[0].bid.length > 0) { - seatbid[0].bid.map(sovrnBid => { - sovrnBidResponses.push({ - requestId: sovrnBid.impid, - cpm: parseFloat(sovrnBid.price), - width: parseInt(sovrnBid.w), - height: parseInt(sovrnBid.h), - creativeId: sovrnBid.crid || sovrnBid.id, - dealId: sovrnBid.dealid || null, - currency: 'USD', - netRevenue: true, - mediaType: BANNER, - ad: decodeURIComponent(`${sovrnBid.adm}`), - ttl: 60 + try { + let sovrnBidResponses = []; + if (id && + seatbid && + seatbid.length > 0 && + seatbid[0].bid && + seatbid[0].bid.length > 0) { + seatbid[0].bid.map(sovrnBid => { + sovrnBidResponses.push({ + requestId: sovrnBid.impid, + cpm: parseFloat(sovrnBid.price), + width: parseInt(sovrnBid.w), + height: parseInt(sovrnBid.h), + creativeId: sovrnBid.crid || sovrnBid.id, + dealId: sovrnBid.dealid || null, + currency: 'USD', + netRevenue: true, + mediaType: BANNER, + ad: decodeURIComponent(`${sovrnBid.adm}`), + ttl: 60 + }); }); - }); + } + return sovrnBidResponses + } catch (e) { + new LogError(e, {id, seatbid}).send() } - return sovrnBidResponses; }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { - if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { - let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) - .map(rsp => { return rsp.body.ext.iid }); - let consentString = ''; - if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { - consentString = gdprConsent.consentString - } - if (iidArr[0]) { - return [{ - type: 'iframe', - url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, - }]; + try { + if (serverResponses && serverResponses.length !== 0 && syncOptions.iframeEnabled) { + let iidArr = serverResponses.filter(rsp => rsp.body && rsp.body.ext && rsp.body.ext.iid) + .map(rsp => { return rsp.body.ext.iid }); + let consentString = ''; + if (gdprConsent && gdprConsent.gdprApplies && typeof gdprConsent.consentString === 'string') { + consentString = gdprConsent.consentString + } + if (iidArr[0]) { + return [{ + type: 'iframe', + url: '//ap.lijit.com/beacon?informer=' + iidArr[0] + '&gdpr_consent=' + consentString, + }]; + } } + return [] + } catch (e) { + new LogError(e, {syncOptions, serverResponses, gdprConsent}).send() } - return []; }, -}; +} + +class LogError { + constructor(e, data) { + utils.logError(e) + this.error = {} + this.error.payload = 'error' + this.error.ts = utils.timestamp() + this.error.message = e.message + this.error.data = data + this.error.source = 'sovrnBidAdapter' + this.error.stack = e.stack + this.error.prebidVersion = $$PREBID_GLOBAL$$.version + this.error.url = utils.getTopWindowLocation().href + this.error.userAgent = navigator.userAgent + } + send() { + ajax( + errorUrl, + null, + JSON.stringify(this.error), + { + contentType: 'application/json', + method: 'POST', + } + ) + } +} registerBidder(spec); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index 22c93505ecf..ce31b9e1771 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -16,7 +16,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -47,7 +48,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -64,6 +66,33 @@ describe('sovrnBidAdapter', function() { expect(request.url).to.equal(ENDPOINT) }); + it('sets the proper banner object', function() { + const payload = JSON.parse(request.data); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) + }) + + it('accepts a single array as a size', function() { + const singleSize = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370', + 'iv': 'vet' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [300, 250], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + const request = spec.buildRequests(singleSize) + const payload = JSON.parse(request.data) + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}]) + expect(payload.imp[0].banner.w).to.equal(1) + expect(payload.imp[0].banner.h).to.equal(1) + }) + it('sends \'iv\' as query param if present', function () { const ivBidRequests = [{ 'bidder': 'sovrn', @@ -73,7 +102,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -116,7 +146,8 @@ describe('sovrnBidAdapter', function() { }, 'adUnitCode': 'adunit-code', 'sizes': [ - [300, 250] + [300, 250], + [300, 600] ], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6',