From 0b39bd73258a811d0ab1a5f58bcf8638779e74ce Mon Sep 17 00:00:00 2001
From: takuhou
Date: Wed, 13 Dec 2017 01:57:05 +0900
Subject: [PATCH] Added YIELDONE Bid Adapter for Prebid.js 1.0 (#1900)
* Added YIELDONE Bid Adapter for Prebid.js 1.0
* Update yieldoneBidAdapter.md
change placementId to 44082
* Changed to get size from bid.sizes
* fix sizes array
---
modules/yieldoneBidAdapter.js | 71 +++++++++
modules/yieldoneBidAdapter.md | 27 ++++
test/spec/modules/yieldoneBidAdapter_spec.js | 147 +++++++++++++++++++
3 files changed, 245 insertions(+)
create mode 100644 modules/yieldoneBidAdapter.js
create mode 100644 modules/yieldoneBidAdapter.md
create mode 100644 test/spec/modules/yieldoneBidAdapter_spec.js
diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js
new file mode 100644
index 00000000000..9f94b5b815e
--- /dev/null
+++ b/modules/yieldoneBidAdapter.js
@@ -0,0 +1,71 @@
+import * as utils from 'src/utils';
+import {config} from 'src/config';
+import {registerBidder} from 'src/adapters/bidderFactory';
+
+const BIDDER_CODE = 'yieldone';
+const ENDPOINT_URL = '//y.one.impact-ad.jp/h_bid';
+
+export const spec = {
+ code: BIDDER_CODE,
+ aliases: ['y1'],
+ isBidRequestValid: function(bid) {
+ return !!(bid.params.placementId);
+ },
+ buildRequests: function(validBidRequests) {
+ return validBidRequests.map(bidRequest => {
+ const params = bidRequest.params;
+ const sizes = utils.parseSizesInput(bidRequest.sizes)[0];
+ const width = sizes.split('x')[0];
+ const height = sizes.split('x')[1];
+ const placementId = params.placementId;
+ const cb = Math.floor(Math.random() * 99999999999);
+ const referrer = encodeURIComponent(utils.getTopWindowUrl());
+ const bidId = bidRequest.bidId;
+ const payload = {
+ v: 'hb1',
+ p: placementId,
+ w: width,
+ h: height,
+ cb: cb,
+ r: referrer,
+ uid: bidId,
+ t: 'i'
+ };
+ return {
+ method: 'GET',
+ url: ENDPOINT_URL,
+ data: payload,
+ }
+ });
+ },
+ interpretResponse: function(serverResponse, bidRequest) {
+ const bidResponses = [];
+ const response = serverResponse.body;
+ const crid = response.crid || 0;
+ const width = response.width || 0;
+ const height = response.height || 0;
+ const cpm = response.cpm * 1000 || 0;
+ if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) {
+ const dealId = response.dealid || '';
+ const currency = response.currency || 'JPY';
+ const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue;
+ const referrer = utils.getTopWindowUrl();
+ const bidResponse = {
+ requestId: bidRequest.data.uid,
+ cpm: cpm,
+ width: response.width,
+ height: response.height,
+ creativeId: crid,
+ dealId: dealId,
+ currency: currency,
+ netRevenue: netRevenue,
+ ttl: config.getConfig('_bidderTimeout'),
+ referrer: referrer,
+ ad: response.adTag
+ };
+ bidResponses.push(bidResponse);
+ }
+ return bidResponses;
+ }
+}
+registerBidder(spec);
diff --git a/modules/yieldoneBidAdapter.md b/modules/yieldoneBidAdapter.md
new file mode 100644
index 00000000000..f1f48637927
--- /dev/null
+++ b/modules/yieldoneBidAdapter.md
@@ -0,0 +1,27 @@
+# Overview
+
+```
+Module Name: YIELDONE Bidder Adapter
+Module Type: Bidder Adapter
+Maintainer: y1dev@platform-one.co.jp
+```
+
+# Description
+
+Connect to YIELDONE for bids.
+
+THE YIELDONE adapter requires setup and approval from the Rubicon Project team. Please reach out to your account team or y1s@platform-one.co.jp for more information.
+
+# Test Parameters
+```
+ var adUnits = [{
+ code: 'banner-ad-div',
+ sizes: [[300, 250]],
+ bids: [{
+ bidder: 'yieldone',
+ params: {
+ placementId: '44082'
+ }
+ }]
+ }];
+```
diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js
new file mode 100644
index 00000000000..e763257f097
--- /dev/null
+++ b/test/spec/modules/yieldoneBidAdapter_spec.js
@@ -0,0 +1,147 @@
+import { expect } from 'chai';
+import { spec } from 'modules/yieldoneBidAdapter';
+import { newBidder } from 'src/adapters/bidderFactory';
+
+const ENDPOINT = '//y.one.impact-ad.jp/h_bid';
+
+describe('yieldoneBidAdapter', function() {
+ const adapter = newBidder(spec);
+
+ describe('isBidRequestValid', () => {
+ let bid = {
+ 'bidder': 'yieldone',
+ 'params': {
+ placementId: '44082'
+ },
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [
+ [300, 250]
+ ],
+ 'bidId': '23beaa6af6cdde',
+ 'bidderRequestId': '19c0c1efdf37e7',
+ 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1',
+ };
+
+ it('should return true when required params found', () => {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('should return false when placementId not passed correctly', () => {
+ bid.params.placementId = '';
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('should return false when require params are not passed', () => {
+ let bid = Object.assign({}, bid);
+ bid.params = {};
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+ });
+
+ describe('buildRequests', () => {
+ let bidRequests = [
+ {
+ 'bidder': 'yieldone',
+ 'params': {
+ placementId: '44082'
+ },
+ 'adUnitCode': 'adunit-code1',
+ 'sizes': [
+ [300, 250]
+ ],
+ 'bidId': '23beaa6af6cdde',
+ 'bidderRequestId': '19c0c1efdf37e7',
+ 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1',
+ },
+ {
+ 'bidder': 'yieldone',
+ 'params': {
+ placementId: '44337'
+ },
+ 'adUnitCode': 'adunit-code2',
+ 'sizes': [
+ [300, 250]
+ ],
+ 'bidId': '382091349b149f"',
+ 'bidderRequestId': '"1f9c98192de251"',
+ 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1',
+ }
+ ];
+
+ const request = spec.buildRequests(bidRequests);
+
+ it('sends bid request to our endpoint via GET', () => {
+ expect(request[0].method).to.equal('GET');
+ expect(request[1].method).to.equal('GET');
+ });
+
+ it('attaches source and version to endpoint URL as query params', () => {
+ expect(request[0].url).to.equal(ENDPOINT);
+ expect(request[1].url).to.equal(ENDPOINT);
+ });
+ });
+
+ describe('interpretResponse', () => {
+ let bidRequest = [
+ {
+ 'method': 'GET',
+ 'url': '//y.one.impact-ad.jp/h_bid',
+ 'data': {
+ 'v': 'hb1',
+ 'p': '44082',
+ 'w': '300',
+ 'h': '250',
+ 'cb': 12892917383,
+ 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836',
+ 'uid': '23beaa6af6cdde',
+ 't': 'i'
+ }
+ }
+ ];
+
+ let serverResponse = {
+ body: {
+ 'adTag': '',
+ 'cpm': 0.0536616,
+ 'crid': '2494768',
+ 'statusMessage': 'Bid available',
+ 'uid': '23beaa6af6cdde',
+ 'width': 300,
+ 'height': 250
+ }
+ };
+
+ it('should get the correct bid response', () => {
+ let expectedResponse = [{
+ 'requestId': '23beaa6af6cdde',
+ 'cpm': 53.6616,
+ 'width': 300,
+ 'height': 250,
+ 'creativeId': '2494768',
+ 'dealId': '',
+ 'currency': 'JPY',
+ 'netRevenue': true,
+ 'ttl': 3000,
+ 'referrer': '',
+ 'ad': ''
+ }];
+ let result = spec.interpretResponse(serverResponse, bidRequest[0]);
+ expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse));
+ });
+
+ it('handles empty bid response', () => {
+ let response = {
+ body: {
+ 'uid': '2c0b634db95a01',
+ 'height': 0,
+ 'crid': '',
+ 'statusMessage': 'Bid returned empty or error response',
+ 'width': 0,
+ 'cpm': 0
+ }
+ };
+ let result = spec.interpretResponse(response, bidRequest[0]);
+ expect(result.length).to.equal(0);
+ });
+ });
+});