diff --git a/modules/zemantaBidAdapter.js b/modules/zemantaBidAdapter.js deleted file mode 100644 index d0ac64e48e4..00000000000 --- a/modules/zemantaBidAdapter.js +++ /dev/null @@ -1,257 +0,0 @@ -// jshint esversion: 6, es3: false, node: true -'use strict'; - -import { - registerBidder -} from '../src/adapters/bidderFactory.js'; -import { NATIVE, BANNER } from '../src/mediaTypes.js'; -import * as utils from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; -import { config } from '../src/config.js'; - -const BIDDER_CODE = 'zemanta'; -const CURRENCY = 'USD'; -const NATIVE_ASSET_IDS = { 0: 'title', 2: 'icon', 3: 'image', 5: 'sponsoredBy', 4: 'body', 1: 'cta' }; -const NATIVE_PARAMS = { - title: { id: 0, name: 'title' }, - icon: { id: 2, type: 1, name: 'img' }, - image: { id: 3, type: 3, name: 'img' }, - sponsoredBy: { id: 5, name: 'data', type: 1 }, - body: { id: 4, name: 'data', type: 2 }, - cta: { id: 1, type: 12, name: 'data' } -}; - -export const spec = { - code: BIDDER_CODE, - aliases: ['outbrain'], - supportedMediaTypes: [ NATIVE, BANNER ], - isBidRequestValid: (bid) => { - return ( - (!!config.getConfig('zemanta.bidderUrl') || !!config.getConfig('outbrain.bidderUrl')) && - !!utils.deepAccess(bid, 'params.publisher.id') && - !!(bid.nativeParams || bid.sizes) - ); - }, - buildRequests: (validBidRequests, bidderRequest) => { - const page = bidderRequest.refererInfo.referer; - const ua = navigator.userAgent; - const test = setOnAny(validBidRequests, 'params.test'); - const publisher = setOnAny(validBidRequests, 'params.publisher'); - const cur = CURRENCY; - const endpointUrl = config.getConfig('zemanta.bidderUrl') || config.getConfig('outbrain.bidderUrl'); - const timeout = bidderRequest.timeout; - - const imps = validBidRequests.map((bid, id) => { - bid.netRevenue = 'net'; - const imp = { - id: id + 1 + '' - } - - if (bid.params.tagid) { - imp.tagid = bid.params.tagid - } - - if (bid.nativeParams) { - imp.native = { - request: JSON.stringify({ - assets: getNativeAssets(bid) - }) - } - } else { - imp.banner = { - format: transformSizes(bid.sizes) - } - } - - return imp; - }); - - const request = { - id: bidderRequest.auctionId, - site: { page, publisher }, - device: { ua }, - source: { fd: 1 }, - cur: [cur], - tmax: timeout, - imp: imps - }; - - if (test) { - request.is_debug = !!test; - request.test = 1; - } - - if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { - utils.deepSetValue(request, 'user.ext.consent', bidderRequest.gdprConsent.consentString) - utils.deepSetValue(request, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1) - } - if (bidderRequest.uspConsent) { - utils.deepSetValue(request, 'regs.ext.us_privacy', bidderRequest.uspConsent) - } - if (config.getConfig('coppa') === true) { - utils.deepSetValue(request, 'regs.coppa', config.getConfig('coppa') & 1) - } - - return { - method: 'POST', - url: endpointUrl, - data: JSON.stringify(request), - bids: validBidRequests - }; - }, - interpretResponse: (serverResponse, { bids }) => { - if (!serverResponse.body) { - return []; - } - const { seatbid, cur } = serverResponse.body; - - const bidResponses = flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => { - result[bid.impid - 1] = bid; - return result; - }, []); - - return bids.map((bid, id) => { - const bidResponse = bidResponses[id]; - if (bidResponse) { - const type = bid.nativeParams ? NATIVE : BANNER; - const bidObject = { - requestId: bid.bidId, - cpm: bidResponse.price, - creativeId: bidResponse.crid, - ttl: 360, - netRevenue: bid.netRevenue === 'net', - currency: cur, - mediaType: type, - nurl: bidResponse.nurl, - }; - if (type === NATIVE) { - bidObject.native = parseNative(bidResponse); - } else { - bidObject.ad = bidResponse.adm; - bidObject.width = bidResponse.w; - bidObject.height = bidResponse.h; - } - return bidObject; - } - }).filter(Boolean); - }, - getUserSyncs: (syncOptions) => { - const syncs = []; - const syncUrl = config.getConfig('zemanta.usersyncUrl') || config.getConfig('outbrain.usersyncUrl'); - if (syncOptions.pixelEnabled && syncUrl) { - syncs.push({ - type: 'image', - url: syncUrl - }); - } - return syncs; - }, - onBidWon: (bid) => { - ajax(utils.replaceAuctionPrice(bid.nurl, bid.originalCpm)) - } -}; - -registerBidder(spec); - -function parseNative(bid) { - const { assets, link, eventtrackers } = JSON.parse(bid.adm); - const result = { - clickUrl: link.url, - clickTrackers: link.clicktrackers || undefined - }; - assets.forEach(asset => { - const kind = NATIVE_ASSET_IDS[asset.id]; - const content = kind && asset[NATIVE_PARAMS[kind].name]; - if (content) { - result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; - } - }); - if (eventtrackers) { - result.impressionTrackers = []; - eventtrackers.forEach(tracker => { - if (tracker.event !== 1) return; - switch (tracker.method) { - case 1: // img - result.impressionTrackers.push(tracker.url); - break; - case 2: // js - result.javascriptTrackers = ``; - break; - } - }); - } - return result; -} - -function setOnAny(collection, key) { - for (let i = 0, result; i < collection.length; i++) { - result = utils.deepAccess(collection[i], key); - if (result) { - return result; - } - } -} - -function flatten(arr) { - return [].concat(...arr); -} - -function getNativeAssets(bid) { - return utils._map(bid.nativeParams, (bidParams, key) => { - const props = NATIVE_PARAMS[key]; - const asset = { - required: bidParams.required & 1, - }; - if (props) { - asset.id = props.id; - let wmin, hmin, w, h; - let aRatios = bidParams.aspect_ratios; - - if (aRatios && aRatios[0]) { - aRatios = aRatios[0]; - wmin = aRatios.min_width || 0; - hmin = aRatios.ratio_height * wmin / aRatios.ratio_width | 0; - } - - if (bidParams.sizes) { - const sizes = flatten(bidParams.sizes); - w = sizes[0]; - h = sizes[1]; - } - - asset[props.name] = { - len: bidParams.len, - type: props.type, - wmin, - hmin, - w, - h - }; - - return asset; - } - }).filter(Boolean); -} - -/* Turn bid request sizes into ut-compatible format */ -function transformSizes(requestSizes) { - if (!utils.isArray(requestSizes)) { - return []; - } - - if (requestSizes.length === 2 && !utils.isArray(requestSizes[0])) { - return [{ - w: parseInt(requestSizes[0], 10), - h: parseInt(requestSizes[1], 10) - }]; - } else if (utils.isArray(requestSizes[0])) { - return requestSizes.map(item => - ({ - w: parseInt(item[0], 10), - h: parseInt(item[1], 10) - }) - ); - } - - return []; -} diff --git a/modules/zemantaBidAdapter.md b/modules/zemantaBidAdapter.md deleted file mode 100644 index d991b67d429..00000000000 --- a/modules/zemantaBidAdapter.md +++ /dev/null @@ -1,107 +0,0 @@ -# Overview - -``` -Module Name: Zemanta Adapter -Module Type: Bidder Adapter -Maintainer: prog-ops-team@outbrain.com -``` - -# Description - -Module that connects to zemanta bidder to fetch bids. -Both native and display formats are supported but not at the same time. Using OpenRTB standard. - -# Configuration - -## Bidder and usersync URLs - -The Zemanta adapter does not work without setting the correct bidder and usersync URLs. -You will receive the URLs when contacting us. - -``` -pbjs.setConfig({ - zemanta: { - bidderUrl: 'https://bidder-url.com', - usersyncUrl: 'https://usersync-url.com' - } -}); -``` - - -# Test Native Parameters -``` - var adUnits = [ - code: '/19968336/prebid_native_example_1', - mediaTypes: { - native: { - image: { - required: false, - sizes: [100, 50] - }, - title: { - required: false, - len: 140 - }, - sponsoredBy: { - required: false - }, - clickUrl: { - required: false - }, - body: { - required: false - }, - icon: { - required: false, - sizes: [50, 50] - } - } - }, - bids: [{ - bidder: 'zemanta', - params: { - publisher: { - id: '2706', // required - name: 'Publishers Name', - domain: 'publisher.com' - }, - tagid: 'tag-id' - } - }] - ]; - - pbjs.setConfig({ - zemanta: { - bidderUrl: 'https://prebidtest.zemanta.com/api/bidder/prebidtest/bid/' - } - }); -``` - -# Test Display Parameters -``` - var adUnits = [ - code: '/19968336/prebid_display_example_1', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [{ - bidder: 'zemanta', - params: { - publisher: { - id: '2706', // required - name: 'Publishers Name', - domain: 'publisher.com' - }, - tagid: 'tag-id' - }, - }] - ]; - - pbjs.setConfig({ - zemanta: { - bidderUrl: 'https://prebidtest.zemanta.com/api/bidder/prebidtest/bid/' - } - }); -``` diff --git a/test/spec/modules/zemantaBidAdapter_spec.js b/test/spec/modules/zemantaBidAdapter_spec.js deleted file mode 100644 index 0284abd41fd..00000000000 --- a/test/spec/modules/zemantaBidAdapter_spec.js +++ /dev/null @@ -1,515 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/zemantaBidAdapter.js'; -import {config} from 'src/config.js'; -import {server} from 'test/mocks/xhr'; - -describe('Zemanta Adapter', function () { - describe('Bid request and response', function () { - const commonBidRequest = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id' - }, - }, - bidId: '2d6815a92ba1ba', - auctionId: '12043683-3254-4f74-8934-f941b085579e', - } - const nativeBidRequestParams = { - nativeParams: { - image: { - required: true, - sizes: [ - 120, - 100 - ], - sendId: true - }, - title: { - required: true, - sendId: true - }, - sponsoredBy: { - required: false - } - }, - } - - const displayBidRequestParams = { - sizes: [ - [ - 300, - 250 - ] - ] - } - - describe('isBidRequestValid', function () { - before(() => { - config.setConfig({ - zemanta: { - bidderUrl: 'https://bidder-url.com', - } - } - ) - }) - after(() => { - config.resetConfig() - }) - - it('should fail when bid is invalid', function () { - const bid = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id', - } - }, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should succeed when bid contains native params', function () { - const bid = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - it('should succeed when bid contains sizes', function () { - const bid = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...displayBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - it('should fail if publisher id is not set', function () { - const bid = { - bidder: 'zemanta', - ...nativeBidRequestParams, - } - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - it('should succeed with outbrain config', function () { - const bid = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...nativeBidRequestParams, - } - config.resetConfig() - config.setConfig({ - outbrain: { - bidderUrl: 'https://bidder-url.com', - } - }) - expect(spec.isBidRequestValid(bid)).to.equal(true) - }) - it('should fail if bidder url is not set', function () { - const bid = { - bidder: 'zemanta', - params: { - publisher: { - id: 'publisher-id', - } - }, - ...nativeBidRequestParams, - } - config.resetConfig() - expect(spec.isBidRequestValid(bid)).to.equal(false) - }) - }) - - describe('buildRequests', function () { - before(() => { - config.setConfig({ - zemanta: { - bidderUrl: 'https://bidder-url.com', - } - } - ) - }) - after(() => { - config.resetConfig() - }) - - const commonBidderRequest = { - refererInfo: { - referer: 'https://example.com/' - } - } - - it('should build native request', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - const expectedNativeAssets = { - assets: [ - { - required: 1, - id: 3, - img: { - type: 3, - w: 120, - h: 100 - } - }, - { - required: 1, - id: 0, - title: {} - }, - { - required: 0, - id: 5, - data: { - type: 1 - } - } - ] - } - const expectedData = { - site: { - page: 'https://example.com/', - publisher: { - id: 'publisher-id' - } - }, - device: { - ua: navigator.userAgent - }, - source: { - fd: 1 - }, - cur: [ - 'USD' - ], - imp: [ - { - id: '1', - native: { - request: JSON.stringify(expectedNativeAssets) - } - } - ] - } - const res = spec.buildRequests([bidRequest], commonBidderRequest) - expect(res.url).to.equal('https://bidder-url.com') - expect(res.data).to.deep.equal(JSON.stringify(expectedData)) - }); - - it('should build display request', function () { - const bidRequest = { - ...commonBidRequest, - ...displayBidRequestParams, - } - const expectedData = { - site: { - page: 'https://example.com/', - publisher: { - id: 'publisher-id' - } - }, - device: { - ua: navigator.userAgent - }, - source: { - fd: 1 - }, - cur: [ - 'USD' - ], - imp: [ - { - id: '1', - banner: { - format: [ - { - w: 300, - h: 250 - } - ] - } - } - ] - } - const res = spec.buildRequests([bidRequest], commonBidderRequest) - expect(res.url).to.equal('https://bidder-url.com') - expect(res.data).to.deep.equal(JSON.stringify(expectedData)) - }) - - it('should pass optional tagid in request', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - bidRequest.params.tagid = 'test-tag' - - const res = spec.buildRequests([bidRequest], commonBidderRequest) - const resData = JSON.parse(res.data) - expect(resData.imp[0].tagid).to.equal('test-tag') - }); - - it('should pass bidder timeout', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - const bidderRequest = { - ...commonBidderRequest, - timeout: 500 - } - const res = spec.buildRequests([bidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.tmax).to.equal(500) - }); - - it('should pass GDPR consent', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - const bidderRequest = { - ...commonBidderRequest, - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - } - } - const res = spec.buildRequests([bidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.user.ext.consent).to.equal('consentString') - expect(resData.regs.ext.gdpr).to.equal(1) - }); - - it('should pass us privacy consent', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - const bidderRequest = { - ...commonBidderRequest, - uspConsent: 'consentString' - } - const res = spec.buildRequests([bidRequest], bidderRequest) - const resData = JSON.parse(res.data) - expect(resData.regs.ext.us_privacy).to.equal('consentString') - }); - - it('should pass coppa consent', function () { - const bidRequest = { - ...commonBidRequest, - ...nativeBidRequestParams, - } - config.setConfig({coppa: true}) - - const res = spec.buildRequests([bidRequest], commonBidderRequest) - const resData = JSON.parse(res.data) - expect(resData.regs.coppa).to.equal(1) - - config.resetConfig() - }); - }) - - describe('interpretResponse', function () { - it('should return empty array if no valid bids', function () { - const res = spec.interpretResponse({}, []) - expect(res).to.be.an('array').that.is.empty - }); - - it('should interpret native response', function () { - const serverResponse = { - body: { - id: '0a73e68c-9967-4391-b01b-dda2d9fc54e4', - seatbid: [ - { - bid: [ - { - id: '82822cf5-259c-11eb-8a52-f29e5275aa57', - impid: '1', - price: 1.1, - nurl: 'http://example.com/win/${AUCTION_PRICE}', - adm: '{"ver":"1.2","assets":[{"id":3,"required":1,"img":{"url":"http://example.com/img/url","w":120,"h":100}},{"id":0,"required":1,"title":{"text":"Test title"}},{"id":5,"data":{"value":"Test sponsor"}}],"link":{"url":"http://example.com/click/url"},"eventtrackers":[{"event":1,"method":1,"url":"http://example.com/impression"}]}', - adomain: [ - 'example.co' - ], - cid: '3487171', - crid: '28023739', - cat: [ - 'IAB10-2' - ] - } - ], - seat: 'acc-5537' - } - ], - bidid: '82822cf5-259c-11eb-8a52-b48e7518c657', - cur: 'USD' - }, - } - const request = { - bids: [ - { - ...commonBidRequest, - ...nativeBidRequestParams, - } - ] - } - const expectedRes = [ - { - requestId: request.bids[0].bidId, - cpm: 1.1, - creativeId: '28023739', - ttl: 360, - netRevenue: false, - currency: 'USD', - mediaType: 'native', - nurl: 'http://example.com/win/${AUCTION_PRICE}', - native: { - clickTrackers: undefined, - clickUrl: 'http://example.com/click/url', - image: { - url: 'http://example.com/img/url', - width: 120, - height: 100 - }, - title: 'Test title', - sponsoredBy: 'Test sponsor', - impressionTrackers: [ - 'http://example.com/impression', - ] - } - } - ] - - const res = spec.interpretResponse(serverResponse, request) - expect(res).to.deep.equal(expectedRes) - }); - - it('should interpret display response', function () { - const serverResponse = { - body: { - id: '6b2eedc8-8ff5-46ef-adcf-e701b508943e', - seatbid: [ - { - bid: [ - { - id: 'd90fe7fa-28d7-11eb-8ce4-462a842a7cf9', - impid: '1', - price: 1.1, - nurl: 'http://example.com/win/${AUCTION_PRICE}', - adm: '