From 35f46f8ff62ee5abd936f7d80dc47c170999ff87 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 29 Dec 2023 14:28:22 +0800 Subject: [PATCH 1/5] feat:zMaticoo Bid Adapter for Prebid.js --- modules/zmaticooBidAdapter.js | 138 +++++++++++++++++++ modules/zmaticooBidAdapter.md | 45 ++++++ test/spec/modules/zmaticooBidAdapter_spec.js | 62 +++++++++ 3 files changed, 245 insertions(+) create mode 100644 modules/zmaticooBidAdapter.js create mode 100644 modules/zmaticooBidAdapter.md create mode 100644 test/spec/modules/zmaticooBidAdapter_spec.js diff --git a/modules/zmaticooBidAdapter.js b/modules/zmaticooBidAdapter.js new file mode 100644 index 00000000000..114520359f3 --- /dev/null +++ b/modules/zmaticooBidAdapter.js @@ -0,0 +1,138 @@ +import {deepAccess, logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER} from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'zmaticoo'; +const ENDPOINT_URL = 'https://bid.zmaticoo.com/prebid/bid'; +const DEFAULT_CUR = 'USD'; +const TTL = 200; +const NET_REV = true; + +export const spec = { + code: BIDDER_CODE, supportedMediaTypes: [BANNER], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + // check for all required bid fields + if (!(bid && bid.bidId && bid.params)) { + logWarn('Invalid bid request - missing required bid data'); + return false; + } + + if (!(bid.params.pubId)) { + logWarn('Invalid bid request - missing required field pubId'); + return false; + } + + if (!(bid.params.device && bid.params.device.ip)) { + logWarn('Invalid bid request - missing required device data'); + return false; + } + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {Bids[]} validBidRequests - an array of bidRequest objects + * @param {BidderRequest} bidderRequest - master bidRequest object + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + const secure = 1; // treat all requests as secure + const request = validBidRequests[0]; + const params = request.params; + let impData = { + id: request.bidId, secure: secure, banner: buildBanner(request), + ext: { + bidder: { + pubId: params.pubId + } + } + }; + let payload = { + id: bidderRequest.bidderRequestId, + imp: [impData], + site: params.site ? params.site : {}, + app: params.app ? params.app : {}, + device: params.device ? params.device : {}, + user: params.user ? params.user : {}, + at: params.at, + tmax: params.tmax, + wseat: params.wseat, + bseat: params.bseat, + allimps: params.allimps, + cur: [DEFAULT_CUR], + wlang: params.wlang, + bcat: deepAccess(bidderRequest.ortb2Imp, 'bcat') || params.bcat, + badv: params.badv, + bapp: params.bapp, + source: params.source ? params.source : {}, + regs: params.regs ? params.regs : {}, + ext: params.ext ? params.ext : {} + }; + + payload.device.ua = navigator.userAgent; + payload.device.ip = navigator.ip; + payload.site.page = bidderRequest.refererInfo.page; + payload.site.mobile = /(ios|ipod|ipad|iphone|android)/i.test(navigator.userAgent) ? 1 : 0; + if (params.test) { + payload.test = params.test; + } + if (request.gdprConsent) { + payload.regs.ext = Object.assign(payload.regs.ext, {gdpr: request.gdprConsent.gdprApplies === true ? 1 : 0}); + } + if (request.gdprConsent && request.gdprConsent.gdprApplies) { + payload.user.ext = Object.assign(payload.user.ext, {consent: request.gdprConsent.consentString}); + } + const postUrl = ENDPOINT_URL; + return { + method: 'POST', url: postUrl, data: JSON.stringify(payload), + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param bidRequest The payload from the server's response. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (serverResponse, bidRequest) { + let bidResponse = []; + if (Object.keys(serverResponse.body).length !== 0) { + let zresponse = serverResponse.body; + let zbid = zresponse.seatbid[0].bid[0]; + let bid = { + requestId: zbid.impid, + cpm: zbid.price, + currency: zbid.cur, + width: zbid.w, + height: zbid.h, + ad: zbid.adm, + ttl: TTL, + creativeId: zbid.crid, + netRevenue: NET_REV + }; + bidResponse.push(bid); + } + return bidResponse; + } +} + +function buildBanner(request) { + let sizes = request.sizes; + if (request.mediaTypes && request.mediaTypes.banner && request.mediaTypes.banner.sizes) { + sizes = request.mediaTypes.banner.sizes; + } + return { + w: sizes[0][0], h: sizes[0][1] + }; +} + +registerBidder(spec); diff --git a/modules/zmaticooBidAdapter.md b/modules/zmaticooBidAdapter.md new file mode 100644 index 00000000000..95959ef218c --- /dev/null +++ b/modules/zmaticooBidAdapter.md @@ -0,0 +1,45 @@ +# Overview + +``` +Module Name: zMaticoo Bidder Adapter +Module Type: Bidder Adapter +Maintainer: adam.li@eclicktech.com.cn +``` + +# Description + +zMaticoo Bidder Adapter for Prebid.js. + +# Test Parameters + +``` + var adUnits = [ + { + mediaTypes: { + banner: { + sizes: [[320, 50]], // a display size + } + }, + bids: [ + { + bidder: 'zmaticoo', + bidId: '12345', + params: { + user: { + uid: '12345', + buyeruid: '12345' + }, + device: { + ip: '111.222.33.44', + geo: { + country: 'USA' + } + }, + pubId: 'prebid-fgh', + test: 1 + } + } + ] + } + ]; +``` diff --git a/test/spec/modules/zmaticooBidAdapter_spec.js b/test/spec/modules/zmaticooBidAdapter_spec.js new file mode 100644 index 00000000000..7c9c32bc783 --- /dev/null +++ b/test/spec/modules/zmaticooBidAdapter_spec.js @@ -0,0 +1,62 @@ +import {spec} from '../../../modules/zmaticooBidAdapter.js' + +describe('zMaticoo Bidder Adapter', function () { + const bannerRequest = [{ + bidId: 12345189, auctionId: 67890, mediaTypes: { + banner: { + sizes: [[320, 50]], + } + }, refererInfo: { + page: 'test.com' + }, params: { + user: { + uid: '12345', buyeruid: '12345' + }, device: { + ip: '111.222.33.44', geo: { + country: 'USA' + } + }, pubId: 'prebid_xx', test: 1 + } + }]; + + it('Test the bid validation function', function () { + const validBid = spec.isBidRequestValid(bannerRequest[0]); + const invalidBid = spec.isBidRequestValid(null); + + expect(validBid).to.be.true; + expect(invalidBid).to.be.false; + }); + + it('Test the request processing function', function () { + const request = spec.buildRequests(bannerRequest, bannerRequest[0]); + expect(request).to.not.be.empty; + + const payload = request.data; + expect(payload).to.not.be.empty; + }); + + const responseBody = { + id: '123451', seatbid: [{ + bid: [{ + id: 'auctionId', impid: 'impId', price: 0.0, adm: 'adMarkup', crid: 'creativeId', h: 50, w: 320 + }] + }], cur: 'USD' + }; + + it('Test the response parsing function', function () { + const receivedBid = responseBody.seatbid[0].bid[0]; + const response = {}; + response.body = responseBody; + + const bidResponse = spec.interpretResponse(response, null); + expect(bidResponse).to.not.be.empty; + + const bid = bidResponse[0]; + expect(bid).to.not.be.empty; + expect(bid.ad).to.equal(receivedBid.adm); + expect(bid.cpm).to.equal(receivedBid.price); + expect(bid.height).to.equal(receivedBid.h); + expect(bid.width).to.equal(receivedBid.w); + expect(bid.requestId).to.equal(receivedBid.impid); + }); +}); From 10f041c541f8955a0e135ad41bbe9588decbeb52 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 29 Dec 2023 19:16:13 +0800 Subject: [PATCH 2/5] feat:zMaticoo Bid Adapter for Prebid.js --- test/spec/modules/zmaticooBidAdapter_spec.js | 46 ++++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/test/spec/modules/zmaticooBidAdapter_spec.js b/test/spec/modules/zmaticooBidAdapter_spec.js index 7c9c32bc783..cee6a1d3769 100644 --- a/test/spec/modules/zmaticooBidAdapter_spec.js +++ b/test/spec/modules/zmaticooBidAdapter_spec.js @@ -2,20 +2,28 @@ import {spec} from '../../../modules/zmaticooBidAdapter.js' describe('zMaticoo Bidder Adapter', function () { const bannerRequest = [{ - bidId: 12345189, auctionId: 67890, mediaTypes: { + bidId: '1234511', + auctionId: '223', + mediaTypes: { banner: { sizes: [[320, 50]], } - }, refererInfo: { - page: 'test.com' - }, params: { + }, + refererInfo: { + page: 'testprebid.com' + }, + params: { user: { - uid: '12345', buyeruid: '12345' - }, device: { - ip: '111.222.33.44', geo: { + uid: '12345', + buyeruid: '12345' + }, + device: { + ip: '111.222.33.44', + geo: { country: 'USA' } - }, pubId: 'prebid_xx', test: 1 + }, + test: 1 } }]; @@ -36,11 +44,23 @@ describe('zMaticoo Bidder Adapter', function () { }); const responseBody = { - id: '123451', seatbid: [{ - bid: [{ - id: 'auctionId', impid: 'impId', price: 0.0, adm: 'adMarkup', crid: 'creativeId', h: 50, w: 320 - }] - }], cur: 'USD' + id: '12345', + seatbid: [ + { + bid: [ + { + id: 'auctionId', + impid: 'impId', + price: 0.0, + adm: 'adMarkup', + crid: 'creativeId', + h: 50, + w: 320 + } + ] + } + ], + cur: 'USD' }; it('Test the response parsing function', function () { From 8e8f91cb13bea19c499834e9889d8eae9455b4c0 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 29 Dec 2023 19:25:05 +0800 Subject: [PATCH 3/5] feat:fix some code style --- modules/zmaticooBidAdapter.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/zmaticooBidAdapter.js b/modules/zmaticooBidAdapter.js index 114520359f3..601906eaa58 100644 --- a/modules/zmaticooBidAdapter.js +++ b/modules/zmaticooBidAdapter.js @@ -9,7 +9,8 @@ const TTL = 200; const NET_REV = true; export const spec = { - code: BIDDER_CODE, supportedMediaTypes: [BANNER], + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], /** * Determines whether or not the given bid request is valid. @@ -48,7 +49,9 @@ export const spec = { const request = validBidRequests[0]; const params = request.params; let impData = { - id: request.bidId, secure: secure, banner: buildBanner(request), + id: request.bidId, + secure: secure, + banner: buildBanner(request), ext: { bidder: { pubId: params.pubId From 7a3c3caa9f4531e2de59ef5fc2e3b0bdf962f0a5 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 29 Dec 2023 19:41:54 +0800 Subject: [PATCH 4/5] feat:fix some code style --- test/spec/modules/zmaticooBidAdapter_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/spec/modules/zmaticooBidAdapter_spec.js b/test/spec/modules/zmaticooBidAdapter_spec.js index cee6a1d3769..898dccf1fde 100644 --- a/test/spec/modules/zmaticooBidAdapter_spec.js +++ b/test/spec/modules/zmaticooBidAdapter_spec.js @@ -23,6 +23,7 @@ describe('zMaticoo Bidder Adapter', function () { country: 'USA' } }, + pubId: 'prebid-test', test: 1 } }]; From 8a21e3f597b7581cbfc5ceef2da1049497e33b46 Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 22 Jan 2024 10:18:25 +0800 Subject: [PATCH 5/5] feat:update package-lock.json --- modules/zmaticooBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/zmaticooBidAdapter.js b/modules/zmaticooBidAdapter.js index 601906eaa58..8566d58c6de 100644 --- a/modules/zmaticooBidAdapter.js +++ b/modules/zmaticooBidAdapter.js @@ -45,7 +45,7 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function (validBidRequests, bidderRequest) { - const secure = 1; // treat all requests as secure + const secure = 1; const request = validBidRequests[0]; const params = request.params; let impData = {