From 900681f1c0a8ff326a74c43ec61528f00f9370df Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Tue, 14 Feb 2023 10:50:48 -0800 Subject: [PATCH 01/17] Flipp Bid Adapter: initial release * Added flippBidAdapter --- modules/flippBidAdapter.js | 110 ++++++++++++++ modules/flippBidAdapter.md | 40 +++++ test/spec/modules/flippBidAdapter_spec.js | 170 ++++++++++++++++++++++ 3 files changed, 320 insertions(+) create mode 100644 modules/flippBidAdapter.js create mode 100644 modules/flippBidAdapter.md create mode 100644 test/spec/modules/flippBidAdapter_spec.js diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js new file mode 100644 index 00000000000..343f002b339 --- /dev/null +++ b/modules/flippBidAdapter.js @@ -0,0 +1,110 @@ +import {isEmpty, parseUrl} from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +const NETWORK_ID = 11090; +const AD_TYPES = [4309, 641]; +const TARGET_NAME = 'inline'; +const BIDDER_CODE = 'flipp'; +const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/prebid_campaigns'; +const DEFAULT_TTL = 30; +const DEFAULT_CURRENCY = 'USD'; + +const generateUUID = () => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); +}; + +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) { + return !!(bid.params.siteId) && !!(bid.params.publisherNameIdentifier); + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} validBidRequests[] an array of bids + * @param {BidderRequest} bidderRequest master bidRequest object + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + const urlParams = parseUrl(bidderRequest.refererInfo.page).search; + const contentCode = urlParams['flipp-content-code']; + const userKey = isEmpty(validBidRequests[0]?.params.userKey) ? generateUUID() : validBidRequests[0]?.params.userKey; + const placements = validBidRequests.map((bid, index) => { + return { + divName: TARGET_NAME, + networkId: NETWORK_ID, + siteId: bid.params.siteId, + adTypes: AD_TYPES, + count: 1, + ...(!isEmpty(bid.params.zoneIds) && {zoneIds: bid.params.zoneIds}), + properties: { + ...(!isEmpty(contentCode) && {contentCode: contentCode.slice(0, 32)}), + }, + prebid: { + requestId: bid.bidId, + publisherNameIdentifier: bid.params.publisherNameIdentifier, + height: bid.mediaTypes.banner.sizes[index][0], + width: bid.mediaTypes.banner.sizes[index][1], + } + } + }); + return { + method: 'POST', + url: ENDPOINT, + data: { + placements, + url: bidderRequest.refererInfo.page, + user: { + key: userKey, + }, + }, + } + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param {BidRequest} bidRequest A bid request object + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + if (!serverResponse?.body) return []; + const res = serverResponse.body; + if (!isEmpty(res) && !isEmpty(res.decisions) && !isEmpty(res.decisions.inline)) { + return res.decisions.inline.map(decision => ({ + bidderCode: BIDDER_CODE, + requestId: decision.prebid?.requestId, + cpm: decision.prebid?.cpm, + width: decision.width, + height: decision.height, + creativeId: decision.adId, + currency: DEFAULT_CURRENCY, + netRevenue: true, + ttl: DEFAULT_TTL, + ad: decision.prebid?.creative, + })); + } + return []; + }, + + /** + * Register the user sync pixels which should be dropped after the auction. + * + * @param {SyncOptions} syncOptions Which user syncs are allowed? + * @param {ServerResponse[]} serverResponses List of server's responses. + * @return {UserSync[]} The user syncs which should be dropped. + */ + getUserSyncs: (syncOptions, serverResponses) => [], +} +registerBidder(spec); diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md new file mode 100644 index 00000000000..0e3c39da0d2 --- /dev/null +++ b/modules/flippBidAdapter.md @@ -0,0 +1,40 @@ +# Overview + +``` +Module Name: Flipp Bid Adapter +Module Type: Bidder Adapter +Maintainer: prebid@flipp.com +``` + +# Description + +This module connects publishers to Flipp's Shopper Experience via Prebid.js. + + +# Test parameters + +```javascript +var adUnits = [ + { + code: 'flipp-scroll-ad-content', + mediaTypes: { + banner: { + sizes: [ + [300, 600] + ] + } + }, + bids: [ + { + bidder: 'flipp', + params: { + publisherNameIdentifier: 'wishabi-test-publisher', // Required + siteId: 1192075, // Required + zoneIds: [260678], // Optional + userKey: "", // Optional + } + } + ] + } +] +``` diff --git a/test/spec/modules/flippBidAdapter_spec.js b/test/spec/modules/flippBidAdapter_spec.js new file mode 100644 index 00000000000..73211d40f37 --- /dev/null +++ b/test/spec/modules/flippBidAdapter_spec.js @@ -0,0 +1,170 @@ +import {expect} from 'chai'; +import {spec} from 'modules/flippBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/prebid_campaigns'; +describe('flippAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + const bid = { + bidder: 'flipp', + params: { + publisherNameIdentifier: 'random', + siteId: 1234, + zoneIds: [1, 2, 3, 4], + } + }; + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let invalidBid = Object.assign({}, bid); + invalidBid.params = { siteId: 1234 } + expect(spec.isBidRequestValid(invalidBid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [{ + bidder: 'flipp', + params: { + siteId: 1234, + }, + adUnitCode: '/10000/unit_code', + sizes: [[300, 600]], + mediaTypes: {banner: {sizes: [[300, 600]]}}, + bidId: '237f4d1a293f99', + bidderRequestId: '1a857fa34c1c96', + auctionId: 'a297d1aa-7900-4ce4-a0aa-caa8d46c4af7', + transactionId: '00b2896c-2731-4f01-83e4-7a3ad5da13b6', + }]; + const bidderRequest = { + refererInfo: { + referer: 'http://example.com' + } + }; + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.method).to.equal('POST'); + }); + + it('sends bid request to ENDPOINT with query parameter', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.equal(ENDPOINT); + }); + }); + + describe('interpretResponse', function() { + it('should get correct bid response', function() { + const bidRequest = { + method: 'POST', + url: ENDPOINT, + data: { + placements: [{ + divName: 'slot', + networkId: 12345, + siteId: 12345, + adTypes: [12345], + count: 1, + prebid: { + requestId: '237f4d1a293f99', + publisherNameIdentifier: 'bid.params.publisherNameIdentifier', + height: 600, + width: 300, + }, + user: '10462725-da61-4d3a-beff-6d05239e9a6e"', + }], + url: 'http://example.com', + }, + }; + + const serverResponse = { + body: { + 'decisions': { + 'inline': [{ + 'bidCpm': 1, + 'adId': 262838368, + 'height': 600, + 'width': 300, + 'storefront': { 'flyer_id': 5435567 }, + 'prebid': { + 'requestId': '237f4d1a293f99', + 'cpm': 1.11, + 'creative': 'Returned from server', + } + }] + }, + 'location': {'city': 'Oakville'}, + }, + }; + + const expectedResponse = [ + { + bidderCode: 'flipp', + requestId: '237f4d1a293f99', + currency: 'USD', + cpm: 1.11, + netRevenue: true, + width: 300, + height: 600, + creativeId: 262838368, + ttl: 30, + ad: 'Returned from server', + } + ]; + + const result = spec.interpretResponse(serverResponse, bidRequest); + expect(result).to.have.lengthOf(1); + expect(result).to.deep.have.same.members(expectedResponse); + }); + + it('should get empty bid response when no ad is returned', function() { + const bidRequest = { + method: 'POST', + url: ENDPOINT, + data: { + placements: [{ + divName: 'slot', + networkId: 12345, + siteId: 12345, + adTypes: [12345], + count: 1, + prebid: { + requestId: '237f4d1a293f99', + publisherNameIdentifier: 'bid.params.publisherNameIdentifier', + height: 600, + width: 300, + }, + user: '10462725-da61-4d3a-beff-6d05239e9a6e"', + }], + url: 'http://example.com', + }, + }; + + const serverResponse = { + body: { + 'decisions': { + 'inline': [] + }, + 'location': {'city': 'Oakville'}, + }, + }; + + const result = spec.interpretResponse(serverResponse, bidRequest); + expect(result).to.have.lengthOf(0); + expect(result).to.deep.have.same.members([]); + }) + + it('should get empty response when bid server returns 204', function() { + expect(spec.interpretResponse({})).to.be.empty; + }); + }); +}); From 3e78053b9c60d20db2fd6c893204a6dfc6381871 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Wed, 15 Mar 2023 12:09:14 -0700 Subject: [PATCH 02/17] OFF-372 Support DTX/Hero in flippBidAdapter (#2) * support creativeType * OFF-422 flippBidAdapter handle AdTypes --------- Co-authored-by: Jairo Panduro --- modules/flippBidAdapter.js | 27 ++++++++++++++++++++++++++- modules/flippBidAdapter.md | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 343f002b339..8ac6df0b750 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -3,11 +3,14 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; const NETWORK_ID = 11090; const AD_TYPES = [4309, 641]; +const DTX_TYPES = [5061]; const TARGET_NAME = 'inline'; const BIDDER_CODE = 'flipp'; const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/prebid_campaigns'; const DEFAULT_TTL = 30; const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_CREATIVE_TYPE = 'NativeX'; +const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; const generateUUID = () => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { @@ -17,6 +20,27 @@ const generateUUID = () => { }); }; +/** + * Determines if a creativeType is valid + * + * @param {string} creativeType The Creative Type to validate. + * @return string creativeType if this is a valid Creative Type, and 'NativeX' otherwise. + */ +const validateCreativeType = (creativeType) => { + if (creativeType && VALID_CREATIVE_TYPES.includes(creativeType)) { + return creativeType; + } else { + return DEFAULT_CREATIVE_TYPE; + } +}; + +const getAdTypes = (creativeType) => { + if (creativeType === 'DTX') { + return DTX_TYPES; + } + return AD_TYPES; +} + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], @@ -45,13 +69,14 @@ export const spec = { divName: TARGET_NAME, networkId: NETWORK_ID, siteId: bid.params.siteId, - adTypes: AD_TYPES, + adTypes: getAdTypes(bid.params.creativeType), count: 1, ...(!isEmpty(bid.params.zoneIds) && {zoneIds: bid.params.zoneIds}), properties: { ...(!isEmpty(contentCode) && {contentCode: contentCode.slice(0, 32)}), }, prebid: { + creativeType: validateCreativeType(bid.params.creativeType), requestId: bid.bidId, publisherNameIdentifier: bid.params.publisherNameIdentifier, height: bid.mediaTypes.banner.sizes[index][0], diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 0e3c39da0d2..8576c345f06 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -28,6 +28,7 @@ var adUnits = [ { bidder: 'flipp', params: { + creativeType: 'NativeX', // Optional, can be one of 'NativeX' (default) or 'DTX' publisherNameIdentifier: 'wishabi-test-publisher', // Required siteId: 1192075, // Required zoneIds: [260678], // Optional From 302de4d3246d50f1083f3335e1fa79d4f6adc236 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 27 Apr 2023 08:44:31 -0700 Subject: [PATCH 03/17] OFF-465 Add getUserKey logic to prebid.js adapter (#3) * Support cookie sync and uid * address pr feedback * remove redundant check --- modules/flippBidAdapter.js | 41 ++++++++++++++++++++++++++++++++++++-- modules/flippBidAdapter.md | 1 + 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 8ac6df0b750..8aae286ce01 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -1,6 +1,8 @@ import {isEmpty, parseUrl} from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; +import {getStorageManager} from '../src/storageManager.js'; + const NETWORK_ID = 11090; const AD_TYPES = [4309, 641]; const DTX_TYPES = [5061]; @@ -11,6 +13,41 @@ const DEFAULT_TTL = 30; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_CREATIVE_TYPE = 'NativeX'; const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; +const FLIPP_USER_KEY = 'flipp-uid'; + +let userKey = null; +export const storage = getStorageManager({bidderCode: BIDDER_CODE}); + +export function getUserKey(options = {}) { + if (userKey) { + return userKey; + } + + // If the partner provides the user key use it, otherwise fallback to cookies + if (options.userKey && isValidUserKey(options.userKey)) { + userKey = options.userKey; + return options.userKey; + } + // Grab from Cookie + const foundUserKey = storage.cookiesAreEnabled() && storage.getCookie(FLIPP_USER_KEY); + if (foundUserKey) { + return foundUserKey; + } + + // Generate if none found + userKey = generateUUID(); + + // Set cookie + if (storage.cookiesAreEnabled()) { + storage.setCookie(FLIPP_USER_KEY, userKey); + } + + return userKey; +} + +function isValidUserKey(userKey) { + return !userKey.startsWith('#'); +} const generateUUID = () => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { @@ -63,7 +100,7 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const urlParams = parseUrl(bidderRequest.refererInfo.page).search; const contentCode = urlParams['flipp-content-code']; - const userKey = isEmpty(validBidRequests[0]?.params.userKey) ? generateUUID() : validBidRequests[0]?.params.userKey; + const userKey = getUserKey(validBidRequests[0]?.params); const placements = validBidRequests.map((bid, index) => { return { divName: TARGET_NAME, @@ -76,11 +113,11 @@ export const spec = { ...(!isEmpty(contentCode) && {contentCode: contentCode.slice(0, 32)}), }, prebid: { - creativeType: validateCreativeType(bid.params.creativeType), requestId: bid.bidId, publisherNameIdentifier: bid.params.publisherNameIdentifier, height: bid.mediaTypes.banner.sizes[index][0], width: bid.mediaTypes.banner.sizes[index][1], + creativeType: validateCreativeType(bid.params.creativeType), } } }); diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 8576c345f06..3ad1f7f3f5c 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -33,6 +33,7 @@ var adUnits = [ siteId: 1192075, // Required zoneIds: [260678], // Optional userKey: "", // Optional + creativeType: 'NativeX', // Optional } } ] From ba3de3ce3632265716855a35a9592cd2413f7145 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Mon, 1 May 2023 08:58:29 -0700 Subject: [PATCH 04/17] OFF-500 Support "startCompact" param for Prebid.JS #4 --- modules/flippBidAdapter.js | 31 +++++++++++++++++++------------ modules/flippBidAdapter.md | 3 +++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 8aae286ce01..79f981a5a35 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -14,6 +14,7 @@ const DEFAULT_CURRENCY = 'USD'; const DEFAULT_CREATIVE_TYPE = 'NativeX'; const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; const FLIPP_USER_KEY = 'flipp-uid'; +const COMPACT_DEFAULT_HEIGHT = 600; let userKey = null; export const storage = getStorageManager({bidderCode: BIDDER_CODE}); @@ -112,6 +113,7 @@ export const spec = { properties: { ...(!isEmpty(contentCode) && {contentCode: contentCode.slice(0, 32)}), }, + options: bid.params.options, prebid: { requestId: bid.bidId, publisherNameIdentifier: bid.params.publisherNameIdentifier, @@ -142,20 +144,25 @@ export const spec = { */ interpretResponse: function(serverResponse, bidRequest) { if (!serverResponse?.body) return []; + const placements = bidRequest.data.placements; const res = serverResponse.body; if (!isEmpty(res) && !isEmpty(res.decisions) && !isEmpty(res.decisions.inline)) { - return res.decisions.inline.map(decision => ({ - bidderCode: BIDDER_CODE, - requestId: decision.prebid?.requestId, - cpm: decision.prebid?.cpm, - width: decision.width, - height: decision.height, - creativeId: decision.adId, - currency: DEFAULT_CURRENCY, - netRevenue: true, - ttl: DEFAULT_TTL, - ad: decision.prebid?.creative, - })); + return res.decisions.inline.map(decision => { + const placement = placements.find(p => p.prebid.requestId === decision.prebid?.requestId); + const height = placement.options?.startCompact ? COMPACT_DEFAULT_HEIGHT : decision.height; + return { + bidderCode: BIDDER_CODE, + requestId: decision.prebid?.requestId, + cpm: decision.prebid?.cpm, + width: decision.width, + height, + creativeId: decision.adId, + currency: DEFAULT_CURRENCY, + netRevenue: true, + ttl: DEFAULT_TTL, + ad: decision.prebid?.creative, + } + }); } return []; }, diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 3ad1f7f3f5c..7b466075870 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -34,6 +34,9 @@ var adUnits = [ zoneIds: [260678], // Optional userKey: "", // Optional creativeType: 'NativeX', // Optional + options: { + startCompact: true // Optional, default to true + } } } ] From 0e29c8cb96eb5889ec152caae30c07f97fade641 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 18 May 2023 13:50:22 -0700 Subject: [PATCH 05/17] set startCompact default value (#5) --- modules/flippBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 79f981a5a35..47fb5e72504 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -103,6 +103,10 @@ export const spec = { const contentCode = urlParams['flipp-content-code']; const userKey = getUserKey(validBidRequests[0]?.params); const placements = validBidRequests.map((bid, index) => { + const options = bid.params.options || {}; + if (!options.hasOwnProperty('startCompact')) { + options.startCompact = true; + } return { divName: TARGET_NAME, networkId: NETWORK_ID, @@ -113,7 +117,7 @@ export const spec = { properties: { ...(!isEmpty(contentCode) && {contentCode: contentCode.slice(0, 32)}), }, - options: bid.params.options, + options, prebid: { requestId: bid.bidId, publisherNameIdentifier: bid.params.publisherNameIdentifier, From 8030c65e4598f3f78c5b6f87175c165b56d40055 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Tue, 29 Aug 2023 18:29:19 -0700 Subject: [PATCH 06/17] fix docs --- modules/flippBidAdapter.md | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 7b466075870..810b883e3f9 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -33,7 +33,6 @@ var adUnits = [ siteId: 1192075, // Required zoneIds: [260678], // Optional userKey: "", // Optional - creativeType: 'NativeX', // Optional options: { startCompact: true // Optional, default to true } From b84ba5bdeceab3e2dc4541506c7b26368b99beee Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Fri, 8 Sep 2023 15:00:32 -0700 Subject: [PATCH 07/17] use client bidding endpoint --- modules/flippBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 47fb5e72504..dfe8141170d 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -8,7 +8,7 @@ const AD_TYPES = [4309, 641]; const DTX_TYPES = [5061]; const TARGET_NAME = 'inline'; const BIDDER_CODE = 'flipp'; -const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/prebid_campaigns'; +const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/client_bidding'; const DEFAULT_TTL = 30; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_CREATIVE_TYPE = 'NativeX'; From ba5dc3ed26010a8818bb2c3fa49b72d658c48faa Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Fri, 8 Sep 2023 15:31:33 -0700 Subject: [PATCH 08/17] update unit testing endpoint --- test/spec/modules/flippBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/flippBidAdapter_spec.js b/test/spec/modules/flippBidAdapter_spec.js index 73211d40f37..518052ad91e 100644 --- a/test/spec/modules/flippBidAdapter_spec.js +++ b/test/spec/modules/flippBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/flippBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/prebid_campaigns'; +const ENDPOINT = 'https://gateflipp.flippback.com/flyer-locator-service/client_bidding'; describe('flippAdapter', function () { const adapter = newBidder(spec); From 1801066a1c31f5865496e454e5ea2ab389bbc9d0 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Wed, 18 Oct 2023 07:29:12 -0700 Subject: [PATCH 09/17] OFF-876 [Prebid Adapter] Check userKey for empty string (#6) * add more checks to userKey * update document * add uuid format statement --- modules/flippBidAdapter.js | 15 +++++++++------ modules/flippBidAdapter.md | 5 +++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index dfe8141170d..480e414992d 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -25,13 +25,16 @@ export function getUserKey(options = {}) { } // If the partner provides the user key use it, otherwise fallback to cookies - if (options.userKey && isValidUserKey(options.userKey)) { - userKey = options.userKey; - return options.userKey; + if ('userKey' in options && options.userKey) { + if (isValidUserKey(options.userKey)) { + userKey = options.userKey; + return options.userKey; + } } + // Grab from Cookie - const foundUserKey = storage.cookiesAreEnabled() && storage.getCookie(FLIPP_USER_KEY); - if (foundUserKey) { + const foundUserKey = storage.cookiesAreEnabled(null) && storage.getCookie(FLIPP_USER_KEY, null); + if (foundUserKey && isValidUserKey(foundUserKey)) { return foundUserKey; } @@ -47,7 +50,7 @@ export function getUserKey(options = {}) { } function isValidUserKey(userKey) { - return !userKey.startsWith('#'); + return typeof userKey === 'string' && !userKey.startsWith('#') && userKey.length > 0; } const generateUUID = () => { diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 810b883e3f9..607422ae391 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -32,9 +32,10 @@ var adUnits = [ publisherNameIdentifier: 'wishabi-test-publisher', // Required siteId: 1192075, // Required zoneIds: [260678], // Optional - userKey: "", // Optional + userKey: `4188d8a3-22d1-49cb-8624-8838a22562bd`, // Optional, in UUID format options: { - startCompact: true // Optional, default to true + startCompact: true, // Optional. Height of the experience will be reduced. Default to true + dwellExpand: true // Optional. Auto expand the experience after a certain time passes. Default to true } } } From 5d18ac6069df95d39efc348b7fa45b1dc8f41dda Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Wed, 18 Oct 2023 09:07:10 -0700 Subject: [PATCH 10/17] modify docs --- modules/flippBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.md b/modules/flippBidAdapter.md index 607422ae391..e823432a60f 100644 --- a/modules/flippBidAdapter.md +++ b/modules/flippBidAdapter.md @@ -32,7 +32,7 @@ var adUnits = [ publisherNameIdentifier: 'wishabi-test-publisher', // Required siteId: 1192075, // Required zoneIds: [260678], // Optional - userKey: `4188d8a3-22d1-49cb-8624-8838a22562bd`, // Optional, in UUID format + userKey: ``, // Optional, but recommended for better user experience. Can be a cookie, session id or any other user identifier options: { startCompact: true, // Optional. Height of the experience will be reduced. Default to true dwellExpand: true // Optional. Auto expand the experience after a certain time passes. Default to true From d872f1bae177ae10223bc2b80c597d57d7b4d383 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 Nov 2023 13:21:24 -0800 Subject: [PATCH 11/17] fix network id --- modules/flippBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 480e414992d..ea5e71ad81d 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -3,7 +3,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; -const NETWORK_ID = 11090; +const NETWORK_ID = 10922; const AD_TYPES = [4309, 641]; const DTX_TYPES = [5061]; const TARGET_NAME = 'inline'; From d839521b946b4329bfd766e00210a0481a3412a8 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:02:41 -0700 Subject: [PATCH 12/17] use compactHeight and standardHeight in customData (#7) --- modules/flippBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index ea5e71ad81d..bfefd20b7ec 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -15,6 +15,7 @@ const DEFAULT_CREATIVE_TYPE = 'NativeX'; const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; const FLIPP_USER_KEY = 'flipp-uid'; const COMPACT_DEFAULT_HEIGHT = 600; +const STANDARD_DEFAULT_HEIGHT = 1800; let userKey = null; export const storage = getStorageManager({bidderCode: BIDDER_CODE}); @@ -156,7 +157,10 @@ export const spec = { if (!isEmpty(res) && !isEmpty(res.decisions) && !isEmpty(res.decisions.inline)) { return res.decisions.inline.map(decision => { const placement = placements.find(p => p.prebid.requestId === decision.prebid?.requestId); - const height = placement.options?.startCompact ? COMPACT_DEFAULT_HEIGHT : decision.height; + const customData = decision.contents[0]?.data?.customData; + const height = placement.options?.startCompact + ? customData?.compactHeight ?? COMPACT_DEFAULT_HEIGHT + : customData?.standardHeight ?? STANDARD_DEFAULT_HEIGHT; return { bidderCode: BIDDER_CODE, requestId: decision.prebid?.requestId, From e6506e7443a8c9855de4bfc0b17b247b445daecc Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:15:57 -0700 Subject: [PATCH 13/17] OFF-1455 [Prebid.js] height should use the compactHeight and standardHeight fields in decisions response (#8) * Flipp Bid Adapter: initial release * Added flippBidAdapter * OFF-372 Support DTX/Hero in flippBidAdapter (#2) * support creativeType * OFF-422 flippBidAdapter handle AdTypes --------- Co-authored-by: Jairo Panduro * OFF-465 Add getUserKey logic to prebid.js adapter (#3) * Support cookie sync and uid * address pr feedback * remove redundant check * OFF-500 Support "startCompact" param for Prebid.JS #4 * set startCompact default value (#5) * fix docs * use client bidding endpoint * update unit testing endpoint * OFF-876 [Prebid Adapter] Check userKey for empty string (#6) * add more checks to userKey * update document * add uuid format statement * modify docs * fix network id * use compactHeight and standardHeight in customData --------- Co-authored-by: Jairo Panduro --- modules/flippBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index f9c424d9da5..95fd67c779b 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -25,6 +25,7 @@ const DEFAULT_CREATIVE_TYPE = 'NativeX'; const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; const FLIPP_USER_KEY = 'flipp-uid'; const COMPACT_DEFAULT_HEIGHT = 600; +const STANDARD_DEFAULT_HEIGHT = 1800; let userKey = null; export const storage = getStorageManager({bidderCode: BIDDER_CODE}); @@ -166,7 +167,10 @@ export const spec = { if (!isEmpty(res) && !isEmpty(res.decisions) && !isEmpty(res.decisions.inline)) { return res.decisions.inline.map(decision => { const placement = placements.find(p => p.prebid.requestId === decision.prebid?.requestId); - const height = placement.options?.startCompact ? COMPACT_DEFAULT_HEIGHT : decision.height; + const customData = decision.contents[0]?.data?.customData; + const height = placement.options?.startCompact + ? customData?.compactHeight ?? COMPACT_DEFAULT_HEIGHT + : customData?.standardHeight ?? STANDARD_DEFAULT_HEIGHT; return { bidderCode: BIDDER_CODE, requestId: decision.prebid?.requestId, From a3dbd42de06ba26c9bd25bc50b2ef3b67a569782 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:22:31 -0700 Subject: [PATCH 14/17] Update flippBidAdapter.js --- modules/flippBidAdapter.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index ea5e71ad81d..9150ce66a13 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -3,6 +3,16 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; +/** + * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest + * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid + * @typedef {import('../src/adapters/bidderFactory.js').BidderRequest} BidderRequest + * @typedef {import('../src/adapters/bidderFactory.js').validBidRequests} validBidRequests + * @typedef {import('../src/adapters/bidderFactory.js').ServerResponse} ServerResponse + * @typedef {import('../src/adapters/bidderFactory.js').SyncOptions} SyncOptions + * @typedef {import('../src/adapters/bidderFactory.js').UserSync} UserSync + */ + const NETWORK_ID = 10922; const AD_TYPES = [4309, 641]; const DTX_TYPES = [5061]; From a5675b49f1a745929a44038da3bb7b0feb483801 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:02:41 -0700 Subject: [PATCH 15/17] use compactHeight and standardHeight in customData (#7) --- modules/flippBidAdapter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index 9150ce66a13..b4b9c4bd023 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -25,6 +25,7 @@ const DEFAULT_CREATIVE_TYPE = 'NativeX'; const VALID_CREATIVE_TYPES = ['DTX', 'NativeX']; const FLIPP_USER_KEY = 'flipp-uid'; const COMPACT_DEFAULT_HEIGHT = 600; +const STANDARD_DEFAULT_HEIGHT = 1800; let userKey = null; export const storage = getStorageManager({bidderCode: BIDDER_CODE}); @@ -166,7 +167,10 @@ export const spec = { if (!isEmpty(res) && !isEmpty(res.decisions) && !isEmpty(res.decisions.inline)) { return res.decisions.inline.map(decision => { const placement = placements.find(p => p.prebid.requestId === decision.prebid?.requestId); - const height = placement.options?.startCompact ? COMPACT_DEFAULT_HEIGHT : decision.height; + const customData = decision.contents[0]?.data?.customData; + const height = placement.options?.startCompact + ? customData?.compactHeight ?? COMPACT_DEFAULT_HEIGHT + : customData?.standardHeight ?? STANDARD_DEFAULT_HEIGHT; return { bidderCode: BIDDER_CODE, requestId: decision.prebid?.requestId, From c5b9b34d399caf71768c32d354e9aa5e0d346e8c Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:25:30 -0700 Subject: [PATCH 16/17] update docs --- modules/flippBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/flippBidAdapter.js b/modules/flippBidAdapter.js index b4b9c4bd023..95fd67c779b 100644 --- a/modules/flippBidAdapter.js +++ b/modules/flippBidAdapter.js @@ -108,7 +108,7 @@ export const spec = { /** * Make a server request from the list of BidRequests. * - * @param {BidRequest[]} validBidRequests[] an array of bids + * @param {validBidRequests} validBidRequests an array of bids * @param {BidderRequest} bidderRequest master bidRequest object * @return ServerRequest Info describing the request to the server. */ From f657c079b1d2583effaccb2c33dbee67913bad84 Mon Sep 17 00:00:00 2001 From: Mike Lei Date: Thu, 30 May 2024 14:46:31 -0700 Subject: [PATCH 17/17] fix unit test --- test/spec/modules/flippBidAdapter_spec.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/flippBidAdapter_spec.js b/test/spec/modules/flippBidAdapter_spec.js index 518052ad91e..9602a156bed 100644 --- a/test/spec/modules/flippBidAdapter_spec.js +++ b/test/spec/modules/flippBidAdapter_spec.js @@ -99,6 +99,14 @@ describe('flippAdapter', function () { 'requestId': '237f4d1a293f99', 'cpm': 1.11, 'creative': 'Returned from server', + }, + 'contents': { + 'data': { + 'customData': { + 'compactHeight': 600, + 'standardHeight': 1800 + } + } } }] }, @@ -114,7 +122,7 @@ describe('flippAdapter', function () { cpm: 1.11, netRevenue: true, width: 300, - height: 600, + height: 1800, creativeId: 262838368, ttl: 30, ad: 'Returned from server',