diff --git a/modules/clickforceBidAdapter.js b/modules/clickforceBidAdapter.js index fbcd5f2685c..c9e54f9efac 100644 --- a/modules/clickforceBidAdapter.js +++ b/modules/clickforceBidAdapter.js @@ -1,12 +1,12 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; - +import {BANNER, NATIVE} from 'src/mediaTypes'; const BIDDER_CODE = 'clickforce'; const ENDPOINT_URL = '//ad.doublemax.net/adserver/prebid.json?cb=' + new Date().getTime() + '&hb=1&ver=1.21'; export const spec = { code: BIDDER_CODE, - + supportedMediaTypes: [BANNER, NATIVE], /** * Determines whether or not the given bid request is valid. * @@ -34,7 +34,8 @@ export const spec = { return { method: 'POST', url: ENDPOINT_URL, - data: bidParams + data: bidParams, + validBidRequests: validBidRequests }; }, @@ -47,18 +48,63 @@ export const spec = { */ interpretResponse: function(serverResponse, bidRequest) { const cfResponses = []; - utils._each(serverResponse.body, function(response) { - cfResponses.push({ - requestId: response.requestId, - cpm: response.cpm, - width: response.width, - height: response.height, - creativeId: response.creativeId, - currency: response.currency, - netRevenue: response.netRevenue, - ttl: response.ttl, - ad: response.tag + const bidRequestList = []; + + if (typeof bidRequest != 'undefined') { + utils._each(bidRequest.validBidRequests, function(req) { + bidRequestList[req.bidId] = req; }); + } + + utils._each(serverResponse.body, function(response) { + if (response.requestId != null) { + // native ad size + if (response.width == 3) { + cfResponses.push({ + requestId: response.requestId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + currency: response.currency, + netRevenue: response.netRevenue, + ttl: response.ttl, + native: { + title: response.tag.content.title, + body: response.tag.content.content, + image: { + url: response.tag.content.image, + height: 900, + width: 1600 + }, + icon: { + url: response.tag.content.icon, + height: 900, + width: 900 + }, + clickUrl: response.tag.cu, + cta: response.tag.content.button_text, + sponsoredBy: response.tag.content.advertiser, + impressionTrackers: response.tag.iu, + }, + mediaType: 'native', + }); + } else { + // display ad + cfResponses.push({ + requestId: response.requestId, + cpm: response.cpm, + width: response.width, + height: response.height, + creativeId: response.creativeId, + currency: response.currency, + netRevenue: response.netRevenue, + ttl: response.ttl, + ad: response.tag, + mediaType: 'banner', + }); + } + } }); return cfResponses; }, @@ -76,4 +122,5 @@ export const spec = { } } }; + registerBidder(spec); diff --git a/modules/clickforceBidAdapter.md b/modules/clickforceBidAdapter.md index 5d8a5ac8119..07fe9475881 100644 --- a/modules/clickforceBidAdapter.md +++ b/modules/clickforceBidAdapter.md @@ -16,7 +16,7 @@ It requires adapters to start bidding and no extra setting is needed. If you'd l joey@clickforce.com.tw (MR. Joey) -# Test Parameters +# Test Parameters (Display ad) ``` var adUnits = [{ code: 'banner-ad-div', @@ -29,6 +29,45 @@ joey@clickforce.com.tw (MR. Joey) }] }]; ``` +# Test Parameters (Native ad) +``` + var adUnits = [{ + code: 'banner-ad-div', + sizes: [[300, 250]], + mediaTypes: { + native: { + title: { + required: true, + }, + body: { + required: true + }, + image: { + required: true, + }, + icon: { + required: false, + }, + clickUrl: { + required: true + }, + cta: { + required: true + }, + sponsoredBy: { + required: true + } + } + }, + bids: [{ + bidder: "clickforce", + params: { + zone: "6878", + } + }] + }]; +``` + ### Configuration CLICKFORCE recommend the UserSync configuration below. It's can be optimize the CPM for the request. diff --git a/test/spec/modules/clickforceBidAdapter_spec.js b/test/spec/modules/clickforceBidAdapter_spec.js index 8b0955590a0..c09b69a6320 100644 --- a/test/spec/modules/clickforceBidAdapter_spec.js +++ b/test/spec/modules/clickforceBidAdapter_spec.js @@ -78,24 +78,87 @@ describe('ClickforceAdapter', () => { 'zone': '6682' }]; - it('should get the correct bid response', () => { - let expectedResponse = [{ - 'requestId': '220ed41385952a', - 'cpm': 0.5, - 'width': '300', - 'height': '250', - 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 60, - 'ad': '' - }]; + let response1 = [{ + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'callback_uid': '2e27ec595bf1a', + 'type': 'public Bid', + 'tag': { + 'content': { + 'title': 'title', + 'content': 'content', + 'advertiser': 'advertiser', + 'button_text': 'button_text', + 'image': 'image', + 'icon': 'icon' + }, + 'cu': ['cu'], + 'iu': ['iu'], + 'p': '6878:11062:32586:8380573788dad9b9fc17edde444c4dcf:2795' + }, + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'requestId': '2e27ec595bf1a', + 'currency': 'USD', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6878' + }]; + + let expectedResponse = [{ + 'requestId': '220ed41385952a', + 'cpm': 0.5, + 'width': '300', + 'height': '250', + 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'ad': '', + 'mediaType': 'banner', + }]; + + let expectedResponse1 = [{ + 'requestId': '2e27ec595bf1a', + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'image', + 'width': 1600, + 'height': 900 + }, + 'title': 'title', + 'sponsoredBy': 'advertiser', + 'body': 'content', + 'icon': { + 'url': 'icon', + 'width': 900, + 'height': 900 + }, + 'clickUrl': 'cu', + 'impressionTrackers': ['iu'] + } + }]; + it('should get the correct bid response by display ad', () => { let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); + it('should get the correct bid response by native ad', () => { + let bidderRequest; + let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse1[0])); + }); + it('handles empty bid response', () => { let response = { body: {}