From 237c88b1e33fa7e8ae9caefa3c525d199964be0d Mon Sep 17 00:00:00 2001 From: Alexey Sukhikh Date: Fri, 9 Jul 2021 18:44:39 +0300 Subject: [PATCH] GrowAdvertising: add native support (#7126) * Add native support * Update docs --- modules/growadvertisingBidAdapter.js | 70 ++++++++-- modules/growadvertisingBidAdapter.md | 32 ++++- .../modules/growadvertisingBidAdapter_spec.js | 125 ++++++++++++++---- 3 files changed, 185 insertions(+), 42 deletions(-) diff --git a/modules/growadvertisingBidAdapter.js b/modules/growadvertisingBidAdapter.js index b5103a06fa8..0626b137a1b 100644 --- a/modules/growadvertisingBidAdapter.js +++ b/modules/growadvertisingBidAdapter.js @@ -2,11 +2,14 @@ import * as utils from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, NATIVE} from '../src/mediaTypes.js'; +import {triggerPixel} from '../src/utils.js'; const BIDDER_CODE = 'growads'; export const spec = { code: BIDDER_CODE, + supportedMediaTypes: [BANNER, NATIVE], isBidRequestValid: function (bid) { return bid.params && !!bid.params.zoneId; @@ -59,6 +62,7 @@ export const spec = { let isCorrectCPM = true; let minCPM; let maxCPM; + let bid = {}; let body = serverResponse.body; @@ -86,32 +90,74 @@ export const spec = { isCorrectCPM = false; } - // Ensure that response ad matches one of the placement sizes. - utils._each(utils.deepAccess(request, 'mediaTypes.banner.sizes', []), function (size) { - if (width === size[0] && height === size[1]) { - isCorrectSize = true; - } - }); - - if (isCorrectCPM && isCorrectSize) { - bidResponses.push({ + if (isCorrectCPM) { + bid = { requestId: request.bidId, bidderCode: request.bidder, creativeId: response.creativeId, cpm: CPM, width: width, height: height, - ad: response.ad, currency: response.currency, netRevenue: true, ttl: response.ttl, + adUnitCode: request.adUnitCode, referrer: utils.deepAccess(request, 'refererInfo.referer') - }); + }; + + if (response.hasOwnProperty(NATIVE)) { + bid[NATIVE] = { + title: response[NATIVE].title, + body: response[NATIVE].body, + body2: response[NATIVE].body2, + cta: response[NATIVE].cta, + sponsoredBy: response[NATIVE].sponsoredBy, + clickUrl: response[NATIVE].clickUrl, + impressionTrackers: response[NATIVE].impressionTrackers, + }; + + if (response[NATIVE].image) { + bid[NATIVE].image = { + url: response[NATIVE].image.url, + height: response[NATIVE].image.height, + width: response[NATIVE].image.width + }; + } + + if (response[NATIVE].icon) { + bid[NATIVE].icon = { + url: response[NATIVE].icon.url, + height: response[NATIVE].icon.height, + width: response[NATIVE].icon.width + }; + } + bid.mediaType = NATIVE; + isCorrectSize = true; + } else { + bid.ad = response.ad; + bid.mediaType = BANNER; + // Ensure that response ad matches one of the placement sizes. + utils._each(utils.deepAccess(request, 'mediaTypes.banner.sizes', []), function (size) { + if (width === size[0] && height === size[1]) { + isCorrectSize = true; + } + }); + } + + if (isCorrectSize) { + bidResponses.push(bid); + } } } return bidResponses; - } + }, + + onBidWon: function (bid) { + if (bid.vurl) { + triggerPixel(bid.vurl); + } + }, }; registerBidder(spec); diff --git a/modules/growadvertisingBidAdapter.md b/modules/growadvertisingBidAdapter.md index f20b853a33f..f17691e9b9f 100644 --- a/modules/growadvertisingBidAdapter.md +++ b/modules/growadvertisingBidAdapter.md @@ -35,6 +35,36 @@ var adUnits = [ } } ] - } + }, + // Native adUnit + { + code: 'native-div', + sizes: [[1, 1]], + mediaTypes: { + native: { + title: { + required: true + }, + body: { + required: true + }, + image: { + required: true + }, + sponsoredBy: { + required: true + }, + } + }, + bids: [ + { + bidder: 'growads', + params: { + zoneId: 'YpQobqT-vEybhHx-1qaNMFx-Wj3Kwc2', + domain: 'native-test.growadvertising.com' + } + } + ] + }, ]; ``` diff --git a/test/spec/modules/growadvertisingBidAdapter_spec.js b/test/spec/modules/growadvertisingBidAdapter_spec.js index 30d9207d4c2..55eea06cca8 100644 --- a/test/spec/modules/growadvertisingBidAdapter_spec.js +++ b/test/spec/modules/growadvertisingBidAdapter_spec.js @@ -1,19 +1,46 @@ import { expect } from 'chai'; import { spec } from 'modules/growadvertisingBidAdapter.js'; import * as utils from '../../../src/utils.js'; +import {BANNER, NATIVE} from '../../../src/mediaTypes.js'; describe('GrowAdvertising Adapter', function() { const ZONE_ID = 'unique-zone-id'; - const serverResponse = { + const serverResponseBanner = { body: { status: 'success', width: 300, height: 250, creativeId: 'ULqaukILu0RnMa0FyidOtkji4Po3qbgQ9ceRVGlhjLLKnrrLAATmGNCwtE99Ems8', - ad: '', + ad: '', cpm: 1, ttl: 180, currency: 'USD', + type: BANNER, + } + }; + const serverResponseNative = { + body: { + status: 'success', + width: 400, + height: 300, + creativeId: 'ULqaukILu0RnMa0FyidOtkji4Po3qbgQ9ceRVGlhjLLKnrrLAATmGNCwtE99Ems9', + cpm: 2, + ttl: 180, + currency: 'USD', + native: { + title: 'Test title', + body: 'Test body', + body2: null, + sponsoredBy: 'Sponsored by', + cta: null, + clickUrl: 'https://example.org', + image: { + width: 400, + height: 300, + url: 'https://image.source.com/img', + } + }, + type: NATIVE } }; let bidRequests = []; @@ -32,6 +59,25 @@ describe('GrowAdvertising Adapter', function() { sizes: [[300, 250], [300, 600]], }, }, + }, + { + bidder: 'growads', + params: { + zoneId: ZONE_ID, + }, + mediaTypes: { + native: { + title: { + required: true + }, + image: { + required: true + }, + sponsoredBy: { + required: true + } + }, + }, } ]; }); @@ -122,39 +168,60 @@ describe('GrowAdvertising Adapter', function() { }); describe('bid responses', function () { - it('should return complete bid response', function () { - let bids = spec.interpretResponse(serverResponse, {bidRequest: bidRequests[0]}); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].bidderCode).to.equal('growads'); - expect(bids[0].cpm).to.equal(1); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].creativeId).to.have.length.above(1); - expect(bids[0].ad).to.have.length.above(1); - }); + describe(BANNER, function () { + it('should return complete bid response banner', function () { + let bids = spec.interpretResponse(serverResponseBanner, {bidRequest: bidRequests[0]}); + + expect(bids).to.be.lengthOf(1); + expect(bids[0].bidderCode).to.equal('growads'); + expect(bids[0].cpm).to.equal(1); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].creativeId).to.have.length.above(1); + expect(bids[0].ad).to.have.length.above(1); + expect(bids[0].mediaType).to.equal(BANNER); + }); - it('should return empty bid on incorrect size', function () { - let response = utils.mergeDeep(serverResponse, { - body: { - width: 150, - height: 150 - } + it('should return empty bid on incorrect size', function () { + let response = utils.mergeDeep(serverResponseBanner, { + body: { + width: 150, + height: 150 + } + }); + + let bids = spec.interpretResponse(response, {bidRequest: bidRequests[0]}); + expect([]).to.be.lengthOf(0); }); - let bids = spec.interpretResponse(response, {bidRequest: bidRequests[0]}); - expect([]).to.be.lengthOf(0); - }); + it('should return empty bid on incorrect CPM', function () { + let response = utils.mergeDeep(serverResponseBanner, { + body: { + cpm: 10 + } + }); - it('should return empty bid on incorrect CPM', function () { - let response = utils.mergeDeep(serverResponse, { - body: { - cpm: 10 - } + let bids = spec.interpretResponse(response, {bidRequest: bidRequests[0]}); + expect([]).to.be.lengthOf(0); }); + }); - let bids = spec.interpretResponse(response, {bidRequest: bidRequests[0]}); - expect([]).to.be.lengthOf(0); + describe(NATIVE, function () { + it('should return complete bid response banner', function () { + let bids = spec.interpretResponse(serverResponseNative, {bidRequest: bidRequests[1]}); + + expect(bids).to.be.lengthOf(1); + expect(bids[0].bidderCode).to.equal('growads'); + expect(bids[0].cpm).to.equal(2); + expect(bids[0].width).to.equal(400); + expect(bids[0].height).to.equal(300); + expect(bids[0].creativeId).to.have.length.above(1); + expect(bids[0]).property('native'); + expect(bids[0].native.title).to.have.length.above(1); + expect(bids[0].native.body).to.have.length.above(1); + expect(bids[0].native).property('image'); + expect(bids[0].mediaType).to.equal(NATIVE); + }); }); }); });