prebid.js 6.8.0 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +8 -1
- package/integrationExamples/gpt/weboramaRtdProvider_example.html +154 -115
- package/integrationExamples/gpt/x-domain/creative.html +13 -6
- package/modules/appnexusBidAdapter.js +3 -2
- package/modules/asealBidAdapter.js +58 -0
- package/modules/asealBidAdapter.md +52 -0
- package/modules/conversantBidAdapter.js +7 -0
- package/modules/improvedigitalBidAdapter.js +5 -0
- package/modules/lunamediahbBidAdapter.js +32 -4
- package/modules/oguryBidAdapter.js +6 -13
- package/modules/priceFloors.js +2 -1
- package/modules/richaudienceBidAdapter.js +7 -2
- package/modules/riseBidAdapter.js +17 -6
- package/modules/rubiconAnalyticsAdapter.js +5 -0
- package/modules/sortableAnalyticsAdapter.js +5 -4
- package/modules/weboramaRtdProvider.js +264 -34
- package/modules/weboramaRtdProvider.md +110 -40
- package/package.json +2 -1
- package/src/adloader.js +2 -1
- package/src/auction.js +59 -64
- package/src/bidderSettings.js +69 -0
- package/src/secureCreatives.js +26 -12
- package/src/targeting.js +3 -2
- package/src/utils.js +0 -7
- package/test/spec/auctionmanager_spec.js +33 -1
- package/test/spec/modules/asealBidAdapter_spec.js +144 -0
- package/test/spec/modules/conversantBidAdapter_spec.js +54 -2
- package/test/spec/modules/improvedigitalBidAdapter_spec.js +19 -0
- package/test/spec/modules/lunamediahbBidAdapter_spec.js +27 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +62 -4
- package/test/spec/modules/riseBidAdapter_spec.js +30 -4
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +31 -1
- package/test/spec/modules/sortableAnalyticsAdapter_spec.js +2 -3
- package/test/spec/modules/weboramaRtdProvider_spec.js +536 -20
- package/test/spec/unit/core/bidderSettings_spec.js +123 -0
- package/test/spec/unit/pbjs_api_spec.js +1 -6
- package/test/spec/unit/secureCreatives_spec.js +66 -32
|
@@ -21,40 +21,51 @@ Compile the Weborama RTD module into your Prebid build:
|
|
|
21
21
|
Add the Weborama RTD provider to your Prebid config.
|
|
22
22
|
|
|
23
23
|
```javascript
|
|
24
|
-
pbjs
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
var pbjs = pbjs || {};
|
|
25
|
+
pbjs.que = pbjs.que || [];
|
|
26
|
+
|
|
27
|
+
pbjs.que.push(function () {
|
|
28
|
+
pbjs.setConfig({
|
|
29
|
+
debug: true,
|
|
30
|
+
realTimeData: {
|
|
31
|
+
auctionDelay: 1000,
|
|
32
|
+
dataProviders: [{
|
|
30
33
|
name: "weborama",
|
|
31
34
|
waitForIt: true,
|
|
32
35
|
params: {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
defaultProfile: { // optional, default is none
|
|
39
|
-
webo_ctx: ['foo'],
|
|
40
|
-
webo_ds: ['bar']
|
|
41
|
-
}
|
|
36
|
+
setPrebidTargeting: true, // optional
|
|
37
|
+
sendToBidders: true, // optional
|
|
38
|
+
onData: function(data, site){ // optional
|
|
39
|
+
var kind = (site)? 'site' : 'user';
|
|
40
|
+
console.log('onData', kind, data);
|
|
42
41
|
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
weboCtxConf: {
|
|
43
|
+
token: "to-be-defined", // mandatory
|
|
44
|
+
targetURL: "https://prebid.org", // default is document.URL
|
|
45
|
+
setPrebidTargeting: true, // override param.setPrebidTargeting or default true
|
|
46
|
+
sendToBidders: true, // override param.sendToBidders or default true
|
|
47
|
+
defaultProfile: { // optional
|
|
48
|
+
webo_ctx: ['moon'],
|
|
49
|
+
webo_ds: ['bar']
|
|
50
|
+
}
|
|
51
|
+
//, onData: function (data, ...) { ...}
|
|
52
|
+
},
|
|
53
|
+
weboUserDataConf: {
|
|
54
|
+
accountId: 12345, // optional, used for logging
|
|
55
|
+
setPrebidTargeting: true, // override param.setPrebidTargeting or default true
|
|
56
|
+
sendToBidders: true, // override param.sendToBidders or default true
|
|
57
|
+
defaultProfile: { // optional
|
|
58
|
+
webo_cs: ['Red'],
|
|
59
|
+
webo_audiences: ['bam']
|
|
60
|
+
},
|
|
61
|
+
localStorageProfileKey: 'webo_wam2gam_entry' // default
|
|
62
|
+
//, onData: function (data, ...) { ...}
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
);
|
|
65
|
+
}]
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
58
69
|
```
|
|
59
70
|
|
|
60
71
|
### Parameter Descriptions for the Weborama Configuration Section
|
|
@@ -64,23 +75,82 @@ pbjs.setConfig(
|
|
|
64
75
|
| name | String | Real time data module name | Mandatory. Always 'Weborama' |
|
|
65
76
|
| waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true |
|
|
66
77
|
| params | Object | | Optional |
|
|
67
|
-
| params.
|
|
68
|
-
| params.
|
|
69
|
-
| params.weboCtxConf
|
|
70
|
-
| params.
|
|
71
|
-
| params.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
+
| params.setPrebidTargeting | Boolean | If true, may use the profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections |
|
|
79
|
+
| params.sendToBidders | Boolean | If true, may send the profile to all bidders | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections |
|
|
80
|
+
| params.weboCtxConf | Object | Weborama Contextual Configuration | Optional
|
|
81
|
+
| params.weboUserDataConf | Object | Weborama User-Centric Configuration | Optional |
|
|
82
|
+
| params.onData | Callback | If set, will receive the profile and site flag | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections |
|
|
83
|
+
|
|
84
|
+
#### Contextual Configuration
|
|
85
|
+
|
|
86
|
+
| Name |Type | Description | Notes |
|
|
87
|
+
| :------------ | :------------ | :------------ |:------------ |
|
|
88
|
+
| token | String | Security Token provided by Weborama, unique per client | Mandatory |
|
|
89
|
+
| targetURL | String | Url to be profiled in the contextual api | Optional. Defaults to `document.URL` |
|
|
90
|
+
| setPrebidTargeting|Boolean|If true, will use the contextual profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.|
|
|
91
|
+
| sendToBidders|Boolean|If true, will send the contextual profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.|
|
|
92
|
+
| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` |
|
|
93
|
+
| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug |
|
|
94
|
+
| enabled | Boolean| if false, will ignore this configuration| default true|
|
|
95
|
+
|
|
96
|
+
#### User-Centric Configuration
|
|
97
|
+
|
|
98
|
+
| Name |Type | Description | Notes |
|
|
99
|
+
| :------------ | :------------ | :------------ |:------------ |
|
|
100
|
+
| accountId|Number|WAM account id. If present, will be used on logging and statistics| Optional.|
|
|
101
|
+
| setPrebidTargeting|Boolean|If true, will use the user profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.|
|
|
102
|
+
| sendToBidders|Boolean|If true, will send the user profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.|
|
|
103
|
+
| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug |
|
|
104
|
+
| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` |
|
|
105
|
+
| localStorageProfileKey| String | can be used to customize the local storage key | Optional |
|
|
106
|
+
| enabled | Boolean| if false, will ignore this configuration| default true|
|
|
107
|
+
|
|
108
|
+
### Supported Bidders
|
|
109
|
+
|
|
110
|
+
We currently support the following bidder adapters:
|
|
111
|
+
* SmartADServer SSP
|
|
112
|
+
* PubMatic SSP
|
|
113
|
+
* AppNexus SSP
|
|
114
|
+
* Rubicon SSP
|
|
115
|
+
|
|
116
|
+
We also set the bidder and global ortb2 `site` and `user` sections. The following bidders may support it, to be sure, check the `First Party Data Support` on the feature list for the particular bidder from here: https://docs.prebid.org/dev-docs/bidders
|
|
117
|
+
|
|
118
|
+
* Adagio
|
|
119
|
+
* AdformOpenRTB
|
|
120
|
+
* AdKernel
|
|
121
|
+
* AdMixer
|
|
122
|
+
* Adnuntius
|
|
123
|
+
* Adrelevantis
|
|
124
|
+
* adxcg
|
|
125
|
+
* AMX RTB
|
|
126
|
+
* Avocet
|
|
127
|
+
* BeOp
|
|
128
|
+
* Criteo
|
|
129
|
+
* Etarget
|
|
130
|
+
* Inmar
|
|
131
|
+
* Index Exchange
|
|
132
|
+
* Livewrapped
|
|
133
|
+
* Mediakeys
|
|
134
|
+
* NoBid
|
|
135
|
+
* OpenX
|
|
136
|
+
* Opt Out Advertising
|
|
137
|
+
* Ozone Project
|
|
138
|
+
* Proxistore
|
|
139
|
+
* Rise
|
|
140
|
+
* Smaato
|
|
141
|
+
* Sonobi
|
|
142
|
+
* TheMediaGrid
|
|
143
|
+
* TripleLift
|
|
144
|
+
* TrustX
|
|
145
|
+
* Yahoo SSP
|
|
146
|
+
* Yieldlab
|
|
147
|
+
* Zeta Global Ssp
|
|
78
148
|
|
|
79
149
|
### Testing
|
|
80
150
|
|
|
81
151
|
To view an example of available segments returned by Weborama's backends:
|
|
82
152
|
|
|
83
|
-
`gulp serve --modules=rtdModule,weboramaRtdProvider,smartadserverBidAdapter`
|
|
153
|
+
`gulp serve --notest --nolint --modules=rtdModule,weboramaRtdProvider,smartadserverBidAdapter,pubmaticBidAdapter,appnexusBidAdapter,rubiconBidAdapter,criteoBidAdapter`
|
|
84
154
|
|
|
85
155
|
and then point your browser at:
|
|
86
156
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prebid.js",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.0",
|
|
4
4
|
"description": "Header Bidding Management Library",
|
|
5
5
|
"main": "src/prebid.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@babel/core": "^7.8.4",
|
|
33
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
33
34
|
"@babel/preset-env": "^7.8.4",
|
|
34
35
|
"@jsdevtools/coverage-istanbul-loader": "^3.0.3",
|
|
35
36
|
"@wdio/browserstack-service": "^6.1.4",
|
package/src/adloader.js
CHANGED
package/src/auction.js
CHANGED
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
|
|
60
60
|
import {
|
|
61
61
|
flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue, parseUrl, generateUUID,
|
|
62
|
-
logMessage, bind, logError, logInfo, logWarn, isEmpty, _each, isFn, isEmptyStr
|
|
62
|
+
logMessage, bind, logError, logInfo, logWarn, isEmpty, _each, isFn, isEmptyStr
|
|
63
63
|
} from './utils.js';
|
|
64
64
|
import { getPriceBucketString } from './cpmBucketManager.js';
|
|
65
65
|
import { getNativeTargeting } from './native.js';
|
|
@@ -72,6 +72,7 @@ import find from 'core-js-pure/features/array/find.js';
|
|
|
72
72
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
73
73
|
import { OUTSTREAM } from './video.js';
|
|
74
74
|
import { VIDEO } from './mediaTypes.js';
|
|
75
|
+
import {bidderSettings} from './bidderSettings.js';
|
|
75
76
|
|
|
76
77
|
const { syncUsers } = userSync;
|
|
77
78
|
|
|
@@ -602,7 +603,7 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) {
|
|
|
602
603
|
|
|
603
604
|
function setupBidTargeting(bidObject, bidderRequest) {
|
|
604
605
|
let keyValues;
|
|
605
|
-
const cpmCheck = (
|
|
606
|
+
const cpmCheck = (bidderSettings.get(bidObject.bidderCode, 'allowZeroCpmBids') === true) ? bidObject.cpm >= 0 : bidObject.cpm > 0;
|
|
606
607
|
if (bidObject.bidderCode && (cpmCheck || bidObject.dealId)) {
|
|
607
608
|
let bidReq = find(bidderRequest.bids, bid => bid.adUnitCode === bidObject.adUnitCode && bid.bidId === bidObject.requestId);
|
|
608
609
|
keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq);
|
|
@@ -650,18 +651,18 @@ export const getPriceGranularity = (mediaType, bidReq) => {
|
|
|
650
651
|
*/
|
|
651
652
|
export const getPriceByGranularity = (granularity) => {
|
|
652
653
|
return (bid, bidReq) => {
|
|
653
|
-
|
|
654
|
-
if (
|
|
654
|
+
const bidGranularity = granularity || getPriceGranularity(bid.mediaType, bidReq);
|
|
655
|
+
if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) {
|
|
655
656
|
return bid.pbAg;
|
|
656
|
-
} else if (
|
|
657
|
+
} else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) {
|
|
657
658
|
return bid.pbDg;
|
|
658
|
-
} else if (
|
|
659
|
+
} else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) {
|
|
659
660
|
return bid.pbLg;
|
|
660
|
-
} else if (
|
|
661
|
+
} else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) {
|
|
661
662
|
return bid.pbMg;
|
|
662
|
-
} else if (
|
|
663
|
+
} else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) {
|
|
663
664
|
return bid.pbHg;
|
|
664
|
-
} else if (
|
|
665
|
+
} else if (bidGranularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) {
|
|
665
666
|
return bid.pbCg;
|
|
666
667
|
}
|
|
667
668
|
}
|
|
@@ -677,6 +678,34 @@ export const getAdvertiserDomain = () => {
|
|
|
677
678
|
}
|
|
678
679
|
}
|
|
679
680
|
|
|
681
|
+
// factory for key value objs
|
|
682
|
+
function createKeyVal(key, value) {
|
|
683
|
+
return {
|
|
684
|
+
key,
|
|
685
|
+
val: (typeof value === 'function')
|
|
686
|
+
? function (bidResponse, bidReq) {
|
|
687
|
+
return value(bidResponse, bidReq);
|
|
688
|
+
}
|
|
689
|
+
: function (bidResponse) {
|
|
690
|
+
return getValue(bidResponse, value);
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function defaultAdserverTargeting() {
|
|
696
|
+
const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS;
|
|
697
|
+
return [
|
|
698
|
+
createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'),
|
|
699
|
+
createKeyVal(TARGETING_KEYS.AD_ID, 'adId'),
|
|
700
|
+
createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity()),
|
|
701
|
+
createKeyVal(TARGETING_KEYS.SIZE, 'size'),
|
|
702
|
+
createKeyVal(TARGETING_KEYS.DEAL, 'dealId'),
|
|
703
|
+
createKeyVal(TARGETING_KEYS.SOURCE, 'source'),
|
|
704
|
+
createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'),
|
|
705
|
+
createKeyVal(TARGETING_KEYS.ADOMAIN, getAdvertiserDomain()),
|
|
706
|
+
]
|
|
707
|
+
}
|
|
708
|
+
|
|
680
709
|
/**
|
|
681
710
|
* @param {string} mediaType
|
|
682
711
|
* @param {string} bidderCode
|
|
@@ -684,40 +713,16 @@ export const getAdvertiserDomain = () => {
|
|
|
684
713
|
* @returns {*}
|
|
685
714
|
*/
|
|
686
715
|
export function getStandardBidderSettings(mediaType, bidderCode) {
|
|
687
|
-
// factory for key value objs
|
|
688
|
-
function createKeyVal(key, value) {
|
|
689
|
-
return {
|
|
690
|
-
key,
|
|
691
|
-
val: (typeof value === 'function')
|
|
692
|
-
? function (bidResponse, bidReq) {
|
|
693
|
-
return value(bidResponse, bidReq);
|
|
694
|
-
}
|
|
695
|
-
: function (bidResponse) {
|
|
696
|
-
return getValue(bidResponse, value);
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
716
|
const TARGETING_KEYS = CONSTANTS.TARGETING_KEYS;
|
|
717
|
+
const standardSettings = Object.assign({}, bidderSettings.settingsFor(null));
|
|
701
718
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {};
|
|
705
|
-
}
|
|
706
|
-
if (!bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) {
|
|
707
|
-
bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [
|
|
708
|
-
createKeyVal(TARGETING_KEYS.BIDDER, 'bidderCode'),
|
|
709
|
-
createKeyVal(TARGETING_KEYS.AD_ID, 'adId'),
|
|
710
|
-
createKeyVal(TARGETING_KEYS.PRICE_BUCKET, getPriceByGranularity()),
|
|
711
|
-
createKeyVal(TARGETING_KEYS.SIZE, 'size'),
|
|
712
|
-
createKeyVal(TARGETING_KEYS.DEAL, 'dealId'),
|
|
713
|
-
createKeyVal(TARGETING_KEYS.SOURCE, 'source'),
|
|
714
|
-
createKeyVal(TARGETING_KEYS.FORMAT, 'mediaType'),
|
|
715
|
-
createKeyVal(TARGETING_KEYS.ADOMAIN, getAdvertiserDomain()),
|
|
716
|
-
]
|
|
719
|
+
if (!standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) {
|
|
720
|
+
standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = defaultAdserverTargeting();
|
|
717
721
|
}
|
|
718
722
|
|
|
719
723
|
if (mediaType === 'video') {
|
|
720
|
-
const adserverTargeting =
|
|
724
|
+
const adserverTargeting = standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING].slice();
|
|
725
|
+
standardSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = adserverTargeting;
|
|
721
726
|
|
|
722
727
|
// Adding hb_uuid + hb_cache_id
|
|
723
728
|
[TARGETING_KEYS.UUID, TARGETING_KEYS.CACHE_ID].forEach(targetingKeyVal => {
|
|
@@ -727,7 +732,7 @@ export function getStandardBidderSettings(mediaType, bidderCode) {
|
|
|
727
732
|
});
|
|
728
733
|
|
|
729
734
|
// Adding hb_cache_host
|
|
730
|
-
if (config.getConfig('cache.url') && (!bidderCode ||
|
|
735
|
+
if (config.getConfig('cache.url') && (!bidderCode || bidderSettings.get(bidderCode, 'sendStandardTargeting') !== false)) {
|
|
731
736
|
const urlInfo = parseUrl(config.getConfig('cache.url'));
|
|
732
737
|
|
|
733
738
|
if (typeof find(adserverTargeting, targetingKeyVal => targetingKeyVal.key === TARGETING_KEYS.CACHE_HOST) === 'undefined') {
|
|
@@ -738,7 +743,7 @@ export function getStandardBidderSettings(mediaType, bidderCode) {
|
|
|
738
743
|
}
|
|
739
744
|
}
|
|
740
745
|
}
|
|
741
|
-
return
|
|
746
|
+
return standardSettings;
|
|
742
747
|
}
|
|
743
748
|
|
|
744
749
|
export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
|
|
@@ -747,19 +752,15 @@ export function getKeyValueTargetingPairs(bidderCode, custBidObj, bidReq) {
|
|
|
747
752
|
}
|
|
748
753
|
|
|
749
754
|
var keyValues = {};
|
|
750
|
-
var bidderSettings = $$PREBID_GLOBAL$$.bidderSettings;
|
|
751
755
|
|
|
752
756
|
// 1) set the keys from "standard" setting or from prebid defaults
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
setKeys(keyValues, bidderSettings[bidderCode], custBidObj, bidReq);
|
|
761
|
-
custBidObj.sendStandardTargeting = bidderSettings[bidderCode].sendStandardTargeting;
|
|
762
|
-
}
|
|
757
|
+
const standardSettings = getStandardBidderSettings(custBidObj.mediaType, bidderCode);
|
|
758
|
+
setKeys(keyValues, standardSettings, custBidObj, bidReq);
|
|
759
|
+
|
|
760
|
+
// 2) set keys from specific bidder setting override if they exist
|
|
761
|
+
if (bidderCode && bidderSettings.getOwn(bidderCode, CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING)) {
|
|
762
|
+
setKeys(keyValues, bidderSettings.ownSettingsFor(bidderCode), custBidObj, bidReq);
|
|
763
|
+
custBidObj.sendStandardTargeting = bidderSettings.get(bidderCode, 'sendStandardTargeting');
|
|
763
764
|
}
|
|
764
765
|
|
|
765
766
|
// set native key value targeting
|
|
@@ -811,19 +812,13 @@ function setKeys(keyValues, bidderSettings, custBidObj, bidReq) {
|
|
|
811
812
|
export function adjustBids(bid) {
|
|
812
813
|
let code = bid.bidderCode;
|
|
813
814
|
let bidPriceAdjusted = bid.cpm;
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (bidCpmAdjustment) {
|
|
822
|
-
try {
|
|
823
|
-
bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid));
|
|
824
|
-
} catch (e) {
|
|
825
|
-
logError('Error during bid adjustment', 'bidmanager.js', e);
|
|
826
|
-
}
|
|
815
|
+
const bidCpmAdjustment = bidderSettings.get(code || null, 'bidCpmAdjustment');
|
|
816
|
+
|
|
817
|
+
if (bidCpmAdjustment && typeof bidCpmAdjustment === 'function') {
|
|
818
|
+
try {
|
|
819
|
+
bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid));
|
|
820
|
+
} catch (e) {
|
|
821
|
+
logError('Error during bid adjustment', 'bidmanager.js', e);
|
|
827
822
|
}
|
|
828
823
|
}
|
|
829
824
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {deepAccess, mergeDeep} from './utils.js';
|
|
2
|
+
import {getGlobal} from './prebidGlobal.js';
|
|
3
|
+
|
|
4
|
+
const CONSTANTS = require('./constants.json');
|
|
5
|
+
|
|
6
|
+
export class ScopedSettings {
|
|
7
|
+
constructor(getSettings, defaultScope) {
|
|
8
|
+
this.getSettings = getSettings;
|
|
9
|
+
this.defaultScope = defaultScope;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get setting value at `path` under the given scope, falling back to the default scope if needed.
|
|
14
|
+
* If `scope` is `null`, get the setting's default value.
|
|
15
|
+
* @param scope {String|null}
|
|
16
|
+
* @param path {String}
|
|
17
|
+
* @returns {*}
|
|
18
|
+
*/
|
|
19
|
+
get(scope, path) {
|
|
20
|
+
let value = this.getOwn(scope, path);
|
|
21
|
+
if (typeof value === 'undefined') {
|
|
22
|
+
value = this.getOwn(null, path);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the setting value at `path` *without* falling back to the default value.
|
|
29
|
+
* @param scope {String}
|
|
30
|
+
* @param path {String}
|
|
31
|
+
* @returns {*}
|
|
32
|
+
*/
|
|
33
|
+
getOwn(scope, path) {
|
|
34
|
+
scope = this.#resolveScope(scope);
|
|
35
|
+
return deepAccess(this.getSettings(), `${scope}.${path}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @returns {string[]} all existing scopes except the default one.
|
|
40
|
+
*/
|
|
41
|
+
getScopes() {
|
|
42
|
+
return Object.keys(this.getSettings()).filter((scope) => scope !== this.defaultScope);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @returns all settings in the given scope, merged with the settings for the default scope.
|
|
47
|
+
*/
|
|
48
|
+
settingsFor(scope) {
|
|
49
|
+
return mergeDeep({}, this.ownSettingsFor(null), this.ownSettingsFor(scope));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @returns all settings in the given scope, *without* any of the default settings.
|
|
54
|
+
*/
|
|
55
|
+
ownSettingsFor(scope) {
|
|
56
|
+
scope = this.#resolveScope(scope);
|
|
57
|
+
return this.getSettings()[scope] || {};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#resolveScope(scope) {
|
|
61
|
+
if (scope == null) {
|
|
62
|
+
return this.defaultScope;
|
|
63
|
+
} else {
|
|
64
|
+
return scope;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const bidderSettings = new ScopedSettings(() => getGlobal().bidderSettings || {}, CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD);
|
package/src/secureCreatives.js
CHANGED
|
@@ -27,6 +27,24 @@ export function listenMessagesFromCreative() {
|
|
|
27
27
|
window.addEventListener('message', receiveMessage, false);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
export function getReplier(ev) {
|
|
31
|
+
if (ev.origin == null && ev.ports.length === 0) {
|
|
32
|
+
return function () {
|
|
33
|
+
const msg = 'Cannot post message to a frame with null origin. Please update creatives to use MessageChannel, see https://github.com/prebid/Prebid.js/issues/7870'
|
|
34
|
+
logError(msg)
|
|
35
|
+
throw new Error(msg);
|
|
36
|
+
}
|
|
37
|
+
} else if (ev.ports.length > 0) {
|
|
38
|
+
return function (message) {
|
|
39
|
+
ev.ports[0].postMessage(JSON.stringify(message));
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
return function (message) {
|
|
43
|
+
ev.source.postMessage(JSON.stringify(message), ev.origin);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
30
48
|
export function receiveMessage(ev) {
|
|
31
49
|
var key = ev.message ? 'message' : 'data';
|
|
32
50
|
var data = {};
|
|
@@ -41,12 +59,12 @@ export function receiveMessage(ev) {
|
|
|
41
59
|
return bid.adId === data.adId;
|
|
42
60
|
});
|
|
43
61
|
if (HANDLER_MAP.hasOwnProperty(data.message)) {
|
|
44
|
-
HANDLER_MAP[data.message](ev, data, adObject);
|
|
62
|
+
HANDLER_MAP[data.message](getReplier(ev), data, adObject);
|
|
45
63
|
}
|
|
46
64
|
}
|
|
47
65
|
}
|
|
48
66
|
|
|
49
|
-
function handleRenderRequest(
|
|
67
|
+
function handleRenderRequest(reply, data, adObject) {
|
|
50
68
|
if (adObject == null) {
|
|
51
69
|
emitAdRenderFail({
|
|
52
70
|
reason: constants.AD_RENDER_FAILED_REASON.CANNOT_FIND_AD,
|
|
@@ -64,7 +82,7 @@ function handleRenderRequest(ev, data, adObject) {
|
|
|
64
82
|
}
|
|
65
83
|
|
|
66
84
|
try {
|
|
67
|
-
_sendAdToCreative(adObject,
|
|
85
|
+
_sendAdToCreative(adObject, reply);
|
|
68
86
|
} catch (e) {
|
|
69
87
|
emitAdRenderFail({
|
|
70
88
|
reason: constants.AD_RENDER_FAILED_REASON.EXCEPTION,
|
|
@@ -81,7 +99,7 @@ function handleRenderRequest(ev, data, adObject) {
|
|
|
81
99
|
events.emit(BID_WON, adObject);
|
|
82
100
|
}
|
|
83
101
|
|
|
84
|
-
function handleNativeRequest(
|
|
102
|
+
function handleNativeRequest(reply, data, adObject) {
|
|
85
103
|
// handle this script from native template in an ad server
|
|
86
104
|
// window.parent.postMessage(JSON.stringify({
|
|
87
105
|
// message: 'Prebid Native',
|
|
@@ -111,13 +129,9 @@ function handleNativeRequest(ev, data, adObject) {
|
|
|
111
129
|
auctionManager.addWinningBid(adObject);
|
|
112
130
|
events.emit(BID_WON, adObject);
|
|
113
131
|
}
|
|
114
|
-
|
|
115
|
-
function reply(message) {
|
|
116
|
-
ev.source.postMessage(JSON.stringify(message), ev.origin);
|
|
117
|
-
}
|
|
118
132
|
}
|
|
119
133
|
|
|
120
|
-
function handleEventRequest(
|
|
134
|
+
function handleEventRequest(reply, data, adObject) {
|
|
121
135
|
if (adObject == null) {
|
|
122
136
|
logError(`Cannot find ad '${data.adId}' for x-origin event request`);
|
|
123
137
|
return;
|
|
@@ -147,21 +161,21 @@ function handleEventRequest(ev, data, adObject) {
|
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
|
|
150
|
-
export function _sendAdToCreative(adObject,
|
|
164
|
+
export function _sendAdToCreative(adObject, reply) {
|
|
151
165
|
const { adId, ad, adUrl, width, height, renderer, cpm } = adObject;
|
|
152
166
|
// rendering for outstream safeframe
|
|
153
167
|
if (isRendererRequired(renderer)) {
|
|
154
168
|
executeRenderer(renderer, adObject);
|
|
155
169
|
} else if (adId) {
|
|
156
170
|
resizeRemoteCreative(adObject);
|
|
157
|
-
|
|
171
|
+
reply({
|
|
158
172
|
message: 'Prebid Response',
|
|
159
173
|
ad: replaceAuctionPrice(ad, cpm),
|
|
160
174
|
adUrl: replaceAuctionPrice(adUrl, cpm),
|
|
161
175
|
adId,
|
|
162
176
|
width,
|
|
163
177
|
height
|
|
164
|
-
})
|
|
178
|
+
});
|
|
165
179
|
}
|
|
166
180
|
}
|
|
167
181
|
|
package/src/targeting.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp,
|
|
3
|
-
deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr,
|
|
3
|
+
deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr,
|
|
4
4
|
} from './utils.js';
|
|
5
5
|
import { config } from './config.js';
|
|
6
6
|
import { NATIVE_TARGETING_KEYS } from './native.js';
|
|
@@ -8,6 +8,7 @@ import { auctionManager } from './auctionManager.js';
|
|
|
8
8
|
import { sizeSupported } from './sizeMapping.js';
|
|
9
9
|
import { ADPOD } from './mediaTypes.js';
|
|
10
10
|
import { hook } from './hook.js';
|
|
11
|
+
import { bidderSettings } from './bidderSettings.js';
|
|
11
12
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
12
13
|
import find from 'core-js-pure/features/array/find.js';
|
|
13
14
|
|
|
@@ -459,7 +460,7 @@ export function newTargeting(auctionManager) {
|
|
|
459
460
|
const adUnitCodes = getAdUnitCodes(adUnitCode);
|
|
460
461
|
return bidsReceived
|
|
461
462
|
.filter(bid => includes(adUnitCodes, bid.adUnitCode))
|
|
462
|
-
.filter(bid => (
|
|
463
|
+
.filter(bid => (bidderSettings.get(bid.bidderCode, 'allowZeroCpmBids') === true) ? bid.cpm >= 0 : bid.cpm > 0)
|
|
463
464
|
.map(bid => bid.adUnitCode)
|
|
464
465
|
.filter(uniques)
|
|
465
466
|
.map(adUnitCode => bidsReceived
|
package/src/utils.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { config } from './config.js';
|
|
3
|
-
import { getGlobal } from './prebidGlobal.js';
|
|
4
3
|
import clone from 'just-clone';
|
|
5
4
|
import find from 'core-js-pure/features/array/find.js';
|
|
6
5
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
@@ -1343,9 +1342,3 @@ export function cyrb53Hash(str, seed = 0) {
|
|
|
1343
1342
|
h2 = imul(h2 ^ (h2 >>> 16), 2246822507) ^ imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
1344
1343
|
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
|
|
1345
1344
|
}
|
|
1346
|
-
|
|
1347
|
-
export function isAllowZeroCpmBidsEnabled(bidderCode) {
|
|
1348
|
-
const bidderSettings = getGlobal().bidderSettings;
|
|
1349
|
-
return ((bidderSettings[bidderCode] && bidderSettings[bidderCode].allowZeroCpmBids === true) ||
|
|
1350
|
-
(bidderSettings.standard && bidderSettings.standard.allowZeroCpmBids === true));
|
|
1351
|
-
}
|
|
@@ -3,7 +3,9 @@ import {
|
|
|
3
3
|
auctionCallbacks,
|
|
4
4
|
AUCTION_COMPLETED,
|
|
5
5
|
adjustBids,
|
|
6
|
-
getMediaTypeGranularity,
|
|
6
|
+
getMediaTypeGranularity,
|
|
7
|
+
getPriceByGranularity,
|
|
8
|
+
addBidResponse
|
|
7
9
|
} from 'src/auction.js';
|
|
8
10
|
import CONSTANTS from 'src/constants.json';
|
|
9
11
|
import * as auctionModule from 'src/auction.js';
|
|
@@ -1280,6 +1282,36 @@ describe('auctionmanager.js', function () {
|
|
|
1280
1282
|
});
|
|
1281
1283
|
});
|
|
1282
1284
|
|
|
1285
|
+
describe('getPriceByGranularity', () => {
|
|
1286
|
+
beforeEach(() => {
|
|
1287
|
+
config.setConfig({
|
|
1288
|
+
mediaTypePriceGranularity: {
|
|
1289
|
+
video: 'medium',
|
|
1290
|
+
banner: 'low'
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
})
|
|
1294
|
+
|
|
1295
|
+
afterEach(() => {
|
|
1296
|
+
config.resetConfig();
|
|
1297
|
+
})
|
|
1298
|
+
|
|
1299
|
+
it('evaluates undef granularity on each call', () => {
|
|
1300
|
+
const gpbg = getPriceByGranularity();
|
|
1301
|
+
expect(gpbg({
|
|
1302
|
+
mediaType: 'video', pbMg: 'medium'
|
|
1303
|
+
}, {
|
|
1304
|
+
'mediaTypes': {video: {id: '1'}}
|
|
1305
|
+
})).to.equal('medium');
|
|
1306
|
+
expect(gpbg({
|
|
1307
|
+
mediaType: 'banner',
|
|
1308
|
+
pbLg: 'low'
|
|
1309
|
+
}, {
|
|
1310
|
+
'mediaTypes': {banner: {}}
|
|
1311
|
+
})).to.equal('low');
|
|
1312
|
+
});
|
|
1313
|
+
})
|
|
1314
|
+
|
|
1283
1315
|
describe('auctionCallbacks', function() {
|
|
1284
1316
|
let bids = TEST_BIDS;
|
|
1285
1317
|
let bidRequests;
|