Skip to content

Commit 1855ed8

Browse files
Merge branch 'prebid:master' into master
2 parents 926ceb8 + 27aab5c commit 1855ed8

139 files changed

Lines changed: 8054 additions & 2019 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

integrationExamples/gpt/x-domain/creative.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
<script>
88
pbRender({
9-
adId: '%%PATTERN:hb_adid%%',
10-
pubUrl: '%%PATTERN:url%%',
11-
clickUrl: '%%CLICK_URL_UNESC%%'
9+
adId: "%%PATTERN:hb_adid%%",
10+
pubUrl: "%%PATTERN:url%%",
11+
clickUrl: "%%CLICK_URL_UNESC%%"
1212
});
1313
</script>

libraries/cookieSync/cookieSync.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { getStorageManager } from '../../src/storageManager.js';
2+
const COOKIE_KEY_MGUID = '__mguid_';
3+
4+
export function cookieSync(syncOptions, gdprConsent, uspConsent, bidderCode, cookieOrigin, ckIframeUrl, cookieTime) {
5+
const storage = getStorageManager({bidderCode: bidderCode});
6+
const origin = encodeURIComponent(location.origin || `https://${location.host}`);
7+
let syncParamUrl = `dm=${origin}`;
8+
9+
if (gdprConsent && gdprConsent.consentString) {
10+
if (typeof gdprConsent.gdprApplies === 'boolean') {
11+
syncParamUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`;
12+
} else {
13+
syncParamUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`;
14+
}
15+
}
16+
if (uspConsent && uspConsent.consentString) {
17+
syncParamUrl += `&ccpa_consent=${uspConsent.consentString}`;
18+
}
19+
20+
if (syncOptions.iframeEnabled) {
21+
window.addEventListener('message', function handler(event) {
22+
if (!event.data || event.origin != cookieOrigin) {
23+
return;
24+
}
25+
26+
this.removeEventListener('message', handler);
27+
28+
event.stopImmediatePropagation();
29+
30+
const response = event.data;
31+
if (!response.optout && response.mguid) {
32+
storage.setCookie(COOKIE_KEY_MGUID, response.mguid, cookieTime);
33+
}
34+
}, true);
35+
return [
36+
{
37+
type: 'iframe',
38+
url: `${ckIframeUrl}?${syncParamUrl}`
39+
}
40+
];
41+
}
42+
}

libraries/liveIntentId/shared.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ export function composeIdObject(value) {
7373
result.bidswitch = { 'id': value.bidswitch, ext: { provider: LI_PROVIDER_DOMAIN } }
7474
}
7575

