diff --git a/modules/dgadsBidAdapter.js b/modules/dgadsBidAdapter.js new file mode 100644 index 00000000000..7d47cc7acf6 --- /dev/null +++ b/modules/dgadsBidAdapter.js @@ -0,0 +1,88 @@ +import {registerBidder} from 'src/adapters/bidderFactory'; +import * as utils from 'src/utils'; +import { BANNER, NATIVE } from 'src/mediaTypes'; + +const BIDDER_CODE = 'dgads'; +const ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [ BANNER, NATIVE ], + isBidRequestValid: function(bid) { + const params = bid.params; + if (!/^\d+$/.test(params.location_id)) { + return false; + } + if (!/^\d+$/.test(params.site_id)) { + return false; + } + return true; + }, + buildRequests: function(bidRequests) { + if (bidRequests.length === 0) { + return {}; + } + + return bidRequests.map(bidRequest => { + const params = bidRequest.params; + const data = {}; + + data['location_id'] = params.location_id; + data['site_id'] = params.site_id; + data['transaction_id'] = bidRequest.transactionId; + data['bid_id'] = bidRequest.bidId; + + return { + method: 'POST', + url: ENDPOINT, + data, + }; + }); + }, + interpretResponse: function(serverResponse, bidRequest) { + const bidResponses = []; + const responseObj = serverResponse.body; + const ads = responseObj.bids; + let bidResponse = {}; + if (utils.isEmpty(ads)) { + return []; + } + utils._each(ads, function(ad) { + bidResponse.requestId = ad.bidId; + bidResponse.bidderCode = BIDDER_CODE; + bidResponse.cpm = ad.cpm; + bidResponse.creativeId = ad.creativeId; + bidResponse.currency = 'JPY'; + bidResponse.netRevenue = true; + bidResponse.ttl = ad.ttl; + bidResponse.referrer = utils.getTopWindowUrl(); + if (ad.isNative == 1) { + bidResponse.mediaType = NATIVE; + bidResponse.native = setNativeResponse(ad); + } else { + bidResponse.width = parseInt(ad.w); + bidResponse.height = parseInt(ad.h); + bidResponse.ad = ad.ad; + } + bidResponses.push(bidResponse); + }); + return bidResponses; + } +}; +function setNativeResponse(ad) { + let nativeResponce = {}; + nativeResponce.image = { + url: ad.image, + width: parseInt(ad.w), + height: parseInt(ad.h) + } + nativeResponce.title = ad.title; + nativeResponce.body = ad.desc; + nativeResponce.sponsoredBy = ad.sponsoredBy; + nativeResponce.clickUrl = ad.clickUrl; + nativeResponce.clickTrackers = ad.clickTrackers || []; + nativeResponce.impressionTrackers = ad.impressionTrackers || []; + return nativeResponce; +} + +registerBidder(spec); diff --git a/modules/dgadsBidAdapter.md b/modules/dgadsBidAdapter.md new file mode 100644 index 00000000000..b1544007a43 --- /dev/null +++ b/modules/dgadsBidAdapter.md @@ -0,0 +1,65 @@ +# Overview + +``` +Module Name: Digital Garage Ads Platform Bidder Adapter +Module Type: Bidder Adapter +Maintainer:dgads-support@garage.co.jp +``` + +# Description + +Connect to Digital Garage Ads Platform for bids. +This adapter supports Banner and Native. + +# Test Parameters +``` + var adUnits = [ + // Banner + { + code: 'banner-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'dgads', + mediaTypes: 'banner', + params: { + location_id: '1', + site_id: '1' + } + }] + }, + // Native + { + code: 'native-div', + sizes: [[300, 250]], + mediaTypes: { + native: { + title: { + required: true, + len: 25 + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + }, + image: { + required: true + }, + clickUrl: { + required: true + }, + } + }, + bids: [{ + bidder: 'dgads', + params: { + location_id: '10', + site_id: '1' + } + }] + }, + ]; +``` diff --git a/test/spec/modules/dgadsBidAdapter_spec.js b/test/spec/modules/dgadsBidAdapter_spec.js new file mode 100644 index 00000000000..89affd94880 --- /dev/null +++ b/test/spec/modules/dgadsBidAdapter_spec.js @@ -0,0 +1,291 @@ +import {expect} from 'chai'; +import * as utils from 'src/utils'; +import {spec} from 'modules/dgadsBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +import { BANNER, NATIVE } from 'src/mediaTypes'; + +describe('dgadsBidAdapter', () => { + const adapter = newBidder(spec); + const VALID_ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'dgads', + params: { + site_id: '1', + location_id: '1' + } + }; + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params(location_id) are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + site_id: '1' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required params(site_id) are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + location_id: '1' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + const bidRequests = [ + { // banner + bidder: 'dgads', + mediaType: 'banner', + params: { + site_id: '1', + location_id: '1' + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250]], + bidId: '2db3101abaec66', + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f', + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' + }, + { // native + bidder: 'dgads', + sizes: [[300, 250]], + params: { + site_id: '1', + location_id: '10' + }, + mediaTypes: { + native: { + image: { + required: true + }, + title: { + required: true, + len: 25 + }, + clickUrl: { + required: true + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + } + }, + }, + adUnitCode: 'adunit-code', + bidId: '2db3101abaec66', + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f', + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' + } + ]; + it('no bidRequests', () => { + const noBidRequests = []; + expect(Object.keys(spec.buildRequests(noBidRequests)).length).to.equal(0); + }); + const data = { + location_id: '1', + site_id: '1', + transaction_id: 'c1f1eff6-23c6-4844-a321-575212939e37', + bid_id: '2db3101abaec66' + }; + it('sends bid request to VALID_ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(VALID_ENDPOINT); + expect(request.method).to.equal('POST'); + }); + it('should attache params to the request', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.data['location_id']).to.equal(data['location_id']); + expect(request.data['site_id']).to.equal(data['site_id']); + expect(request.data['transaction_id']).to.equal(data['transaction_id']); + expect(request.data['bid_id']).to.equal(data['bid_id']); + }); + }); + + describe('interpretResponse', () => { + const bidRequests = { + banner: { + bidRequest: { + bidder: 'dgads', + params: { + location_id: '1', + site_id: '1' + }, + transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37', + bidId: '2db3101abaec66', + adUnitCode: 'adunit-code', + sizes: [[300, 250]], + bidderRequestId: '14a9f773e30243', + auctionId: 'c0cd37c5-af11-464d-b83e-35863e533b1f' + }, + }, + native: { + bidRequest: { + bidder: 'adg', + params: { + site_id: '1', + location_id: '10' + }, + mediaTypes: { + native: { + image: { + required: true + }, + title: { + required: true, + len: 25 + }, + body: { + required: true, + len: 140 + }, + sponsoredBy: { + required: true, + len: 40 + } + } + }, + transactionId: 'f76f6dfd-d64f-4645-a29f-682bac7f431a', + bidId: '2f6ac468a9c15e', + adUnitCode: 'adunit-code', + sizes: [[1, 1]], + bidderRequestId: '14a9f773e30243', + auctionId: '4aae9f05-18c6-4fcd-80cf-282708cd584a', + }, + }, + }; + + const serverResponse = { + noAd: { + results: [], + }, + banner: { + bids: { + ads: { + ad: '', + cpm: 1.22, + w: 300, + h: 250, + creativeId: 'xuidx62944aab4fx37f', + ttl: 60, + bidId: '2f6ac468a9c15e' + } + } + }, + native: { + bids: { + ads: { + cpm: 1.22, + title: 'title', + desc: 'description', + sponsoredBy: 'sponsoredBy', + image: 'https://ads-tr.bigmining.com/img/300_250_1.jpg', + w: 300, + h: 250, + ttl: 60, + bidId: '2f6ac468a9c15e', + creativeId: 'xuidx62944aab4fx37f', + isNative: 1, + impressionTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.gif'], + clickTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.png'], + clickUrl: 'http://www.garage.co.jp/ja/' + }, + } + } + }; + + const bidResponses = { + banner: { + requestId: '2f6ac468a9c15e', + cpm: 1.22, + width: 300, + height: 250, + creativeId: 'xuidx62944aab4fx37f', + currency: 'JPY', + netRevenue: true, + ttl: 60, + referrer: utils.getTopWindowUrl(), + ad: '', + }, + native: { + requestId: '2f6ac468a9c15e', + cpm: 1.22, + creativeId: 'xuidx62944aab4fx37f', + currency: 'JPY', + netRevenue: true, + ttl: 60, + native: { + image: { + url: 'https://ads-tr.bigmining.com/img/300_250_1.jpg', + width: 300, + height: 250 + }, + title: 'title', + body: 'description', + sponsoredBy: 'sponsoredBy', + clickUrl: 'http://www.garage.co.jp/ja/', + impressionTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.gif'], + clickTrackers: ['https://ads-tr.bigmining.com/ad/view/beacon.png'] + }, + referrer: utils.getTopWindowUrl(), + creativeid: 'xuidx62944aab4fx37f', + mediaType: NATIVE + } + }; + + it('no bid responses', () => { + const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); + expect(result.length).to.equal(0); + }); + it('handles banner responses', () => { + const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; + expect(result.requestId).to.equal(bidResponses.banner.requestId); + expect(result.width).to.equal(bidResponses.banner.width); + expect(result.height).to.equal(bidResponses.banner.height); + expect(result.creativeId).to.equal(bidResponses.banner.creativeId); + expect(result.currency).to.equal(bidResponses.banner.currency); + expect(result.netRevenue).to.equal(bidResponses.banner.netRevenue); + expect(result.ttl).to.equal(bidResponses.banner.ttl); + expect(result.referrer).to.equal(bidResponses.banner.referrer); + expect(result.ad).to.equal(bidResponses.banner.ad); + }); + + it('handles native responses', () => { + const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; + expect(result.requestId).to.equal(bidResponses.native.requestId); + expect(result.creativeId).to.equal(bidResponses.native.creativeId); + expect(result.currency).to.equal(bidResponses.native.currency); + expect(result.netRevenue).to.equal(bidResponses.native.netRevenue); + expect(result.ttl).to.equal(bidResponses.native.ttl); + expect(result.referrer).to.equal(bidResponses.native.referrer); + expect(result.native.title).to.equal(bidResponses.native.native.title); + expect(result.native.body).to.equal(bidResponses.native.native.body); + expect(result.native.sponsoredBy).to.equal(bidResponses.native.native.sponsoredBy); + expect(result.native.image.url).to.equal(bidResponses.native.native.image.url); + expect(result.native.image.width).to.equal(bidResponses.native.native.image.width); + expect(result.native.image.height).to.equal(bidResponses.native.native.image.height); + expect(result.native.clickUrl).to.equal(bidResponses.native.native.clickUrl); + expect(result.native.impressionTrackers[0]).to.equal(bidResponses.native.native.impressionTrackers[0]); + expect(result.native.clickTrackers[0]).to.equal(bidResponses.native.native.clickTrackers[0]); + }); + }); +});