-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cwire bid adapter: initial release (#7421)
* working prebid response * add cwid to local storage * wip * write prebid tests, and prepare for release * cleanup * change param types & add cw refgroups array url parser * working prebid response * add cwid to local storage * wip * write prebid tests, and prepare for release * cleanup * change param types & add cw refgroups array url parser * required changes * remove double line * revert file to old content * bump * import only used functions from utils
- Loading branch information
Showing
3 changed files
with
561 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
import {registerBidder} from '../src/adapters/bidderFactory.js'; | ||
import { getRefererInfo } from '../src/refererDetection.js'; | ||
import { getStorageManager } from '../src/storageManager.js'; | ||
import {BANNER, VIDEO} from '../src/mediaTypes.js'; | ||
import { OUTSTREAM } from '../src/video.js'; | ||
import { | ||
isArray, | ||
isNumber, | ||
generateUUID, | ||
parseSizesInput, | ||
deepAccess, | ||
getParameterByName, | ||
getValue, | ||
getBidIdParameter, | ||
logError, | ||
logWarn, | ||
} from '../src/utils.js'; | ||
import { Renderer } from '../src/Renderer.js'; | ||
import find from 'core-js-pure/features/array/find.js'; | ||
|
||
// ------------------------------------ | ||
const BIDDER_CODE = 'cwire'; | ||
export const ENDPOINT_URL = 'https://embed.cwi.re/delivery/prebid'; | ||
export const RENDERER_URL = 'https://cdn.cwi.re/prebid/renderer/LATEST/renderer.min.js'; | ||
// ------------------------------------ | ||
export const CW_PAGE_VIEW_ID = generateUUID(); | ||
const LS_CWID_KEY = 'cw_cwid'; | ||
const CW_GROUPS_QUERY = 'cwgroups'; | ||
|
||
const storage = getStorageManager(); | ||
|
||
/** | ||
* ------------------------------------ | ||
* ------------------------------------ | ||
* @param bid | ||
* @returns {Array<string>} | ||
*/ | ||
export function getSlotSizes(bid) { | ||
return parseSizesInput(getAllMediaSizes(bid)); | ||
} | ||
|
||
/** | ||
* ------------------------------------ | ||
* ------------------------------------ | ||
* @param bid | ||
* @returns {*[]} | ||
*/ | ||
export function getAllMediaSizes(bid) { | ||
let playerSizes = deepAccess(bid, 'mediaTypes.video.playerSize'); | ||
let videoSizes = deepAccess(bid, 'mediaTypes.video.sizes'); | ||
let bannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes'); | ||
|
||
const sizes = []; | ||
|
||
if (isArray(playerSizes)) { | ||
playerSizes.forEach((s) => { | ||
sizes.push(s); | ||
}) | ||
} | ||
|
||
if (isArray(videoSizes)) { | ||
videoSizes.forEach((s) => { | ||
sizes.push(s); | ||
}) | ||
} | ||
|
||
if (isArray(bannerSizes)) { | ||
bannerSizes.forEach((s) => { | ||
sizes.push(s); | ||
}) | ||
} | ||
return sizes; | ||
} | ||
|
||
const getQueryVariable = (variable) => { | ||
let value = getParameterByName(variable); | ||
if (value === '') { | ||
value = null; | ||
} | ||
return value; | ||
}; | ||
|
||
/** | ||
* ------------------------------------ | ||
* ------------------------------------ | ||
* @param validBidRequests | ||
* @returns {*[]} | ||
*/ | ||
export const mapSlotsData = function(validBidRequests) { | ||
const slots = []; | ||
validBidRequests.forEach(bid => { | ||
const bidObj = {}; | ||
// get the pacement and page ids | ||
let placementId = getValue(bid.params, 'placementId'); | ||
let pageId = getValue(bid.params, 'pageId'); | ||
let adUnitElementId = getValue(bid.params, 'adUnitElementId'); | ||
// get the rest of the auction/bid/transaction info | ||
bidObj.auctionId = getBidIdParameter('auctionId', bid); | ||
bidObj.adUnitCode = getBidIdParameter('adUnitCode', bid); | ||
bidObj.adUnitElementId = adUnitElementId; | ||
bidObj.bidId = getBidIdParameter('bidId', bid); | ||
bidObj.bidderRequestId = getBidIdParameter('bidderRequestId', bid); | ||
bidObj.placementId = placementId; | ||
bidObj.pageId = pageId; | ||
bidObj.mediaTypes = getBidIdParameter('mediaTypes', bid); | ||
bidObj.transactionId = getBidIdParameter('transactionId', bid); | ||
bidObj.sizes = getSlotSizes(bid); | ||
slots.push(bidObj); | ||
}); | ||
|
||
return slots; | ||
}; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER, VIDEO], | ||
/** | ||
* 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) { | ||
bid.params = bid.params || {}; | ||
|
||
// if ad unit elemt id not provided - use adUnitCode by default | ||
if (!bid.params.adUnitElementId) { | ||
bid.params.adUnitElementId = bid.code; | ||
} | ||
|
||
if (!bid.params.placementId || !isNumber(bid.params.placementId)) { | ||
logError('placementId not provided or invalid'); | ||
return false; | ||
} | ||
|
||
if (!bid.params.pageId || !isNumber(bid.params.pageId)) { | ||
logError('pageId not provided'); | ||
return false; | ||
} | ||
|
||
return true; | ||
}, | ||
|
||
/** | ||
* ------------------------------------ | ||
* Make a server request from the | ||
* list of BidRequests. | ||
* ------------------------------------ | ||
* @param {validBidRequests[]} - an array of bids | ||
* @return ServerRequest Info describing the request to the server. | ||
*/ | ||
buildRequests: function(validBidRequests, bidderRequest) { | ||
let slots = []; | ||
let referer; | ||
try { | ||
referer = getRefererInfo().referer; | ||
slots = mapSlotsData(validBidRequests); | ||
} catch (e) { | ||
logWarn(e); | ||
} | ||
|
||
let refgroups = []; | ||
|
||
const rgQuery = getQueryVariable(CW_GROUPS_QUERY); | ||
if (rgQuery !== null) { | ||
refgroups = rgQuery.split(','); | ||
} | ||
|
||
const localStorageCWID = storage.localStorageIsEnabled() ? storage.getDataFromLocalStorage(LS_CWID_KEY) : null; | ||
|
||
const payload = { | ||
cwid: localStorageCWID, | ||
refgroups, | ||
slots: slots, | ||
httpRef: referer || '', | ||
pageViewId: CW_PAGE_VIEW_ID, | ||
}; | ||
|
||
return { | ||
method: 'POST', | ||
url: ENDPOINT_URL, | ||
data: payload | ||
}; | ||
}, | ||
|
||
/** | ||
* Unpack the response from the server into a list of bids. | ||
* | ||
* @param {ServerResponse} serverResponse A successful response from the server. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
*/ | ||
interpretResponse: function(serverResponse, bidRequest) { | ||
const bidResponses = []; | ||
|
||
try { | ||
if (typeof bidRequest.data === 'string') { | ||
bidRequest.data = JSON.parse(bidRequest.data); | ||
} | ||
const serverBody = serverResponse.body; | ||
serverBody.bids.forEach((br) => { | ||
const bidReq = find(bidRequest.data.slots, bid => bid.bidId === br.requestId); | ||
|
||
let mediaType = BANNER; | ||
|
||
const bidResponse = { | ||
requestId: br.requestId, | ||
cpm: br.cpm, | ||
bidderCode: BIDDER_CODE, | ||
width: br.dimensions[0], | ||
height: br.dimensions[1], | ||
creativeId: br.creativeId, | ||
currency: br.currency, | ||
netRevenue: br.netRevenue, | ||
ttl: br.ttl, | ||
meta: { | ||
advertiserDomains: br.adomains ? br.advertiserDomains : [], | ||
}, | ||
|
||
}; | ||
|
||
// ------------------------------------ | ||
// IF BANNER | ||
// ------------------------------------ | ||
|
||
if (deepAccess(bidReq, 'mediaTypes.banner')) { | ||
bidResponse.ad = br.html; | ||
} | ||
// ------------------------------------ | ||
// IF VIDEO | ||
// ------------------------------------ | ||
if (deepAccess(bidReq, 'mediaTypes.video')) { | ||
mediaType = VIDEO; | ||
bidResponse.vastXml = br.vastXml; | ||
bidResponse.videoScript = br.html; | ||
const mediaTypeContext = deepAccess(bidReq, 'mediaTypes.video.context'); | ||
if (mediaTypeContext === OUTSTREAM) { | ||
const r = Renderer.install({ | ||
id: bidResponse.requestId, | ||
adUnitCode: bidReq.adUnitCode, | ||
url: RENDERER_URL, | ||
loaded: false, | ||
config: { | ||
...deepAccess(bidReq, 'mediaTypes.video'), | ||
...deepAccess(br, 'outstream', {}) | ||
} | ||
}); | ||
|
||
// set renderer | ||
try { | ||
bidResponse.renderer = r; | ||
bidResponse.renderer.setRender(function(bid) { | ||
if (window.CWIRE && window.CWIRE.outstream) { | ||
window.CWIRE.outstream.renderAd(bid); | ||
} | ||
}); | ||
} catch (err) { | ||
logWarn('Prebid Error calling setRender on newRenderer', err); | ||
} | ||
} | ||
} | ||
|
||
bidResponse.mediaType = mediaType; | ||
bidResponses.push(bidResponse); | ||
}); | ||
} catch (e) { | ||
logWarn(e); | ||
} | ||
|
||
return bidResponses; | ||
}, | ||
} | ||
registerBidder(spec); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Overview | ||
|
||
Module Name: C-WIRE Bid Adapter | ||
Module Type: Adagio Adapter | ||
Maintainer: dragan@cwire.ch | ||
|
||
## Description | ||
|
||
Connects to C-WIRE demand source to fetch bids. | ||
|
||
## Configuration | ||
|
||
|
||
Below, the list of C-WIRE params and where they can be set. | ||
|
||
| Param name | Global config | AdUnit config | Type | Required | | ||
| ---------- | ------------- | ------------- | ---- | ---------| | ||
| pageId | | x | number | YES | | ||
| placementId | | x | number | YES | | ||
| adUnitElementId | | x | string | NO | | ||
|
||
### adUnit configuration | ||
|
||
```javascript | ||
var adUnits = [ | ||
{ | ||
code: 'target_div_id', // REQUIRED | ||
bids: [{ | ||
bidder: 'cwire', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[1, 1]], | ||
} | ||
}, | ||
params: { | ||
pageId: 1422, // required - number | ||
placementId: 2211521, // required - number | ||
adUnitElementId: 'other_div', // optional, div id to write to, if not set it will default to ad unit code | ||
} | ||
}] | ||
} | ||
]; | ||
``` |
Oops, something went wrong.