76+
if (value.triplelift) {
77+
result.triplelift = { 'id': value.triplelift, ext: { provider: LI_PROVIDER_DOMAIN } }
78+
}
79+
80+
if (value.zetassp) {
81+
result.zetassp = { 'id': value.zetassp, ext: { provider: LI_PROVIDER_DOMAIN } }
82+
}
83+
7684
if (value.medianet) {
7785
result.medianet = { 'id': value.medianet, ext: { provider: LI_PROVIDER_DOMAIN } }
7886
}
@@ -258,6 +266,30 @@ export const eids = {
258266
}
259267
}
260268
},
269+
'triplelift': {
270+
source: 'liveintent.triplelift.com',
271+
atype: 3,
272+
getValue: function(data) {
273+
return data.id;
274+
},
275+
getUidExt: function(data) {
276+
if (data.ext) {
277+
return data.ext;
278+
}
279+
}
280+
},
281+
'zetassp': {
282+
source: 'zeta-ssp.liveintent.com',
283+
atype: 3,
284+
getValue: function(data) {
285+
return data.id;
286+
},
287+
getUidExt: function(data) {
288+
if (data.ext) {
289+
return data.ext;
290+
}
291+
}
292+
},
261293
'vidazoo': {
262294
source: 'liveintent.vidazoo.com',
263295
atype: 3,

libraries/mspa/activityControls.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export function isBasicConsentDenied(cd) {
2424
cd.PersonalDataConsents === 2 ||
2525
// minors 13+ who have not given consent
2626
cd.KnownChildSensitiveDataConsents[0] === 1 ||
27+
// minors 16+ who have not given consent (added in usnat version 2)
28+
cd.KnownChildSensitiveDataConsents[2] === 1 ||
2729
// minors under 13 cannot consent
2830
isApplicable(cd.KnownChildSensitiveDataConsents[1]) ||
2931
// covered cannot be zero
@@ -53,14 +55,31 @@ export function isConsentDenied(cd) {
5355
}
5456

5557
export const isTransmitUfpdConsentDenied = (() => {
56-
// deny anything that smells like: genetic, biometric, state/national ID, financial, union membership,
57-
// or personal communication data
58-
const cannotBeInScope = [6, 7, 9, 10, 12].map(el => --el);
59-
// require consent for everything else (except geo, which is treated separately)
60-
const allExceptGeo = Array.from(Array(12).keys()).filter((el) => el !== SENSITIVE_DATA_GEO)
61-
const mustHaveConsent = allExceptGeo.filter(el => !cannotBeInScope.includes(el));
58+
const sensitiveFlags = (() => {
59+
// deny anything that smells like: genetic, biometric, state/national ID, financial, union membership,
60+
// personal communication data, status as victim of crime (version 2), status as transgender/nonbinary (version 2)
61+
const cannotBeInScope = [6, 7, 9, 10, 12, 14, 16].map(el => --el);
62+
// require consent for everything else (except geo, which is treated separately)
63+
const allExceptGeo = Array.from(Array(16).keys()).filter((el) => el !== SENSITIVE_DATA_GEO)
64+
const mustHaveConsent = allExceptGeo.filter(el => !cannotBeInScope.includes(el));
65+
66+
return Object.fromEntries(
67+
Object.entries({
68+
1: 12,
69+
2: 16
70+
}).map(([version, cardinality]) => {
71+
const isInVersion = (el) => el < cardinality
72+
return [version, {
73+
cannotBeInScope: cannotBeInScope.filter(isInVersion),
74+
allExceptGeo: allExceptGeo.filter(isInVersion),
75+
mustHaveConsent: mustHaveConsent.filter(isInVersion)
76+
}]
77+
})
78+
)
79+
})()
6280

6381
return function (cd) {
82+
const {cannotBeInScope, mustHaveConsent, allExceptGeo} = sensitiveFlags[cd.Version];
6483
return isConsentDenied(cd) ||
6584
// no notice about sensitive data was given
6685
sensitiveNoticeIs(cd, 2) ||
@@ -97,7 +116,7 @@ export function mspaRule(sids, getConsent, denies, applicableSids = () => gppDat
97116
if (consent == null) {
98117
return {allow: false, reason: 'consent data not available'};
99118
}
100-
if (consent.Version !== 1) {
119+
if (![1, 2].includes(consent.Version)) {
101120
return {allow: false, reason: `unsupported consent specification version "${consent.Version}"`}
102121
}
103122
if (denies(consent)) {

libraries/ortbConverter/README.md

Lines changed: 62 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Prebid.js - ORTB conversion library
22

3-
This library provides methods to convert Prebid.js bid request objects to ORTB requests,
4-
and ORTB responses to Prebid.js bid response objects.
3+
This library provides methods to convert Prebid.js bid request objects to ORTB requests,
4+
and ORTB responses to Prebid.js bid response objects.
55

66
## Usage
77

@@ -37,13 +37,25 @@ registerBidder({
3737
})
3838
```
3939

40-
Without any customization, the library will generate complete ORTB requests, but ignores your [bid params](#params).
40+
Without any customization, the library will generate complete ORTB requests, but ignores your [bid params](#params).
4141
If your endpoint sets `response.seatbid[].bid[].mtype` (part of the ORTB 2.6 spec), it will also parse the response into complete bidResponse objects. See [setting response mediaTypes](#response-mediaTypes) if that is not the case.
4242

4343
### Module-specific conversions
4444

4545
Prebid.js features that require a module also require it for their corresponding ORTB conversion logic. For example, `imp.bidfloor` is only populated if the `priceFloors` module is active; `request.cur` needs the `currency` module, and so on. Notably, this means that to get those fields populated from your unit tests, you must import those modules first; see [this suite](https://github.com/prebid/Prebid.js/blob/master/test/spec/modules/openxOrtbBidAdapter_spec.js) for an example.
4646

47+
#### priceFloors extensions
48+
49+
In addition to `imp.bidfloor` and `imp.bidfloorcur`, the `priceFloors` module also populates media type and `format` objects, if their floors differ:
50+
51+
| Path | `getFloor` invocation |
52+
|-----------------------------------------------------|----------------------------------------------------------------|
53+
| `imp.bidfloor` & `.bidfloorcur` | `.getFloor()` |
54+
| `imp.banner.ext.bidfloor` & `.bidfloorcur` | `.getFloor({mediaType: 'banner', size: '*'})` |
55+
| `imp.banner.format[].ext.bidfloor` & `.bidfloorcur` | `.getFloor({mediaType: 'banner', size: [format.w, format.h]})` |
56+
| `imp.native.ext.bidfloor` & `.bidfloorcur` | `.getFloor({mediaType: 'native', size: '*'})` |
57+
| `imp.video.ext.bidfloor` & `.bidfloorcur` | `.getFloor({mediaType: 'video', size: '*'})` |
58+
4759
## Customization
4860

4961
### Modifying return values directly
@@ -57,35 +69,35 @@ deepSetValue(data.imp[0], 'ext.myCustomParam', bidRequests[0].params.myCustomPar
5769

5870
However, there are two restrictions (to avoid them, use the [other customization options](#fine-customization)):
5971

60-
- you may not change the `imp[].id` returned by `toORTB`; they ared used internally to match responses to their requests.
61-
```javascript
62-
const data = converter.toORTB({bidRequests, bidderRequest});
63-
data.imp[0].id = 'custom-imp-id' // do not do this - it will cause an error later in `fromORTB`
64-
```
65-
See also [overriding `imp.id`](#imp-id).
66-
- the `request` argument passed to `fromORTB` must be the same object returned by `toORTB`.
72+
- you may not change the `imp[].id` returned by `toORTB`; they ared used internally to match responses to their requests.
6773
```javascript
68-
let data = converter.toORTB({bidRequests, bidderRequest});
69-
70-
data = mergeDeep( // the original object is lost
71-
{ext: {myCustomParam: bidRequests[0].params.myCustomParam}}, // `fromORTB` will later throw an error
72-
data
73-
);
74-
75-
// do this instead:
76-
mergeDeep(
77-
data,
78-
{ext: {myCustomParam: bidRequests[0].params.myCustomParam}},
79-
data
80-
)
74+
const data = converter.toORTB({bidRequests, bidderRequest});
75+
data.imp[0].id = 'custom-imp-id' // do not do this - it will cause an error later in `fromORTB`
8176
```
77+
See also [overriding `imp.id`](#imp-id).
78+
- the `request` argument passed to `fromORTB` must be the same object returned by `toORTB`.
79+
```javascript
80+
let data = converter.toORTB({bidRequests, bidderRequest});
81+
82+
data = mergeDeep( // the original object is lost
83+
{ext: {myCustomParam: bidRequests[0].params.myCustomParam}}, // `fromORTB` will later throw an error
84+
data
85+
);
86+
87+
// do this instead:
88+
mergeDeep(
89+
data,
90+
{ext: {myCustomParam: bidRequests[0].params.myCustomParam}},
91+
data
92+
)
93+
```
8294

8395
### <a id="fine-customization" /> Fine grained customization - imp, request, bidResponse, response
8496

8597
When invoked, `toORTB({bidRequests, bidderRequest})` first loops through each request in `bidRequests`, converting them into ORTB `imp` objects.
8698
It then packages them into a single ORTB request, adding other parameters that are not imp-specific (such as for example `request.tmax`).
8799

88-
Likewise, `fromORTB({request, response})` first loops through each `response.seatbid[].bid[]`, converting them into Prebid bidResponses; it then packages them into
100+
Likewise, `fromORTB({request, response})` first loops through each `response.seatbid[].bid[]`, converting them into Prebid bidResponses; it then packages them into
89101
a single return value.
90102

91103
You can customize each of these steps using the `ortbConverter` arguments `imp`, `request`, `bidResponse` and `response`:
@@ -98,8 +110,8 @@ The arguments are:
98110
- `buildImp`: a function taking `(bidRequest, context)` and returning an ORTB `imp` object;
99111
- `bidRequest`: the bid request object to convert;
100112
- `context`: a [context object](#context) that contains at least:
101-
- `bidderRequest`: the `bidderRequest` argument passed to `toORTB`.
102-
113+
- `bidderRequest`: the `bidderRequest` argument passed to `toORTB`.
114+
103115
#### <a id="params" /> Example: attaching custom bid params
104116

105117
```javascript
@@ -194,7 +206,7 @@ const converter = ortbConverter({
194206
})
195207
```
196208

197-
If you know that a particular ORTB request/response pair deals with exclusively one mediaType, you may also pass it directly in the [context parameter](#context).
209+
If you know that a particular ORTB request/response pair deals with exclusively one mediaType, you may also pass it directly in the [context parameter](#context).
198210
Note that - compared to the above - this has additional effects, because `context.mediaType` is also considered during `imp` generation - see [special context properties](#special-context).
199211

200212
```javascript
@@ -223,7 +235,7 @@ const converter = ortbConverter({
223235

224236
### <a id="response" /> Customizing the response: `response(buildResponse, bidResponses, ortbResponse, context)`
225237

226-
Invoked once, after all `seatbid[].bid[]` objects have been converted to corresponding bid responses. The value returned
238+
Invoked once, after all `seatbid[].bid[]` objects have been converted to corresponding bid responses. The value returned
227239
by this function is also the value returned by `fromORTB`.
228240
The arguments are:
229241

@@ -249,7 +261,7 @@ const converter = ortbConverter({
249261
### Even finer grained customization - processor overrides
250262

251263
Each of the four conversion steps described above - imp, request, bidResponse and response - is further broken down into
252-
smaller units of work (called _processors_). For example, when the currency module is included, it adds a _request processor_
264+
smaller units of work (called _processors_). For example, when the currency module is included, it adds a _request processor_
253265
that sets `request.cur`; the priceFloors module adds an _imp processor_ that sets `imp.bidfloor` and `imp.bidfloorcur`, and so on.
254266

255267
Each processor can be overridden or disabled through the `overrides` argument:
@@ -310,21 +322,21 @@ const converter = ortbConverter({
310322
Processor overrides are similar to the override options described above, except that they take the object to process as argument:
311323

312324
- `imp` processor overrides take `(orig, imp, bidRequest, context)`, where:
313-
- `orig` is the processor function being overridden, which itself takes `(imp, bidRequest, context)`;
314-
- `imp` is the (partial) imp object to modify;
315-
- `bidRequest` and `context` are the same arguments passed to [imp](#imp).
325+
- `orig` is the processor function being overridden, which itself takes `(imp, bidRequest, context)`;
326+
- `imp` is the (partial) imp object to modify;
327+
- `bidRequest` and `context` are the same arguments passed to [imp](#imp).
316328
- `request` processor overrides take `(orig, ortbRequest, bidderRequest, context)`, where:
317-
- `orig` is the processor function being overridden, and takes `(ortbRequest, bidderRequest, context)`;
318-
- `ortbRequest` is the partial request to modify;
319-
- `bidderRequest` and `context` are the same arguments passed to [request](#reuqest).
320-
- `bidResponse` processor overrides take `(orig, bidResponse, bid, context)`, where:
321-
- `orig` is the processor function being overridden, and takes `(bidResponse, bid, context)`;
322-
- `bidResponse` is the partial bid response to modify;
323-
- `bid` and `context` are the same arguments passed to [bidResponse](#bidResponse)
329+
- `orig` is the processor function being overridden, and takes `(ortbRequest, bidderRequest, context)`;
330+
- `ortbRequest` is the partial request to modify;
331+
- `bidderRequest` and `context` are the same arguments passed to [request](#reuqest).
332+
- `bidResponse` processor overrides take `(orig, bidResponse, bid, context)`, where:
333+
- `orig` is the processor function being overridden, and takes `(bidResponse, bid, context)`;
334+
- `bidResponse` is the partial bid response to modify;
335+
- `bid` and `context` are the same arguments passed to [bidResponse](#bidResponse)
324336
- `response` processor overrides take `(orig, response, ortbResponse, context)`, where:
325-
- `orig` is the processor function being overriden, and takes `(response, ortbResponse, context)`;
326-
- `response` is the partial response to modify;
327-
- `ortbRespones` and `context` are the same arguments passed to [response](#response).
337+
- `orig` is the processor function being overriden, and takes `(response, ortbResponse, context)`;
338+
- `response` is the partial response to modify;
339+
- `ortbRespones` and `context` are the same arguments passed to [response](#response).
328340

329341
### <a id="context" /> The `context` argument
330342

@@ -354,19 +366,19 @@ const converter = ortbConverter({
354366

355367
For ease of use, the conversion logic gives special meaning to some context properties:
356368

357-
- `currency`: a currency string (e.g. `'EUR'`). If specified, overrides the currency to use for computing price floors and `request.cur`. If omitted, both default to `getConfig('currency.adServerCurrency')`.
358-
- `mediaType`: a bid mediaType (`'banner'`, `'video'`, or `'native'`). If specified:
369+
- `currency`: a currency string (e.g. `'EUR'`). If specified, overrides the currency to use for computing price floors and `request.cur`. If omitted, both default to `getConfig('currency.adServerCurrency')`.
370+
- `mediaType`: a bid mediaType (`'banner'`, `'video'`, or `'native'`). If specified:
359371
- disables `imp` generation for other media types (i.e., if `context.mediaType === 'banner'`, only `imp.banner` will be populated; `imp.video` and `imp.native` will not, even if the bid request specifies them);
360372
- is passed as the `mediaType` option to `bidRequest.getFloor` when computing price floors;
361373
- sets `bidResponse.mediaType`.
362-
- `nativeRequest`: a plain object that serves as the base value for `imp.native.request` (and is relevant only for native bid requests).
363-
If not specified, the only property that is guaranteed to be populated is `assets`, since Prebid does not require anything else to define a native adUnit. You can use `context.nativeRequest` to provide other properties; for example, you may want to signal support for native impression trackers by setting it to `{eventtrackers: [{event: 1, methods: [1, 2]}]}` (see also the [ORTB Native spec](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf)).
364-
- `netRevenue`: the value to set as `bidResponse.netRevenue`. This is a required property of bid responses that does not have a clear ORTB counterpart.
365-
- `ttl`: the default value to use for `bidResponse.ttl` (if the ORTB response does not provide one in `seatbid[].bid[].exp`).
366-
374+
- `nativeRequest`: a plain object that serves as the base value for `imp.native.request` (and is relevant only for native bid requests).
375+
If not specified, the only property that is guaranteed to be populated is `assets`, since Prebid does not require anything else to define a native adUnit. You can use `context.nativeRequest` to provide other properties; for example, you may want to signal support for native impression trackers by setting it to `{eventtrackers: [{event: 1, methods: [1, 2]}]}` (see also the [ORTB Native spec](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf)).
376+
- `netRevenue`: the value to set as `bidResponse.netRevenue`. This is a required property of bid responses that does not have a clear ORTB counterpart.
377+
- `ttl`: the default value to use for `bidResponse.ttl` (if the ORTB response does not provide one in `seatbid[].bid[].exp`).
378+
367379
## Prebid Server extensions
368380

369-
If your endpoint is a Prebid Server instance, you may take advantage of the `pbsExtension` companion library, which adds a number of processors that can populate and parse PBS-specific extensions (typically prefixed `ext.prebid`); these include bidder params (with `transformBidParams`), bidder aliases, targeting keys, and others.
381+
If your endpoint is a Prebid Server instance, you may take advantage of the `pbsExtension` companion library, which adds a number of processors that can populate and parse PBS-specific extensions (typically prefixed `ext.prebid`); these include bidder params (with `transformBidParams`), bidder aliases, targeting keys, and others.
370382

371383
```javascript
372384
import {pbsExtensions} from '../../libraries/pbsExtensions/pbsExtensions.js'

0 commit comments

Comments
 (0)