Skip to content

Commit c1bdd55

Browse files
acsbendirenebaudisch
authored andcommitted
Kobler adapter: remove outdated parameters, simplify testing (prebid#8445)
* Removed position parameter. * Removed zip parameter. * Removed placementId parameter and make sizes required instead. * Updated price-related macros. * Fixed error when params is not provided. * Removed last occurrence of placementId. * Read currency.adServerCurrency as publisherCurrency. * Use DEV endpoint for testing. * Use config.pageUrl when test is set to true. * Added more details about page URL. * `config.pageUrl`. * Added a comment explaining why pageUrl is considered only when testing. * Fixed double quotes in tests.
1 parent 436a5e0 commit c1bdd55

File tree

3 files changed

+226
-186
lines changed

3 files changed

+226
-186
lines changed

modules/koblerBidAdapter.js

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
1-
import { deepAccess, isStr, replaceAuctionPrice, triggerPixel, isArray, parseQueryStringParameters, getWindowSelf } from '../src/utils.js';
1+
import {
2+
deepAccess,
3+
getWindowSelf,
4+
isArray,
5+
isStr,
6+
parseQueryStringParameters,
7+
replaceAuctionPrice,
8+
triggerPixel
9+
} from '../src/utils.js';
210
import {config} from '../src/config.js';
311
import {registerBidder} from '../src/adapters/bidderFactory.js';
412
import {BANNER} from '../src/mediaTypes.js';
513
import {getRefererInfo} from '../src/refererDetection.js';
614

715
const BIDDER_CODE = 'kobler';
816
const BIDDER_ENDPOINT = 'https://bid.essrtb.com/bid/prebid_rtb_call';
17+
const DEV_BIDDER_ENDPOINT = 'https://bid-service.dev.essrtb.com/bid/prebid_rtb_call';
918
const TIMEOUT_NOTIFICATION_ENDPOINT = 'https://bid.essrtb.com/notify/prebid_timeout';
1019
const SUPPORTED_CURRENCY = 'USD';
1120
const DEFAULT_TIMEOUT = 1000;
1221
const TIME_TO_LIVE_IN_SECONDS = 10 * 60;
1322

1423
export const isBidRequestValid = function (bid) {
15-
return !!(bid && bid.bidId && bid.params && bid.params.placementId);
24+
if (!bid || !bid.bidId) {
25+
return false;
26+
}
27+
28+
const sizes = deepAccess(bid, 'mediaTypes.banner.sizes', bid.sizes);
29+
return isArray(sizes) && sizes.length > 0;
1630
};
1731

1832
export const buildRequests = function (validBidRequests, bidderRequest) {
33+
const bidderEndpoint = isTest(validBidRequests[0]) ? DEV_BIDDER_ENDPOINT : BIDDER_ENDPOINT;
1934
return {
2035
method: 'POST',
21-
url: BIDDER_ENDPOINT,
36+
url: bidderEndpoint,
2237
data: buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest),
2338
options: {
2439
contentType: 'application/json'
@@ -27,14 +42,11 @@ export const buildRequests = function (validBidRequests, bidderRequest) {
2742
};
2843

2944
export const interpretResponse = function (serverResponse) {
30-
const adServerPriceCurrency = config.getConfig('currency.adServerCurrency') || SUPPORTED_CURRENCY;
3145
const res = serverResponse.body;
3246
const bids = []
3347
if (res) {
3448
res.seatbid.forEach(sb => {
3549
sb.bid.forEach(b => {
36-
const adWithCorrectCurrency = b.adm
37-
.replace(/\${AUCTION_PRICE_CURRENCY}/g, adServerPriceCurrency);
3850
bids.push({
3951
requestId: b.impid,
4052
cpm: b.price,
@@ -45,7 +57,7 @@ export const interpretResponse = function (serverResponse) {
4557
dealId: b.dealid,
4658
netRevenue: true,
4759
ttl: TIME_TO_LIVE_IN_SECONDS,
48-
ad: adWithCorrectCurrency,
60+
ad: b.adm,
4961
nurl: b.nurl,
5062
meta: {
5163
advertiserDomains: b.adomain
@@ -58,13 +70,15 @@ export const interpretResponse = function (serverResponse) {
5870
};
5971

6072
export const onBidWon = function (bid) {
61-
const cpm = bid.cpm || 0;
62-
const cpmCurrency = bid.currency || SUPPORTED_CURRENCY;
73+
// We intentionally use the price set by the publisher to replace the ${AUCTION_PRICE} macro
74+
// instead of the `originalCpm` here. This notification is not used for billing, only for extra logging.
75+
const publisherPrice = bid.cpm || 0;
76+
const publisherCurrency = bid.currency || config.getConfig('currency.adServerCurrency') || SUPPORTED_CURRENCY;
6377
const adServerPrice = deepAccess(bid, 'adserverTargeting.hb_pb', 0);
6478
const adServerPriceCurrency = config.getConfig('currency.adServerCurrency') || SUPPORTED_CURRENCY;
6579
if (isStr(bid.nurl) && bid.nurl !== '') {
66-
const winNotificationUrl = replaceAuctionPrice(bid.nurl, bid.originalCpm || cpm)
67-
.replace(/\${AUCTION_PRICE_CURRENCY}/g, cpmCurrency)
80+
const winNotificationUrl = replaceAuctionPrice(bid.nurl, publisherPrice)
81+
.replace(/\${AUCTION_PRICE_CURRENCY}/g, publisherCurrency)
6882
.replace(/\${AD_SERVER_PRICE}/g, adServerPrice)
6983
.replace(/\${AD_SERVER_PRICE_CURRENCY}/g, adServerPriceCurrency);
7084
triggerPixel(winNotificationUrl);
@@ -73,17 +87,13 @@ export const onBidWon = function (bid) {
7387

7488
export const onTimeout = function (timeoutDataArray) {
7589
if (isArray(timeoutDataArray)) {
76-
const refererInfo = getRefererInfo();
77-
const pageUrl = (refererInfo && refererInfo.referer)
78-
? refererInfo.referer
79-
: window.location.href;
90+
const pageUrl = getPageUrlFromRefererInfo();
8091
timeoutDataArray.forEach(timeoutData => {
8192
const query = parseQueryStringParameters({
8293
ad_unit_code: timeoutData.adUnitCode,
8394
auction_id: timeoutData.auctionId,
8495
bid_id: timeoutData.bidId,
8596
timeout: timeoutData.timeout,
86-
placement_id: deepAccess(timeoutData, 'params.0.placementId'),
8797
page_url: pageUrl,
8898
});
8999
const timeoutNotificationUrl = `${TIMEOUT_NOTIFICATION_ENDPOINT}?${query}`;
@@ -92,27 +102,41 @@ export const onTimeout = function (timeoutDataArray) {
92102
}
93103
};
94104

95-
function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) {
96-
const imps = validBidRequests.map(buildOpenRtbImpObject);
97-
const timeout = bidderRequest.timeout || config.getConfig('bidderTimeout') || DEFAULT_TIMEOUT;
98-
const pageUrl = (bidderRequest.refererInfo && bidderRequest.refererInfo.referer)
105+
function getPageUrlFromRefererInfo() {
106+
const refererInfo = getRefererInfo();
107+
return (refererInfo && refererInfo.referer)
108+
? refererInfo.referer
109+
: window.location.href;
110+
}
111+
112+
function getPageUrlFromRequest(validBidRequest, bidderRequest) {
113+
// pageUrl is considered only when testing to ensure that non-test requests always contain the correct URL
114+
if (isTest(validBidRequest) && config.getConfig('pageUrl')) {
115+
return config.getConfig('pageUrl');
116+
}
117+
118+
return (bidderRequest.refererInfo && bidderRequest.refererInfo.referer)
99119
? bidderRequest.refererInfo.referer
100120
: window.location.href;
121+
}
101122

123+
function buildOpenRtbBidRequestPayload(validBidRequests, bidderRequest) {
124+
const imps = validBidRequests.map(buildOpenRtbImpObject);
125+
const timeout = bidderRequest.timeout || config.getConfig('bidderTimeout') || DEFAULT_TIMEOUT;
126+
const pageUrl = getPageUrlFromRequest(validBidRequests[0], bidderRequest)
102127
const request = {
103128
id: bidderRequest.auctionId,
104129
at: 1,
105130
tmax: timeout,
106131
cur: [SUPPORTED_CURRENCY],
107132
imp: imps,
108133
device: {
109-
devicetype: getDevice(),
110-
geo: getGeo(validBidRequests[0])
134+
devicetype: getDevice()
111135
},
112136
site: {
113137
page: pageUrl,
114138
},
115-
test: getTest(validBidRequests[0])
139+
test: getTestAsNumber(validBidRequests[0])
116140
};
117141

118142
return JSON.stringify(request);
@@ -128,14 +152,8 @@ function buildOpenRtbImpObject(validBidRequest) {
128152
banner: {
129153
format: buildFormatArray(sizes),
130154
w: mainSize[0],
131-
h: mainSize[1],
132-
ext: {
133-
kobler: {
134-
pos: getPosition(validBidRequest)
135-
}
136-
}
155+
h: mainSize[1]
137156
},
138-
tagid: validBidRequest.params.placementId,
139157
bidfloor: floorInfo.floor,
140158
bidfloorcur: floorInfo.currency,
141159
pmp: buildPmpObject(validBidRequest)
@@ -157,17 +175,12 @@ function getDevice() {
157175
return 2; // personal computers
158176
}
159177

160-
function getGeo(validBidRequest) {
161-
if (validBidRequest.params.zip) {
162-
return {
163-
zip: validBidRequest.params.zip
164-
};
165-
}
166-
return {};
178+
function getTestAsNumber(validBidRequest) {
179+
return isTest(validBidRequest) ? 1 : 0;
167180
}
168181

169-
function getTest(validBidRequest) {
170-
return validBidRequest.params.test ? 1 : 0;
182+
function isTest(validBidRequest) {
183+
return validBidRequest.params && validBidRequest.params.test === true;
171184
}
172185

173186
function getSizes(validBidRequest) {
@@ -188,10 +201,6 @@ function buildFormatArray(sizes) {
188201
});
189202
}
190203

191-
function getPosition(validBidRequest) {
192-
return parseInt(validBidRequest.params.position) || 0;
193-
}
194-
195204
function getFloorInfo(validBidRequest, mainSize) {
196205
if (typeof validBidRequest.getFloor === 'function') {
197206
const sizeParam = mainSize[0] === 0 && mainSize[1] === 0 ? '*' : mainSize;
@@ -209,11 +218,11 @@ function getFloorInfo(validBidRequest, mainSize) {
209218
}
210219

211220
function getFloorPrice(validBidRequest) {
212-
return parseFloat(validBidRequest.params.floorPrice) || 0.0;
221+
return parseFloat(deepAccess(validBidRequest, 'params.floorPrice', 0.0));
213222
}
214223

215224
function buildPmpObject(validBidRequest) {
216-
if (validBidRequest.params.dealIds) {
225+
if (validBidRequest.params && validBidRequest.params.dealIds && isArray(validBidRequest.params.dealIds)) {
217226
return {
218227
deals: validBidRequest.params.dealIds.map(dealId => {
219228
return {

modules/koblerBidAdapter.md

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ This adapter currently only supports Banner Ads.
1212

1313
# Parameters
1414

15-
| Parameter (in `params`) | Scope | Type | Description | Example |
16-
| --- | --- | --- | --- | --- |
17-
| placementId | Required | String | The identifier of the placement, it has to be issued by Kobler. | `'xjer0ch8'` |
18-
| zip | Optional | String | Zip code of the user or the medium. When multiple ad units are submitted together, it is enough to set this parameter on the first one. | `'102 22'` |
19-
| test | Optional | Boolean | Whether the request is for testing only. When multiple ad units are submitted together, it is enough to set this parameter on the first one. Defaults to false. | `true` |
20-
| floorPrice | Optional | Float | Floor price in CPM and USD. Can be used as an alternative to the [Floors module](https://docs.prebid.org/dev-docs/modules/floors.html), which is also supported by this adapter. Defaults to 0. | `5.0` |
21-
| position | Optional | Integer | The position of the ad unit. Can be used to differentiate between ad units if the same placement ID is used across multiple ad units. The first ad unit should have a `position` of 0, the second one should have a `position` of 1 and so on. Defaults to 0. | `1` |
22-
| dealIds | Optional | Array of Strings | Array of deal IDs. | `['abc328745', 'mxw243253']` |
15+
| Parameter (in `params`) | Scope | Type | Description | Example |
16+
|-------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|
17+
| test | Optional | Boolean | Whether the request is for testing only. When multiple ad units are submitted together, it is enough to set this parameter on the first one. Enables providing a custom URL through config.pageUrl. Defaults to false. | `true` |
18+
| floorPrice | Optional | Float | Floor price in CPM and USD. Can be used as an alternative to the [Floors module](https://docs.prebid.org/dev-docs/modules/floors.html), which is also supported by this adapter. Defaults to 0. | `5.0` |
19+
| dealIds | Optional | Array of Strings | Array of deal IDs. | `['abc328745', 'mxw243253']` |
20+
21+
## Implicit parameters
22+
23+
Kobler identifies the placement using the combination of the page URL and the allowed sizes. As a result, it's important that the correct sizes are provided in `banner.sizes` in order for Kobler to correctly identify the placement. The main, desired format should be the first element of this array.
2324

2425
# Test Parameters
2526
```javascript
@@ -31,17 +32,14 @@ This adapter currently only supports Banner Ads.
3132
}
3233
},
3334
bids: [{
34-
bidder: 'kobler',
35-
params: {
36-
placementId: 'k5H7et3R0'
37-
}
35+
bidder: 'kobler'
3836
}]
3937
}];
4038
```
4139

4240
In order to see a sample bid from Kobler (without a proper setup), you have to also do the following:
43-
- Change the [`refererInfo` function](https://github.com/prebid/Prebid.js/blob/master/src/refererDetection.js) to return `'https://www.tv2.no/a/11734615'` as a [`referer`](https://github.com/prebid/Prebid.js/blob/caead3ccccc448e4cd09d074fd9f8833f56fe9b3/src/refererDetection.js#L169). This is necessary because Kobler only bids on recognized articles.
44-
- Change the adapter's [`BIDDER_ENDPOINT`](https://github.com/prebid/Prebid.js/blob/master/modules/koblerBidAdapter.js#L8) to `'https://bid-service.dev.essrtb.com/bid/prebid_rtb_call'`. This endpoint belongs to the development server that is set up to always return a bid for the correct `placementId` and page URL combination.
41+
- Set the `test` parameter to `true`.
42+
- Set `config.pageUrl` to `'https://www.tv2.no/mening-og-analyse/14555348/'`. This is necessary because Kobler only bids on recognized articles. Kobler runs its own test campaign to make sure there is always a bid for this specific page URL.
4543

4644
# Test Optional Parameters
4745
```javascript
@@ -55,11 +53,8 @@ In order to see a sample bid from Kobler (without a proper setup), you have to a
5553
bids: [{
5654
bidder: 'kobler',
5755
params: {
58-
placementId: 'k5H7et3R0',
59-
zip: '102 22',
6056
test: true,
6157
floorPrice: 5.0,
62-
position: 1,
6358
dealIds: ['abc328745', 'mxw243253']
6459
}
6560
}]

0 commit comments

Comments
 (0)