` |
+
+Kinesso will then attach these users to deals ids that they will target in the ORTB bid stream by brands and agencies represented by IPG.
+
+Add it to your Prebid.js package with:
+
+{: .alert.alert-info :}
+gulp build --modules=kinessoIdSystem
+
+#### Kinesso ID Registration
+
+You can set up Kinesso ID sub adapter by contacting Kinesso at prebid@kinesso.com
+
+The Kinesso ID privacy policy is covered under the [Kinesso Privacy Notice](https://kinesso.com/privacy-policy/). Please note, at present the Kinesso ID module is not meant for use inside the EEA.
+
+{: .table .table-bordered .table-striped }
+| Param under userSync.userIds[] | Scope | Type | Description | Example |
+| --- | --- | --- | --- | --- |
+| name | Required | String | The name of this module. | `'kinessoId'` |
+| params | Required | Object | Details for KinessoId initialization | |
+| params.accountid | Required | Int | Your SSP Account Id | 123 |
+
### LiveIntent nonID
LiveIntent offers audience resolution by leveraging our next-generation identity solutions. The LiveIntent identity graph is built around a people-based set of data that is authenticated daily through active engagements with email newsletters and media across the web. The LiveIntent nonID is a user identifier tied to an active, encrypted email in our graph and functions in cookie-challenged environments and browsers.
@@ -971,6 +1152,49 @@ pbjs.setConfig({
});
{% endhighlight %}
+### MediaWallah OpenLinkID
+
+MediaWallah's openLink is an anonymous person based ID that enables buyers and sellers of media to connect a person and their devices across the web and mobile apps. openLink facilities the buying of media between DSPs, SSPs and publishers.
+
+Add support for MediaWallah OpenLinkID to your Prebid.js package with:
+
+{: .alert.alert-info :}
+gulp build --modules=userId,mwOpenLinkIdSystem
+
+#### MediaWallah OpenLinkID Registration
+
+MediaWallah requires the creation of an accountId a partnerId in order to take advantage of openLink. Please contact your partner resource to get these Ids provisioned.
+
+#### MediaWallah OpenLinkID Configuration
+
+
+| Param under userSync.userIds[] | Scope | Type | Description | Example |
+| --- | --- | --- | --- | --- |
+| name | Required | String | The name of this module. | `'mwOpenLinkId'` |
+| params | Required | Object | Details for mwOLID syncing. ||
+| params.accountId | Required | String | The MediaWallah assigned Account Id | `1000` |
+| params.partnerId | Required | String | The MediaWallah assign partner Id |`'1001'`|
+| params.uid | Optional | String | Your unique Id for the user or browser. Used for matching. | `'u-123xyz'` |
+{: .table .table-bordered .table-striped }
+
+
+#### MediaWallah OpenLinkID Examples
+
+```
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: 'mwOpenLinkId',
+ params: {
+ accountId: '1000',
+ partnerId: '1001',
+ uid: 'u-123xyz'
+ }
+ }]
+ }
+})
+```
+
### Merkle ID
[Merkury by Merkle](https://merkury.merkleinc.com/contact) enables marketers, media owners, and publishers to own, build, and control a cookie-less Private Identity Graph. Merkury uses an organization’s first-party CRM data and valuable interactions such as logins, outbound email campaigns and media reach to create and grow a universe of person-based IDs for cross-channel targeting, personalization, measurement and more.
@@ -1000,6 +1224,24 @@ pbjs.setConfig({
});
{% endhighlight %}
+### Navegg ID
+
+[Navegg](https://www.navegg.com) enables publishers, advertisers and agencies to use their own first party data together to activate media in a cookie-less way across several Ad Tech platforms. Navegg has one of the largest data networks in Latin America which also allows the enhancement of data with unique categories.
+
+#### Navegg ID Examples
+
+Publisher stores NaveggId in local storage and/or 1st party cookies
+
+{% highlight javascript %}
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: 'naveggId'
+ }]
+ }
+});
+{% endhighlight %}
+
### netID
The [European netID Foundation (EnID)](https://developerzone.netid.de/index.html) aims to establish with the netID an independent European alternative in the digital market for Demand and Supply side. With the netID Single-Sign-On, the EnID established an open standard for consumer logins for services of Buyers and Brands, that also includes user-centric consent management capabilities that results in a standardized, EU-GDPR compliant, IAB TCF aware, cross-device enabled Advertising Identifier, which can be leveraged by publishers and advertisers (and vendors supporting them) to efficiently deliver targeted advertising through programmatic systems to already more than 38 million Europeans on mobile and desktop devices.
@@ -1162,36 +1404,153 @@ pbjs.setConfig({
});
{% endhighlight %}
-### PubCommon ID
+### Publisher Link
+Publisher Link, provided by [Epsilon](https://www.epsilon.com/us), is a cross-device identity solution that activates publisher first-party, authenticated
+data to improve audience identification and increase bid opportunities, specifically designed for sites with authenticated
+traffic. Publisher first-party authenticated data and a user's unique encrypted ID is linked to an existing people-based
+Epsilon CORE ID. By utilizing Publisher Link, publishers are able to reap the benefits of Epsilon's CORE ID.
+
+#### Publisher Link Registration
+There is no registration needed.
+
+The Epsilon privacy is covered in the [Epsilon Privacy Policy](https://www.epsilon.com/us/privacy-policy).
-This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support Publisher Common ID will be able to pick up the user ID and return it for additional server-side cross device tracking.
+The Publisher Link opt-out is include [here](https://www.epsilon.com/privacy/dms/opt-out/email)
-There is no special registration or configuration for PubCommon ID. Each publisher's privacy policy should take
-PubCommon ID into account.
+#### Publisher Link Configuration
+
+In addition to the parameters documented above in the Basic Configuration section the following Publisher Link specific configuration is available:
+
+{: .table .table-bordered .table-striped }
+| Param under userSync.userIds[] | Scope | Type | Description | Example |
+| --- | --- | --- | --- | --- |
+| name | Required | String | The name of this module. | `'publinkId'` |
+| params | Required | Object | Customized parameters | |
+| params.e | Required | String | Hashed email address of the user | `e80b5017098950fc58aad83c8c14978e` |
+
+#### Publisher Link Examples
+```javascript
+ pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: "publinkId",
+ storage: {
+ name: "pbjs_publink",
+ type: "cookie",
+ expires: 30
+ },
+ params: {
+ e: "e80b5017098950fc58aad83c8c14978e", // example hashed email (md5)
+ }
+ }]
+ }
+ });
+```
+
+### RampID
+
+RampID, formerly known as IdentityLink, provided by [LiveRamp](https://liveramp.com) is a single person-based identifier which allows marketers, platforms and publishers to perform personalized segmentation, targeting and measurement use cases that require a consistent, cross-channel view of the user in anonymous spaces.
+
+Add it to your Prebid.js package with:
+
+{: .alert.alert-info :}
+gulp build --modules=identityLinkIdSystem
+
+#### RampID Registration
+
+Please sign up through our [Console](https://launch.liveramp.com) platform and request a `placementId`.
+
+The RampID privacy policy is at [https://liveramp.com/privacy/service-privacy-policy/](https://liveramp.com/privacy/service-privacy-policy/).
+
+#### RampID Configuration
+
+{: .table .table-bordered .table-striped }
+| Param under userSync.userIds[] | Scope | Type | Description | Example |
+| --- | --- | --- | --- | --- |
+| name | Required | String | `"identityLink"` | `"identityLink"` |
+| params | Required for Id Link | Object | Details for RampID initialization. | |
+| params.pid | This parameter is required for RampID | String | This is the placementId, value needed for obtaining user’s RampID envelope
+| params.notUse3P | This parameter is not required for RampID | Boolean | Property for choosing should 3P Liveramp envelope endpoint be fired or not, in order to get RampID envelope
+
+#### RampID Examples
+
+1) Publisher passes a placement ID and elects to store the RampID envelope in a cookie.
+
+
+{% highlight javascript %}
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: "identityLink",
+ params: {
+ pid: '999', // Set your real RampID placement ID here
+ // notUse3P: true/false // If you do not want to use 3P endpoint to retrieve the envelope. If you do not set this property to true, 3P endpoint will be fired. By default this property is undefined and 3P request will be fired.
+ },
+ storage: {
+ type: "cookie",
+ name: "idl_env", // create a cookie with this name
+ expires: 30 // cookie can last for 30 days
+ }
+ }],
+ syncDelay: 3000 // 3 seconds after the first auction
+ }
+});
+{% endhighlight %}
+
+2) Publisher passes a placement ID and elects to store the RampID envelope in HTML5 localStorage.
+
+{% highlight javascript %}
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: "identityLink",
+ params: {
+ pid: '999', // Set your real RampID placement ID here
+ // notUse3P: true/false // If you do not want to use 3P endpoint to retrieve the envelope. If you do not set this property to true, 3P endpoint will be fired. By default this property is undefined and 3P request will be fired.
+ },
+ storage: {
+ type: "html5",
+ name: "idl_env", // set localstorage with this name
+ expires: 30
+ }
+ }],
+ syncDelay: 3000
+ }
+});
+{% endhighlight %}
+
+### SharedID
+
+This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support SharedId will be able to pick up the user ID and return it for additional server-side cross device tracking.
+
+There is no special registration or configuration for SharedID. Each publisher's privacy policy should take
+SharedID into account. Prebid recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page. For more information check out Prebid's dedicated [identity page](/identity/sharedid.html)
Add it to your Prebid.js package with:
{: .alert.alert-info :}
gulp build --modules=pubCommonIdSystem
-#### PubCommon ID Configuration
+#### SharedID ID Configuration
-In addition to the parameters documented above in the Basic Configuration section the following PubCommon specific configuration is available:
+In addition to the parameters documented above in the Basic Configuration section the following SharedID specific configuration is available:
{: .table .table-bordered .table-striped }
| Param under userSync.userIds[] | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Required | String | The name of this module. | `'pubCommonId'` |
| params | Optional | Object | Customized parameters | |
-| params.create | Optional | Boolean | For publisher server support only. If true, the publisher's server will create the PubCommon ID cookie. Default is true. | `true` |
-| params.pixelUrl | Optional | String | For publisher server support only. This is a URL of a pixel for updating cookies' expiration times. Fired after a new ID has been created or an existing ID is being extended. No default. | `'https://example.com/ping'`
+| params.create | Optional | Boolean | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` |
+| params.pixelUrl | Optional | String | For publisher server support only. Where to call out to for a server cookie -- see [Prebid Identity](/identity/sharedid.html) for more information. | `/wp-json/pubcid/v1/extend/`
| params.extend | Optional | Boolean | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `false` |
-| params.enableSharedId | Optional | Boolean | Invokes [SharedID](/dev-docs/modules/userId.html#shared-id-user-id-submodule) as well as setting PubCommon ID. Defaults to `false` | `true` |
-
+| storage | Required | Object | The publisher must specify some kind of local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. |
+| storage.expires | Integer | Required | How long the user ID information will be stored. | `365` |
+| storage.name | String | Required | The name of the cookie or html5 local storage where the user ID will be stored. | `_pubcid`
+| storage.type | String | Required | This is where the results of the user ID will be stored. Must be either: Must be either: "cookie" or "html5". For server side implementations, which have the best identifier life and revenue impact, this must be a cookie. | `cookie`
-#### PubCommon ID Examples
+#### SharedID Examples
-1) Publisher supports PubCommonID and first party domain cookie storage
+1) Publisher supports SharedID and first party domain cookie storage
{% highlight javascript %}
pbjs.setConfig({
@@ -1200,7 +1559,7 @@ pbjs.setConfig({
name: "pubCommonId",
storage: {
type: "cookie",
- name: "_pubcid", // create a cookie with this name
+ name: `"_pubcid"`, // create a cookie with this name
expires: 365 // expires in 1 years
}
}]
@@ -1208,7 +1567,7 @@ pbjs.setConfig({
});
{% endhighlight %}
-2) Publisher supports both UnifiedID and PubCommonID and first party domain cookie storage
+2) Publisher supports both UnifiedID and SharedID and first party domain cookie storage
{% highlight javascript %}
pbjs.setConfig({
@@ -1226,11 +1585,11 @@ pbjs.setConfig({
},{
name: "pubCommonId",
params: {
- enableSharedId: true // optionally enable Prebid sharedID
+ pixelUrl: "/wp-json/pubcid/v1/extend/"
},
storage: {
type: "cookie",
- name: "_pubcid", // create a cookie with this name
+ name: `"_pubcid"`, // create a cookie with this name
expires: 180
}
}],
@@ -1239,9 +1598,25 @@ pbjs.setConfig({
});
{% endhighlight %}
-{: .alert.alert-info :}
-When enableSharedId is true, the browser will make an additional call to id.sharedid.org/usync. Calling to Shareid.org sets a user id in a 3rd party cookie under the sharedid.org domain. Anyone setting this additional identity should reference Sharedid.orgs optout policy at https://sharedid.org/. Prebid.js 5.0 will enable the enableSharedId option by default.
+3) Publisher supports SharedID and first party domain cookie storage initiated by a first party server
+{% highlight javascript %}
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: "pubCommonId",
+ params: {
+ pixelUrl: "/wp-json/pubcid/v1/extend/" //pixelUrl should be specified when the server plugin is used
+ },
+ storage: {
+ type: "cookie",
+ name: `"_pubcid"`, // create a cookie with this name
+ expires: 365 // expires in 1 years
+ }
+ }]
+ }
+});
+{% endhighlight %}
### PubProvided ID
@@ -1267,27 +1642,27 @@ Or, the eids values can be passed directly into the `setConfig` call:
pbjs.setConfig({
userSync: {
userIds: [{
- name: "example.com",
+ name: "pubProvidedId",
params: {
eids: [{
source: "domain.com",
- uids:[{
- id: "value read from cookie or local storage",
- atype: 1,
- ext: {
- stype: "ppuid"
- }
-
- }]
- },{
+ uids: [{
+ id: "value read from cookie or local storage",
+ atype: 1,
+ ext: {
+ stype: "ppuid"
+ }
+
+ }]
+ }, {
source: "3rdpartyprovided.com",
- uids:[{
- id: "value read from cookie or local storage",
- atype: 3,
- ext: {
- stype: "dmp"
- }
- }]
+ uids: [{
+ id: "value read from cookie or local storage",
+ atype: 3,
+ ext: {
+ stype: "dmp"
+ }
+ }]
}]
}
}]
@@ -1328,25 +1703,32 @@ gulp build --modules=pubProvidedId
### Quantcast ID
-Quantcast ID enables publishers that use Quantcast Measure tag to uniquely identify
-their clients within Quantcast's extensive publisher network without relying on third party
-cookies. The Quantcast User ID submodule makes the existing Quantcast first party
-cookie available in the bid request. The first party cookie allows Quantcast to correlate
-the bid request with Quantcast's Measure dataset.
-
-Currently, Quantcast ID only works with the presence of Quantcast Measure tag. More information
-about Measure can be found in https://www.quantcast.com/measure.
-
-The Quantcast privacy policy is at https://www.quantcast.com/privacy/.
+The Prebid Quantcast ID module stores a Quantcast ID in a first party cookie. The ID is then made available in the bid request. The ID from the cookie added in the bidstream allows Quantcast to more accurately bid on publisher inventories without third party cookies, which can result in better monetization across publisher sites from Quantcast. And, it’s free to use! For easier integration, you can work with one of our SSP partners, like PubMatic, who can facilitate the legal process as well as the software integration for you.
Add it to your Prebid.js package with:
{: .alert.alert-info :}
gulp build --modules=userId,quantcastIdSystem
+Quantcast’s privacy policies for the services rendered can be found at
+ https://www.quantcast.com/privacy/
+
+Publishers deploying the module are responsible for ensuring legally required notices and choices for users.
+
+The Quantcast ID module will only perform any action and return an ID in situations where:
+1. the publisher has not set a ‘coppa' flag on the prebid configuration on their site (see [pbjs.setConfig.coppa](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa))
+2. there is not a IAB us-privacy string indicating the digital property has provided user notice and the user has made a choice to opt out of sale
+3. if GDPR applies, an IAB TCF v2 string exists indicating that Quantcast does not have consent for purpose 1 (cookies, device identifiers, or other information can be stored or accessed on your device for the purposes presented to you), or an established legal basis (by default legitimate interest) for purpose 10 (your data can be used to improve existing systems and software, and to develop new products).
+
#### Quantcast ID Configuration
-Quantcast ID module does not require any configuration parameters at this time.
+{: .table .table-bordered .table-striped }
+| Param under userSync.userIds[] | Scope | Type | Description | Example |
+| --- | --- | --- | --- | --- |
+| name | Required | String | `"quantcastId"` | `"quantcastId"` |
+| params | Optional | Object | Details for Quantcast initialization. | |
+| params.ClientID | Optional | String | Optional parameter for Quantcast prebid managed service partners. The parameter is not required for websites with Quantcast Measure tag. Reach out to Quantcast for ClientID if you are not an existing Quantcast prebid managed service partner: quantcast-idsupport@quantcast.com | |
+
#### Quantcast ID Example
@@ -1354,13 +1736,14 @@ Quantcast ID module does not require any configuration parameters at this time.
pbjs.setConfig({
userSync: {
userIds: [{
- name: "quantcastId",
+ name: "quantcastId"
}]
}
});
{% endhighlight %}
+
### Tapad ID
Tapad's ID module provides access to a universal identifier that publishers, ad tech platforms and advertisers can use for data collection and collation without reliance on third-party cookies.
@@ -1406,52 +1789,6 @@ pbjs.setConfig({
});
{% endhighlight %}
-
-
-### SharedID User ID Submodule
-
-The SharedID User Module generates a UUID that can be utilized to improve user matching. This module enables timely synchronization and handles opt-out via sharedid.org. This module does not require any registration.
-
-#### Building Prebid with SharedID Support
-Add it to your Prebid.js package with:
-
-{: .alert.alert-info :}
-ex: $ gulp build --modules=sharedIdSystem
-
-#### Prebid Params
-
-Individual params may be set for the SharedID User ID Submodule.
-```
-pbjs.setConfig({
- userSync: {
- userIds: [{
- name: 'sharedId',
- params: {
- syncTime: 60 // in seconds, default is 24 hours
- },
- storage: {
- name: 'sharedid',
- type: 'cookie',
- expires: 28
- },
- }]
- }
-});
-```
-
-#### SharedID Configuration
-
-{: .table .table-bordered .table-striped }
-| Params under usersync.userIds[]| Scope | Type | Description | Example |
-| --- | --- | --- | --- | --- |
-| name | Required | String | ID value for the SharedID module - `"sharedId"` | `"sharedId"` |
-| params | Optional | Object | Details for sharedId syncing. | |
-| params.syncTime | Optional | Object | Configuration to define the frequency(in seconds) of id synchronization. By default id is synchronized every 24 hours | 60 |
-| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | |
-| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` |
-| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"sharedid"` |
-| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `28` |
-
### Unified ID
The Unified ID solution is provided by adsrvr.org and the Trade Desk.
@@ -1637,49 +1974,6 @@ pbjs.setConfig({
})
```
-### MediaWallah OpenLinkID
-
-MediaWallah's openLink is an anonymous person based ID that enables buyers and sellers of media to connect a person and their devices across the web and mobile apps. openLink facilities the buying of media between DSPs, SSPs and publishers.
-
-Add support for MediaWallah OpenLinkID to your Prebid.js package with:
-
-{: .alert.alert-info :}
-gulp build --modules=userId,mwOpenLinkIdSystem
-
-#### MediaWallah OpenLinkID Registration
-
-MediaWallah requires the creation of an accountId a partnerId in order to take advantage of openLink. Please contact your partner resource to get these Ids provisioned.
-
-#### MediaWallah OpenLinkID Configuration
-
-
-| Param under userSync.userIds[] | Scope | Type | Description | Example |
-| --- | --- | --- | --- | --- |
-| name | Required | String | The name of this module. | `'mwOpenLinkId'` |
-| params | Required | Object | Details for mwOLID syncing. ||
-| params.accountId | Required | String | The MediaWallah assigned Account Id | `1000` |
-| params.partnerId | Required | String | The MediaWallah assign partner Id |`'1001'`|
-| params.uid | Optional | String | Your unique Id for the user or browser. Used for matching. | `'u-123xyz'` |
-{: .table .table-bordered .table-striped }
-
-
-#### MediaWallah OpenLinkID Examples
-
-```
-pbjs.setConfig({
- userSync: {
- userIds: [{
- name: 'mwOpenLinkId',
- params: {
- accountId: '1000',
- partnerId: '1001',
- uid: 'u-123xyz'
- }
- }]
- }
-})
-```
-
## Adapters Supporting the User ID Sub-Modules
{% assign bidder_pages = site.pages | where: "layout", "bidder" %}
@@ -1699,163 +1993,55 @@ pbjs.setConfig({
Bidders that want to support the User ID module in Prebid.js, need to update their bidder adapter to read the indicated bidRequest attributes and pass them to their endpoint.
-
-| ID System Name | ID System Host | Prebid.js Attr | Example Value |
-| --- | --- | --- | --- | --- | --- |
-| Admixer ID | Admixer | bidRequest.userId.admixerId | `"1111"` |
-| BritePool ID | BritePool | bidRequest.userId.britepoolid | `"1111"` |
-| DMD ID | DMD | bidRequest.userId.dmdId | `"1111"` |
-| CriteoID | Criteo | bidRequest.userId.criteoId | `"1111"` |
-| Halo ID | Audigent | bidRequest.userId.haloId | `{"haloId":"user-halo-id", "auSeg":["segment1","segment2"]}` |
-| ID+ | Zeotap | bidRequest.userId.IDP | `"1111"` |
-| ID5 ID | ID5 | bidRequest.userId.id5id | `{ uid: "1111", ext: { linkType: 2, abTestingControlGroup: false } }` |
-| IdentityLink | Trade Desk | bidRequest.userId.idl_env | `"1111"` |
-| Intent IQ ID | Intent IQ | bidRequest.userId.intentiqid | `"1111"` |
-| LiveIntent ID | Live Intent | bidRequest.userId.lipb.lipbid | `"1111"` |
-| Lotame Panorama ID | Lotame | bidRequest.userId.lotamePanoramaId | `"e4b96a3d9a8e8761cef5656fb05f16d53938069f1684df4b2257e276e8b89a0e"` |
-| merkleID | Merkle | bidRequest.userId.merkleId | `"1111"` |
-| netID | netID | bidRequest.userId.netId | `"fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg"` |
-| NextRoll ID | NextRoll | bidRequest.userId.nextrollId | `"bf3KawPMRifn1iXLtufo4AhoZHaBEYQpYOe1ZTJsY7IzuZ0LW/SjP/zpVGr09voA"` |
-| Parrable ID | Parrable | bidRequest.userId.parrableId | `{"eid":"01.1594654046.cd0972d861e98ff3723a368a6efa69287a0df3f1cac9142afc2e7aed1caa8dd1b7fc0590b3baf67525f53e1228024c2805b6041206c7a23e34bb823b0659547d7d1d0dac2a11938e867f"}` |
-| PubCommon ID | n/a | bidRequest.userId.pubcid | `"1111"` |
-| PubProvided ID | n/a | bidRequest.userId.pubProvidedId | `"1111"` |
-| Quantcast ID | n/a | bidRequest.userId.quantcastId | `"1111"` |
-| Tapad ID | Tapad | bidRequest.userId.tapadId | `"1111"` |
-| SharedID | Prebid | bidRequest.userId.sharedid | `{"id":"01EAJWWNEPN3CYMM5N8M5VXY22","third":"01EAJWWNEPN3CYMM5N8M5VXY22"}` |
-| Unified ID | Trade Desk | bidRequest.userId.tdid | `"1111"` |
-| Verizon Media ConnectID | Verizon Media | bidRequest.userId.connectid | `"72d04af6e07c2eb93e9c584a131f48b6a9b963bcb2736d624e987ff8cf36d472"` |
-| MediaWallah OpenLink ID | MediaWallah | bidRequest.userId.mwOpenLinkId | `"1111"` |
{: .table .table-bordered .table-striped }
-
+| ID System Name | ID System Host | Prebid.js Attr: bidRequest.userId. | EID Source | Example Value |
+| --- | --- | --- | --- | --- | --- | --- |
+| Admixer ID | Admixer | admixerId | admixer.net | "1111" |
+| Adtelligent ID | Adtelligent | bidRequest.userId.adtelligentId | `"1111"` |
+| Akamai DAP ID | Akamai DAP | dapId | akamai.com | "eyJhbGciOiJka....YIsj7"|
+| AMX RTB ID | AMX RTB | amxId | amxrtb.com | "3ca11058-..." |
+| BritePool ID | BritePool | britepoolid | britepool.com | "1111" |
+| DeepIntent ID | Deep Intent | deepintentId | deepintent.com | "1111" |
+| DMD ID | DMD | dmdId | hcn.health | "1111" |
+| CriteoID | Criteo | criteoId | criteo.com | "1111" |
+| Fabrick ID | Neustar | fabrickId | neustar.biz | "1111" |
+| FLoC ID | n/a | flocId | | |
+| Halo ID | Audigent | haloId | audigent.com | {"haloId":"user-halo-id", "auSeg":["segment1", "segment2"]} |
+| ID+ | Zeotap | IDP | zeotap.com | "1111" |
+| ID5 ID | ID5 | id5id | id5-sync.com | {uid: "1111", ext: { linkType: 2, abTestingControlGroup: false } } |
+| IdentityLink | LiveRamp | idl_env | liveramp.com | "1111" |
+| Intent IQ ID | Intent IQ | intentiqid | intentiq.com | "1111" |
+| Kinesso ID | Kinesso | kpuid | kpuid.com | "1111" |
+| LiveIntent ID | Live Intent | lipb.lipbid | liveintent.com | "1111" |
+| Lotame Panorama ID | Lotame | lotamePanoramaId | crwdcntrl.net | "e4b9..." |
+| MediaWallah OpenLink ID | MediaWallah | mwOpenLinkId | mediawallahscript.com | "1111" |
+| merkleID | Merkle | merkleId | merkleinc.com | "1111" |
+| naveggId | Navegg | naveggId | navegg.com | "1111" |
+| netID | netID | netId | netid.de | "fH5A..." |
+| NextRoll ID | NextRoll | nextrollId | nextroll.com | "bf3Ka.../SjP/zpVGr09voA" |
+| Novatiq ID | Novatiq | novatiqId | novatiq.com | "1111" |
+| Parrable ID | Parrable | parrableId | parrable.com | {"eid":"01.15946..."} |
+| PubProvided ID | n/a | pubProvidedId | publisher domain | "1111" |
+| Quantcast ID | n/a | quantcastId | quantcast.com | "1111" |
+| Tapad ID | Tapad | tapadId | tapad.com | "1111" |
+| SharedID (PBJS 5.x) | n/a | pubcid | pubcid.org | "1111" |
+| SharedID (PBJS 4.x)| Prebid | sharedid | sharedid.org | {"id":"01EAJWWN...", "third":"01EAJ..."} |
+| Unified ID | Trade Desk | tdid | adserver.org | "1111" |
+| Verizon Media ConnectID | Verizon Media | connectid | verizonmedia.com | "72d04af6..." |
For example, the adapter code might do something like:
{% highlight javascript %}
- if (bidRequest.userId && bidRequest.userId.pubcid) {
- url+="&pubcid="+bidRequest.userId.pubcid;
+ if (bidRequest.userId && bidRequest.userId.sharedid) {
+ url+="&pubcid="+bidRequest.userId.sharedid;
}
{% endhighlight %}
### Prebid Server Adapters
-Bidders that want to support the User ID module in Prebid Server, need to update their server-side bid adapter to read the desired OpenRTB attributes noted in the example below and send them to their endpoint.
+Bidders that want to support the User ID module in Prebid Server, need to update their server-side bid adapter to read the desired OpenRTB 'user.ext.eids.source' object and forward the relevant values to their endpoint.
-{% highlight bash %}
-{
- "user": {
- "ext": {
- "eids": [{
- "source": "adserver.org", // Unified ID
- "uids": [{
- "id": "111111111111",
- "ext": {
- "rtiPartner": "TDID"
- }
- }]
- },{
- "source": "pubcid.org",
- "uids": [{
- "id":"11111111"
- }]
- },
- {
- "source": "id5-sync.com",
- "uids": [{
- "id": "ID5-12345",
- "ext": {
- "linkType": 2,
- "abTestingControlGroup": false
- }
- }]
- },
- {
- source: "parrable.com",
- uids: [{
- id: "01.1594654046.cd0972d861e98ff3723a368a6efa69287a0df3f1cac9142afc2e7aed1caa8dd1b7fc0590b3baf67525f53e1228024c2805b6041206c7a23e34bb823b0659547d7d1d0dac2a11938e867f"
- }]
- },{
- "source": "audigent.com",
- "atype": 1,
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "identityLink",
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "criteo.com",
- "uids": [{
- "id": "11111111"
- }]
- },{
- },{
- "source": "hcn.health",
- atype: 3,
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "britepool.com",
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "liveintent.com",
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "crwdcntrl.net", // Lotame Panorama ID
- "uids": [{
- "id": "e4b96a3d9a8e8761cef5656fb05f16d53938069f1684df4b2257e276e8b89a0e"
- }]
- },{
- "source": "netid.de",
- "uids": [{
- "id": "11111111"
- }]
- },{
- "source": "novatiq.com",
- "uids": [{
- "id": "81b001ec-8914-488c-a96e-8c220d4ee08895ef",
- "atype":1
- }]
- },{
- "source": "sharedid.org", // SharedID
- "uids": [{
- "id": "01EAJWWNEPN3CYMM5N8M5VXY22",
- "ext": {
- "third": "01EAJWWNEPN3CYMM5N8M5VXY22"
- }
- }]
- },{
- "source": "pub.com", // Publisher must configure their domain here
- "uids": [{
- "id": "01EAJWWNEPN3CYMM5N8M5VXY22",
- "atype":1 //ADCOM - Type of user agent the match is from
- "ext": {
- "stype": "dmp" //currently supported values (dmp,ppuid,other)
- }
- }]
- },{
- "source": "verizonmedia.com",
- "uids": [{
- "id": "61cef5656fb05f16d53938069f1684df4b2257e27"
- }]
- },{
- "source": "mediawallahscript.com",
- "uids": [{
- "id": "01EAJWWNEPN3CYMM5N8M5VXY22",
- "atype": 1
- }]
- }
- ]
- }
- }
-}
-{% endhighlight %}
+See the [Prebid.js EIDs javascript source](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.js) for the definitive list of user EID sources.
### Exporting User IDs
@@ -1910,7 +2096,7 @@ If you're an ID provider that wants to get on this page:
- Add your *IdSystem name into the modules/.submodules.json file
- Follow all the guidelines in the [contribution page](https://github.com/prebid/Prebid.js/blob/master/CONTRIBUTING.md).
- Submit a Pull Request against the [Prebid.js repository](https://github.com/prebid/Prebid.js).
-- Fork the prebid.org [documentation repository](https://github.com/prebid/prebid.github.io), modify the /dev-docs/modules/userId.md, and submit a documentation Pull Request as well.
+- Fork the prebid.org [documentation repository](https://github.com/prebid/prebid.github.io), modify /dev-docs/modules/userId.md, /download.md, and submit a documentation Pull Request.
diff --git a/dev-docs/modules/validationFpdModule.md b/dev-docs/modules/validationFpdModule.md
index 00c3cae15a..571eb26f7f 100644
--- a/dev-docs/modules/validationFpdModule.md
+++ b/dev-docs/modules/validationFpdModule.md
@@ -2,7 +2,7 @@
layout: page_v2
page_type: module
title: Module - First Party Data Validation
-description: Validates First Party Data
+description: Verify First Party Data fields and data types. Not recommended for production use.
module_code : validationFpdModule
display_name : First Party Data Validation
enable_download : true
diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-api.md b/dev-docs/plugins/bc/bc-prebid-plugin-api.md
index e263a90657..143fd7add2 100644
--- a/dev-docs/plugins/bc/bc-prebid-plugin-api.md
+++ b/dev-docs/plugins/bc/bc-prebid-plugin-api.md
@@ -113,10 +113,10 @@ If the results of the prebid process is being determined outside of the plugin,
{"prebidPath": "//files.prebid.org/prebid-org.js",
"biddersSpec": {
”code": "my-video-tag",
- "sizes": [640,480],
"mediaTypes": {
"video": {
"context": "instream",
+ "playerSize": [640, 480],
"mimes": ["video/mp4","application/javascript"],
"protocols": [1,2,3,4,5,6,7,8],
"playbackmethod": [1,2],
@@ -126,10 +126,7 @@ If the results of the prebid process is being determined outside of the plugin,
"bids": [{
"bidder": "appnexus",
"params": {
- "placementId": 8845778,
- "video": {"skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 8845778
}
}]
},
diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-integration-studio.md b/dev-docs/plugins/bc/bc-prebid-plugin-integration-studio.md
index 7dbfd86d8c..1b211504c4 100644
--- a/dev-docs/plugins/bc/bc-prebid-plugin-integration-studio.md
+++ b/dev-docs/plugins/bc/bc-prebid-plugin-integration-studio.md
@@ -131,10 +131,10 @@ Example:
{"prebidPath": "//files.prebid.org/prebid-org.js", // not for production use
"biddersSpec": {
”code": "my-video-tag",
- "sizes": [640,480],
"mediaTypes": {
"video": {
"context": "instream",
+ "playerSize": [640,480],
"mimes": ["video/mp4","application/javascript"],
"protocols": [1,2,3,4,5,6,7,8],
"playbackmethod": [1,2],
@@ -144,11 +144,7 @@ Example:
"bids": [{
"bidder": "appnexus",
"params": {
- "placementId": 8845778,
- "video": {"skippable": true,
- "playback_method":
- ["auto_play_sound_off"]
- }
+ "placementId": 8845778
}
}]
},
@@ -259,10 +255,10 @@ None
],
"biddersSpec": {
"code": "my-video-tag",
- "sizes": [640,480],
"mediaTypes": {
"video": {
"context": "instream",
+ "playerSize": [640,480],
"mimes": ["video/mp4","application/javascript"],
"protocols": [1,2,3,4,5,6,7,8],
"playbackmethod": [1,2],
diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.md b/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.md
index 83bcfa5d85..72260d6d0f 100644
--- a/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.md
+++ b/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.md
@@ -46,25 +46,21 @@ The following is a sample JSON definition of the plugin configuration defining c
"scriptLoadTimeout": 3000,
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
- "context": "instream",
- "mimes": ["video/mp4", "application/javascript"],
- "protocols" : [1,2,3,4,5,6,7,8],
- "playbackmethod" : [1, 2],
- "api":[1,2]
+ "context": "instream",
+ "playerSize": [640,480],
+ "mimes": ["video/mp4", "application/javascript"],
+ "protocols" : [1,2,3,4,5,6,7,8],
+ "playbackmethod" : [1, 2],
+ "api":[1,2]
}
},
"bids": [
{
"bidder": "appnexus",
"params": {
- "placementId": 12527596,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 12527596
}
}
]
@@ -145,25 +141,21 @@ The following is a sample JSON definition of the plugin configuration defining c
"prebidPath" : "//files.prebid.org/prebid-org.js", // not for production use
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
- "context": "instream",
- "mimes": ["video/mp4", "application/javascript"],
- "protocols" : [1,2,3,4,5,6,7,8],
- "playbackmethod" : [1, 2],
- "api":[1,2]
+ "context": "instream",
+ "playerSize": [640,480],
+ "mimes": ["video/mp4", "application/javascript"],
+ "protocols" : [1,2,3,4,5,6,7,8],
+ "playbackmethod" : [1, 2],
+ "api":[1,2]
}
},
"bids": [
{
"bidder": "appnexus",
"params": {
- "placementId": 12531984,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 12531984
}
}
]
@@ -254,25 +246,22 @@ The following is a sample JSON definition of the plugin configuration defining c
"scriptLoadTimeout": 3000,
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
- "context": "instream",
- "mimes": ["video/mp4", "application/javascript"],
- "protocols" : [1,2,3,4,5,6,7,8],
- "playbackmethod" : [1, 2],
- "api":[1,2]
+ "context": "instream",
+ "playerSize": [640,480],
+ "mimes": ["video/mp4", "application/javascript"],
+ "protocols" : [1,2,3,4,5,6,7,8],
+ "playbackmethod" : [1, 2],
+ "api":[1,2],
+ "skip": 1
}
},
"bids": [
{
"bidder": "appnexus",
"params": {
- "placementId": 12527596,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 12527596
}
}
]
@@ -353,25 +342,22 @@ The following is a sample JSON definition of the plugin configuration defining c
"prebidPath" : "//files.prebid.org/prebid-org.js", // not for production use
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
- "context": "instream",
- "mimes": ["video/mp4", "application/javascript"],
- "protocols" : [1,2,3,4,5,6,7,8],
- "playbackmethod" : [1, 2],
- "api":[1,2]
+ "context": "instream",
+ "playerSize": [640,480],
+ "mimes": ["video/mp4", "application/javascript"],
+ "protocols" : [1,2,3,4,5,6,7,8],
+ "playbackmethod" : [1, 2],
+ "api":[1,2],
+ "skip": 1
}
},
"bids": [
{
"bidder": "appnexus",
"params": {
- "placementId": 12531984,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 12531984
}
}
]
@@ -452,25 +438,22 @@ The following is a sample JSON definition of the plugin configuration defining c
"prebidPath" : "//files.prebid.org/prebid-org.js", // not for production use
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
- "context": "instream",
- "mimes": ["video/mp4", "application/javascript"],
- "protocols" : [1,2,3,4,5,6,7,8],
- "playbackmethod" : [1, 2],
- "api":[1,2]
+ "context": "instream",
+ "playerSize": [640,480],
+ "mimes": ["video/mp4", "application/javascript"],
+ "protocols" : [1,2,3,4,5,6,7,8],
+ "playbackmethod" : [1, 2],
+ "api":[1,2],
+ "skip": 1
}
},
"bids": [
{
"bidder": "appnexus",
"params": {
- "placementId": 12531977,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 12531977
}
}
]
diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.md b/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.md
index 7f75fe1abb..0ab409f6cd 100644
--- a/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.md
+++ b/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.md
@@ -51,17 +51,20 @@ The following is a sample Brightcove Player Prebid Plugin integration that invok
// the set of bidders here shows how to specify the AppNexus video bidder: appnexus
var params = {
code : 'my-video-tag',
- sizes : [640, 480],
- mediaType: 'video',
+ mediaTypes: {
+ video: {
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
+ }
bids: [
{
bidder: 'appnexus',
params: {
- placementId: 12334567,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 12334567
}
}
]
diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-sample-studio-integration-general-method.md b/dev-docs/plugins/bc/bc-prebid-plugin-sample-studio-integration-general-method.md
index b684bc04fe..3f8ee393f8 100644
--- a/dev-docs/plugins/bc/bc-prebid-plugin-sample-studio-integration-general-method.md
+++ b/dev-docs/plugins/bc/bc-prebid-plugin-sample-studio-integration-general-method.md
@@ -54,23 +54,20 @@ This page presents a sample publisher page using the General Integration Method
"prebidPath": "//files.prebid.org/prebid-org.js", // not for production use
"biddersSpec": {
”code": "my-video-tag",
- "sizes": [640,480],
"mediaTypes": {
"video": {
"context": "instream",
- "mimes": ["video/mp4","application/javascript"],
- "protocols": [1,2,3,4,5,6,7,8],
- "playbackmethod": [1,2],
+ "playerSize": [640,480],
+ "mimes": ["video/mp4","application/javascript"],
+ "protocols": [1,2,3,4,5,6,7,8],
+ "playbackmethod": [1,2],
"api": [1,2 ]
}
},
"bids": [{
"bidder": "appnexus",
"params": {
- "placementId": 8845778,
- "video": {"skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 8845778
}
}]
},
diff --git a/dev-docs/plugins/cross-player-prebid-component/cross-player-config.md b/dev-docs/plugins/cross-player-prebid-component/cross-player-config.md
index 555f092124..7a62c85734 100644
--- a/dev-docs/plugins/cross-player-prebid-component/cross-player-config.md
+++ b/dev-docs/plugins/cross-player-prebid-component/cross-player-config.md
@@ -300,10 +300,10 @@ Here is a sample Prebid configuration JSON object returned via URL:
"prebidPath" : "//acdn.adnxs.com/prebid/not-for-prod/prebid.js",
"biddersSpec" : {
"code" : "my-video-tag",
- "sizes" : [640, 480],
"mediaTypes": {
"video": {
"context": "instream",
+ "playerSize": [640, 480],
"mimes": ["video/mp4", "application/javascript"],
"protocols" : [1,2,3,4,5,6,7,8],
"playbackmethod" : [1, 2],
@@ -314,11 +314,7 @@ Here is a sample Prebid configuration JSON object returned via URL:
{
"bidder": "appnexus",
"params": {
- "placementId": 9999,
- "video": {
- "skippable": true,
- "playback_method": ["auto_play_sound_off"]
- }
+ "placementId": 9999
}
}
]
diff --git a/dev-docs/prebid-troubleshooting-guide.md b/dev-docs/prebid-troubleshooting-guide.md
index a842461c37..70f4d1f22b 100644
--- a/dev-docs/prebid-troubleshooting-guide.md
+++ b/dev-docs/prebid-troubleshooting-guide.md
@@ -2,10 +2,6 @@
layout: page_v2
title: Prebid.js Troubleshooting Guide
head_title: Prebid.js Troubleshooting Guide
-description: How to troubleshoot Prebid.js from the perspective of an ad call from start to finish.
-pid: 10
-top_nav_section: dev_docs
-nav_section: troubleshooting
sidebarType: 1
---
@@ -14,109 +10,4 @@ sidebarType: 1
# Prebid.js Troubleshooting Guide
{:.no_toc}
-{: .alert.alert-danger :}
-Prebid.org does not support any version of Prebid.js prior to version 1.0.
-
-Use this guide to troubleshoot your Prebid.js integration. You can follow this guide sequentially to determine whether Prebid.js is working as intended on your website. It takes you through the ad call from start to finish.
-
-* TOC
-{:toc}
-
-## Check Your Prebid Version
-
-The open source code in Prebid.js can change frequently. To see what version of Prebid.js you are using, open your browser console and type `pbjs.version;`.
-
-You can reference this against the changes listed in the [Prebid.js Release Notes](https://github.com/prebid/Prebid.js/releases).
-
-## Delay the Ad Server Call so Key-Values can be Set
-
-Make sure that you delay any calls to the ad server. This allows all of the key-values to be set before the auction in the ad server occurs.
-
-Within Google Ad Manager, this is achieved by adding the following code to your page. It should be called before any of the ad server code to make sure it runs first.
-
-{% highlight js %}
-var googletag = googletag || {};
-googletag.cmd = googletag.cmd || [];
-googletag.cmd.push(function() {
- googletag.pubads().disableInitialLoad();
-});
-{% endhighlight %}
-
-## Check the Ad Units on the Page
-
-Make sure the ad units configured for Prebid.js match up with the ad units that have been set up in your ad server.
-
-You can review what ad units have been configured for Prebid by opening your browser console and typing `pbjs.getBidResponses();`. This will show a list of what div IDs are present:
-
- showing ad units in browser console"){: .pb-lg-img :}
-
-## List your Bids and Bidders
-
-Open your browser console and type `pbjs.getBidResponses();` to see a list of the ad units that have been configured. This also shows what bids have been returned from each of the bidder partners in chronological order as shown in the screenshot below.
-
-To see all of the winning bids, open your browser console and type [`pbjs.getAllWinningBids();`]({{site.baseurl}}/dev-docs/publisher-api-reference/getAllWinningBids.html).
-
-{: .alert.alert-danger :}
-Keep in mind that any bid responses that come back after [the timeout you configured during setup]({{site.github.url}}/dev-docs/getting-started.html#set-the-ad-server-timeout) will not be sent to the ad server.
-
-{: .alert.alert-success :}
-You can also [print this data to the console in table format]({{site.baseurl}}/dev-docs/troubleshooting-tips.html#see-all-bids-in-the-console) for easier reading.
-
-"){: .pb-lg-img :}
-
-## Verify your Ad Server Targeting
-
-After the auction on page has occurred, Prebid.js will set key-value targeting for the ad server for those bids that have been returned before the [timeout you configured during setup]({{site.github.url}}/dev-docs/getting-started.html#set-the-ad-server-timeout).
-
-To see what values Prebid.js intends to send to the ad server, open your browser console and type `pbjs.getAdserverTargeting();` as shown below:
-
-"){: .pb-lg-img :}
-
-{: .alert.alert-danger :}
-Note that if no bids are returned, no key-values will be set. You may need to increase your timeout setting or reach out to your bidder partners to determine why no bid responses are being sent.
-
-## Check the Ad Server's Auction
-
-After the Prebid auction has occurred and key-values have been set for the ad server, the ad server will use the line items targeting those key-values within its auction.
-
-If you're using Google Ad Manager, you can verify this by using the [Google Publisher Console](https://support.google.com/dfp_sb/answer/2462712?hl=en), which can be accessed as follows:
-
-+ Open your browser's console and type `googletag.openConsole();`
-
-+ Append `googfc` as a query parameter to the URL. Then, click the *Delivery Diagnostics* option to reveal most of the information described below.
-
-To make sure your ad server is set up correctly, answer the following questions:
-
-+ **How many ads have been fetched for an ad unit?** Ideally, only 1 ad will be requested on page load. If not, check for unnecessary extra calls to the ad server in your page's source code.
-
- {: .pb-sm-img :}
-
-+ **Are the key-values being set in the ad server?** If not, review your page's source code to ensure that the Prebid auction completes **before** sending the key-value targeting to the ad server.
-
- {: .pb-lg-img :}
-
-+ **Has the ad server order been activated?** If not, you'll have to activate the order to see Prebid-delivered ads.
-
-+ **Are there other higher priority campaigns running within your ad server?** Higher priority campaigns will prevent Prebid ads with a higher CPM bid from winning in the ad server's auction. For testing purposes, you may want to pause these campaigns or have them excluded when the prebid key values are present.
-
-+ **Is there other remnant inventory in the ad server with a higher CPM that is winning?** To test for this, you may want to use a test creative set up within a bidder partner that has a high CPM or create artificial demand with a [bidCPMadjustment]({{site.github.url}}/dev-docs/publisher-api-reference/bidderSettings.html).
-
-+ **Have you set up all of the line items in the ad server to match the [setPriceGranularity setting]({{site.github.url}}/dev-docs/examples/custom-price-buckets.html) within Prebid.js?** All of the line items that correspond to your price granularity settings must be set up in your ad server. When there are gaps in the price granularity of your line item setup, bids will be reduced according to the size of the gap. For example, with [dense granularity]({{site.github.url}}/dev-docs/publisher-api-reference.html#dense-granularity), a $3.32 bid will be sent to the ad server as $3.30.
-
-## Look for the Winning Bid
-
-When a prebid line item wins the ad server's auction, a `renderAd` event will be logged in the browser console. To see this event, you need to do either of the following before the auction:
-
-+ Have typed `pbjs.logging=true` into your your browser console
-
-+ Appended `pbjs_debug=true` as a query parameter to the URL
-
-When this event is logged, it shows that Prebid.js has requested to render the ad from the winning bidder partner, and that this partner's bid has won both the Prebid and ad server auctions.
-
-{: .pb-lg-img :}
-
-## Related Topics
-
-+ [Developer Troubleshooting Tips]({{site.github.url}}/dev-docs/troubleshooting-tips.html)
-
-+ [Common Setup Issues]({{site.github.url}}/dev-docs/common-issues.html)
+Moved to a new [Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html)
diff --git a/dev-docs/publisher-api-reference/addAdUnits.md b/dev-docs/publisher-api-reference/addAdUnits.md
index c955e885ce..60df9ebc50 100644
--- a/dev-docs/publisher-api-reference/addAdUnits.md
+++ b/dev-docs/publisher-api-reference/addAdUnits.md
@@ -123,17 +123,17 @@ pbjs.addAdUnits({
mediaTypes: {
video: {
context: 'instream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
},
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361,
- video: {
- skippable: true,
- playback_methods: ['auto_play_sound_off']
- }
+ placementId: 13232361
}
}]
});
@@ -147,7 +147,11 @@ pbjs.addAdUnit({
mediaTypes: {
video: {
context: 'outstream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
renderer: {
@@ -209,7 +213,11 @@ pbjs.addAdUnits({
},
video: {
context: 'outstream',
- playerSize: [400, 600],
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
},
},
bids: [
diff --git a/dev-docs/publisher-api-reference/bidderSettings.md b/dev-docs/publisher-api-reference/bidderSettings.md
index 224ef27548..c2ddb80c18 100644
--- a/dev-docs/publisher-api-reference/bidderSettings.md
+++ b/dev-docs/publisher-api-reference/bidderSettings.md
@@ -58,8 +58,8 @@ you'll need to fully manage the targeting -- the default `hb_` targeting variabl
**Keyword targeting for all bidders**
The below code snippet is the *default* setting for ad server targeting. For each bidder's bid,
-Prebid.js will set 6 keys (`hb_bidder`, `hb_adid`, `hb_pb`, `hb_size`, `hb_source`, `hb_format`) with their corresponding values.
-In addition, video will receive additional keys: `hb_cache_id`, `hb_uuid`, and `hb_cache_host`.
+Prebid.js will set 6 keys (`hb_bidder`, `hb_adid`, `hb_pb`, `hb_size`, `hb_format`) with their corresponding values.
+In addition, video will receive additional keys: `hb_cache_id` and `hb_cache_host`.
The key value pair targeting is applied to the bid's corresponding ad unit. Your ad ops team will have the ad server's line items and creatives to utilize these keys.
If you'd like to customize the key value pairs, you can overwrite the settings as the below example shows. *Note* that once you updated the settings, let your ad ops team know about the change, so they can update the line item targeting accordingly. See the [Ad Ops](/adops/before-you-start.html) documentation for more information.
@@ -110,7 +110,7 @@ pbjs.bidderSettings = {
{% endhighlight %}
{: .alert.alert-warning :}
-Note that the existence of `bidderSettings.adserverTargeting.standard` will prevent the system from adding the standard display targeting values: hb_bidder, hb_adid, hb_pb, hb_size, hb_source, and hb_format. However, if the mediaType is video and `bidderSettings.adserverTargeting.standard` does not specify hb_uuid, hb_cache_id, or hb_cache_host, they will be added unless `bidderSettings.sendStandardTargeting` is set to false.
+Note that the existence of `bidderSettings.adserverTargeting.standard` will prevent the system from adding the standard display targeting values: hb_bidder, hb_adid, hb_pb, hb_size, and hb_format. However, if the mediaType is video and `bidderSettings.adserverTargeting.standard` does not specify hb_uuid, hb_cache_id, or hb_cache_host, they will be added unless `bidderSettings.sendStandardTargeting` is set to false.
**Keyword targeting for a specific bidder**
diff --git a/dev-docs/publisher-api-reference/getConfig.md b/dev-docs/publisher-api-reference/getConfig.md
index 9ff5f12ff9..99ac02fd88 100644
--- a/dev-docs/publisher-api-reference/getConfig.md
+++ b/dev-docs/publisher-api-reference/getConfig.md
@@ -4,8 +4,9 @@ title: pbjs.getConfig([string])
description:
---
+## Overview
-The `getConfig` function is for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned.
+The `getConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. Be careful with use of this function, as it returns a reference to the configuration instead of a clone. The readConfig function has been introduced for safer use.
{% highlight js %}
/* Get config object */
@@ -15,7 +16,10 @@ config.getConfig()
config.getConfig('debug')
{% endhighlight %}
-The `getConfig` function also contains a 'subscribe' ability that adds a callback function to a set of listeners that are invoked whenever `setConfig` is called. The subscribed function will be passed the options object that was used in the `setConfig` call. Individual topics can be subscribed to by passing a string as the first parameter and a callback function as the second. For example:
+
+### Subscribe
+
+The `getConfig` function contains a `subscribe` feature that adds a callback function to a set of listeners that are invoked whenever `setConfig` is called. The `subscribed` function will be passed the `options` object that was used in the `setConfig` call. Individual topics can be subscribed to by passing a string as the first parameter and a callback function as the second. For example:
{% highlight js %}
@@ -31,4 +35,4 @@ unsubscribe(); // no longer listening
{% endhighlight %}
-
\ No newline at end of file
+
diff --git a/dev-docs/publisher-api-reference/getEvents.md b/dev-docs/publisher-api-reference/getEvents.md
index 70fd24a5a7..fb1168f5fd 100644
--- a/dev-docs/publisher-api-reference/getEvents.md
+++ b/dev-docs/publisher-api-reference/getEvents.md
@@ -4,23 +4,19 @@ title: pbjs.getEvents()
description:
---
+The `getEvents` method returns a copy of all emitted events since the page loaded.
-The methods `onEvent` and `offEvent` are provided for you to register
-a callback to handle a Prebid.js event.
+**Kind**: static method of `pbjs`
-The `getEvents` method returns a copy of all emitted events.
+**Args**: none
-The optional `id` parameter provides more finely-grained event
-callback registration. This makes it possible to register callback
-events for a specific item in the event context.
+**Returns**: `array of objects`
-For example, `bidWon` events will accept an `id` for ad unit code.
-`bidWon` callbacks registered with an ad unit code id will be called
-when a bid for that ad unit code wins the auction. Without an `id`
-this method registers the callback for every `bidWon` event.
-
-{: .alert.alert-info :}
-Currently, `bidWon` is the only event that accepts the `id` parameter.
+**Returned Object Params**:
+- eventType (see table below)
+- args (varies for each event type)
+- id (only for bidWon, set to adUnit.code)
+- elapsedTime
The available events are:
@@ -30,6 +26,7 @@ The available events are:
| auctionInit | The auction has started | Object containing auction details |
| auctionEnd | The auction has ended | Object containing auction details |
| beforeRequestBids | Bids are about to be requested from adapters (added in 3.x) | Array of adunits in the auction |
+| beforeBidderHttp | bidder network request is about be triggered | Array of Bid request objects |
| bidRequested | A bid was requested from a specific bidder | Bid request object |
| bidResponse | A bid response has arrived | Bid response object |
| bidAdjustment | A bid was adjusted | Bid response object |
@@ -39,75 +36,20 @@ The available events are:
| requestBids | Bids have been requested from adapters (i.e. pbjs.requestBids() was called) | None |
| addAdUnits | Ad units have been added to the auction | None |
| adRenderFailed| Ad rendering failed | Object containing 'reason' and 'message' |
+| adRenderSucceeded | Ad rendering succeeded| Object containing the document containing the ad, the bid, and the adId |
| auctionDebug | An error was logged to the console | Object containing 'type' and 'arguments' |
| bidderDone | A bidder has signaled they are done responding | Bid request object |
| tcf2Enforcement | There was a TCF2 enforcement action taken | `{ storageBlocked: ['moduleA', 'moduleB'], biddersBlocked: ['moduleB'], analyticsBlocked: ['moduleC'] }` |
-The examples below show how these events can be used.
-
-Events example 1
-{% highlight js %}
-
- /* Log when ad units are added to Prebid */
- pbjs.onEvent('addAdUnits', function() {
- console.log('Ad units were added to Prebid.')
- console.log(pbjs.adUnits);
- });
-
- /* Log when Prebid wins the ad server auction */
- pbjs.onEvent('bidWon', function(data) {
- console.log(data.bidderCode+ ' won the ad server auction for ad unit ' +data.adUnitCode+ ' at ' +data.cpm+ ' CPM');
- });
-
-{% endhighlight %}
-
-Events example 2: Use the optional 3rd parameter for the `bidWon` event
-{% highlight js %}
- /* This handler will be called only for rightAdUnit */
- /* Uses the `pbjs.offEvent` method to remove the handler once it has been called */
- var bidWonHandler = function bidWonHandler() {
- console.log('bidWonHandler: ', arguments);
- pbjs.offEvent('bidWon', bidWonHandler, rightAdUnit);
- };
-
- var rightAdUnit="/111111/right";
- pbjs.que.push(function () {
- var adUnits = [{
- code: rightAdUnit,
- ...
- },{
- ...
- }];
-
- pbjs.addAdUnits(adUnits);
- pbjs.requestBids({
- ...
- });
-
- /* Register a callback for just the rightSlot `bidWon` event */
- /* Note that defining an event that uses the 3rd parameter must come after initiating the auction */
- pbjs.onEvent('bidWon', bidWonHandler, rightAdUnit);
+The example below shows how these events can be used.
- ...
-{% endhighlight %}
-
-Events example 3: Dynamically modify the auction
{% highlight js %}
- var bidderFilter = function bidderFilter(adunits) {
- // pub-specific logic to optimize bidders
- // e.g. "remove any that haven't bid in the last 4 refreshes"
- };
- pbjs.onEvent('beforeRequestBids', bidderFilter);
+ pbjs.getEvents().forEach(event => {
+ console.log("event: "+event.eventType)
+ });
{% endhighlight %}
-Events example 4: Log errors and render fails to your own endpoint
-{% highlight js %}
- pbjs.onEvent('adRenderFailed', function () {
- // pub-specific logic to call their own endpoint
- });
- pbjs.onEvent('auctionDebug', function () {
- // pub-specific logic to call their own endpoint
- });
-{% endhighlight %}
-
\ No newline at end of file
+## See Also
+- [onEvent](/dev-docs/publisher-api-reference/onEvent.html)
+- [offEvent](/dev-docs/publisher-api-reference/offEvent.html)
diff --git a/dev-docs/publisher-api-reference/getNoBids.md b/dev-docs/publisher-api-reference/getNoBids.md
index 8730a42852..aa2ebd491f 100644
--- a/dev-docs/publisher-api-reference/getNoBids.md
+++ b/dev-docs/publisher-api-reference/getNoBids.md
@@ -5,6 +5,6 @@ description:
---
-Use this method to get all of the bid requests that resulted in a NO_BID. These are bid requests that were sent to a bidder but, for whatever reason, the bidder decided not to bid on. Used by debugging snippet in [Tips for Troubleshooting](/dev-docs/troubleshooting-tips.html).
+Use this method to get all of the bid requests that resulted in a NO_BID. These are bid requests that were sent to a bidder but, for whatever reason, the bidder decided not to bid on. Used by debugging snippet in the [Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html).
-+ `pbjs.getNoBids()`: returns an array of bid request objects that were deliberately not bid on by a bidder.
\ No newline at end of file
++ `pbjs.getNoBids()`: returns an array of bid request objects that were deliberately not bid on by a bidder.
diff --git a/dev-docs/publisher-api-reference/offEvent.md b/dev-docs/publisher-api-reference/offEvent.md
index 1a365aafc2..31dc71af82 100644
--- a/dev-docs/publisher-api-reference/offEvent.md
+++ b/dev-docs/publisher-api-reference/offEvent.md
@@ -1,6 +1,56 @@
---
layout: api_prebidjs
-title: pbjs.offEvent(event, handler, id)
+title: pbjs.offEvent(eventType, handler, id)
description:
---
+Turns off an event callback defined with [onEvent](/dev-docs/publisher-api-reference/onEvent.html)
+
+**Kind**: static method of `pbjs`
+
+**Args**: eventType, callbackFunction, id
+
+**Returns**: none
+
+See the [getEvents](/publisher-api-reference/getEvents.html) function for the full list of eventTypes supported.
+
+Causes PBJS to search through registered event callbacks and remove the
+supplied callbackFunction for the specifc eventType.
+
+The optional `id` parameter provides more finely-grained event
+callback de-registration. This makes it possible to de-register callback
+events for a specific item in the event context.
+
+Example
+
+{% highlight js %}
+ /* This handler will be called only for rightAdUnit */
+ /* Uses the `pbjs.offEvent` method to remove the handler once it has been called */
+ var bidWonHandler = function bidWonHandler() {
+ console.log('bidWonHandler: ', arguments);
+ pbjs.offEvent('bidWon', bidWonHandler, rightAdUnit);
+ };
+
+ var rightAdUnit="/111111/right";
+ pbjs.que.push(function () {
+ var adUnits = [{
+ code: rightAdUnit,
+ ...
+ },{
+ ...
+ }];
+ pbjs.addAdUnits(adUnits);
+ pbjs.requestBids({
+ ...
+ });
+
+ /* Register a callback for just the rightSlot `bidWon` event */
+ /* Note that defining an event that uses the 3rd parameter must come after initiating the auction */
+ pbjs.onEvent('bidWon', bidWonHandler, rightAdUnit);
+
+ ...
+{% endhighlight %}
+
+## See Also
+- [getEvents](/dev-docs/publisher-api-reference/getEvents.html)
+- [onEvent](/dev-docs/publisher-api-reference/onEvent.html)
diff --git a/dev-docs/publisher-api-reference/onEvent.md b/dev-docs/publisher-api-reference/onEvent.md
index 716048f519..e322367352 100644
--- a/dev-docs/publisher-api-reference/onEvent.md
+++ b/dev-docs/publisher-api-reference/onEvent.md
@@ -1,6 +1,65 @@
---
layout: api_prebidjs
-title: pbjs.onEvent(event, handler, id)
+title: pbjs.onEvent(eventType, handler, id)
description:
---
+This routine allows the page (or module) to create a callback function that's invoked when heading bidding events are fired.
+
+**Kind**: static method of `pbjs`
+
+**Args**: eventType, callbackFunction, id
+
+**Returns**: none
+
+See the [getEvents](/publisher-api-reference/getEvents.html) function for the full list of eventTypes supported.
+
+The optional `id` parameter provides more finely-grained event
+callback registration. This makes it possible to register callback
+events for a specific item in the event context.
+
+For example, `bidWon` events will accept an `id` for ad unit code.
+`bidWon` callbacks registered with an ad unit code id will be called
+when a bid for that ad unit code wins the auction. Without an `id`
+this method registers the callback for every `bidWon` event.
+
+{: .alert.alert-info :}
+Currently, `bidWon` is the only event that accepts the `id` parameter.
+
+Example 1: Basic event logging
+```
+ /* Log when ad units are added to Prebid */
+ pbjs.onEvent('addAdUnits', function() {
+ console.log('Ad units were added to Prebid.')
+ console.log(pbjs.adUnits);
+ });
+
+ /* Log when Prebid wins the ad server auction */
+ pbjs.onEvent('bidWon', function(data) {
+ console.log(data.bidderCode+ ' won the ad server auction for ad unit ' +data.adUnitCode+ ' at ' +data.cpm+ ' CPM');
+ });
+
+```
+
+Example 2: Dynamically modify the auction
+```
+ var bidderFilter = function bidderFilter(adunits) {
+ // pub-specific logic to optimize bidders
+ // e.g. "remove any that haven't bid in the last 4 refreshes"
+ };
+ pbjs.onEvent('beforeRequestBids', bidderFilter);
+```
+
+Example 3: Log errors and render fails to your own endpoint
+```
+ pbjs.onEvent('adRenderFailed', function () {
+ // pub-specific logic to call their own endpoint
+ });
+ pbjs.onEvent('auctionDebug', function () {
+ // pub-specific logic to call their own endpoint
+ });
+```
+
+## See Also
+- [getEvents](/dev-docs/publisher-api-reference/getEvents.html)
+- [offEvent](/dev-docs/publisher-api-reference/offEvent.html)
diff --git a/dev-docs/publisher-api-reference/readConfig.md b/dev-docs/publisher-api-reference/readConfig.md
new file mode 100644
index 0000000000..734647e762
--- /dev/null
+++ b/dev-docs/publisher-api-reference/readConfig.md
@@ -0,0 +1,18 @@
+---
+layout: api_prebidjs
+title: pbjs.readConfig([string])
+description:
+---
+
+
+The `readConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. The readConfig function has been introduced for safer use of the getConfig functionality, as it returns a clone.
+
+{% highlight js %}
+/* Get config object */
+config.readConfig()
+
+/* Get debug config */
+config.readConfig('debug')
+{% endhighlight %}
+
+
diff --git a/dev-docs/publisher-api-reference/setConfig.md b/dev-docs/publisher-api-reference/setConfig.md
index e3e02a8832..e9c0a4ee33 100644
--- a/dev-docs/publisher-api-reference/setConfig.md
+++ b/dev-docs/publisher-api-reference/setConfig.md
@@ -52,7 +52,7 @@ Debug mode can be enabled permanently in a page if desired. In debug mode,
Prebid.js will post additional messages to the browser console and cause Prebid Server to
return additional information in its response. If not specified, debug is off.
Note that debugging can be specified for a specific page view by adding
-`pbjs_debug=true` to the URL's query string. e.g. /pbjs_demo.html?pbjs_debug=true See [Prebid.js troubleshooting tips](/dev-docs/troubleshooting-tips.html) for more information.
+`pbjs_debug=true` to the URL's query string. e.g. /pbjs_demo.html?pbjs_debug=true See [Prebid.js troubleshooting guide](/troubleshooting/troubleshooting-guide.html) for more information.
Turn on debugging permanently in the page:
{% highlight js %}
@@ -268,6 +268,9 @@ pbjs.setConfig({ pageUrl: "https://example.com/index.html" })
#### Publisher Domain
+{: .alert.alert-warning :}
+This API is deprecated. Please use 'pageUrl' instead.
+
Set the publisher's domain where Prebid is running, for cross-domain iframe communication:
{% highlight js %}
@@ -371,34 +374,44 @@ This implies that ranges should have max values that are really the min value of
#### Media Type Price Granularity
-The default [Prebid price granularities](#setConfig-Price-Granularity) cap out at $20, which isn't always convenient for video ads, which can command more than $20. One solution is to just set up a
-custom price
-granularity as described above. Another approach is
-`mediaTypePriceGranularity` config that may be set to define granularities for each of five media types:
-banner, video, video-instream, video-outstream, and native. e.g.
+The standard [Prebid price granularities](#setConfig-Price-Granularity) cap out at 20, which isn't always convenient for video ads, which can command more than that. One solution is to set up a custom price
+granularity as described above. Another approach is to use
+`mediaTypePriceGranularity` config that may be set to define different price bucket
+structures for different types of media:
+- for each of five media types: banner, video, video-instream, video-outstream, and native.
+- it is recommended that defined granularities be custom. It's possible to define "standard" granularities (e.g. "medium"), but it's not possible to mix both custom and standard granularities.
{% highlight js %}
-const customPriceGranularity = {
+const customPriceGranularityVideo = {
'buckets': [
- { 'precision': 2, 'max':x 5, 'increment': 0.25 },
+ { 'precision': 2, 'max': 5, 'increment': 0.25 },
{ 'precision': 2, 'max': 20, 'increment': 0.5 },
{ 'precision': 2, 'max': 100, 'increment': 1 }
]
};
+const customPriceGranularityBanner = {
+ 'buckets': [
+ { 'precision': 2, 'max': 5, 'increment': 0.5 },
+ { 'precision': 2, 'max': 20, 'increment': 1 }
+ ]
+};
pbjs.setConfig({'mediaTypePriceGranularity': {
'video': customPriceGranularity, // used as default for instream video
- 'video-outstream': customPriceGranularityOutstream,
- 'banner': 'medium',
- 'native': 'medium',
+ 'video-outstream': customPriceGranularityBanner,
+ 'banner': 'customPriceGranularityBanner'
}
});
{% endhighlight %}
Any `mediaTypePriceGranularity` setting takes precedence over `priceGranularity`.
+{: .alert.alert-warning :}
+mediaTypePriceGranularity works in two modes: either auctions contain adunits with a single media type, or all defined price granularities are custom.
+i.e. You cannot run an auction containing a mix of mediatypes across an adunit AND having a mix of "custom" and "standard" price granularities across mediatypes.
+
{: .alert.alert-info :}
-Note: mediaTypePriceGranularity is the only place that 'video-outstream' or 'video-instream'
+Note that mediaTypePriceGranularity is the only place that 'video-outstream' or 'video-instream'
are recognized. This was driven by the recognition that outstream often shares line items with banner.
If the mediatype is video, the price bucketing code further looks at the context (e.g. outstream) to see if there's
a price granularity override. If it doesn't find 'video-outstream' defined, it will then look for just 'video'.
@@ -456,8 +469,8 @@ The `s2sConfig` properties:
| `enabled` | Optional | Boolean | Enables this s2sConfig block - defaults to `false` |
| `timeout` | Required | Integer | Number of milliseconds allowed for the server-side auctions. This should be approximately 200ms-300ms less than your Prebid.js timeout to allow for all bids to be returned in a timely manner. See the Additional Notes below for more information. |
| `adapter` | Required | String | Adapter to use to connect to Prebid Server. Defaults to 'prebidServer' |
-| `endpoint` | Required | URL | Defines the auction endpoint for the Prebid Server cluster |
-| `syncEndpoint` | Required | URL | Defines the cookie_sync endpoint for the Prebid Server cluster |
+| `endpoint` | Required | URL or Object | Defines the auction endpoint for the Prebid Server cluster. See table below for object config properties. |
+| `syncEndpoint` | Required | URL or Object | Defines the cookie_sync endpoint for the Prebid Server cluster. See table below for object config properties. |
| `userSyncLimit` | Optional | Integer | Max number of userSync URLs that can be executed by Prebid Server cookie_sync per request. If not defined, PBS will execute all userSync URLs included in the request. |
| `coopSync` | Optional | Boolean | Whether or not PBS is allowed to perform "cooperative syncing" for bidders not on this page. Publishers help each other improve match rates by allowing this. Default is true. Supported in PBS-Java only. |
| `defaultTtl` | Optional | Integer | Configures the default TTL in the Prebid Server adapter to use when Prebid Server does not return a bid TTL - 60 if not set |
@@ -465,11 +478,20 @@ The `s2sConfig` properties:
| `extPrebid` | Optional | Object | Arguments will be added to resulting OpenRTB payload to Prebid Server in request.ext.prebid. See the examples below. |
| `syncUrlModifier` | Optional | Object | Function to modify a bidder's sync url before the actual call to the sync endpoint. Bidder must be enabled for s2sConfig. |
+If `endpoint` and `syncEndpoint` are objects, these are the supported properties:
+
+{: .table .table-bordered .table-striped }
+| Attribute | Scope | Type | Description |
+|------------+---------+---------+---------------------------------------------------------------|
+| p1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for non-consent requests or users who grant consent. |
+| noP1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for users who do not grant consent. (This is useful for a server configured to not accept any cookies to ensure compliance regulations.) |
+
**Notes on s2sConfig properties**
-- Currently supported vendors are: appnexus & rubicon
+- Currently supported vendors are: appnexus, openx, and rubicon
- When using `defaultVendor` option, `accountId` and `bidders` properties still need to be defined.
- If the `s2sConfig` timeout is greater than the Prebid.js timeout, the `s2sConfig` timeout will be automatically adjusted to 75% of the Prebid.js timeout in order to fit within the auction process.
+- When using the `endpoint` or `syncEndpoint` object configs, you should define both properties. If either property is not defined, Prebid Server requests for that type of user will not be made. If you do not need to distinguish endpoints for consent reasons, you can simply define the same URL value in both fields or use the String version of the field (which is configured to use defined URL for all users).
{: .alert.alert-warning :}
**Errors in bidder parameters will cause Prebid Server to reject the
@@ -503,6 +525,38 @@ pbjs.setConfig({
Additional options for `s2sConfig` may be enabled by including the [Server-to-Server testing module]({{site.baseurl}}/dev-docs/modules/s2sTesting.html).
+s2sConfig example with the endpoint attributes defined as strings:
+{% highlight js %}
+pbjs.setConfig({
+ s2sConfig: [{
+ accountId: '1001',
+ bidders: ['bidderA', 'bidderB'],
+ endpoint: 'https://mypbs.example.com/path',
+ syncEndpoint: 'https://mypbs.example.com/path',
+ timeout: 300
+ }]
+})
+{% endhighlight %}
+
+s2sConfig example with the endpoint attributes defined as objects:
+{% highlight js %}
+pbjs.setConfig({
+ s2sConfig: [{
+ accountId: '1001',
+ bidders: ['bidderA', 'bidderB'],
+ endpoint: {
+ p1Consent: 'https://mypbs.example.com/path',
+ noP1Consent: 'https://mypbs2.example.com/path'
+ },
+ syncEndpoint: {
+ p1Consent: 'https://mypbs.example.com/path',
+ noP1Consent: 'https://mypbs2.example.com/path'
+ }
+ timeout: 300
+ }]
+})
+{% endhighlight %}
+
**Server-Side Aliases**
You may want to run a particular bidder on the client for banner, but that same bidder on the
@@ -713,6 +767,7 @@ The `targetingControls` object passed to `pbjs.setConfig` provides some options
| auctionKeyMaxChars | integer | Specifies the maximum number of characters the system can add to ad server targeting. |
| alwaysIncludeDeals | boolean | If [enableSendAllBids](#setConfig-Send-All-Bids) is false, set this value to `true` to ensure that deals are sent along with the winning bid |
| allowTargetingKeys | Array of Strings | Selects supported default targeting keys. |
+| allowSendAllBidsTargetingKeys | Array of Strings | Selects supported default targeting keys. |
{: .alert.alert-info :}
Note that this feature overlaps and can be used in conjunction with [sendBidsControl.bidLimit](#setConfig-Send-Bids-Control).
@@ -780,9 +835,9 @@ The targeting key names and the associated prefix value filtered by `allowTarget
| PRICE_BUCKET | `hb_pb` | yes | The results of the [price granularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity) calculation. |
| SIZE | `hb_size` | yes | '300x250' |
| DEAL | `hb_deal` | yes | |
-| SOURCE | `hb_source` | yes | 'client' or 's2s' |
+| SOURCE | `hb_source` | no | 'client' or 's2s' |
| FORMAT | `hb_format` | yes | 'banner', 'video', or 'native' |
-| UUID | `hb_uuid` | yes | Network cache ID for video |
+| UUID | `hb_uuid` | no | Network cache ID for video |
| CACHE_ID | `hb_cache_id` | yes | Network cache ID for AMP or Mobile |
| CACHE_HOST | `hb_cache_host` | yes | |
| ADOMAIN | `hb_adomain` | no | Set to bid.meta.advertiserDomains[0]. Use cases: report on VAST errors, set floors on certain buyers, monitor volume from a buyer, track down bad creatives. |
@@ -824,6 +879,20 @@ config.setConfig({
});
```
+##### Details on the allowSendAllBidsTargetingKeys setting
+
+The `allowSendAllBidsTargetingKeys` is similar to `allowTargetingKeys` except it limits any default bidder specific keys sent to the adserver when sendAllBids is enabled. Any default bidder specific keys that do not match the mask will not be sent to the adserver. This setting can be helpful if you find that your default Prebid.js implementation is sending key values that your adserver isn't configured to process; extraneous key values may lead to the ad server request being truncated, which can cause potential issues with the delivery or rendering ads. An example of an extraneous key value many publishers may find redundant and want to remove is `hb_bidder_biddercode = biddercode`.
+
+Below is an example config of `allowSendAllBidsTargetingKeys` excluding all default send all bids targeting keys except `hb_adid_biddercode`, `hb_pb_biddercode`:
+
+```javascript
+config.setConfig({
+ targetingControls: {
+ allowSendAllBidsTargetingKeys: ['AD_ID', 'PRICE_BUCKET'],
+ },
+});
+```
+
@@ -1184,15 +1253,16 @@ pbjs.setConfig({
#### Auction Options
-The `auctionOptions` object passed to `pbjs.setConfig` provides a method to specify bidders that the Prebid auction will no longer wait for before determing the auction has completed. This may be helpful if you find there are a number of low performing and/or high timeout bidders in your page's rotation.
+The `auctionOptions` object controls aspects related to auctions.
{: .table .table-bordered .table-striped }
| Field | Scope | Type | Description |
|----------+---------+--------+---------------------------------------------------------------------------------------|
-| `secondaryBidders` | Required | Array of Strings | The bidders that will be removed from determining when an Auction has completed. |
-
-Example config:
+| `secondaryBidders` | Optional | Array of Strings | Specifies bidders that the Prebid auction will no longer wait for before determining the auction has completed. This may be helpful if you find there are a number of low performing and/or high timeout bidders in your page's rotation. |
+| `suppressStaleRender` | Optional | Boolean | When true, prevents `banner` bids from being rendered more than once. It should only be enabled after auto-refreshing is implemented correctly. Default is false.
+##### Examples
+Exclude status of bidder _doNotWaitForMe_ when checking auction completion.
{% highlight js %}
pbjs.setConfig({
'auctionOptions': {
@@ -1201,6 +1271,25 @@ pbjs.setConfig({
});
{% endhighlight %}
+Render winning bids only once.
+{% highlight js %}
+pbjs.setConfig({
+ 'auctionOptions': {
+ 'suppressStaleRender': true
+ }
+});
+{% endhighlight %}
+
+##### More on Stale Rendering
+When auto-refreshing is done incorrectly, it could cause the same bids to be rendered repeatedly. For instance, when googletag.pubads.refresh() is called directly without removing the PBJS targeting, the same hb_ variables get re-sent to GAM, re-chosen, and re-rendered. Over and over without ever asking PBJS for updated targeting variables.
+
+PBJS performs following actions when stale rendering is detected.
+* Log a warning in the browser console if pbjs_debug=true.
+* Emit a `STALE_RENDER` event before `BID_WON` event.
+
+Stale winning bids will continue to be rendered unless `suppressStaleRender` is set to true. Events including `STALE_RENDER` and `BID_WON` are unaffected by this option.
+
+
#### maxNestedIframes
diff --git a/dev-docs/requirements/tcf2/PrebidSupportforEnforcingTCF2.html b/dev-docs/requirements/tcf2/PrebidSupportforEnforcingTCF2.html
index 26e8d898a9..bd7edfa7a2 100644
--- a/dev-docs/requirements/tcf2/PrebidSupportforEnforcingTCF2.html
+++ b/dev-docs/requirements/tcf2/PrebidSupportforEnforcingTCF2.html
@@ -1 +1 @@
-Prebid Support for Enforcing TCF 2.0
Overview
Definitions
Assumptions
Summary of Prebid TCF 2.0 Enforcement
Basic-vs-Full Enforcement
Basic Enforcement
Full Enforcement (Prebid Server Only)
Prebid.js Functional Requirements
Prebid SDK Functional Requirements
Prebid Server Functional Requirements
Overview
The IAB's Transparency and Consent Framework version 2.0 for enhanced support of GDPR is scheduled to take effect Apr 1 2020. It's a major update from TCF 1.1 which Prebid currently supports, and is not compatible with the previous release.
The key changes are:
- More 'purposes' are defined.
- More flexibility for the legal bases used by vendors.
- Different in-page javascript API
References
Definitions
- GDPR - General Data Protection Regulation. The EU's privacy regulations.
- EEA - European Economic Area. The region where the GDPR is in effect.
- IAB - Interactive Advertising Bureau. The ad industry consortium that developed the TCF as a way to help the ad ecosystem adhere to GDPR rules.
- TCF - Transparency and Consent Framework.
- CMP - Consent Management Platform. The user interface part of the TCF.
- GVL - Global Vendors List. The place where each ad entity registers what they do with user data.
- PBS - Prebid Server
- PBJS - Prebid.js
- PBS Host Company - the organization running a cluster of Prebid Servers
- Purpose 1 - Under TCF, there are many defined uses of private data. "Purpose 1" is "Store and/or access information on a device". This means that users must consent before an ad tech vendor reads or writes data from their computer or phone. Those of us dealing with these things a lot memorize the numbers. Forgive us.
- Purpose 2 - "Basic Ad Selection". This looks to be one of the bigger areas of concern because the TCF policy could be interpreted to be a form of ad blocking. Or maybe not. Talk to your lawyers.
- Purpose 4 - "Personalized Ad Selection". Basically, if the user doesn’t consent, they don’t want ads based on any type of direct user profile.
- Purpose 7 - "Measure ad performance". This is another area of concern, because the TCF policy doesn’t clearly define what it means to measure the “effectiveness” of ads. Talk to your lawyers about what this means for your organization.
- Special Feature 1 - "Use precise geolocation data". Special Features are quite different than Purposes. They only allow user "opt-in", and don't have as many layers of nuance as Purposes.
- Legal Basis - how an ad tech vendor views the importance of each Purpose for their mission. If they define "consent" as their "basis" for a given Purpose, they're able to work without some or all aspects of the user's data. But if they define "Legitimate Interest" (LI), they're basically saying "We can't do our job without this data".
- Basic enforcement - a high-level mode of consent confirmation where the looks for a good-faith indication that the user has provided consent or legal basis signals before engaging in a privacy-protected activity. Does not read the GVL.
- Full enforcement - a detailed confirmation mode that reads the GVL, interprets the consent string, and performs legal basis analysis.
Assumptions
Important Legal Note: Prebid.org cannot provide legal advice about GDPR or any other governmental regulation. Our aim is to provide a toolkit of functionality that will let publishers configure header bidding as defined by their legal counsel. We will consider feature suggestions, and review any code offered by the community.
Enforcement of Purpose 2 (basic ad selection) looks to be one of the bigger areas of concern because the TCF policy could be interpreted to be a form of ad blocking. You will need to work with your legal counsel to determine how you intend to handle this scenario. Prebid.js and Prebid Server offer publishers the ability to enforce or not-enforce purposes individually. As an example of the kind of flexibility we aim to offer (*), here are some options you could discuss with your lawyers:
- Treat Purpose 2 as an ad blocker.
- Ignore enforcement of selected Purposes at the Prebid level entirely, assuming that downstream vendors will handle the TCF strings appropriately.
- Ignore enforcement Purpose 2, assuming that users who object to ‘Basic Ads’ will also object to ‘Personalized Ads’, causing any User IDs to be removed from ad requests.
- Ignore the Purpose-Consent portion of Purpose 2, but allow the user to block specific vendors.
(*) - Note on phasing: Please be aware that Prebid.js and Prebid Server will likely not deliver on the full TCF functionality by April 1st. Our initial goal for both products is to support Purpose 1 (Device Access) enforcement by that date. The ability to enforce the other purposes will be developed as soon as we can.
(**) Did we mention that you cannot rely on this document to learn how to configure your header bidding for GDPR? Seriously, talk to your lawyers. |
General
- Prebid.org is neither a data controller nor data processor, but we supply software to both types of entities. Therefore, our software should provide a flexible set of controls necessary for both types of entities to run their businesses.
- Even if Prebid is configured to enforce activities by parsing consent data, publishers and downstream vendors are still responsible for ensuring their legal bases using the consent data they're provided.
- Prebid will ignore the TCF "stack" feature, assuming that the CMP will set the underlying Purposes appropriately.
- Data from the CMP will never be modified before passing to downstream entities.
- If TCF processing is turned on, and the user is determined to be in GDPR scope, and hasn’t provided a consent string, the system should assume a consent string that has no consent offered.
Prebid.js
- Prebid.js will only support parsing the TCF 2.0 consent string.
- TCF 2.0 features are available in Prebid.js only in a consent module, not as part of core. This allows publishers to build two versions of their wrappers: one for users in the EEA, one for users outside of the EEA.
- It's assumed that publishers run in two modes:
- A CMP is loaded on every page so TCF functions and data are fully available.
- Consent data is stored in first party storage and passed to Prebid directly. TCF functions are not available from the CMP.
- Prebid.js will not load the Global Vendors List (GVL) as this would significantly impact the success of header bidding implementations. However, Prebid.js will require a mapping of GVL vendor IDs to Prebid.js bidder codes.
- Further, we assume that not all Prebid adapters will be in the GVL, so we'll need to support reference by GVL ID or bidder code.
- Further, we assume that bidder aliases within one adapter may have different GVL IDs.
- As a result of not having access to GVL entries, Prebid.js will only support ‘Basic Enforcement’.
- TCF2 will be supported in Prebid.js 3.x, with 'no enforcement' being the default option. Prebid.js 4.0 will enforce Purpose 1 by default when the module is included.
- PurposeOneTreatment is ignored for Prebid.js. Publishers who don’t want to enforce Purpose 1 (or any other purpose) need to set Prebid’s configuration appropriately.
Prebid Server
- Prebid Server will need concurrent support of TCF 1.1 and TCF 2.0.
- Prebid Server will need to support “Full Enforcement” checks.
- AMP TCF 2.0 will be passed on the same parameter as TCF 1.1.
Prebid SDK
- Prebid SDK should parse the consent string in order to read the IDFA. Other than that, SDK just passes consent values to Prebid Server..
Summary of Prebid TCF 2.0 Enforcement
TCF Field | In-scope Activities | System | Enforcement | Publisher/ Host Company Controls |
Purpose 1 - Store and/or access information on a device | usersync pixels, user ID modules, and device storage | Prebid.js and Prebid Server and Prebid SDK | May result in preventing one or more uesrsync activities for one or more vendors. | Do not enforce purpose 1 Do not enforce purpose 1 for vendor V Enforce purpose 1 at the vendor level only. |
Purpose 2 - Select basic ads | call bid adapters | Prebid.js and Prebid Server | May result in skipping one or more bid adapters.
All configured modules will be called as usual unless all bidders are eliminated. | Do not enforce purpose 2 Do not enforce purpose 2 for vendor V Enforce purpose 2 at the vendor level only.
|
Purpose 4 - Select Personalized Ads | call bid adapters with userIds | Prebid.js and Prebid Server | May result in removing the userIds before calling one or more bid adapters. | Do not enforce purpose 4 Do not enforce purpose 4 for vendor V Enforce purpose 4 at the vendor level only. |
Purpose 7 - Measure ad performance | initiate analytics | Prebid.js and Prebid Server | May result in skipping one or more analytics adapters. | Do not enforce purpose 7 Do not enforce purpose 7 for vendor V Enforce purpose 7 at the vendor level only. |
Special Feature 1 - Use precise geolocation data | passing lat/long to server-side bid adapters | Prebid Server | May result in rounding lat/long values and IP address before sending to server-side adapters. | Do not enforce Special Feature 1 |
Special Purpose 2 - Technically deliver ads or content | n/a |
Special Purposes do not require consent. If a publisher’s legal team wants to consider SP2, Prebid software should not be called. |
PurposeOneConsent | n/a | Prebid does not provide specific support for enforcing this flag. Instead, publishers may use the provided controls for Purpose 1 and other Prebid configuration to control whether the user’s device is accessed. |
Basic-vs-Full Enforcement
Prebid offers publishers several controls for whether consent/legal basis confirmation is even performed. The following flowchart shows how the controls

Basic Enforcement
The goal of 'basic enforcement' is to confirm that there's enough evidence of consent to pass data on to vendors who have access to the GVL and can fully parse and enforce.
Before allowing a Purpose for a given Vendor, one of these scenarios must be true: :
- User’s purpose consent and user’s vendor consent
- The Prebid-specific ‘enforceVendor’ flag is set and user’s vendor consent
- purpose LI established and vendor LI established
- The Prebid-specific ‘enforceVendor’ flag is set and vendor LI established
In terms of the TCF 2.0 fields, Purpose P is ok for vendor V if either of these is true:
- PurposesConsent[P,V]==1 AND VendorConsentBitfield[V]==1
- pbEnforceVendor[P]==true AND VendorConsentBitfield[V]==1
- PurposesLITransparency[P]==1 AND VendorLegitimateInterestBitfield[V]==1
- pbEnforceVendor[P,V]==true AND VendorLegitimateInterestBitfield[V]==1
Before allowing Special Feature 1, SpecialFeatureOptIns[1] must be true.
Full Enforcement (Prebid Server Only)
The big difference between 'basic' and 'full' enforcement is that Prebid Server has the GVL available to examine vendor legal bases.
Before allowing an activity that falls under a specific Purpose for a given Vendor, one of these 6 basic scenarios needs to be true:
- Vendor claims consent as their basis, publisher doesn't restrict the purpose, user consents to the purpose (if the enforcePurpose flag is on), and user consents to the vendor (if the enforceVendor flag is on).
- Vendor claims (inflexible) legitimate interest as their basis, publisher doesn't restrict the purpose, user was provided notice of the legitimate interest basis for this purpose (if the enforcePurpose flag is on), and user was provided notice for the LI basis for this vendor (if the enforceVendor flag is on)
- Vendor claims flexible legal basis with legitimate interest as the default, publisher restriction doesn't require consent, and ((user was provided notice of the legitimate interest basis for this purpose+vendor) OR (user consents to purpose+vendor)) [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with legitimate interest as the default, publisher does require consent, user consents to the purpose, and user consents to the vendor. [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with consent as the default, publisher restriction doesn't require legitimate interest, ((user consents to the purpose+vendor) OR (user was provided notice for the legitimate interest basis for this purpose+vendor)) [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with consent as the default, publisher restriction does require legitimate interest, and user was provided notice for the legitimate interest basis for this purpose+vendor. [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
Note that there are many more scenarios where the activity would not be allowed.
The technical definition in terms of the TCF 2.0 fields follows. Purpose P is ok for vendor V if any of these is true:
- GVL[V].purposes contains P and GVL[V].flexiblePurposes doesn't contain P and publisherRestrictions[P]!=0 and (!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes doesn't contain P and publisherRestrictions[P]!=0 and (!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==2 and (((!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)) OR ((!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)))
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==1 and (!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)
- GVL[V].purposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==1 and (((!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)) OR ((!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)))
- GVL[V].purposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==2 and (!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)
Before allowing Special Feature 1, SpecialFeatureOptIns[1] must be true.
Prebid.js Functional Requirements
1) An optional module must be available for reading the IAB TCF 2.0 API data. Publishers will include this module in their Prebid.js package when they need to support EEA users.
2) Prebid.js must support scenarios where the TCF string parsing functions are not available. If the codebase for parsing the TCF string is significant, it should be made an optional module separate from the enforcement functions. A key goal of Prebid.js is to include only the code that publishers need for their particular use case. The technical design should consider whether it makes sense to bundle all of these components together, or break them into 2 or 3 separate modules:
- Reading the TCF string
- Enforcing the TCF string
- Parsing the TCF string (?)
3) Prebid.js must support the following publisher controls:
- Don't even read the TCF string (accomplished by not configuring the module)
- Enforce/Do not enforce purpose P
- Enforce/Do not enforce purpose P for vendor V
Here's a set of proposed configurations within the existing consentManagement config object:
Param | Type | Description | Details |
gdpr.allowAuctionWithoutConsent | boolean | Available in 3.x only, defines behavior for backwards compatibility. | For 3.x: If true, consider all Purposes as not enforceable. If false, consider only Purpose 2 enforceable. |
gdpr.consentData | object | Consent data provided statically. | Used when cmpApi is "static". |
gdpr.defaultGdprScope | boolean |
|
|
gdpr.rules | object | Lets the publisher override the defaults set by the enforceMode |
|
gdpr.rules[].purpose | string | Possible values are "storage", "basicAds", "personalizedAds", and "measurement" corresponding to Purposes 1,2,4, and 7 respectively. | For some reason, people tend to prefer using the string names rather than the numbers. |
gdpr.rules[].enforcePurpose | boolean | Whether to enforce this purpose or not. Overrides the setting from enforceMode. | The default in PBJS 3.x will be to enforce no purposes, and in 4.0 to enforce Purpose 1 and no others. |
gdpr.rules[].enforceVendor | boolean | Whether to enforce vendor consent/legal basis for this purpose or not.. | The default in PBJS 3.x will be to enforce no purposes, and in 4.0 to enforce Purpose 1 and no others. |
gdpr.rules[].vendorExceptions | array of strings | Which biddercodes or module names should be treated as the opposite of the enforceVendor flag. | If enforceVendor=false, then vendorExceptions are those that will be treated as true. If enforce=true, then vendorExceptions are those that will be treated as false. |
Example configurations:
pbjs.setConfig({ consentManagement: { gdpr: { cmpApi: 'iab', defaultGdprScope: true/false (0/1?) timeout: 3000, // allowAuctionWithoutConsent: false, // deprecated rules: [{ // don’t enforce Purpose 1 except for bidderA. // this means that TCF approval is only considered // for this one bidder. purpose: "storage", enforcePurpose: false, enforceVendor: false, vendorExceptions: ["bidderA"] },{ // Allow the user to object to vendors for Purpose 2 // but don’t allow them to turn off header bidding // altogether. // The exception is bidderB, which the user will // not be allowed to reject purpose: "basicAds", enforcePurpose: false, enforceVendor: true, vendorExceptions: ["bidderB"] },{ // allow the user to have their userId removed from // header bidding except for bidders A and B purpose: "personalizedAds", enforcePurpose: true, enforceVendor: true vendorExceptions: ["bidderA","bidderB"] },{ // analytics adapters are ok purpose: "measurement", enforcePurpose: false, enforcePurpose: false }] } } }); |
You may notice that the examples above provide more flexibility than TCF requires. This allows publishers to establish custom legal bases in consultation with their legal counsel.
4) If the 'gdprApplies' flag is defined and is false, then Prebid.js may assume that GDPR is not in scope and therefore doesn't need to be enforced. All Purposes will be set to enforce=false.
4) There should be a way for bidAdapters to supply a GVL ID for each alias they support.
5) The aliasBidder() function should be extended to support specification of a GVL ID. e.g.
pbjs.aliasBidder('appnexus', 'newAlias', 999);
6) If a bidder code isn't associated with a GVL ID, enforcement should assume that the vendor is not allowed unless the publisher has specifically named their bidder code.
7) Analytics adapters must be associated with a GVL ID and/or a "name" to allow the system to determine which analytics adapter(s) are permitted to operate in the current context.
8) User ID modules and Real Time Data modules should be associated with a GVL ID and/or a "name" to allow the system to determine which modules are permitted to operate in the current context.
9) The system must be able to verify vendor consent in two ways:
- User consents to GVL ID 52, and Prebid.js knows that 52 corresponds to the Rubicon bid adapter (and the Rubicon analytics adapter)
- The publisher consents to the name "pubcommonId", which would allow that ID module to fire even if Purpose 1 doesn't have consent.
10) The internal interface to bid adapters should remain the same: bidrequest.gdprConsent
11) The OpenRTB interface to Prebid Server should remain the same:
- regs.ext.gdpr
- user.ext.consent
12) The system must support all the activity enforcement noted in the 'Summary of Prebid TCF 2.0 Enforcement' section.
- If Purpose 1 is being enforced:
- Before invoking usersync pixels for each enforceable vendor, verify consent as described in 'Basic Enforcement'.
- Before reading or storing cookies or HTML 5 localstorage for each enforceable vendor, verify consent as described in 'Basic Enforcement'. This will require enhancing the getCookie and setCookie utility functions to determine or accept the biddercode or module name.
- Before invoking each enforceable userID sub-module, verify consent as described in 'Basic Enforcement'.
- If Purpose 2 is being enforced, verify consent for each vendor as described in 'Basic Enforcement' before calling a bid adapter. If consent is not granted, log a console warning and skip it.
- If Purpose 4 is being enforced, verify consent for each vendor that passed the Purpose 2 test. If consent is not granted, log a console warning, remove the bidrequest.userId attribute and call the adapter.
- If Purpose 7 is being enforced, verify consent for each analytics module. If consent is not granted, log a console warning and skip it.
13) If consentManagement.gdpr is configured but no consent string is available, the system must assume that the user does not consent to either purpose or vendor. Activities may still take place if the publisher has configured the relevant Purposes as 'not enforced'.
13) Bid adapters must do one of the following for all device access activities (reading or setting cookies or local storage):
- Use the PBJS core utility functions, which will handle Purpose 1 enforcement.
- Post a public disclosure in the code and on prebid.org explaining the legal basis for not adhering to GDPR.
14) Prebid core must make the following information available to analytics adapters:
- Enforcement status of Purposes 1,2,4 and 7.
- An array of bidders and modules skipped due to TCF enforcement.
15) It should be possible for a pub to define a mapping between a module code and a GVL ID
pbjs.setConfig({
gvlMapping: {
“id5”: 9999
“bidderX”: 8888
}
Prebid SDK Functional Requirements
1) Prebid SDK must accept the following optional parameters to support TCF 2.0. It’s assumed the app will pass these values directly or indirectly from a mobile CMP.
- GDPR in-scope
- TCF Consent string
- ‘deviceAccessConsent’ flag defining whether the SDK is allowed to read the IDFA or equivalent. It’s assumed that the app will parse the consent string to confirm the user has consented to Purpose 1.
2) When a request is defined to be GDPR in-scope, the SDK must confirm that the ‘deviceAccessConsent’ flag is true. Here’s the truth table for when the SDK is allowed to access the device ID:
| deviceAccessConsent=true | deviceAccessConsent=false | deviceAccessConsent undefined |
GDPR scope=false | Yes, read IDFA | No, don’t read IDFA | Yes, read IDFA |
GDPR scope=true | Yes, read IDFA | No, don’t read IDFA | No, don’t read IDFA |
GDPR scope undefined | Yes, read IDFA | No, don’t read IDFA | Yes, read IDFA |
3) The SDK must pass the consent data to Prebid Server on the same OpenRTB attributes as defined in TCF 1.1:
- GDPR in-scope flag is regs.ext.gdpr
- Consent string is user.ext.consent
Prebid Server Functional Requirements
1) Optional configuration must be available for host companies to turn on and off enforcing GDPR with IAB TCF 2.0 API data. There should be global and publisher account level configuration. The default should be to enforce.
2) If enforcement is turned on for this request, Prebid Server must be able to determine whether it's in-scope for GDPR processing. If any of the following conditions are true, the request is in-scope:
- the incoming request defines regs.ext.gdpr:true.
- regs.ext.gdpr is undefined, geo-lookup is turned on, and the user's IP address is in a configurable set of countries.
- regs.ext.gdpr is undefined and the host company's default scope is to enforce.
3) Prebid Server must support the following host company controls:
- Enforce/Do not enforce purpose P (globally and per-account)
- Enforce/Do not enforce purpose P for vendor V (globally and per-account)
- Enforce/Do not enforce special purpose 1
- Enforce/Do not enforce special purpose 1 for vendor V
- ACCOUNT
4) Prebid Server must give host company config to say what to do with the purposeOneTreatment - both as a default and for each account:
- ignore the flag entirely
- if purposeOneTreatment=1 and IsServiceSpecific=1 then Purpose 1 is overridden to no-access-allowed
- if purposeOneTreatment=1 and IsServiceSpecific=1 then Purpose 1 is overridden to access-allowed
The implementation of this “PurposeOneTreatmentInterpretation flag modifies the flowchart above: it may short-circuit the logic, jumping straight to Yes or No without a normal enforcement check.

5) It must be possible for a Host Company to define its GVL ID to use for confirming user user consent for setting cookies.
Example configuration/DB entries:
gdpr.host-vendor-id: 52
gdpr.enabled: true/false // default true
gdpr.purpose.P.enforcePurpose: no/basic/full // default full
gdpr.purpose.P.enforceVendors: true/false // default true
gdpr.purpose.P.vendorExceptions: list of biddercodes
gdpr.specialfeature.S.enforce: true/false // default true
gdpr.specialfeature.S.vendorExceptions: list of biddercodes
gdpr.purposeOneTreatmentInterpretation: ignore/no-access-allowed/access-allowed
account.A.gdpr.enabled: true/false // default true
account.A.gdpr.purpose.P.enforcePurpose
account.A.gdpr.purpose.P.enforceVendors
account.A.gdpr.purpose.P.vendorExceptions
account.A.gdpr.specialfeature.S.enforce
account.A.gdpr.specialfeature.S.vendorExceptions
account.A.gdpr.purposeOneTreatmentInterpretation
geolocation.VENDOR.server: url // location of geo lookup service
6) There should be a way for bidAdapters to supply a GVL ID for each alias they support.
7) The external definition of aliases should be extended to support specification of a GVL ID. e.g.
"ext": {
"prebid": {
"aliases": { // existing feature
"districtm": "appnexus"
},
"aliasgvlids": { // new feature
"districtm": 144
}
}
}
8) Prebid Server's enforcement should be "Full" mode unless it doesn't have access to the proper GVL version.
9) Prebid Server should be able to read the TCF2.0 GVL that's specified in the consent string. If it does not have immediate access to that version of the GVL, it may downgrade enforcement to "Basic". The assumption is that subsequent requests for that version of the GVL will succeed. The system should log any usage of Basic Enforcement.
10) If a bidder code isn't associated with a GVL ID, enforcement should assume that the vendor is not allowed unless the publisher has specifically named the bidder code as a configured exception.
11) Analytics adapters must be associated with a GVL ID and/or a "name" to allow the system to determine which analytics adapter(s) are permitted to operate in the current context.
12) User ID modules and Real Time Data modules should be associated with a GVL ID and/or a "name" to allow the system to determine which modules are permitted to operate in the current context.
13) The system must be able to verify vendor consent in two ways:
- User consents to GVL ID 52, and Prebid Server knows that 52 corresponds to the Rubicon bid adapter (and the Rubicon analytics adapter)
- The Host Company consents to the name "bidderB", which would allow that biddercode to bid even if the user's Purpose 1 doesn't have specific consent.
14) The internal interface to bid adapters should remain the same.
15) The OpenRTB interface to Prebid Server should remain the same:
- regs.ext.gdpr
- user.ext.consent
16) The system must support all the activity enforcement noted in the 'Summary of Prebid TCF 2.0 Enforcement' section.
- If Purpose 1 is being enforced:
- Before invoking /cookie_sync pixels for each enforceable vendor, verify consent as appropriate for the enforcement method.
- Before setting a cookie on /setuid, verify consent for the Host Company's GVL ID as appropriate for the enforcement method
- Before passing ID values to each enforceable vendor, verify consent as appropriate for the enforcement method.
- If Purpose 2 is being enforced, verify consent for each vendor as appropriate for the enforcement method before calling a bid adapter. If consent is not granted, log a metric and skip it.
- If Purpose 4 is being enforced, verify consent for each vendor that passed the Purpose 2 test. If consent is not granted, log a metric, remove the bidrequest.userId attribute and call the adapter.
- If Purpose 7 is being enforced, verify consent for each analytics module. If consent is not granted, log a metric and skip it.
- If Special Feature 1 is being enforced, verify user opt-in. If the user has opted out, round off the IP address and lat/long details and log a metric.
- IP masking: for IPv4, zero out the last byte. For IPv6, zero out the last 2 bytes.
- Check the OpenRtb packet for $.device.geo.lat, $.device.geo.lon, $.user.geo.lat, $.user.geo.lon. Round off the values to the last two decimal points if they exist.
17) If GDPR is being enforced but no consent string is available, the system must assume that the user does not consent to either purpose or vendor. Activities may still take place if the Host Company has configured the relevant Purposes as 'not enforced'.
18) Prebid Server core must make the following information available to analytics adapters:
- Enforcement status of Purposes 1,2,4,7, and Special Purpose 1
- An array of bidders and modules skipped due to TCF enforcement.
\ No newline at end of file
+Prebid Support for Enforcing TCF 2.0
Overview
Definitions
Assumptions
Summary of Prebid TCF 2.0 Enforcement
Basic-vs-Full Enforcement
Basic Enforcement
Full Enforcement (Prebid Server Only)
Prebid.js Functional Requirements
Prebid SDK Functional Requirements
Prebid Server Functional Requirements
Overview
The IAB's Transparency and Consent Framework version 2.0 for enhanced support of GDPR is scheduled to take effect Apr 1 2020. It's a major update from TCF 1.1 which Prebid currently supports, and is not compatible with the previous release.
The key changes are:
- More 'purposes' are defined.
- More flexibility for the legal bases used by vendors.
- Different in-page javascript API
References
Definitions
- GDPR - General Data Protection Regulation. The EU's privacy regulations.
- EEA - European Economic Area. The region where the GDPR is in effect.
- IAB - Interactive Advertising Bureau. The ad industry consortium that developed the TCF as a way to help the ad ecosystem adhere to GDPR rules.
- TCF - Transparency and Consent Framework.
- CMP - Consent Management Platform. The user interface part of the TCF.
- GVL - Global Vendors List. The place where each ad entity registers what they do with user data.
- PBS - Prebid Server
- PBJS - Prebid.js
- PBS Host Company - the organization running a cluster of Prebid Servers
- Purpose 1 - Under TCF, there are many defined uses of private data. "Purpose 1" is "Store and/or access information on a device". This means that users must consent before an ad tech vendor reads or writes data from their computer or phone. Those of us dealing with these things a lot memorize the numbers. Forgive us.
- Purpose 2 - "Basic Ad Selection". This looks to be one of the bigger areas of concern because the TCF policy could be interpreted to be a form of ad blocking. Or maybe not. Talk to your lawyers.
- Purpose 4 - "Personalized Ad Selection". Basically, if the user doesn’t consent, they don’t want ads based on any type of direct user profile.
- Purpose 7 - "Measure ad performance". This is another area of concern, because the TCF policy doesn’t clearly define what it means to measure the “effectiveness” of ads. Talk to your lawyers about what this means for your organization.
- Special Feature 1 - "Use precise geolocation data". Special Features are quite different than Purposes. They only allow user "opt-in", and don't have as many layers of nuance as Purposes.
- Legal Basis - how an ad tech vendor views the importance of each Purpose for their mission. If they define "consent" as their "basis" for a given Purpose, they're able to work without some or all aspects of the user's data. But if they define "Legitimate Interest" (LI), they're basically saying "We can't do our job without this data".
- Basic enforcement - a high-level mode of consent confirmation where the looks for a good-faith indication that the user has provided consent or legal basis signals before engaging in a privacy-protected activity. Does not read the GVL.
- Full enforcement - a detailed confirmation mode that reads the GVL, interprets the consent string, and performs legal basis analysis.
Assumptions
Important Legal Note: Prebid.org cannot provide legal advice about GDPR or any other governmental regulation. Our aim is to provide a toolkit of functionality that will let publishers configure header bidding as defined by their legal counsel. We will consider feature suggestions, and review any code offered by the community.
Enforcement of Purpose 2 (basic ad selection) looks to be one of the bigger areas of concern because the TCF policy could be interpreted to be a form of ad blocking. You will need to work with your legal counsel to determine how you intend to handle this scenario. Prebid.js and Prebid Server offer publishers the ability to enforce or not-enforce purposes individually. As an example of the kind of flexibility we aim to offer (*), here are some options you could discuss with your lawyers:
- Treat Purpose 2 as an ad blocker.
- Ignore enforcement of selected Purposes at the Prebid level entirely, assuming that downstream vendors will handle the TCF strings appropriately.
- Ignore enforcement Purpose 2, assuming that users who object to ‘Basic Ads’ will also object to ‘Personalized Ads’, causing any User IDs to be removed from ad requests.
- Ignore the Purpose-Consent portion of Purpose 2, but allow the user to block specific vendors.
(*) - Note on phasing: Please be aware that Prebid.js and Prebid Server will likely not deliver on the full TCF functionality by April 1st. Our initial goal for both products is to support Purpose 1 (Device Access) enforcement by that date. The ability to enforce the other purposes will be developed as soon as we can.
(**) Did we mention that you cannot rely on this document to learn how to configure your header bidding for GDPR? Seriously, talk to your lawyers. |
General
- Prebid.org is neither a data controller nor data processor, but we supply software to both types of entities. Therefore, our software should provide a flexible set of controls necessary for both types of entities to run their businesses.
- Even if Prebid is configured to enforce activities by parsing consent data, publishers and downstream vendors are still responsible for ensuring their legal bases using the consent data they're provided.
- Prebid will ignore the TCF "stack" feature, assuming that the CMP will set the underlying Purposes appropriately.
- Data from the CMP will never be modified before passing to downstream entities.
- If TCF processing is turned on, and the user is determined to be in GDPR scope, and hasn’t provided a consent string, the system should assume a consent string that has no consent offered.
Prebid.js
- Prebid.js will only support parsing the TCF 2.0 consent string.
- TCF 2.0 features are available in Prebid.js only in a consent module, not as part of core. This allows publishers to build two versions of their wrappers: one for users in the EEA, one for users outside of the EEA.
- It's assumed that publishers run in two modes:
- A CMP is loaded on every page so TCF functions and data are fully available.
- Consent data is stored in first party storage and passed to Prebid directly. TCF functions are not available from the CMP.
- Prebid.js will not load the Global Vendors List (GVL) as this would significantly impact the success of header bidding implementations. However, Prebid.js will require a mapping of GVL vendor IDs to Prebid.js bidder codes.
- Further, we assume that not all Prebid adapters will be in the GVL, so we'll need to support reference by GVL ID or bidder code.
- Further, we assume that bidder aliases within one adapter may have different GVL IDs.
- As a result of not having access to GVL entries, Prebid.js will only support ‘Basic Enforcement’.
- TCF2 will be supported in Prebid.js 3.x, with 'no enforcement' being the default option. Prebid.js 4.0 will enforce Purpose 1 by default when the module is included.
- PurposeOneTreatment is ignored for Prebid.js. Publishers who don’t want to enforce Purpose 1 (or any other purpose) need to set Prebid’s configuration appropriately.
Prebid Server
- Prebid Server will need concurrent support of TCF 1.1 and TCF 2.0.
- Prebid Server will need to support “Full Enforcement” checks.
- AMP TCF 2.0 will be passed on the same parameter as TCF 1.1.
Prebid SDK
- Prebid SDK should parse the consent string in order to read the IDFA. Other than that, SDK just passes consent values to Prebid Server..
Summary of Prebid TCF 2.0 Enforcement
TCF Field | In-scope Activities | System | Enforcement | Publisher/ Host Company Controls |
Purpose 1 - Store and/or access information on a device | usersync pixels, user ID modules, and device storage | Prebid.js and Prebid Server and Prebid SDK | May result in preventing one or more uesrsync activities for one or more vendors. | Do not enforce purpose 1 Do not enforce purpose 1 for vendor V Enforce purpose 1 at the vendor level only. |
Purpose 2 - Select basic ads | call bid adapters | Prebid.js and Prebid Server | May result in skipping one or more bid adapters.
All configured modules will be called as usual unless all bidders are eliminated. | Do not enforce purpose 2 Do not enforce purpose 2 for vendor V Enforce purpose 2 at the vendor level only.
|
Purpose 4 - Select Personalized Ads | call bid adapters with userIds | Prebid.js and Prebid Server | May result in removing the userIds before calling one or more bid adapters. | Do not enforce purpose 4 Do not enforce purpose 4 for vendor V Enforce purpose 4 at the vendor level only. |
Purpose 7 - Measure ad performance | initiate analytics | Prebid.js and Prebid Server | May result in skipping one or more analytics adapters. | Do not enforce purpose 7 Do not enforce purpose 7 for vendor V Enforce purpose 7 at the vendor level only. |
Special Feature 1 - Use precise geolocation data | passing lat/long to server-side bid adapters | Prebid Server | May result in rounding lat/long values and IP address before sending to server-side adapters. | Do not enforce Special Feature 1 |
Special Purpose 2 - Technically deliver ads or content | n/a |
Special Purposes do not require consent. If a publisher’s legal team wants to consider SP2, Prebid software should not be called. |
PurposeOneConsent | n/a | Prebid does not provide specific support for enforcing this flag. Instead, publishers may use the provided controls for Purpose 1 and other Prebid configuration to control whether the user’s device is accessed. |
Basic-vs-Full Enforcement
Prebid offers publishers several controls for whether consent/legal basis confirmation is even performed. The following flowchart shows how the controls

Basic Enforcement
The goal of 'basic enforcement' is to confirm that there's enough evidence of consent to pass data on to vendors who have access to the GVL and can fully parse and enforce.
Before allowing a Purpose for a given Vendor, one of these scenarios must be true: :
- User’s purpose consent and user’s vendor consent
- The Prebid-specific ‘enforceVendor’ flag is set and user’s vendor consent
- purpose LI established and vendor LI established
- The Prebid-specific ‘enforceVendor’ flag is set and vendor LI established
In terms of the TCF 2.0 fields, Purpose P is ok for vendor V if either of these is true:
- PurposesConsent[P,V]==1 AND VendorConsentBitfield[V]==1
- pbEnforceVendor[P]==true AND VendorConsentBitfield[V]==1
- PurposesLITransparency[P]==1 AND VendorLegitimateInterestBitfield[V]==1
- pbEnforceVendor[P,V]==true AND VendorLegitimateInterestBitfield[V]==1
Before allowing Special Feature 1, SpecialFeatureOptIns[1] must be true.
Full Enforcement (Prebid Server Only)
The big difference between 'basic' and 'full' enforcement is that Prebid Server has the GVL available to examine vendor legal bases.
Before allowing an activity that falls under a specific Purpose for a given Vendor, one of these 6 basic scenarios needs to be true:
- Vendor claims consent as their basis, publisher doesn't restrict the purpose, user consents to the purpose (if the enforcePurpose flag is on), and user consents to the vendor (if the enforceVendor flag is on).
- Vendor claims (inflexible) legitimate interest as their basis, publisher doesn't restrict the purpose, user was provided notice of the legitimate interest basis for this purpose (if the enforcePurpose flag is on), and user was provided notice for the LI basis for this vendor (if the enforceVendor flag is on)
- Vendor claims flexible legal basis with legitimate interest as the default, publisher restriction doesn't require consent, and ((user was provided notice of the legitimate interest basis for this purpose+vendor) OR (user consents to purpose+vendor)) [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with legitimate interest as the default, publisher does require consent, user consents to the purpose, and user consents to the vendor. [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with consent as the default, publisher restriction doesn't require legitimate interest, ((user consents to the purpose+vendor) OR (user was provided notice for the legitimate interest basis for this purpose+vendor)) [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
- Vendor claims flexible legal basis with consent as the default, publisher restriction does require legitimate interest, and user was provided notice for the legitimate interest basis for this purpose+vendor. [Purpose checked only if the enforcePurpose flag is on, and vendor checked only if the enforceVendor flag is on]
Note that there are many more scenarios where the activity would not be allowed.
The technical definition in terms of the TCF 2.0 fields follows. Purpose P is ok for vendor V if any of these is true:
- GVL[V].purposes contains P and GVL[V].flexiblePurposes doesn't contain P and publisherRestrictions[P]!=0 and (!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes doesn't contain P and publisherRestrictions[P]!=0 and (!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==2 and (((!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)) OR ((!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)))
- GVL[V].legIntPurposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==1 and (!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)
- GVL[V].purposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==1 and (((!enforcePurpose[P] or PurposesConsent[P]==1) AND (!enforceVendor[P,V] or VendorConsentBitfield[V]==1)) OR ((!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)))
- GVL[V].purposes contains P and GVL[V].flexiblePurposes contains P and publisherRestrictions[P]==2 and (!enforcePurpose[P] or PurposesLITransparency[P]==1) AND (!enforceVendor[P,V] or VendorLegitimateInterestBitfield[V]==1)
Before allowing Special Feature 1, SpecialFeatureOptIns[1] must be true.
Prebid.js Functional Requirements
1) An optional module must be available for reading the IAB TCF 2.0 API data. Publishers will include this module in their Prebid.js package when they need to support EEA users.
2) Prebid.js must support scenarios where the TCF string parsing functions are not available. If the codebase for parsing the TCF string is significant, it should be made an optional module separate from the enforcement functions. A key goal of Prebid.js is to include only the code that publishers need for their particular use case. The technical design should consider whether it makes sense to bundle all of these components together, or break them into 2 or 3 separate modules:
- Reading the TCF string
- Enforcing the TCF string
- Parsing the TCF string (?)
3) Prebid.js must support the following publisher controls:
- Don't even read the TCF string (accomplished by not configuring the module)
- Enforce/Do not enforce purpose P
- Enforce/Do not enforce purpose P for vendor V
Here's a set of proposed configurations within the existing consentManagement config object:
Param | Type | Description | Details |
gdpr.allowAuctionWithoutConsent | boolean | Available in 3.x only, defines behavior for backwards compatibility. | For 3.x: If true, consider all Purposes as not enforceable. If false, consider only Purpose 2 enforceable. |
gdpr.consentData | object | Consent data provided statically. | Used when cmpApi is "static". |
gdpr.defaultGdprScope | boolean |
|
|
gdpr.rules | object | Lets the publisher override the defaults set by the enforceMode |
|
gdpr.rules[].purpose | string | Possible values are "storage", "basicAds", "personalizedAds", and "measurement" corresponding to Purposes 1,2,4, and 7 respectively. | For some reason, people tend to prefer using the string names rather than the numbers. |
gdpr.rules[].enforcePurpose | boolean | Whether to enforce this purpose or not. Overrides the setting from enforceMode. | The default in PBJS 3.x will be to enforce no purposes, and in 4.0 to enforce Purpose 1 and no others. |
gdpr.rules[].enforceVendor | boolean | Whether to enforce vendor consent/legal basis for this purpose or not.. | The default in PBJS 3.x will be to enforce no purposes, and in 4.0 to enforce Purpose 1 and no others. |
gdpr.rules[].vendorExceptions | array of strings | Which biddercodes or module names should be treated as the opposite of the enforceVendor flag. | If enforceVendor=false, then vendorExceptions are those that will be treated as true. If enforce=true, then vendorExceptions are those that will be treated as false. |
Example configurations:
pbjs.setConfig({ consentManagement: { gdpr: { cmpApi: 'iab', defaultGdprScope: true/false (0/1?) timeout: 3000, // allowAuctionWithoutConsent: false, // deprecated rules: [{ // don’t enforce Purpose 1 except for bidderA. // this means that TCF approval is only considered // for this one bidder. purpose: "storage", enforcePurpose: false, enforceVendor: false, vendorExceptions: ["bidderA"] },{ // Allow the user to object to vendors for Purpose 2 // but don’t allow them to turn off header bidding // altogether. // The exception is bidderB, which the user will // not be allowed to reject purpose: "basicAds", enforcePurpose: false, enforceVendor: true, vendorExceptions: ["bidderB"] },{ // allow the user to have their userId removed from // header bidding except for bidders A and B purpose: "personalizedAds", enforcePurpose: true, enforceVendor: true vendorExceptions: ["bidderA","bidderB"] },{ // analytics adapters are ok purpose: "measurement", enforcePurpose: false, enforcePurpose: false }] } } }); |
You may notice that the examples above provide more flexibility than TCF requires. This allows publishers to establish custom legal bases in consultation with their legal counsel.
4) If the 'gdprApplies' flag is defined and is false, then Prebid.js may assume that GDPR is not in scope and therefore doesn't need to be enforced. All Purposes will be set to enforce=false.
4) There should be a way for bidAdapters to supply a GVL ID for each alias they support.
5) The aliasBidder() function should be extended to support specification of a GVL ID. e.g.
pbjs.aliasBidder('appnexus', 'newAlias', 999);
6) If a bidder code isn't associated with a GVL ID, enforcement should assume that the vendor is not allowed unless the publisher has specifically named their bidder code.
7) Analytics adapters must be associated with a GVL ID and/or a "name" to allow the system to determine which analytics adapter(s) are permitted to operate in the current context.
8) User ID modules and Real Time Data modules should be associated with a GVL ID and/or a "name" to allow the system to determine which modules are permitted to operate in the current context.
9) The system must be able to verify vendor consent in two ways:
- User consents to GVL ID 52, and Prebid.js knows that 52 corresponds to the Rubicon bid adapter (and the Rubicon analytics adapter)
10) The internal interface to bid adapters should remain the same: bidrequest.gdprConsent
11) The OpenRTB interface to Prebid Server should remain the same:
- regs.ext.gdpr
- user.ext.consent
12) The system must support all the activity enforcement noted in the 'Summary of Prebid TCF 2.0 Enforcement' section.
- If Purpose 1 is being enforced:
- Before invoking usersync pixels for each enforceable vendor, verify consent as described in 'Basic Enforcement'.
- Before reading or storing cookies or HTML 5 localstorage for each enforceable vendor, verify consent as described in 'Basic Enforcement'. This will require enhancing the getCookie and setCookie utility functions to determine or accept the biddercode or module name.
- Before invoking each enforceable userID sub-module, verify consent as described in 'Basic Enforcement'.
- If Purpose 2 is being enforced, verify consent for each vendor as described in 'Basic Enforcement' before calling a bid adapter. If consent is not granted, log a console warning and skip it.
- If Purpose 4 is being enforced, verify consent for each vendor that passed the Purpose 2 test. If consent is not granted, log a console warning, remove the bidrequest.userId attribute and call the adapter.
- If Purpose 7 is being enforced, verify consent for each analytics module. If consent is not granted, log a console warning and skip it.
13) If consentManagement.gdpr is configured but no consent string is available, the system must assume that the user does not consent to either purpose or vendor. Activities may still take place if the publisher has configured the relevant Purposes as 'not enforced'.
13) Bid adapters must do one of the following for all device access activities (reading or setting cookies or local storage):
- Use the PBJS core utility functions, which will handle Purpose 1 enforcement.
- Post a public disclosure in the code and on prebid.org explaining the legal basis for not adhering to GDPR.
14) Prebid core must make the following information available to analytics adapters:
- Enforcement status of Purposes 1,2,4 and 7.
- An array of bidders and modules skipped due to TCF enforcement.
15) It should be possible for a pub to define a mapping between a module code and a GVL ID
pbjs.setConfig({
gvlMapping: {
“id5”: 9999
“bidderX”: 8888
}
Prebid SDK Functional Requirements
1) Prebid SDK must accept the following optional parameters to support TCF 2.0. It’s assumed the app will pass these values directly or indirectly from a mobile CMP.
- GDPR in-scope
- TCF Consent string
- ‘deviceAccessConsent’ flag defining whether the SDK is allowed to read the IDFA or equivalent. It’s assumed that the app will parse the consent string to confirm the user has consented to Purpose 1.
2) When a request is defined to be GDPR in-scope, the SDK must confirm that the ‘deviceAccessConsent’ flag is true. Here’s the truth table for when the SDK is allowed to access the device ID:
| deviceAccessConsent=true | deviceAccessConsent=false | deviceAccessConsent undefined |
GDPR scope=false | Yes, read IDFA | No, don’t read IDFA | Yes, read IDFA |
GDPR scope=true | Yes, read IDFA | No, don’t read IDFA | No, don’t read IDFA |
GDPR scope undefined | Yes, read IDFA | No, don’t read IDFA | Yes, read IDFA |
3) The SDK must pass the consent data to Prebid Server on the same OpenRTB attributes as defined in TCF 1.1:
- GDPR in-scope flag is regs.ext.gdpr
- Consent string is user.ext.consent
Prebid Server Functional Requirements
1) Optional configuration must be available for host companies to turn on and off enforcing GDPR with IAB TCF 2.0 API data. There should be global and publisher account level configuration. The default should be to enforce.
2) If enforcement is turned on for this request, Prebid Server must be able to determine whether it's in-scope for GDPR processing. If any of the following conditions are true, the request is in-scope:
- the incoming request defines regs.ext.gdpr:true.
- regs.ext.gdpr is undefined, geo-lookup is turned on, and the user's IP address is in a configurable set of countries.
- regs.ext.gdpr is undefined and the host company's default scope is to enforce.
3) Prebid Server must support the following host company controls:
- Enforce/Do not enforce purpose P (globally and per-account)
- Enforce/Do not enforce purpose P for vendor V (globally and per-account)
- Enforce/Do not enforce special purpose 1
- Enforce/Do not enforce special purpose 1 for vendor V
- ACCOUNT
4) Prebid Server must give host company config to say what to do with the purposeOneTreatment - both as a default and for each account:
- ignore the flag entirely
- if purposeOneTreatment=1 and IsServiceSpecific=1 then Purpose 1 is overridden to no-access-allowed
- if purposeOneTreatment=1 and IsServiceSpecific=1 then Purpose 1 is overridden to access-allowed
The implementation of this “PurposeOneTreatmentInterpretation flag modifies the flowchart above: it may short-circuit the logic, jumping straight to Yes or No without a normal enforcement check.

5) It must be possible for a Host Company to define its GVL ID to use for confirming user user consent for setting cookies.
Example configuration/DB entries:
gdpr.host-vendor-id: 52
gdpr.enabled: true/false // default true
gdpr.purpose.P.enforcePurpose: no/basic/full // default full
gdpr.purpose.P.enforceVendors: true/false // default true
gdpr.purpose.P.vendorExceptions: list of biddercodes
gdpr.specialfeature.S.enforce: true/false // default true
gdpr.specialfeature.S.vendorExceptions: list of biddercodes
gdpr.purposeOneTreatmentInterpretation: ignore/no-access-allowed/access-allowed
account.A.gdpr.enabled: true/false // default true
account.A.gdpr.purpose.P.enforcePurpose
account.A.gdpr.purpose.P.enforceVendors
account.A.gdpr.purpose.P.vendorExceptions
account.A.gdpr.specialfeature.S.enforce
account.A.gdpr.specialfeature.S.vendorExceptions
account.A.gdpr.purposeOneTreatmentInterpretation
geolocation.VENDOR.server: url // location of geo lookup service
6) There should be a way for bidAdapters to supply a GVL ID for each alias they support.
7) The external definition of aliases should be extended to support specification of a GVL ID. e.g.
"ext": {
"prebid": {
"aliases": { // existing feature
"districtm": "appnexus"
},
"aliasgvlids": { // new feature
"districtm": 144
}
}
}
8) Prebid Server's enforcement should be "Full" mode unless it doesn't have access to the proper GVL version.
9) Prebid Server should be able to read the TCF2.0 GVL that's specified in the consent string. If it does not have immediate access to that version of the GVL, it may downgrade enforcement to "Basic". The assumption is that subsequent requests for that version of the GVL will succeed. The system should log any usage of Basic Enforcement.
10) If a bidder code isn't associated with a GVL ID, enforcement should assume that the vendor is not allowed unless the publisher has specifically named the bidder code as a configured exception.
11) Analytics adapters must be associated with a GVL ID and/or a "name" to allow the system to determine which analytics adapter(s) are permitted to operate in the current context.
12) User ID modules and Real Time Data modules should be associated with a GVL ID and/or a "name" to allow the system to determine which modules are permitted to operate in the current context.
13) The system must be able to verify vendor consent in two ways:
- User consents to GVL ID 52, and Prebid Server knows that 52 corresponds to the Rubicon bid adapter (and the Rubicon analytics adapter)
- The Host Company consents to the name "bidderB", which would allow that biddercode to bid even if the user's Purpose 1 doesn't have specific consent.
14) The internal interface to bid adapters should remain the same.
15) The OpenRTB interface to Prebid Server should remain the same:
- regs.ext.gdpr
- user.ext.consent
16) The system must support all the activity enforcement noted in the 'Summary of Prebid TCF 2.0 Enforcement' section.
- If Purpose 1 is being enforced:
- Before invoking /cookie_sync pixels for each enforceable vendor, verify consent as appropriate for the enforcement method.
- Before setting a cookie on /setuid, verify consent for the Host Company's GVL ID as appropriate for the enforcement method
- Before passing ID values to each enforceable vendor, verify consent as appropriate for the enforcement method.
- If Purpose 2 is being enforced, verify consent for each vendor as appropriate for the enforcement method before calling a bid adapter. If consent is not granted, log a metric and skip it.
- If Purpose 4 is being enforced, verify consent for each vendor that passed the Purpose 2 test. If consent is not granted, log a metric, remove the bidrequest.userId attribute and call the adapter.
- If Purpose 7 is being enforced, verify consent for each analytics module. If consent is not granted, log a metric and skip it.
- If Special Feature 1 is being enforced, verify user opt-in. If the user has opted out, round off the IP address and lat/long details and log a metric.
- IP masking: for IPv4, zero out the last byte. For IPv6, zero out the last 2 bytes.
- Check the OpenRtb packet for $.device.geo.lat, $.device.geo.lon, $.user.geo.lat, $.user.geo.lon. Round off the values to the last two decimal points if they exist.
17) If GDPR is being enforced but no consent string is available, the system must assume that the user does not consent to either purpose or vendor. Activities may still take place if the Host Company has configured the relevant Purposes as 'not enforced'.
18) Prebid Server core must make the following information available to analytics adapters:
- Enforcement status of Purposes 1,2,4,7, and Special Purpose 1
- An array of bidders and modules skipped due to TCF enforcement.
diff --git a/dev-docs/show-multi-format-ads.md b/dev-docs/show-multi-format-ads.md
index b99068625f..4d6bc1cb8d 100644
--- a/dev-docs/show-multi-format-ads.md
+++ b/dev-docs/show-multi-format-ads.md
@@ -76,7 +76,11 @@ The ad unit below supports the banner, native, and video media types.
},
video: {
context: 'outstream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
},
},
bids: [
diff --git a/dev-docs/show-outstream-video-ads.md b/dev-docs/show-outstream-video-ads.md
index 2da4f7cdf0..6b4a9dde66 100644
--- a/dev-docs/show-outstream-video-ads.md
+++ b/dev-docs/show-outstream-video-ads.md
@@ -39,7 +39,11 @@ var videoAdUnits = [{
mediaTypes: {
video: {
context: 'outstream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
@@ -47,7 +51,7 @@ var videoAdUnits = [{
params: {
placementId: 13232385,
video: {
- skippable: true,
+ skip: 1,
playback_method: ['auto_play_sound_off']
}
}
@@ -95,6 +99,11 @@ pbjs.addAdUnit({
video: {
context: 'outstream',
playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
+
// but a renderer passed in here would apply only to this mediaType.
// This renderer would override the above renderer if it exists.
renderer: {
@@ -121,7 +130,11 @@ pbjs.addAdUnit({
mediaTypes: {
video: {
context: 'outstream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
renderer: {
diff --git a/dev-docs/show-prebid-ads-on-amp-pages.md b/dev-docs/show-prebid-ads-on-amp-pages.md
index 0195cc63fe..e03048365e 100644
--- a/dev-docs/show-prebid-ads-on-amp-pages.md
+++ b/dev-docs/show-prebid-ads-on-amp-pages.md
@@ -91,34 +91,40 @@ that doesn't come from /amp parameters:
}
}
},
- "imp": [
- {
- "id": "some-impression-id",
- "banner": {
- "format": [
- {
- "w": 300,
- "h": 250
- }
- ]
- },
- "ext": {
+ "imp": [{
+ "id": "some-impression-id",
+ "banner": {
+ "format": [{
+ "w": 300,
+ "h": 250
+ }]
+ },
+ "ext": {
+ "prebid": {
+ "bidder": {
"bidderA": {
// Insert parameters here
},
"bidderB": {
// Insert parameters here
}
- }
+ }
}
- ]
+ }
+ }]
}
-
```
This basic OpenRTB record will be enhanced by the parameters from the call to the [/amp endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html).
### AMP content page
+First ensure that the amp-ad component is imported in the header.
+
+```
+
+```
+This script provides code libraries that will convert `` properties to the endpoint query parameters usint the [Real Time Config](https://github.com/ampproject/amphtml/blob/main/extensions/amp-a4a/rtc-documentation.md) (RTC) protocol.
+
The `amp-ad` elements in the page body need to be set up as shown below, especially the following attributes:
+ `data-slot`: Identifies the ad slot for the auction.
@@ -130,7 +136,7 @@ e.g. for the AppNexus cluster of Prebid Servers:
```html
```
@@ -139,11 +145,20 @@ e.g. for Rubicon Project's cluster of Prebid Servers:
```html
```
+For other hosts, you can specify the URL directly rather than using one of the convenient vendor aliases. e.g.
+```html
+
+```
+
### HTML Creative
This is the creative that your Ad Ops team needs to upload to the ad server (it's also documented at [Setting up Prebid for AMP in Google Ad Manager]({{site.github.url}}/adops/setting-up-prebid-for-amp-in-dfp.html)).
@@ -244,37 +259,45 @@ If you're using AppNexus' managed service, you would enter something like this:
height="1"
sandbox="allow-scripts allow-same-origin"
frameborder="0"
- src="https://acdn.adnxs.com/prebid/amp/user-sync/load-cookie.html?endpoint=appnexus&max_sync_count=5">
+ src="https://acdn.adnxs.com/prebid/amp/user-sync/load-cookie.html?endpoint=appnexus&max_sync_count=5&source=amp">
```
-If you are utilizing Magnite's managed service, there's an extra parameter:
+If you are utilizing Magnite's managed service, there's an extra `args` parameter:
```html
+ src="https://GET_URL_FROM_MAGNITE_ACCOUNT_TEAM/prebid/load-cookie.html?endpoint=rubicon&max_sync_count=5&source=amp&args=account:MAGNITE_ACCOUNT_ID">
```
+
+Or you can specify a full URL to another Prebid Server location (including a QA site) by setting `endpoint` to a URL-encoded string. e.g.
+```html
+
+
+
+```
+
The usage of `load-cookie.html` and `load-cookie-with-consent.html` is the same. The arguments available on the query string are:
{: .table .table-bordered .table-striped }
| Param | Scope | Values | Description |
| --- | --- | --- | --- |
-| endpoint | recommended | appnexus or rubicon | Determines which cluster of prebid servers to load from. Default, for legacy reasons, is appnexus. |
+| endpoint | recommended | 'appnexus', 'rubicon', or URL | Determines which cluster of prebid servers to load from. Default, for legacy reasons, is appnexus. |
+| source | optional | recommended | Set it to 'amp' to tell Prebid Server to exclude iframe syncs, which don't work on AMP. |
| max_sync_count | optional | integer | How many sync pixels should be returned from Prebid Server |
| args | optional | attr1:val1,attr2:val2 | These attribute value pairs will be passed to Prebid Server in the /cookie_sync call. The attribute and value will be quoted by the system when appropriate. |
| gdpr | optional | 0 or 1 | Defines whether GDPR processing is in scope for this request. 0=no, 1=yes. Leave unknown if not sure. |
| gdpr_consent | optional | String | IAB CMP-formatted consent string |
-{% capture endpointNote %}
-Currently, if you need to sync with a Prebid Server other than appnexus or rubicon, you'll need to fork the repo, change the endpoint, and host it somewhere. There is an [issue open to resolve](https://github.com/prebid/prebid-universal-creative/issues/122) this.
-{% endcapture %}
-{% include alerts/alert_note.html content=endpointNote %}
-
### AMP RTC and GDPR
The two Prebid Server RTC vendor strings 'prebidappnexus' and 'prebidrubicon'
@@ -283,7 +306,25 @@ support passing GDPR consent to Prebid Server.
The CONSENT_STRING macro will be populated if you've integrated with a CMP
that supports amp-consent v2 -- custom CMP integration.
-If you're using a custom RTC callout, you'll need to add `gdpr_consent=CONSENT_STRING` to the list of parameters.
+If you're using a custom RTC callout, here are the parameters that can be passed through the RTC string:
+- tag_id
+- w=ATTR(width)
+- h=ATTR(height)
+- ow=ATTR(data-override-width)
+- oh=ATTR(data-override-height)
+- ms=ATTR(data-multi-size)
+- slot=ATTR(data-slot)
+- targeting=TGT
+- curl=CANONICAL_URL
+- timeout=TIMEOUT
+- adc=ADCID
+- purl=HREF
+- gdpr_consent=CONSENT_STRING
+- consent_type=CONSENT_METADATA(consentStringType)
+- gdpr_applies=CONSENT_METADATA(gdprApplies)
+- attl_consent=CONSENT_METADATA(additionalConsent)
+
+See the entries in the [AMP vendors callout file](https://github.com/ampproject/amphtml/blob/main/src/service/real-time-config/callout-vendors.js).
## Debugging Tips
To review that Prebid on AMP is working properly the following aspects can be looked at:
diff --git a/dev-docs/show-video-with-a-dfp-video-tag.md b/dev-docs/show-video-with-a-dfp-video-tag.md
index a16adf693c..929cffe49b 100644
--- a/dev-docs/show-video-with-a-dfp-video-tag.md
+++ b/dev-docs/show-video-with-a-dfp-video-tag.md
@@ -59,17 +59,17 @@ var videoAdUnit = {
mediaTypes: {
video: {
context: 'instream',
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
},
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361,
- video: {
- skippable: true,
- playback_methods: ['auto_play_sound_off']
- }
+ placementId: 13232361
}
}]
};
diff --git a/dev-docs/troubleshooting-tips.md b/dev-docs/troubleshooting-tips.md
index 874e3d90e6..1b2375c9e1 100644
--- a/dev-docs/troubleshooting-tips.md
+++ b/dev-docs/troubleshooting-tips.md
@@ -3,12 +3,9 @@ layout: page_v2
title: Dev Tips
description: Troubleshooting tips for developers implementing Prebid.js Header Bidding.
pid: 0
-
-top_nav_section: dev_docs
nav_section: troubleshooting
redirect_from: "/dev-docs/toubleshooting-tips.html"
sidebarType: 1
-
---
@@ -16,221 +13,4 @@ sidebarType: 1
# Tips for Troubleshooting
{:.no_toc}
-This page has tips and tricks for troubleshooting issues with your Prebid.js integration.
-
-* TOC
-{:toc}
-
-## Turn on Prebid.js debug messages
-
-Add `pbjs_debug=true` to the end of your page's URL. For example: /pbjs_demo.html?pbjs_debug=true. This will add two types of messages to your browser's developer console:
-
-1. Prebid.js suppresses Javascript errors in the normal mode to not break the rest of your page. Adding the `pbjs_debug` parameter will expose the Javascript errors.
-2. You'll find additional debug messages. Filter the messages by string `MESSAGE:`. For example:
-
-
-
-{: .pb-sm-img :}
-
-
-
-{: .table .table-bordered .table-striped }
-| Message | Description |
-| :---- |:--------|
-| Calling bidder | When Prebid.js sends out bid requests, this message is logged |
-| Set key value for placement | After all the bids came back, or when timeout is reached, prebid.js will set keyword targeting for the defined ad units. |
-| Calling renderAd | If a header bidding bid wins the ad server's auction, prebid.js will render the winning bid's creative. |
-
-
-
-## Turn on your ad server's developer console
-
-The ad server's developer console usually provide information such as targeting, latency, and key events logging. For example, here is a screenshot of Google Ad Manager's GPT developer console logs:
-
-
-
-{: .pb-md-img :}
-
-
-
-## See all bids in the console
-
-To print information about all of the bids that come in to the Console on any page that is running Prebid.js, follow these steps.
-
-Open the Chrome Dev Tools. In the **Sources** tab, next to **Content Scripts**, click the **>>** button and you can add **Snippets**:
-
-{: .pb-sm-img :}
-
-
-
-Right-click to add a **New** snippet:
-
-{: .pb-sm-img :}
-
-
-
-Paste in the following code using Control-V (or Command-V on Mac), and give the snippet a name, such as 'show-all-bids':
-
-```javascript
-(function() {
- function forEach(responses, cb) {
- Object.keys(responses).forEach(function(adUnitCode) {
- var response = responses[adUnitCode];
- response.bids.forEach(function(bid) {
- cb(adUnitCode, bid);
- });
- });
- }
- var winners = pbjs.getAllWinningBids();
- var output = [];
- forEach(pbjs.getBidResponses(), function(code, bid) {
- output.push({
- bid: bid,
- adunit: code,
- adId: bid.adId,
- bidder: bid.bidder,
- time: bid.timeToRespond,
- cpm: bid.cpm,
- msg: bid.statusMessage,
- rendered: !!winners.find(function(winner) {
- return winner.adId==bid.adId;
- })
- });
- });
- forEach(pbjs.getNoBids && pbjs.getNoBids() || {}, function(code, bid) {
- output.push({
- msg: "no bid",
- adunit: code,
- adId: bid.bidId,
- bidder: bid.bidder
- });
- });
- if (output.length) {
- if (console.table) {
- console.table(output);
- } else {
- for (var j = 0; j < output.length; j++) {
- console.log(output[j]);
- }
- }
- } else {
- console.warn('NO prebid responses');
- }
-})();
-```
-
-
-
-Right-click the snippet and choose **Run**:
-
-{: .pb-sm-img :}
-
-
-
-Check the output in Console to see the bids:
-
-{: .pb-sm-img :}
-
-## See all winning bids in the console
-
-To print information about all of the winning bids that come in to the Console on any page that is running Prebid.js, follow these steps.
-
-Open the Chrome Dev Tools. In the **Sources** tab, next to **Content Scripts**, click the **>>** button and you can add **Snippets**:
-
-{: .pb-sm-img :}
-
-
-
-Right-click to add a **New** snippet:
-
-{: .pb-sm-img :}
-
-
-
-Paste in the following code using Control-V (or Command-V on Mac), and give the snippet a name, such as 'show-all-winning-bids':
-
-```javascript
-var bids = pbjs.getAllWinningBids();
-var output = [];
-for (var i = 0; i < bids.length; i++) {
- var b = bids[i];
- output.push({
- 'adunit': b.adUnitCode, 'adId': b.adId, 'bidder': b.bidder,
- 'time': b.timeToRespond, 'cpm': b.cpm
- });
-}
-if (output.length) {
- if (console.table) {
- console.table(output);
- } else {
- for (var j = 0; j < output.length; j++) {
- console.log(output[j]);
- }
- }
-} else {
- console.warn('No prebid winners');
-}
-```
-
-
-
-Right-click the snippet and choose **Run**:
-
-{: .pb-sm-img :}
-
-
-
-Check the output in Console to see the bids (note that this screenshot shows the output from "see all bids" but they're very similar):
-
-{: .pb-sm-img :}
-
-## Modify bid responses for testing
-
-Using `pbjs.setConfig({debugging:{ ... }})` from the javascript console, it is possible to override and filter bids as they come in.
-When this type of debugging is enabled it will persist across page loads using `sessionStorage`. This allows
-for easy testing of pages that immediately start auctions (most pages), but also means you need to remember
-to deactivate debugging when you are done (or clear your local storage / use incognito mode when testing).
-
-```
-// Filtering bidders
-javascript console> pbjs.setConfig({
- debugging: {
- enabled: true, // suppresses bids from other bidders
- bidders: ['bidderA', 'bidderB']
- }
-});
-
-// Overwriting bid responses for all bidders
-javascript console> pbjs.setConfig({
- debugging: {
- enabled: true,
- bids: [{
- cpm: 1.5
- }]
- }
-});
-
-// Overwriting bid responses for a specific bidder and adUnit code (can use either separately)
-javascript console> pbjs.setConfig({
- debugging: {
- enabled: true,
- bids: [{
- bidder: 'bidderA',
- adUnitCode: '/19968336/header-bid-tag-0',
- cpm: 1.5
- }]
- }
-});
-
-// Disabling debugging
-javascript console> pbjs.setConfig({
- debugging: {
- enabled: false
- }
-});
-```
-
-## Related Reading
-
-+ [Prebid.js FAQ](/dev-docs/faq.html)
-+ [Prebid.js Common Issues](/dev-docs/common-issues.html)
+Moved to [the PBJS Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html).
diff --git a/download.md b/download.md
index 25f47e9173..6d4c3be385 100644
--- a/download.md
+++ b/download.md
@@ -5,6 +5,33 @@ description: Documentation on how to download Prebid.js for header bidding.
sidebarType: 0
---
+
+
-
\ No newline at end of file
+
diff --git a/examples/video/instream/flowplayer/pb-ve-flowplayer.html b/examples/video/instream/flowplayer/pb-ve-flowplayer.html
index 42ec91f94e..e5744635ba 100644
--- a/examples/video/instream/flowplayer/pb-ve-flowplayer.html
+++ b/examples/video/instream/flowplayer/pb-ve-flowplayer.html
@@ -97,18 +97,19 @@ Place this code in the page header.
sizes: [640,480],
mediaTypes: {
video: {
- context: "instream"
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [
{
bidder: 'appnexus',
params: {
- placementId: '13232361', // Add your own placement id here
- video: {
- skipppable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: '13232361' // Add your own placement id here
}
}
]
@@ -233,4 +234,4 @@ Place this code in the page body.
-
\ No newline at end of file
+
diff --git a/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html b/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html
index 2e9a0921e8..350fdfea7d 100644
--- a/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html
+++ b/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html
@@ -58,18 +58,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream'
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here
- video: {
- skipppable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here
}
}]
};
diff --git a/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html b/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html
index 359ea4756d..3370763d1f 100644
--- a/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html
+++ b/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html
@@ -54,18 +54,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
+ context: 'instream',
playerSize: [640, 480],
- context: 'instream'
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, //put your placement id here
- video: {
- skipppable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 //put your placement id here
}
}]
};
diff --git a/examples/video/instream/kaltura/pb-ve-kaltura.html b/examples/video/instream/kaltura/pb-ve-kaltura.html
index 0e22a65686..a5ce534724 100644
--- a/examples/video/instream/kaltura/pb-ve-kaltura.html
+++ b/examples/video/instream/kaltura/pb-ve-kaltura.html
@@ -65,18 +65,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
+ context: 'instream',
playerSize: [640, 480],
- context: 'instream'
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement ID here
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement ID here
}
}]
};
diff --git a/examples/video/instream/ooyala/pb-ve-ooyala.html b/examples/video/instream/ooyala/pb-ve-ooyala.html
index d9977f5e77..efa39ea99d 100644
--- a/examples/video/instream/ooyala/pb-ve-ooyala.html
+++ b/examples/video/instream/ooyala/pb-ve-ooyala.html
@@ -98,18 +98,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream'
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: iosDevice ? 13239390 : 13232361, // Add your own placement id here. Note, skippable video is not supported on iOS
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: iosDevice ? 13239390 : 13232361 // Add your own placement id here.
}
}]
};
diff --git a/examples/video/instream/radiant/pb-ve-radiant.html b/examples/video/instream/radiant/pb-ve-radiant.html
index c1f9d7278f..30426eb6e2 100644
--- a/examples/video/instream/radiant/pb-ve-radiant.html
+++ b/examples/video/instream/radiant/pb-ve-radiant.html
@@ -85,18 +85,18 @@ Place this code in the page body.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream'
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361
}
}]
};
@@ -226,18 +226,18 @@ Place this code in the page body.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream'
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361
}
}]
};
diff --git a/examples/video/instream/videojs/pb-ve-videojs.html b/examples/video/instream/videojs/pb-ve-videojs.html
index f90604804d..4a5f96e4ac 100644
--- a/examples/video/instream/videojs/pb-ve-videojs.html
+++ b/examples/video/instream/videojs/pb-ve-videojs.html
@@ -61,18 +61,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
+ context: 'instream',
playerSize: [640, 480],
- context: 'instream'
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361
}
}]
};
diff --git a/examples/video/outstream/pb-ve-outstream-app.html b/examples/video/outstream/pb-ve-outstream-app.html
index 321bd7bcad..34524e8540 100644
--- a/examples/video/outstream/pb-ve-outstream-app.html
+++ b/examples/video/outstream/pb-ve-outstream-app.html
@@ -78,18 +78,18 @@ Place this code in the page body.
code: videoId,
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}]
}];
@@ -154,18 +154,18 @@ Place this code in the page body.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}]
}];
diff --git a/examples/video/outstream/pb-ve-outstream-dfp.html b/examples/video/outstream/pb-ve-outstream-dfp.html
index 21208d218e..0a62332454 100644
--- a/examples/video/outstream/pb-ve-outstream-dfp.html
+++ b/examples/video/outstream/pb-ve-outstream-dfp.html
@@ -72,19 +72,19 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
+ context: 'outstream',
playerSize: [640, 480],
- context: 'outstream'
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [
{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}
]
@@ -148,4 +148,4 @@ Place this code in the page body.
-
\ No newline at end of file
+
diff --git a/examples/video/outstream/pb-ve-outstream-no-server.html b/examples/video/outstream/pb-ve-outstream-no-server.html
index 28f793f34a..bb78701f5e 100644
--- a/examples/video/outstream/pb-ve-outstream-no-server.html
+++ b/examples/video/outstream/pb-ve-outstream-no-server.html
@@ -61,18 +61,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
+ context: 'outstream',
playerSize: [640, 480],
- context: 'outstream'
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}]
}];
diff --git a/examples/video/outstream/pb-ve-outstream-radiant.html b/examples/video/outstream/pb-ve-outstream-radiant.html
index a32442769a..60315adaa6 100644
--- a/examples/video/outstream/pb-ve-outstream-radiant.html
+++ b/examples/video/outstream/pb-ve-outstream-radiant.html
@@ -79,18 +79,18 @@ Place this code in the page body.
code: videoId,
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}]
}];
@@ -159,18 +159,18 @@ Place this code in the page body.
code: videoId,
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}]
}];
diff --git a/examples/video/pb-video-template.html b/examples/video/pb-video-template.html
index a5cf9ff8e2..1d1f9e5ef8 100644
--- a/examples/video/pb-video-template.html
+++ b/examples/video/pb-video-template.html
@@ -197,18 +197,18 @@ Place this code in the page header.
mediaTypes: {
video: {
playerSize: [640, 480],
- context: 'outstream'
+ context: 'outstream',
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [
{
bidder: 'appnexus',
params: {
- placementId: 13232385,
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232385
}
}
]
diff --git a/examples/video/server/brid/pbs-ve-brid.html b/examples/video/server/brid/pbs-ve-brid.html
index 3f089c85a7..93b89d953b 100644
--- a/examples/video/server/brid/pbs-ve-brid.html
+++ b/examples/video/server/brid/pbs-ve-brid.html
@@ -70,21 +70,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
context: 'instream',
+ playerSize: [640, 480],
mimes: ['video/mp4'],
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here
}
}]
};
diff --git a/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html b/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html
index 3020ae9bb0..62e4108e2e 100644
--- a/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html
+++ b/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html
@@ -72,21 +72,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
context: 'instream',
+ playerSize: [640, 480],
mimes: ['video/mp4'],
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here
}
}]
};
diff --git a/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html b/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html
index 637be3738e..f5a15deb27 100644
--- a/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html
+++ b/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html
@@ -63,21 +63,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream',
- mimes: ['video/mp4'],
- protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
diff --git a/examples/video/server/kaltura/pbs-ve-kaltura.html b/examples/video/server/kaltura/pbs-ve-kaltura.html
index ba6d4b6666..5bf385058e 100644
--- a/examples/video/server/kaltura/pbs-ve-kaltura.html
+++ b/examples/video/server/kaltura/pbs-ve-kaltura.html
@@ -68,21 +68,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
context: 'instream',
+ playerSize: [640, 480],
mimes: ['video/mp4'],
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
diff --git a/examples/video/server/ooyala/pbs-ve-ooyala.html b/examples/video/server/ooyala/pbs-ve-ooyala.html
index 33ad48c4e8..6bbe7c407e 100644
--- a/examples/video/server/ooyala/pbs-ve-ooyala.html
+++ b/examples/video/server/ooyala/pbs-ve-ooyala.html
@@ -99,21 +99,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
context: 'instream',
+ playerSize: [640, 480],
mimes: ['video/mp4'],
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
diff --git a/examples/video/server/radiant/pbs-ve-radiant.html b/examples/video/server/radiant/pbs-ve-radiant.html
index 1b8f4abe42..d64d43b0ec 100644
--- a/examples/video/server/radiant/pbs-ve-radiant.html
+++ b/examples/video/server/radiant/pbs-ve-radiant.html
@@ -84,21 +84,18 @@ Place this code in the page body.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream',
- mimes: ['video/mp4'],
- protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
@@ -236,21 +233,18 @@ Place this code in the page body.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
- context: 'instream',
- mimes: ['video/mp4'],
- protocols: [1, 2, 3, 4, 5, 6, 7, 8],
- playbackmethod: [2]
+ context: 'instream',
+ playerSize: [640, 480],
+ mimes: ['video/mp4'],
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
@@ -262,7 +256,6 @@ Place this code in the page body.
cache: {
url: 'https://prebid.adnxs.com/pbc/v1/cache'
},
- debug: true,
enableSendAllBids: true,
s2sConfig: {
endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction',
diff --git a/examples/video/server/videojs/pbs-ve-videojs.html b/examples/video/server/videojs/pbs-ve-videojs.html
index b1d0542319..cb3172c5eb 100644
--- a/examples/video/server/videojs/pbs-ve-videojs.html
+++ b/examples/video/server/videojs/pbs-ve-videojs.html
@@ -82,21 +82,18 @@ Place this code in the page header.
code: 'video1',
mediaTypes: {
video: {
- playerSize: [640, 480],
context: 'instream',
+ playerSize: [640, 480],
mimes: ['video/mp4'],
- protocols: [1, 2, 3, 4, 5, 6],
- playbackmethod: [2]
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
},
bids: [{
bidder: 'appnexus',
params: {
- placementId: 13232361, // Add your own placement id here.
- video: {
- skippable: true,
- playback_method: ['auto_play_sound_off']
- }
+ placementId: 13232361 // Add your own placement id here.
}
}]
};
diff --git a/features/firstPartyData.md b/features/firstPartyData.md
index faf215e1da..cceb41322d 100644
--- a/features/firstPartyData.md
+++ b/features/firstPartyData.md
@@ -204,12 +204,12 @@ here to their page. For now, here's the beta table defining the segtax values:
{: .table .table-bordered .table-striped }
| Segtax ID | Taxonomy Type | Version | Description |
|-----------+---------------+---------+-------------|
-| 1 | Content | 2.1 | [IAB - Content Taxonomy version 2.1](https://iabtechlab.com/wp-content/uploads/2020/07/IABTL-Content-Taxonomy-2.1-Final.xlsx) |
-| 2 | Content | 2.2 | [IAB - Content Taxonomy version 2.2](https://iabtechlab.com/wp-content/uploads/2020/12/IABTechLab_Content_Taxonomy_2-2_Final.xlsx) |
-| 3 | Audience | 1.0 | [IAB - Audience Taxonomy version 1.0](https://iabtechlab.com/wp-content/uploads/2020/07/IABTL-Audience-Taxonomy-1.1-Final.xlsx) |
+| 1 | Content | 1.x | IAB - Content Taxonomy version 1 |
+| 2 | Content | 2.x | [IAB - Content Taxonomy version 2](https://iabtechlab.com/wp-content/uploads/2020/12/IABTechLab_Content_Taxonomy_2-2_Final.xlsx) |
+| 4 | Audience | 1.1 | [IAB - Audience Taxonomy version 1.1](https://iabtechlab.com/wp-content/uploads/2020/07/IABTL-Audience-Taxonomy-1.1-Final.xlsx) |
{: .alert.alert-info :}
-Publishers need to check with their SSPs and DSPs to confirm which
+The [IAB version of this table](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--category-taxonomies-) is associated with ADCOM. Publishers should check with their SSPs and DSPs to confirm which
segment taxonomies they support.
## How Bid Adapters Should Read First Party Data
diff --git a/identity/prebid-identity.md b/identity/prebid-identity.md
new file mode 100644
index 0000000000..d83d63b126
--- /dev/null
+++ b/identity/prebid-identity.md
@@ -0,0 +1,63 @@
+---
+layout: page_v2
+title: Prebid User Identity
+description: What is Prebid User Identity
+sidebarType: 9
+---
+
+# Prebid User Identity Overview
+
+Prebid's aim is to enable the protection of user privacy while still supporting publisher's ability to make revenue,
+keeping the Open Web healthy.
+
+To do this, Prebid offers a number of identity-related products that encourage awareness of privacy regulations such as GDPR, CCPA, and COPPA. The most important projects are:
+
+- [Prebid.js User Identity Module](/dev-docs/modules/userId.html). This module supports more than 20 different flavors of global IDs with different features that publishers can work with.
+- [SharedID](/identity/sharedid.html). This native hosted ID offering from Prebid is simple, free, robust, and privacy-minded.
+- **Coming soon:** [Unified ID 2.0](https://prebid.org/blog/prebid-org-to-serve-as-operator-of-unified-id-2-0/)
+
+## Prebid.js and Identity
+
+Publishers have several ways to include user identity as part of
+the header bidding auction:
+
+1. Install one or more [User ID modules](/dev-docs/modules/userId.html). These modules obtain
+the user's ID from the service and make it available to participating bidders. Publishers
+can define [permissions](/dev-docs/modules/userId.html#permissions) to control which bidders receive which IDs.
+2. Install the [ID Import Module](/dev-docs/modules/idLibrary.html). This module can be
+used to generate a map of identities present on the page.
+3. Pass [First Party Data](/features/firstPartyData.html), such as interests, to bidders for more relevant advertising.
+4. Include [User Syncing](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) to allow bid adapters to establish IDs. Publishers have control over which bidders may sync, which syncing mechanisms are allowed, and when the syncing occurs. Syncing is subject to privacy controls such as GDPR, CCPA, and COPPA.
+
+## Prebid Server and Identity
+
+Prebid Server has user sync functionality, allowing server-side bidders to establish
+IDs given appropriate permission from the user for setting cookies.
+
+Prebid Server can receive extended ID arrays (eids) from Prebid.js and provide them to
+participating server-side bid adapters. It also supports permissioning to determine
+which eids can be sent to which bidders.
+
+User IDs are not sent to bid adapters in privacy scenarios such as COPPA and
+GDPR requests lacking appropriate consent. For more details see [Prebid Server Privacy](/prebid-server/features/pbs-privacy.html).
+
+## Prebid SDK and Identity
+
+In application environments, performance-based advertisers rely on a device’s IDFA to target,
+frequency cap, and determine attribution, similar to how cookies are used in desktop
+environments. However, IDFAs are persistent to the device. Prebid SDK will read the IDFA from
+the device when available. Additionally, Prebid SDK supports third party identity IDs.
+
+Prebid Server will strip the IDFA and/or third party identity IDs when enforcing regulations such as GDPR and CCPA.
+
+## AMP, Prebid, and Identity
+
+Prebid Server supports a user [cookie-sync](/prebid-server/developers/pbs-cookie-sync.html) functionality, including integration with
+a consent management platform. This allows server-side bidders to establish IDs given
+the appropriate cookie-setting permissions from the user.
+
+## Further Reading
+
+- [PBJS User ID module](/dev-docs/modules/userId.html)
+- [SharedID](/identity/sharedid.html)
+- [Prebid Server Privacy](/prebid-server/features/pbs-privacy.html)
diff --git a/identity/sharedid.md b/identity/sharedid.md
new file mode 100644
index 0000000000..be8913d04a
--- /dev/null
+++ b/identity/sharedid.md
@@ -0,0 +1,376 @@
+---
+layout: page_v2
+title: SharedID
+description: What is SharedID
+sidebarType: 9
+---
+
+# Prebid SharedID
+{: .no_toc}
+
+* TOC
+{:toc}
+
+{: .alert.alert-warning :}
+As of Prebid.js 5.0, PubCommon ID is no longer supported -- it's been merged into SharedId. Also, SharedId no longer syncs to sharedid.org like it did in Prebid.js 4.x.
+
+## What is it?
+
+SharedId is a convenient Prebid-owned first party identifier within the [Prebid UserId Module framework](/dev-docs/modules/userId.html).
+
+There are multiple ways to integrate SharedId on your site. See the table below for a breakout of options, and the rest of this document for detailed integration instructions.
+
+{: .table .table-bordered .table-striped }
+| Implementation | Description | Cookie Lifetime | Safari Cookie Lifetime | Technical Difficulty | Revenue Benefit |
+| --- | --- | --- | --- | --- | --- |
+| 3rd Party Cookie Only | No first party cookie solution. | Some Blocked | Blocked | None | Low |
+| User Id Submodule | Including User Id Module in your Prebid.js installation. | 365 days | 7 days | Basic | Good |
+| PubCID Script | Adding the legacy PubCID script; not maintained by Prebid.org. | 365 days | 7 days | High | Varies |
+| SharedId First Party Endpoint | Writing a first party cookie from your web server code. | 365 days | 365 days | Intermediate | Best |
+
+## How does the Prebid UserId Module implementation work?
+
+The SharedID ID system sets a user id cookie in the publisher’s domain.
+Since the cookie is set in the publisher's first party domain it does not fall in scope of browser restrictions on third party cookies. Safari has restrictions on first party cookies set via document.cookie. For this reason we recommend considering a server endpoint installation for maximum effect. See the "Alternate Implementations" section below.
+
+### Prebid.js 5.x
+
+The SharedId module reads and/or sets a random ID in
+the cookie name defined by the publisher when initializing
+the module:
+
+Example 1: client-side cookie setting
+```
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: 'sharedId', //"pubCommonId" as a name is supported for backwards compatibility,
+ storage: {
+ name: '_sharedID', // name of the 1st party cookie, _pubcid is supported for backwards compatibility
+ type: 'cookie',
+ expires: 30
+ }
+ }]
+ }
+});
+```
+
+Example 2: setting the cookie with a first party endpoint
+```
+pbjs.setConfig({
+ userSync: {
+ userIds: [{
+ name: 'sharedId', //"pubCommonId" as a name is supported for backwards compatibility,
+ params: {
+ pixelUrl: "/wp-json/pubcid/v1/extend/" // this parameter identifies your server-side endpoint that will set a first party cookie'
+ },
+ storage: {
+ name: '_sharedID', // name of the 1st party cookie, _pubcid is supported for backwards compatibility
+ type: 'cookie',
+ expires: 30
+ }
+ }]
+ }
+});
+```
+
+The 'source' value transmitted through OpenRTB (user.ext.eids) is pubcid.org. For example:
+```
+user: {
+ ext: {
+ eids: {
+ "source":"pubcid.org",
+ "uids":[
+ {
+ "id":"01EAJWWNEPN3CYMM5N8M5VXY22",
+ "atype":1
+ }
+ ]
+ }
+ }
+}
+```
+
+{: .alert.alert-info :}
+The 'pubcid.org' EID source was adopted by more buyers than 'sharedid.org', so
+when PubCommon was folded into SharedID, we kept the more commonly recognized
+source value.
+
+### Before Prebid.js 5.0
+
+In addition to setting a first party cookie, SharedId in Prebid.js 4.x also sets a third party cookie where possible, syncing the first and third party cookies (subject to browser capability and user opt-out).
+
+SharedId in Prebid.js 4.x was transmitted through the header-bidding ecosystem on user.ext.eids with a different 'source':
+```
+user: {
+ ext: {
+ eids: {
+ "source":"sharedid.org",
+ "uids":[
+ {
+ "id":"01EAJWWNEPN3CYMM5N8M5VXY22",
+ "atype":1,
+ "ext":{
+ "third":"01EAJWWNEPN3CYMM5N8M5VXY22"
+ }
+ }
+ ]
+ }
+ }
+}
+```
+
+### Detailed Walkthrough
+
+This diagram summarizes the workflow for SharedId:
+
+{: .pb-lg-img :}
+
+1. The page loads the Prebid.js package, which includes the SharedId module.
+2. The page enables one or more user ID modules with pbjs.setConfig({usersync}) per the module documentation. The publisher can control which bidders are allowed to receive each type of ID.
+3. If permitted, the SharedId module retrieves and/or sets the designated first party cookie for this user.
+4. When a header bidding auction is run, the ID modules are invoked to add their IDs into the bid requests.
+5. Bid adapters send the additional IDs to the bidding endpoints, along with other privacy information such as GDPR consent, US Privacy consent, and the Global Privacy Control header.
+6. SharedId is used by the bidder for ad targeting, frequency capping, and/or sequential ads.
+7. Bids are sent to the publisher's ad server, where the best ad is chosen for rendering.
+
+{: .alert.alert-info :}
+In Prebid.js 4.x, when SharedId performed third-party syncing there
+was an extra step in the diagram between steps 3 and 4 where the module would connect to a server on sharedid.org. This step was
+removed in Prebid.js 5.0.
+
+### Privacy Discussion
+
+There are several privacy scenarios in which a user ID is not created or read:
+
+1. The User ID module suppresses all cookie reading and setting activity
+when the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html) is in place and there's no consent for Purpose 1.
+2. The User ID module infrastructure supports a first-party opt-out, by setting the `_pbjs_id_optout` cookie or local storage to any value. No other cookies will be set if this one is set.
+3. The SharedId module will suppress the ID when the COPPA flag is set.
+
+For all other privacy-sensitive scenarios, it is encumbent upon bid adapters and endpoints
+to be aware of and enforce relevant regulations such as CCPA and Global Privacy Control.
+
+## Opt-Out
+
+Prebid recommends that publishers provide their users with information about how IDs are utilized, including targeting, frequency capping, and special ad features like sequential ads.
+
+If the publisher's legal staff has determined that a user opt-out is necessary beyond existing
+mechanisms like GDPR and CCPA, the use of first party cookies requires that opt-out flow be owned
+by the publisher.
+
+Publishers that decide to build a first-party opt-out workflow might follow a process like this:
+- User is presented with an option to turn off ad targeting
+- If the user opts out, the page can do one of two things:
+ - set a `_pbjs_id_optout` first party cookie
+ - avoid calling pbjs.setConfig to initialize the user ID modules
+
+## Alternative Implementations
+
+For those not using Prebid's header bidding solution, SharedId can deployed via in inline script reference or from a web server.
+
+### SharedId Script
+
+For those interested in implementing SharedId without prebid.js.
+1. Clone the [SharedId script repository](https://github.com/prebid/Shared-id-v2)
+2. Implement the pubcid.js script on the desired page by following the build instructions in the [readme.md](https://github.com/prebid/Shared-id-v2#readme)
+
+Prebid also recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page.
+
+If there are no custom configurations, then just include the script and it'll use the default values.
+
+```
+
+```
+
+If custom configurations are needed, define the pubcid_options object before inclusion of the script. Below is an example to switch from using local storage to cookie:
+
+```
+
+
+```
+
+#### Configuration
+
+Below are the available configuration options for the PubCID script.
+
+{: .table .table-bordered .table-striped }
+| Parameter Name | Type | Description | | Example |
+| --- | --- | --- | --- | --- |
+| create | boolean | If true, then an id is created automatically by the script if it's missing. Default is true. If your server has a component that generates the id instead, then this should be set to false | | `true` |
+| expInterval | decimal | Expiration interval in minutes. Default is 525600, or 1 year | | `525600` |
+| extend | boolean | If true, the the expiration time is automatically extended whenever the script is executed even if the id exists already. Default is true. If false, then the id expires from the time it was initially created. | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` |
+| pixelUrl | string (optional) | For publisher server support only. Where to call out to for a server cookie. | | `/wp-json/pubcid/v1/extend/`
+| type | string | Type of storage. It's possible to specify one of the following: 'html5', 'cookie'. Default is 'html5' priority, aka local storage, and fall back to cookie if local storage is unavailable. | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `cookie` |
+
+#### Example Configurations
+
+Always use cookies and create an ID that expires in 30 days after creation.
+
+```
+{
+ type: 'cookie',
+ extend: false,
+ expInterval: 43200
+}
+```
+
+Using a SharedId Endpoint implementation, create the cookie once, which will be allowed to expire before it is created again.
+
+```
+{
+ type: 'cookie',
+ pixelUrl: '/wp-json/pubcid/v1/extend/',
+ create: false,
+ extend: false
+}
+
+```
+
+### SharedId First Party Endpoint
+
+Add server-side support for SharedId to better handle the ever-increasing restrictions on cookies in modern web browsers by having the SharedId first party cookie written and extended by your web server.
+
+#### CMS
+
+PubCID/SharedId plugins are available for Wordpress and Drupal. Because the CMS can cache pages to improve scalability, it's impractical to set unique cookies during page generation. Instead these plugins require a dynamic endpoint that serves back a blank pixel along with a unique cookie value. The client side script needs one additional parameter for this URL. Please consult the corresponding plugin documents for default values:
+
+1. Wordpress : Install directly from the [Wordpress admin page](https://wordpress.org/plugins/publisher-common-id/). Install from [GITHUB](https://github.com/prebid/sharedid-wordpress)
+2. Drupal : Install from [Github](https://github.com/prebid/sharedid-drupal).
+
+#### Endpoint Implementations
+
+The Wordpress and Drupal plugins require that the host company integrate a new endpoint into their webserver that can receive request from the page and set a unique cookie.
+Below are some examples for how to implement this function in various languages or platforms. It is up to the site owner to integrate an appropriate script for their specific scenario.
+
+##### JAVA
+```JAVA
+public class PubCid {
+ private static final String pubcidCookieName = "_pubcid";
+ private static final int expireTime = (int) TimeUnit.DAYS.toSeconds(365); //store cookie for 1 year
+
+ /**
+ * Returns the pubcid cookie found in the user's list of cookies.
+ * Always update the expire time to another year so that the cookie persists.
+ *
+ * @param cookies User's list of cookies
+ * @return the pubcid cookie if found, null otherwise
+ */
+ public static Cookie getPubcidCookie(Cookie[] cookies) {
+
+ Cookie pubcidCookie = fetchPubcidCookie(cookies);
+ if (pubcidCookie != null)
+ pubcidCookie.setMaxAge(expireTime);
+
+ return pubcidCookie;
+ }
+
+ /**
+ * Simple function to test if the user has a pubcid cookie
+ *
+ * @param cookies User's list of cookies
+ * @return true if the cookie is found, false otherwise
+ */
+ public static boolean hasPubcidCookie(Cookie[] cookies) {
+ return fetchPubcidCookie(cookies) != null;
+ }
+
+ /**
+ * Local function to find the pubcid cookie within the user's list of cookie
+ *
+ * @param cookies User's list of cookies
+ * @return pubcid cookie if found, null otherwise
+ */
+ private static Cookie fetchPubcidCookie(Cookie[] cookies) {
+ if (cookies == null) return null;
+ return Arrays.stream(cookies)
+ .filter(e -> e.getName().equals(pubcidCookieName))
+ .findFirst()
+ .orElse(null);
+ }
+}
+```
+##### PHP
+```PHP
+$cookie_name = '_pubcid';
+$cookie_path = '/';
+$max_age = 365;
+
+$value = NULL;
+
+// See if the cookie exist already
+
+if (isset($_COOKIE[$cookie_name ]))
+ $value = $_COOKIE[$cookie_name];
+
+// Obtain site domain if defined
+if (defined(COOKIE_DOMAIN))
+ $cookie_domain = COOKIE_DOMAIN;
+else
+ $cookie_domain = "";
+
+// Update the cookie
+if (isset($value)) {
+ setcookie(
+ $cookie_name,
+ $value,
+ time() + $max_age * DAY_IN_SECONDS,
+ $cookie_path,
+ $cookie_domain
+ );
+}
+```
+##### Node.js
+```Node
+const express = require('express');
+const cookieParser = require('cookie-parser');
+const app = express();
+const port = 3000;
+
+app.use(cookieParser());
+
+app.get('/', function(req, res) {
+
+ // Check for existence of _pubcid cookie
+ let value = req.cookies['_pubcid'];
+
+ // If pubcid exists, then update its expiration time
+ if (value) {
+ res.cookie('_pubcid', value, {domain: '.example.com', path: '/', expires: new Date(Date.now() + 1000*60*60*24*365)});
+ }
+
+ res.render('index');
+});
+
+app.listen(port, ()=>console.log(`App listening on port ${port}`));
+```
+##### Apache
+```Apache
+# Add to httpd.conf
+# Requires mod_headers and mod_env
+
+# Capture _pubcid cookie value if available
+SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" PUBCID_VALUE=$2
+SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" HAVE_PUBCID=1
+
+# Add _pubcid cookie if it exists to the response with 1 year expiration time
+Header add Set-Cookie "_pubcid=%{PUBCID_VALUE}e;Domain=.example.com;Path=/;Max-Age=31536000" env=HAVE_PUBCID
+```
+##### Nginx
+```Nginx
+# Add to a location directive
+
+ location /example {
+ set $pubcid_value $cookie__pubcid;
+ if ($pubcid_value) {
+ add_header Set-Cookie "_pubcid=$pubcid_value;Domain=.example.com;Path=/;Max-Age=31536000";
+ }
+ }
+```
+
+## Related Topics
+
+- [Prebid Identity Overview](/identity/prebid-identity.html)
+- [Prebid.js User ID modules](/dev-docs/modules/userId.html)
diff --git a/overview/ga-analytics.md b/overview/ga-analytics.md
index 503ac5ca0f..004a08a5a9 100644
--- a/overview/ga-analytics.md
+++ b/overview/ga-analytics.md
@@ -24,7 +24,7 @@ It includes:
- Bidder bid/win price analysis by geo, domain, with price range distribution.
- Bid latency by bidder, geo, and domain.
-- Seamless integration with your Google Analytics account and scheduled reports delivered to your mailbox.
+- Seamless integration with your Google Analytics account and scheduled reports delivered to your mailbox.
@@ -32,15 +32,15 @@ It includes:
The day starts from making sure the bidders are not generating less revenue:
-
+
Something is not right here - total revenue from yesterday dropped quite a bit. This could be caused by certain bidders were down or experienced technical issues. Let's take a look at the bidder timeout rate:
-
+
Bidder timeout seems okay. The problem might then be caused by bidders' lower bid rate:
-
+
Here we go. Bidder 1 and 4 bid much less than usual. You may want to drill down even further - Prebid.js Analytics also provides:
@@ -59,7 +59,7 @@ To understand exactly how much time per bidder spent, the Analytics Platform all
-
+
You might derive:
@@ -72,7 +72,7 @@ Similar query for bidders' bid CPM:
-
+
> **Try out the product and explore the demo dashboard here!** This will be the base of your dashboard!
@@ -91,5 +91,3 @@ Prebid.js has a seamless integration with Google Analytics and Google Spreadshee
- [Analytics for Prebid]({{site.baseurl}}/overview/analytics.html) (Overview and list of analytics providers)
- [Integrate with the Prebid Analytics API]({{site.baseurl}}/dev-docs/integrate-with-the-prebid-analytics-api.html) (For developers)
-
-
diff --git a/overview/how-many-bidders-for-header-bidding.md b/overview/how-many-bidders-for-header-bidding.md
index a006ab240f..1ce008e967 100644
--- a/overview/how-many-bidders-for-header-bidding.md
+++ b/overview/how-many-bidders-for-header-bidding.md
@@ -3,7 +3,7 @@ layout: page_v2
title: Optimize header bidding setup
head_title: Optimize header bidding setup
-description: An analysis of the optimal number of bidders to work with for header bidding, to optimize yield and user experience.
+description: An analysis of the optimal number of bidders to work with for header bidding, to optimize yield and user experience.
pid: 10
@@ -23,7 +23,7 @@ While helping publishers run header bidding, we hear the same questions asked ma
* How many bidders should I work with?
* How can I maximize revenue while maintaining a good user experience?
-We've all heard anecdotally a webpage should not have more than 10 bidders' bids, or the page should not wait for longer than 1 second before it sends the bids to the ad server. Are they true?
+We've all heard anecdotally a webpage should not have more than 10 bidders' bids, or the page should not wait for longer than 1 second before it sends the bids to the ad server. Are they true?
Luckily, the publishers using Prebid.js are curious about these questions too. We thus ran A/B tests and collected real data from pages running header bidding. We measured overall revenue & latency versus the number of bidders and how long the ad server waits for.
@@ -31,7 +31,7 @@ Luckily, the publishers using Prebid.js are curious about these questions too. W
### Q1: How is revenue affected by different factors?
-{: .pb-lg-img :}
+{: .pb-lg-img :}
(_the above data is normalized to CPM = 1 for anonymity_)
Revenue is mainly determined by:
@@ -53,17 +53,17 @@ Conclusions:
##### 3. Revenue actually drops if the page waits for too long
-* This could be caused by users leaving the page, when the ads took too long to load.
+* This could be caused by users leaving the page, when the ads took too long to load.
### Q2: How is page content load time affected?
-{: .pb-lg-img :}
+{: .pb-lg-img :}
_(The above page has on average 130 HTTP requests, 1.5MB data transferred per refresh)_
-Page content load time is critical to measure user experience. Your page's content taking 200 millisecond to load delivers a MUCH BETTER experience than if it takes 2 seconds.
+Page content load time is critical to measure user experience. Your page's content taking 200 millisecond to load delivers a MUCH BETTER experience than if it takes 2 seconds.
In this test, we measured the front section's load time. We define the front section as what's visible to the user when they open the webpage. For example, when the above graph's Y-axis is at 100ms, it means that the front section took 100ms to load before a user can see it.
@@ -71,15 +71,15 @@ Conclusions:
##### Page content load time is NOT really affected by the number of bidders or by how long the page waits.
-* The front section continues to load between 60 to 120ms, unaffected by the given factors.
-* **This is expected**, as Prebid.js sends out bids asynchronously and they **do NOT block** the page content from loading. Modern browsers also prioritize the page content load over asynchronous Javascript scripts.
+* The front section continues to load between 60 to 120ms, unaffected by the given factors.
+* **This is expected**, as Prebid.js sends out bids asynchronously and they **do NOT block** the page content from loading. Modern browsers also prioritize the page content load over asynchronous Javascript scripts.
### Q3: How about ad load time?
-{: .pb-lg-img :}
+{: .pb-lg-img :}
_(The above page has on average 130 HTTP requests, 1.5MB data transferred per refresh)_
Ad load time measures how long a user has to wait before he/she can see the ad. This is less important than the page's content load time. However, the initial blank space in the ad unit, or the page elements shifting around due to a late ad load, can both demage the user experience.
@@ -90,7 +90,7 @@ Conclusions:
* This makes perfect sense. It's important to note that the ads load at around 1200ms even when the adserver waits for 2 seconds, because most of the bids come back within 1200ms and Prebid.js stops the adserver from waiting.
-##### 2. When your ad server waits for < a threshold (500ms in this case), working with more bids take longer for the ads to load.
+##### 2. When your ad server waits for < a threshold (500ms in this case), working with more bids take longer for the ads to load.
* This makes sense, because sending out more bid requests takes longer.
@@ -102,7 +102,7 @@ Conclusions:
### Recommendations:
-Every webpage is different. Every site's users are different. Different publishers will put different weights on revenue vs. user experience. Our main recommendation is: **Create the above 3 graphs.** They will help you understand how many bids you should work with and how long your page should wait for.
+Every webpage is different. Every site's users are different. Different publishers will put different weights on revenue vs. user experience. Our main recommendation is: **Create the above 3 graphs.** They will help you understand how many bids you should work with and how long your page should wait for.
Prebid.js is a good place to start for free : )
@@ -115,5 +115,3 @@ Note that the above data is collected by pages that run true header bidding auct
* Ad server only waits for a limited amount of time, ignoring all bids that come after.
If your page does not run a true header bidding auction, the above analysis may not apply.
-
-
diff --git a/overview/how-to-simplify-line-item-setup.md b/overview/how-to-simplify-line-item-setup.md
index 3e1a05061d..6d3d392ebf 100644
--- a/overview/how-to-simplify-line-item-setup.md
+++ b/overview/how-to-simplify-line-item-setup.md
@@ -43,16 +43,16 @@ In this section, we'll learn how to remove the creative size dimension for heade
Let's first clarify what "different set of line items for different creative sizes" means. In this scenario, a line item's creative is only of one size. In Google Ad Manager, this looks like:
-{: .pb-md-img :}
+{: .pb-md-img :}
Because a site would have many creative sizes, with this setup you need X number of line item sets for X number of creative sizes.
There's a reason bidders recommend different set of line items for different creative sizes. If we simply attach all creative sizes to a line item, the line item wouldn't know which size of creative to choose. Consider this case:
-* Your line item has all creatives of different sizes attached.
+* Your line item has all creatives of different sizes attached.
* Your ad unit can accept both 300x250 and 300x600. A bidder bid $6.00 for the 300x600 size and has the highest price.
-* The $6.00 line item got picked by the line item.
+* The $6.00 line item got picked by the line item.
* The best your ad server can do is to RANDOMLY choose a creative. If the 300x250 one is chosen, the ad will be cut in half.
#### How Prebid.js solves this problem:
@@ -60,10 +60,10 @@ There's a reason bidders recommend different set of line items for different cre
Prebid.js can dynamically resize the returned creative to the right size. Here's the setup:
* Submit a few creatives of size 1x1 and make them override the line items' sizes when you [attach creatives to the line item](/adops/step-by-step.html#step-3-attach-the-creative-to-the-line-item).
-* Your ad unit can accept both 300x250 and 300x600. A bidder bid $6.00 for the 300x600 size and has the highest price. Prebid.js passed the bid in, as well as a generated bid ID.
-* The $6.00 line item got picked by the line item.
+* Your ad unit can accept both 300x250 and 300x600. A bidder bid $6.00 for the 300x600 size and has the highest price. Prebid.js passed the bid in, as well as a generated bid ID.
+* The $6.00 line item got picked by the line item.
* Your ad server randomly choose a 1x1 creative. However, because all creatives have the same content, it does not make a difference.
-* The creative content has the bid ID. Prebid.js reads this bid ID, which is mapped to size 300x600.
+* The creative content has the bid ID. Prebid.js reads this bid ID, which is mapped to size 300x600.
* Prebid.js resize the returned creative to size 300x600 and injects the bid's cretive payload.
There you go!
@@ -77,7 +77,7 @@ There're a few reasons why previously you'd need different set of line items for
1. Bidders did not design their implementation guide with other bidders in mind.
2. Bidders all have different targeting parameters.
-3. You need to run reports to learn fill rates and CPM from different bidders.
+3. You need to run reports to learn fill rates and CPM from different bidders.
Assume we have 1 set of line items for ALL bidders. Consider the below key-value pairs came in: (AppNexus bid $1.60, Rubicon bid $1.20. Ad IDs are used for rendering the right creative):
@@ -98,7 +98,7 @@ Prebid.js only picks the highest price bid and sends its key-value pairs to the
* `hb_adId`: 65432
* `hb_bidder`: appnexus
-This simplifies the setup and the right creative (with adId 65432) will get displayed.
+This simplifies the setup and the right creative (with adId 65432) will get displayed.
#### How about reporting?
@@ -107,10 +107,8 @@ It's important to understand the fill rates and CPM from different bidders. Preb
* For bidder X, at what CPM does it fill?
* For bidder X, what's the fill rate out of all the winning header bidding bids?
-Note that because Prebid.js only sends in the highest price bid, Google Ad Manager does not see the rest of the lost bids. However, from working with publishers, we conclude that the rest of the bids do NOT matter that much. Let's say one bidder always fills at 1 penny and bids 100% of the time. Is that information helpful? Not really, only the winning bids count. We belive the above 2 queries well serve the reporting and analytics needs.
+Note that because Prebid.js only sends in the highest price bid, Google Ad Manager does not see the rest of the lost bids. However, from working with publishers, we conclude that the rest of the bids do NOT matter that much. Let's say one bidder always fills at 1 penny and bids 100% of the time. Is that information helpful? Not really, only the winning bids count. We belive the above 2 queries well serve the reporting and analytics needs.
### Conclusion
Enjoy the much more simplified line items, creatives, and targeting setup!
-
-
diff --git a/overview/intro.md b/overview/intro.md
index 914e35f5d9..23342c615b 100644
--- a/overview/intro.md
+++ b/overview/intro.md
@@ -31,7 +31,7 @@ Our flagship product, Prebid.js, is sometimes referred to as simply *Prebid*, bu
### What is Header Bidding?
-Header bidding is a response to a fragmented and inefficient process for digital ad display. It is an alternative to the "waterfall" method, in which impressions impressions are offered to one sales channel at a time, moving down an inflexible stack of sources.
+Header bidding is a response to a fragmented and inefficient process for digital ad display. It is an alternative to the "waterfall" method, in which impressions are offered to one sales channel at a time, moving down an inflexible stack of sources.
With header bidding, the publisher creates a short delay in their ad serving to obtain bids from many SSPs and ad exchanges. In this way, publishers can receive high value bids on their inventory that may be unavailable through their primary ad server and exchange.
The returned bids are then passed into the ad server so they can compete with direct demand and the primary ad server's exchange on a level playing field.
diff --git a/overview/what-is-post-bid.md b/overview/what-is-post-bid.md
index 276209bb36..0bbd22b652 100644
--- a/overview/what-is-post-bid.md
+++ b/overview/what-is-post-bid.md
@@ -21,7 +21,7 @@ they all compete in one single line item based on price.
This diagram summarizes the post-bid scenario:
-{: .pb-lg-img :}
+{: .pb-lg-img :}
Steps:
diff --git a/package.json b/package.json
index 27b2226477..320ee697a4 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
- "watch": "npm run development -- --watch",
+ "watch": "bundle exec jekyll serve",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --nide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
diff --git a/prebid-mobile/pbm-api/android/pbm-targeting-params-android.md b/prebid-mobile/pbm-api/android/pbm-targeting-params-android.md
index cd857e9ad4..01cce946bc 100755
--- a/prebid-mobile/pbm-api/android/pbm-targeting-params-android.md
+++ b/prebid-mobile/pbm-api/android/pbm-targeting-params-android.md
@@ -114,9 +114,9 @@ TargetingParams.setStoreUrl(storeUrl);
```
-### Open Measurment SDK (OMSDK)
+### Open Measurement SDK (OMSDK)
-OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is elligible for OMSDK support. Prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code.
+OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is eligible for OMSDK support. Prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code.
There three components to signaling support for OMSDK:
* Partner Name
diff --git a/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md b/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md
index 414d830d01..a118da3145 100644
--- a/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md
+++ b/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md
@@ -151,9 +151,9 @@ Targeting.shared.itunesID
Targeting.shared.itunesID = itunesID
```
-### Open Measurment SDK (OMSDK)
+### Open Measurement SDK (OMSDK)
-OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is elligible for OMSDK support. Prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code.
+OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is eligible for OMSDK support. Prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code.
There three components to signaling support for OMSDK:
* Partner Name
diff --git a/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md
index d1be426cc1..2befade496 100755
--- a/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md
+++ b/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md
@@ -21,7 +21,7 @@ Create a new Video Rewarded Ad Unit associated with a Prebid Server configuratio
-# Paramaters
+# Parameters
Parameters is a sub class of RewardedVideoAdUnit.Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes.
diff --git a/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md
index 385bac77d3..7d54ba038a 100755
--- a/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md
+++ b/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md
@@ -20,7 +20,7 @@ Video Insterstital is only supported with Google Ad Manager.
`configId(String)`: Prebid Server configuration ID.
-# Paramaters
+# Parameters
Parameters is a sub class of VideoInterstitialAdUnit.Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes.
diff --git a/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md
index f5379e6be3..93c063b712 100755
--- a/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md
+++ b/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md
@@ -61,7 +61,7 @@ OpenRTB Placement Type represented as an enumeration of values:
* inFeed is transformed into OpenRTB value 4 to bid adapters
-### Paramaters
+### Parameters
Parameters is a sub class of videoAdUnit. Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes.
diff --git a/prebid-server/developers/add-new-bidder-go.md b/prebid-server/developers/add-new-bidder-go.md
index 7cfc39e2f7..b710431d91 100644
--- a/prebid-server/developers/add-new-bidder-go.md
+++ b/prebid-server/developers/add-new-bidder-go.md
@@ -62,7 +62,7 @@ Please be attentive in reading and responding to emails and [GitHub issues](http
Prebid Server bid adapters consist of several components: bidder info, bidder parameters, adapter code, user sync code, registration with the core framework, and default configuration values. This chapter will guide you though each component.
-Please refer to [existing bid adapters](https://github.com/prebid/prebid-server/tree/master/adapters) for working examples and practical guidance, but understand that our adapter interfaces and coding style evolve over time. Please prefer the examples in this document over differences you may find in code.
+Please refer to [existing bid adapters](https://github.com/prebid/prebid-server/tree/master/adapters) for working examples and practical guidance, but understand that our adapter interfaces and coding style evolve over time. Please refer to the examples in this document over differences you may find in an existing bid adapter.
Our project is written in the [Go programming language](https://golang.org/). We understand not everyone has prior experience writing Go code. Please try your best and we'll respectfully steer you in the right direction during the review process.
@@ -504,7 +504,12 @@ if request.Imp[i].W == nil && request.Imp[i].H == nil && len(request.Imp[i].Form
-The second argument, `requestInfo`, is for extra information and helper methods provided by the core framework. For now, this just includes `requestInfo.PbsEntryPoint` which is commonly used to determine if the request is for AMP or Long Form Video Ad Pods. This object will be expanded in the future to also include currency conversion and extension unmarshalling helper methods.
+The second argument, `requestInfo`, is for extra information and helper methods provided by the core framework. This includes:
+
+- `requestInfo.PbsEntryPoint` to access the entry point of the bid request, commonly used to determine if the request is for AMP or for a Long Form Video Ad Pod.
+- `requestInfo.GlobalPrivacyControlHeader` to read the value of the Sec-GPC Global Privacy Control (GPC) header of the bid request.
+- `requestInfo.ConvertCurrency` a method to perform currency conversions.
+
The `MakeRequests` method is expected to return a slice (similar to a C# `List` or a Java `ArrayList`) of `adapters.RequestData` objects representing the HTTP calls to be sent to your bidding server and a slice of type `error` for any issues encountered creating them. If there are no HTTP calls or if there are no errors, please return `nil` for both return values. Neither slices may contain `nil` elements.
@@ -546,7 +551,49 @@ func (a *adapter) MakeRequests(request *openrtb.BidRequest, requestInfo *adapter
If your bidding server supports multiple currencies, please be sure to pass through the `request.cur` field. If your bidding server only bids in a single currency, such as USD or EUR, that's fine. Prebid Server will convert your bid to the request currency if you include it in the bid response, otherwise we assume USD and conversion will not occur.
-Please ensure you forward the bid floor (`request.imp[].bidfloor`) and bid floor currency (`request.imp[].bidfloorcur`) values to your bidding server for enforcement. You'll soon have access to currency conversion helper methods if your endpoint only supports floors in a single currency.
+Please ensure you forward the bid floor (`request.imp[].bidfloor`) and bid floor currency (`request.imp[].bidfloorcur`) values to your bidding server for enforcement. You have access to the currency conversion helper method `ConvertCurrency` in case your endpoint only supports floors in a single currency.
+
+
+ Example: Currency conversion needed for bid floor values in impressions.
+
+```go
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) (*adapters.RequestData, []error) {
+
+ for _, imp := range request.Imp {
+
+ // Check if imp comes with bid floor amount defined in a foreign currency
+ if imp.BidFloor > 0 && imp.BidFloorCur != "" && strings.ToUpper(imp.BidFloorCur) != "USD" {
+
+ // Convert to US dollars
+ convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD")
+ if err != nil {
+ return nil, []error{err}
+ }
+
+ // Update after conversion. All imp elements inside request.Imp are shallow copies
+ // therefore, their non-pointer values are not shared memory and are safe to modify
+ // without risking a data race condition
+ imp.BidFloorCur = "USD"
+ imp.BidFloor = convertedValue
+ }
+ }
+
+ requestJSON, err := json.Marshal(request)
+ if err != nil {
+ return nil, []error{err}
+ }
+
+ requestData := &adapters.RequestData{
+ Method: "POST",
+ Uri: a.endpoint,
+ Body: requestJSON,
+ }
+
+ return []*adapters.RequestData{requestData}, nil
+}
+```
+
+
There are a several values of a bid that publishers expect to be populated. Some are defined by the OpenRTB 2.5 specification and some are defined by Prebid conventions.
@@ -557,6 +604,7 @@ There are a several values of a bid that publishers expect to be populated. Some
| COPPA | OpenRTB | `request.regs.ext.us_privacy`
The publisher is specifying the Children's Online Privacy Protection flag.
| Currency | OpenRTB |`request.cur`
The publisher is specifying the desired bid currency. The Prebid Server default is USD.
| [Debug](https://github.com/prebid/prebid-server/issues/745) | Prebid | `request.ext.prebid.debug`
The publisher is requesting verbose debugging information from Prebid Server.
+| [Request-Defined currency conversion rates](https://docs.prebid.org/prebid-server/features/pbs-currency.html) | Prebid | `request.ext.prebid.currency`
The publisher decides to prioritize its own custom currency conversion rates over Prebid Server's currency conversion rates. If a currency rate is not found in `request.ext.prebid.currency`, Prebid Server's rates will be used unless `usepbsrates` is set to `false`. If missing, `usepbsrates` defaults to true.
| [First Party Data (FPD)](https://docs.prebid.org/prebid-server/features/pbs-fpd.html)| Prebid | `request.imp[].ext.context.data.*`, `request.app.ext.data.*`, `request.site.ext.data.*`, `request.user.ext.data.*`
The publisher may provide first party data (e.g. keywords).
| GDPR | OpenRTB | `request.regs.ext.gdpr`, `request.user.ext.consent`
The publisher is specifying the European General Data Protection Regulation flag and TCF consent string.
| Site or App | OpenRTB | `request.site`, `request.app`
The publisher will provide either the site or app, but not both, representing the client's device.
@@ -619,7 +667,7 @@ Either `.Bids[].BidVideo.PrimaryCategory` or `.Bids[].Bid.Cat` should be provide
Prebid has historically struggled with sharing granular bid response data with publishers, analytics, and reporting systems. To address this, we've introduced a standard object model. We encourage adapters to provide as much information as possible in the bid response.
{: .alert.alert-danger :}
-Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for AdvertiserDomains and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid.
+Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for bid.ADomain and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid.
{: .table .table-bordered .table-striped }
| Path | Description
@@ -630,13 +678,12 @@ Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for Adve
| `.AgencyName` | Bidder-specific agency name.
| `.AdvertiserID` | Bidder-specific advertiser id.
| `.AdvertiserName` | Bidder-specific advertiser name.
-| `.AdvertiserDomains` | Advertiser domains for the landing page(s). Should match `.Bids[].Bid.ADomain`.
| `.BrandID` | Bidder-specific brand id for advertisers with multiple brands.
| `.BrandName` | Bidder-specific brand name.
-| `.dchain` | Demand Chain Object.
+| `.DChain` | Demand Chain Object.
| `.PrimaryCategoryID` | Primary IAB category id.
| `.SecondaryCategoryIDs` | Secondary IAB category ids.
-| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. Should match `.Bids[].BidType`.
+| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe.
@@ -673,8 +720,7 @@ func buildMeta(bid *adapters.TypedBid) (json.RawMessage, error) {
AgencyName: "Some Agency Name",
AdvertiserID: 3,
AdvertiserName: "Some Advertiser Name",
- AdvertiserDomains: bid.ADomain,
- dchain: bid.ext.dchain,
+ DChain: json.RawMessage(`{Some Demand Chain JSON}`),
BrandID: 4,
BrandName: "Some Brand Name",
PrimaryCategoryID: "IAB-1",
@@ -883,7 +929,7 @@ This chapter will guide you through the creation of automated unit tests to cove
### Adapter Code Tests
-Bid requests and server responses can be quite verbose. To avoid large blobs of text embedded within test code, we've created a framework for bid adapters which use a JSON body and/or a url. If your bidding server uses another payload format, such as XML, you're on your own.
+Bid requests and server responses can be quite verbose. To avoid large blobs of text embedded within test code, we've created a framework for bid adapters which use a JSON body and/or a url to send a bid request. We require the use of our test framework as it includes checks to ensure no changes are made to shared memory.
We strive for as much test coverage as possible, but recognize that some code paths are impractical to simulate and rarely occur. You do not need to test the error conditions for `json.Marshal` calls, for template parse errors within `MakeRequests` or `MakeBids`, or for `url.Parse` calls. Following this guidance usually results in a coverage rate of around 90% - 95%, although we don't enforce a specific threshold.
@@ -1004,19 +1050,6 @@ func TestEmptyConfig(t *testing.T) {
}
```
-### Adapter Race Condition Tests
-
-You must define race condition tests for each media type supported by your bid adapter. We don't expect bid adapters to run concurrent code. Rather, these tests attempt to verify your bid adapter doesn't modify shared memory. We use Go's [race detector](https://golang.org/doc/articles/race_detector.html) which is a great line of defense, but it may produce false negatives. It will not produce false positives, so please investigate further if these tests ever fail.
-
-Create a file with the path `adapters/{bidder}/{bidder}test/params/race/{mediaType}.json` for each `banner`, `video`, `audio`, and `native` media type supported by your adapter. Include all required and optional bidder parameters defined by your JSON Schema.
-
-Here's an example file using the same example JSON Schema from other chapters:
-```json
-{
- "placementId": "Some Placement"
-}
-```
-
### Bidder Parameter Tests
The bidder parameter JSON Schema files are considered a form of code and must be tested. Create a file with the path `adapters/{bidder}/params_test.go` using the following template:
diff --git a/prebid-server/developers/add-new-bidder-java.md b/prebid-server/developers/add-new-bidder-java.md
index 692954b274..a40bebcad0 100644
--- a/prebid-server/developers/add-new-bidder-java.md
+++ b/prebid-server/developers/add-new-bidder-java.md
@@ -78,13 +78,7 @@ Create a file with the path `static/bidder-info/{bidder}.yaml` and begin with th
```yaml
adapters:
yourBidderCode:
- enabled: false
endpoint: http://possible.endpoint
- pbs-enforces-gdpr: true
- pbs-enforces-ccpa: true
- modifying-vast-xml-allowed: true
- deprecated-names:
- aliases:
meta-info:
maintainer-email: maintainer@email.com
app-media-types:
@@ -109,8 +103,9 @@ adapters:
Modify this template for your bid adapter:
- Change the maintainer email address to a group distribution list on your ad server's domain. A distribution list is preferred over an individual mailbox to allow for robustness, as roles and team members naturally change.
-- Change the `modifyingVastXmlAllowed` value to `true` if you'd like to opt-in for video impression tracking.
-- Change the `enabled` value to `true` if you'd like to make your bid adapter enabled.
+- Change the `modifying-vast-xml-allowed` value to `false` if you'd like to opt out of video impression tracking. It defaults to `true`.
+- Change the `pbs-enforces-gdpr` to `false` if you'd like to disable gdpr enforcement. Defaults to `true`.
+- Change the `pbs-enforces-ccpa` to `false` if you'd like to disable ccpa enforcement. Defaults to `true`.
- Change the `vendor-id` value to id of your bidding server as registered with the [GDPR Global Vendor List (GVL)](https://iabeurope.eu/vendor-list-tcf-v2-0/). Leave this as `0` if you are not registered with IAB Europe.
- Remove the `capabilities` (app/site) and `mediaTypes` (banner/video/audio/native) combinations which your adapter does not support.
- Change the `cookie-family-name` to the name which will be used for storing your user sync id within the federated cookie. Please keep this the same as your bidder name.
@@ -124,6 +119,23 @@ The url of your user syncer can make use of the following privacy policy macros
- Change the `usersync:type` value to `redirect` or `iframe` specific to your bidder.
+### Default bidder configuration
+
+Prebid Server has default configuration for common bidder properties, which can be overriden by bidders in their
+configurations.
+
+Default configuration:
+
+```yaml
+adapter-defaults:
+ enabled: false
+ pbs-enforces-gdpr: true
+ pbs-enforces-ccpa: true
+ deprecated-names:
+ aliases: {}
+ modifying-vast-xml-allowed: true
+```
+
### Create bidder alias
If you want to add bidder that is an alias of existing bidder, you need just to update configuration of parent bidder:
@@ -131,12 +143,7 @@ Example of adding bidder alias:
```yaml
adapters:
yourBidderCode:
- enabled: false
endpoint: http://possible.endpoint
- pbs-enforces-gdpr: true
- pbs-enforces-ccpa: true
- modifying-vast-xml-allowed: true
- deprecated-names:
aliases:
yourBidderAlias:
endpoint: http://possible.alias/endpoint
@@ -563,7 +570,7 @@ Please review the entire [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-conte
| `.Bids[].Bid.Price` | Required | Net price CPM of the bid, not gross price. Publishers can correct for gross price bids by setting Bid Adjustments to account for fees. We recommend the most granular price a bidder can provide.
| `.Bids[].Bid.W` | Optional | Width of the creative in pixels.
| `.Bids[].Bid.H` | Optional | Height of the creative in pixels.
-| `.Bids[].Bid.Ext` | Optional | Embedded JSON containing Prebid metadata (see below) or custom information.
+| `.Bids[].Bid.Ext.Prebid.Meta` | Optional | Embedded JSON containing Prebid metadata (see below) or custom information.
{: .alert.alert-info :}
We recommend resolving creative OpenRTB macros in your adapter. Otherwise, AUCTION_PRICE will eventually get resolved by the [Prebid Universal Creative](https://github.com/prebid/prebid-universal-creative), but by then the bid price will be in the ad server currency and quantized by the price granularity.
@@ -584,7 +591,7 @@ Either `.Bids[].BidVideo.PrimaryCategory` or `.Bids[].Bid.Cat` should be provide
Prebid has historically struggled with sharing granular bid response data with publishers, analytics, and reporting systems. To address this, we've introduced a standard object model. We encourage adapters to provide as much information as possible in the bid response.
{: .alert.alert-danger :}
-Bid metadata will be *required* in Prebid.js 5.x+ release, specifically for AdvertiserDomains and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid.
+Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for bid.ADomain and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid.
{: .table .table-bordered .table-striped }
| Path | Description |
@@ -595,13 +602,12 @@ Bid metadata will be *required* in Prebid.js 5.x+ release, specifically for Adve
| `.AgencyName` | Bidder-specific agency name |
| `.AdvertiserID` | Bidder-specific advertiser id |
| `.AdvertiserName` | Bidder-specific advertiser name |
-| `.AdvertiserDomains` | Advertiser domains for the landing page(s). Should match `.Bids[].Bid.ADomain` |
| `.BrandID` | Bidder-specific brand id for advertisers with multiple brands |
| `.BrandName` | Bidder-specific brand name |
| `.dchain` | Demand Chain Object
| `.PrimaryCategoryID` | Primary IAB category id |
| `.SecondaryCategoryIDs` | Secondary IAB category ids |
-| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. Should match `.Bids[].BidType` |
+| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe. |
diff --git a/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md b/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md
index cf36b98875..c984822090 100644
--- a/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md
+++ b/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md
@@ -6,10 +6,14 @@ title: Prebid Server | Endpoints | OpenRTB2 | AMP
---
# Prebid Server | Endpoints | /openrtb2/amp
+{:.no_toc}
+
+* TOC
+{:toc}
This document describes the behavior of the Prebid Server AMP endpoint in detail.
For a more general reference, see the [Prebid AMP Implementation Guide
-]({{site.baseurl}}/dev-docs/show-prebid-ads-on-amp-pages.html).
+](/dev-docs/show-prebid-ads-on-amp-pages.html).
## GET /openrtb2/amp
@@ -19,24 +23,28 @@ For a more general reference, see the [Prebid AMP Implementation Guide
| Param | Scope | Type | Description |
| --- | --- | --- | --- |
| tag_id | Required | `String` | The `tag_id` ID must reference a [Stored BidRequest]({{site.baseurl}}/prebid-server/features/pbs-storedreqs.html). For a thorough description of bid request JSON, see the [/openrtb2/auction](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html) docs. |
-| w | recommended | `String` | Comes from the amp-ad.width attribute. The stored request may contain width already, but this parameter reflects what's actually in the page. It replaces imp.banner.format[0].w |
-| h | recommended | `String` | Comes from the amp-ad.height attribute. The stored request may contain height already, but this parameter reflects what's actually in the page. It replaces imp.banner.format[0].h |
+| w | recommended | `String` | Comes from the amp-ad.width attribute. The stored request may contain width already, but this parameter reflects what's actually in the page. It's used to help determine imp.banner.format[0].w. See [resolving sizes](#resolving-sizes). |
+| h | recommended | `String` | Comes from the amp-ad.height attribute. The stored request may contain height already, but this parameter reflects what's actually in the page. It's used to help determine imp.banner.format[0].h. See [resolving sizes](#resolving-sizes). |
| ms | optional | `String` | Comes from the amp-ad.data-multi-size attribute. e.g. "970x90, 728x90". Sizes are parsed and added to imp.banner.format |
-| oh | optional | `String` | Comes from the amp-ad.data-override-height attribute. See below for details on size calculation. |
-| ow | optional | `String` | Comes from the amp-ad.data-override-width attribute. See below for details on size calculation. |
+| oh | optional | `String` | Comes from the amp-ad.data-override-height attribute. See [resolving sizes](#resolving-sizes). |
+| ow | optional | `String` | Comes from the amp-ad.data-override-width attribute. See [resolving sizes](#resolving-sizes). |
| curl | optional | `String` | Added to OpenRTB request as site.page |
| slot | optional | `String` | Added to OpenRTB request as imp[0].tagid |
| timeout | optional | `String` | Added to OpenRTB request as tmax |
-| targeting | optional | `String` | First Party Data (PBS-Java only) |
+| targeting | optional | `String` | First Party Data |
| gdpr_consent | optional | `String` | Consent string passed from CMP. Note this is used for both GDPR and CCPA. |
+| consent_type | optional | `String` | If "1", request is TCFv1 and GDPR fields are ignored. If "2", the 'gdpr_consent' field is interpreted as TCFv2. If "3", the 'gdpr_consent' field is interpreted as us_privacy. |
+| gdpr_applies | optional | `String` | Takes the values "true", "false" or empty. This is used as the value of regs.ext.gdpr. If "true", regs.ext.gdpr:1, if "false", regs.ext.gdpr:0. |
+| addtl_consent | optional | `String` | GAM "additional consent". If present, this value is copied to user.ext.ConsentedProvidersSettings.consented_providers |
| account | optional | `String` | Can be used to pass the Prebid-Server specific account ID. This is useful if `tag_id` parameters aren't unique across accounts. |
-| debug | optional | `integer` | If 1, returns additional debug info. |
+| debug | optional | `integer` | If 1, sets ext.prebid.debug to true to obtain additional debug info. |
To be compatible with AMP, this endpoint behaves different from normal `/openrtb2/auction` requests.
-1. The Stored `request.imp` data must have exactly one element.
-2. `request.imp[0].secure` will be always be set to `1`, because AMP requires all content to be `https`.
-3. AMP query params will overwrite parts of your Stored Request. For details, see the [Query Parameters](#query_params) section.
+1. The 'tag_id' parameter points to a stored request.
+2. The stored request must have exactly one `imp` element.
+3. The request `imp[0].secure` will be always be set to `1`, because AMP requires all content to be `https`.
+4. AMP query params will overwrite parts of your Stored Request. See the table above.
### Request
@@ -63,20 +71,22 @@ An example Stored Request is given below:
}
}
},
- "imp": [
- {
- "id": "some-impression-id",
- "banner": {}, // The sizes are defined by your AMP tag query params settings
- "ext": {
- "appnexus": {
+ "imp": [{
+ "id": "some-impression-id",
+ "banner": {}, // The sizes are defined by your AMP tag query params settings
+ "ext": {
+ "prebid": {
+ "bidder": {
+ "bidderA": {
// Insert parameters here
},
- "rubicon": {
+ "bidderB": {
// Insert parameters here
}
}
- }
- ]
+ }
+ }
+ }]
}
```
@@ -90,77 +100,38 @@ Note that other ext.prebid extensions can be specified in the stored request suc
(Currently only supported in PBS-Java)
-You can send first party data into an AMP request by encoding a JSON
-targeting block like this:
+The nature of AMP is that user-level FPD is difficult or impossible. All of the pages are cached on a CDN and page javascript that can modify RTC calls is severely limited.
-```
-GET /openrtb2/amp?tag_id=7470-Eater_AMP_ROS_ATF&w=300&h=250&ow=&oh=&ms=&slot=%2F172968584%2Feater%2Fgoogle%2Famp_med_rec_02&targeting=%7B%22site%22%3A%7B%22keywords%22%3A%22article%2C%20las%20vegas%22%2C%22cat%22%3A%7B%22blah%22%3A%221%22%7D%2C%22other-attribute%22%3A%22other-value%22%2C%22ext%22%3A%7B%22data%22%3A%7B%22entry_group%22%3A%5B%22front-page%22%2C%22featured-stories%22%5D%2C%22page_type%22%3A%22AMP%22%7D%7D%7D%2C%22user%22%3A%7B%22gender%22%3A%22m%22%7D%2C%22bidders%22%3A%5B%22rubicon%22%2C%22appnexus%22%5D%2C%22keywords%22%3A%22las%20vegas%20hospitality%20employees%22%2C%22foo%22%3A%7B%22bar%22%3A%22baz%22%7D%7D...
-```
+Contextual First Party Data must be defined in the stored request entries.
-Prebid Server will expand the targeting value and merge the data into
-the resulting OpenRTB JSON for the appropriate bidders.
+The only field that PBS supports in the AMP call that can be considered FPD is the 'targeting' block. These are key-value pairs that are sent to the ad server. They are also copied to the ORTB JSON in imp[].ext.data.
-For example, if this AMP targeting is provided:
+For example, if the AMP JSON targeting provided is:
```
-{
- "site": {
- "keywords": "article, las vegas", // (1)
- "cat": { "blah": "1" }, // invalid data type, will be dropped
- "other-attribute": "other-value", // not openrtb2, remove
- "ext": {
- "data": {
- "entry_group": ["front-page","featured-stories"], // (4)
- "page_type": "AMP" // (5)
- }
- }
- },
- "user": {
- "gender": "m", // (2)
- },
- "bidders": ["rubicon","appnexus"], // (3)
- "keywords": "las vegas hospitality employees", // (6)
- "foo": { // (7)
- "bar": "baz"
- }
-}
+
+
+```
+The AMP URL would be something like this:
```
-The numbered elements from the raw targeting data above are merged into the resulting OpenRTB like this:
+GET /openrtb2/amp?tag_id=1001-my-test&w=300&h=250&ow=&oh=&ms=&slot=%2F1111%2Famp_test&targeting=%7B%22attr1%22%3A%22val1%22%2C%22attr2%22%3A%22val2%22%7D&...
+```
+And the resulting OpenRTB would merge these targeting values as FPD on imp.ext.data:
```
{
- "imp": [...],
- "site": {
- "publisher": { … },
- "keywords": "article, las vegas" // (1)
- "ext":{
- "data": {
- "entry_group": ["front-page","featured-stories"], // (4)
- "page_type": "AMP" // (5)
- }
- }
- },
- "user": {
- "gender": "m" // (2)
- },
- "ext": {
- "prebid": {
- "data": {
- "bidders": ["rubicon",appnexus"], // (3)
- }
- }
- },
- "imp": [
+ "imp": [{
...
"ext": {
- "context": {
- "data": {
- "keywords": "las vegas hospitality employees", // (6)
- "foo": { // (7)
- "bar": "baz"
- }
- }
- }
+ "data": {
+ "attr1": "val1",
+ "attr2": "val2"
+ }
}
- ]
+ }],
+ ...
}
```
@@ -228,41 +199,7 @@ The following errors can occur when loading a stored OpenRTB request for an inco
| Checking stored request for match against tag_id. | 999 | No AMP config found for tag_id `%s`. | Error is returned. |
| Checking if imp exists. | 999 | Data for tag_id=`'%s'` does not define the required imp array. | Error is returned. |
| Checking if imp count is greater than one. | 999 | Data for tag_id `'%s'` includes `%d` imp elements. Only one is allowed. | Error is returned. |
-| Checking if request.app exists. | 999 | `request.app` must not exist in AMP stored requests. | Error is returned. |
-
-
-
-### Query Parameter Details
-
- - A configuration option `amp_timeout_adjustment_ms` may be set to account for estimated latency so that Prebid Server can handle timeouts from adapters and respond to the AMP RTC request before it times out.
-
-Ensure that the amp-ad component was imported in the header.
-
-```html
-
- ```
-
-This script provides code libraries that will convert the `` properties to the endpoint query parameters. In the most basic usage pass `width` and `height` as well as `type` and a `rtc-config`. The `type` value is the ad network you will be using. The `rtc-config` is used to pass JSON configuration to the Prebid Server, which handles the communication with [AMP RTC](https://medium.com/ampfuel/better-than-header-bidding-amp-rtc-fc54e80f3999). Vendors is an object that defines any vendors that will be receiving the RTC callout. In this example, the required parameter `tag_id` will receive the `PLACEMENT_ID` (or `REQUEST_ID`) value.
-
-```html
-
-```
-Here's a simplified URL:
-
-```
-/openrtb2/amp?tag_id='ef8299d0-cc32-46cf-abcd-41cebe8b4b85'&w=300&h=250&timeout=500
-```
-
-Some endpoint parameters will override parts of the Stored Request.
-
-1. `ow`, `oh`, `w`, `h`, and/or `ms` will be used to set `request.imp[0].banner.format` if `request.imp[0].banner` is present.
-2. `curl` will be used to set `request.site.page`
-3. `timeout` will generally be used to set `request.tmax`. However, the Prebid Server host can [configure](https://github.com/prebid/prebid-server/blob/master/docs/developers/configuration.md) their deploy to reduce this timeout for technical reasons.
-4. `debug` will be used to set `request.test`, causing the `response.debug` to have extra debugging info in it.
+| Checking if app exists. | 999 | The `app` object must not exist in AMP stored requests. | Error is returned. |
### Resolving Sizes
@@ -271,15 +208,23 @@ track the logic used by `doubleclick` when resolving sizes used to fetch ads fro
Specifically:
-1. If `ow` and `oh` exist, `request.imp[0].banner.format` will be a single element with `w: ow` and `h: oh`
-2. If `ow` and `h` exist, `request.imp[0].banner.format` will be a single element with `w: ow` and `h: h`
-3. If `oh` and `w` exist, `request.imp[0].banner.format` will be a single element with `w: w` and `h: oh`
-4. If `ms` exists, `request.imp[0].banner.format` will contain an element for every size it uses.
-5. If `w` and `h` exist, `request.imp[0].banner.format` will be a single element with `w: w` and `h: h`
-6. If `w` _or_ `h` exist, it will be used to override _one_ of the dimensions inside each element of `request.imp[0].banner.format`
-7. If none of these exist then the Stored Request values for `request.imp[0].banner.format` will be used without modification.
+1. If `ow` and `oh` exist, `imp[0].banner.format` will be a single element with `w: ow` and `h: oh`
+2. If `ow` and `h` exist, `imp[0].banner.format` will be a single element with `w: ow` and `h: h`
+3. If `oh` and `w` exist, `imp[0].banner.format` will be a single element with `w: w` and `h: oh`
+4. If `ms` exists, `imp[0].banner.format` will contain an element for every size it uses.
+5. If `w` and `h` exist, `imp[0].banner.format` will be a single element with `w: w` and `h: h`
+6. If `w` _or_ `h` exist, it will be used to override _one_ of the dimensions inside each element of `imp[0].banner.format`
+7. If none of these exist then the Stored Request values for `imp[0].banner.format` will be used without modification.
+
+## Configuration Options
+
+- settings.generate-storedrequest-bidrequest-id: replace the stored request `id` with a UUID (PBS-Java only)
+- amp.default-timeout-ms: default operation timeout for AMP requests
+- amp.timeout-adjustment-ms: reduces timeout value passed in AMP request. Can be used to account for estimated latency so that Prebid Server can respond to the AMP RTC request before it times out.
+- amp.max-timeout-ms: maximum operation timeout for AMP requests
## Further Reading
- [Prebid and AMP](/formats/amp.html)
- [Prebid Server AMP Use Case Overview](/prebid-server/use-cases/pbs-amp.html)
- [Prebid Server First Party Data](/prebid-server/features/pbs-fpd.html)
+- [Stored Requests](/prebid-server/features/pbs-storedreqs.html)
diff --git a/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.md b/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.md
index 5f40fc3242..079e38ee65 100644
--- a/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.md
+++ b/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.md
@@ -239,6 +239,24 @@ Targeting refers to strings which are sent to the adserver to
`request.ext.prebid.targeting` is an optional property which causes Prebid Server
to set these params on the response at `response.seatbid[i].bid[j].ext.prebid.targeting`.
+{: .table .table-bordered .table-striped }
+| Attribute | Required? | Description | Example | Type |
+| --- | --- | --- | --- | --- |
+| pricegranularity | no | Defines how PBS quantizes bid prices into buckets | (see below) | object |
+| pricegranularity.precision | no | How many decimal places are there in price buckets | Defaults to 2 | integer |
+| pricegranularity.ranges | no | Non-overlapping price bucket definitions | (see below) | array of objects |
+| pricegranularity.ranges.max | no | Top end of this range of price buckets. The bottom end is 0 or the max of the previous bucket. Note: in order to prevent ranges with gaps, there's no 'min' attribute. | 5.55 | float |
+| pricegranularity.ranges.increment | no | Size of the buckets in this range. | 1.50 | float |
+| mediatypepricegranularity | no | Defines how PBS quantizes bid prices into buckets, allowing for different ranges by media type. | (see below) | object |
+| mediatypepricegranularity.banner | no | Defines how PBS quantizes bid prices into buckets for banners. | (see below) | object |
+| mediatypepricegranularity.video | no | Defines how PBS quantizes bid prices into buckets for video. | (see below) | object |
+| mediatypepricegranularity.TYPE.precision | no | How many decimal places are there in price buckets. | Defaults to 2 | integer |
+| mediatypepricegranularity.TYPE.ranges | no | Same as pricegranularity.ranges | (see below) | array of objects |
+| includewinners | no | Whether to include targeting for the winning bids in response.seatbid[].bid[]. ext.prebid.targeting. Defaults to false. | true | boolean |
+| includebidderkeys | no | Whether to include targeting for the best bid from each bidder in response.seatbid[].bid[]. ext.prebid.targeting. Defaults to false. | true | boolean |
+| includeformat | no | Whether to include the "hb_format" targeting key. Defaults to false. | false | boolean |
+| preferdeals | no | If targeting is returned and this is true, PBS will choose the highest value deal before choosing the highest value non-deal. Defaults to false. | true | boolean |
+
**Request format** (optional param `request.ext.prebid.targeting`)
```
@@ -253,9 +271,10 @@ to set these params on the response at `response.seatbid[i].bid[j].ext.prebid.ta
"increment": 0.10 // This is equivalent to the deprecated "pricegranularity": "medium"
}]
},
- "includewinners": false, // Optional param defaulting to true
- "includebidderkeys": false // Optional param defaulting to true
- "includeformat": false // Optional param defaulting to false
+ "includewinners": true, // Optional param defaulting to false
+ "includebidderkeys": false, // Optional param defaulting to false
+ "includeformat": false, // Optional param defaulting to false
+ "preferdeals": true // Optional param defaulting to false
}
}
}
@@ -265,7 +284,7 @@ The list of price granularity ranges must be given in order of increasing `max`
For backwards compatibility the following strings will also be allowed as price granularity definitions. There is no guarantee that these will be honored in the future. "One of ['low', 'med', 'high', 'auto', 'dense']" See [price granularity definitions](/prebid-mobile/adops-price-granularity.html)
-One of "includewinners" or "includebidderkeys" must be true (both default to true if unset). If both were false, then no targeting keys would be set, which is better configured by omitting targeting altogether.
+One of "includewinners" or "includebidderkeys" must be true (both default to false if unset). If both are false, then no targeting keys will be set, which is better configured by omitting targeting altogether.
The parameter "includeformat" indicates the type of the bid (banner, video, etc) for multiformat requests. It will add the key `hb_format` and/or `hb_format_{bidderName}` as per "includewinners" and "includebidderkeys" above.
@@ -593,7 +612,7 @@ Prebid Server adapters can support the [Prebid.js User ID modules](/dev-docs/mod
}]
},
{
- "source": "pubcommon",
+ "source": "pubcid.org",
"id":"11111111"
}
]
@@ -639,7 +658,7 @@ client can declare a given adunit as eligible for rewards by declaring `imp.ext.
The OpenRTB `test` flag has a special meaning that bidders may react to: they may not perform a normal auction, or may not pay for test requests.
-You can turn on the extra Prebid Server debug log without the formal `test` behavior by instead setting `ext.prebid.debug:1`.
+You can turn on the extra Prebid Server debug log without the formal `test` behavior by instead setting `ext.prebid.debug: true`.
##### Stored Responses (PBS-Java only)
@@ -783,7 +802,7 @@ It specifies where in the OpenRTB request non-standard attributes should be pass
"keywords": "",
"search": "",
"ext": {
- data: { GLOBAL CONTEXT DATA } // only seen by bidders named in ext.prebid.data.bidders[]
+ data: { GLOBAL SITE DATA } // only seen by bidders named in ext.prebid.data.bidders[]
}
},
"user": {
@@ -796,25 +815,41 @@ It specifies where in the OpenRTB request non-standard attributes should be pass
}
},
"imp": [
+ ...
"ext": {
- "context": {
- "keywords": "",
- "search": "",
- "data": { ADUNIT SPECFIC CONTEXT DATA } // can be seen by all bidders
+ "data": {
+ ADUNIT SPECFIC CONTEXT DATA // can be seen by all bidders
}
}
]
```
-Prebid Server enforces the data permissioning. So before passing the values to the bidder adapters, the PBS core will:
+Bidder-specific data can be defined with ext.prebid.bidderconfig:
+```
+ext: {
+ prebid: {
+ bidderconfig:
+ bidders: ["bidderA", "bidderB"],
+ config: [
+ ortb2: {
+ site: { ... },
+ user: { ... }
+ }
+ ]
+ }
+ }
+}
+```
+
+Prebid Server enforces data permissioning. So before passing values to the bidder adapters, the PBS core will:
-1. check for ext.prebid.data.bidders
-1. if it exists, store it locally, but remove it from the OpenRTB before being sent to the adapters
+1. Check for ext.prebid.bidderconfig
+ 1. If it exists, merge config.ortb2 into the bidder-specific request
1. As the OpenRTB request is being sent to each adapter:
- 1. if ext.prebid.data.bidders exists in the original request, and this bidder is on the list then copy site.ext.data, app.ext.data, and user.ext.data to their bidder request -- otherwise don't copy those blocks
+ 1. If ext.prebid.data.bidders exists in the original request and this bidder is on the list, then copy site.content.data, site.ext.data, app.ext.data, user.data, and user.ext.data to the bidder request -- otherwise don't copy those blocks. Remove ext.prebid.data.bidders from the bidder-specific request
1. copy other objects as normal
-Each adapter must be coded to read the values from these locations and pass it to their endpoints appropriately.
+Each adapter must be coded to read the values from the ortb and pass it to their endpoints appropriately.
##### Custom Targeting (PBS-Java only)
@@ -875,6 +910,27 @@ In order to pull AMP parameters out into targeting, Prebid Server places AMP que
}
```
+##### EID Permissions (PBS-Go only)
+
+This feature allows publishers to specify ext.prebid.eidpermissions, defining which extended ID
+in user.ext.eids is allowed to be passed to which bid adapter. For example:
+
+```
+{
+ ext: {
+ prebid: {
+ data: {
+ eidpermissions: [ // prebid server will use this to filter user.ext.eids
+ {"source": "sharedid.org", "bidders": ["*"]}, // * is the default
+ {"source": "neustar.biz", "bidders": ["bidderB"]},
+ {"source": "id5-sync.com", "bidders": ["bidderA","bidderC"]}
+ ]
+ }
+ }
+ }
+}
+```
+
##### MultiBid (PBS-Java only)
Allows a single bidder to bid more than once into an auction and have extra bids passed
@@ -957,6 +1013,68 @@ seatbid: [{
}
```
+##### Echo StoredRequest Video Attributes (PBS-Java only)
+
+Several video specific fields can be set in the Stored Request that
+the device player would not have context to at time of render.
+The requester (e.g. Prebid SDK) can send this signal to Prebid Server,
+which causes PBS-core to place the video-related attributes on the response.
+
+```
+{
+ ...
+
+ "imp": [
+ {
+ "id": "123456789",
+ "video": { ... },
+ "ext": {
+ "prebid": {
+ "storedrequest": { "id": "xxx" },
+ "options": {
+ "echovideoattrs": true
+ }
+ }
+ },
+ ...
+ }
+ ]
+ ...
+}
+```
+1. Prebid Server receives this request and expands the `storedrequest` value, merging it with the imp object.
+2. Because `echovideoattrs` is true, video parameters in the storedrequest imp[].video are copied to seatbid.bid.ext.prebid.storedrequestattributes.
+
+```
+{
+ "seatbid": [{
+ "bid": [{
+ ...
+ "ext": {
+ "prebid": {
+ "storedrequestattributes":{
+ "maxduration": 60,
+ "mimes": [
+ "video/mp4"
+ ],
+ "minduration": 15,
+ "protocols": [
+ 1,
+ 2
+ ],
+ "skipafter": 0,
+ "skipmin": 0,
+ "startdelay": 0,
+ "playbackmethod": [1]
+ }
+ }
+ }
+ }]
+ }],
+...
+}
+```
+
#### OpenRTB Response Extensions
##### Bidder Response Times
@@ -1002,9 +1120,54 @@ The codes currently defined are:
999 UnknownErrorCode
```
-#### Test Flag
+##### Ad Server Targeting
-The standard OpenRTB `test` flag triggers Prebid Server to dump additional debug info into the OpenRTB response. e.g.
+Prebid Server will generate ad server targeting variables as defined by request parameters:
+
+1. If ext.prebid.targeting.includewinners is true, seatbid.bid.ext.prebid.targeting will be defined for the top bid in each imp object and will carry the following targeting values: hb_pb, hb_size, and hb_bidder.
+1. If ext.prebid.targeting.includebidderkeys is true, seatbid.bid.ext.prebid.targeting will be defined for the top bid from each bidder in each imp object and will carry the following targeting values: hb_pb_BIDDER and hb_size_BIDDER.
+1. If ext.prebid.cache.bids is specified, any targeting objects will also contain hb_cache_id, hb_cache_id_BIDDER, hb_cache_host, and hb_cache_path.
+1. If ext.prebid.cache.vastxml is specified, any targeting objects will also contain hb_uuid, hb_uuid_BIDDER, hb_cache_host, and hb_cache_path.
+1. If the bid response defines a deal, any targeting objects will also contain hb_deal or hb_deal_BIDDER
+1. If ext.prebid.adservertargeting is defined, arbitrary targeting values may be specified.
+
+```
+{
+seatbid: [{
+ seat: "bidderA",
+ bid: [{
+ id: "bid1",
+ impid: "imp1",
+ price: 1.04,
+ ext: {
+ prebid: {
+ targeting: {
+ hb_pb: 1.00, // values without prefixes on the winning bids only
+ hb_pb_bidderA: 1.00, // only if includebidderkeys is true
+ hb_bidder: "bidderA",
+ hb_size: "300x250",
+ hb_size_bidderA: "300x250",
+ hb_format: "video" // only if includeformat is specified
+ hb_deal: "123" // only if bid response contains a deal
+ }
+ }
+ }
+ ...
+ }]
+}]
+```
+
+
+##### Debug Output
+
+`response.ext.debug.httpcalls.{bidder}` will be populated only if `test:1` or `ext.prebid.debug:true`.
+
+This contains info about every request and response sent by the bidder to its server.
+It is only returned on `test` bids for performance reasons, but may be useful during debugging.
+
+`response.ext.debug.resolvedrequest` will be populated **only if** `request.test` **was set to 1**.
+
+This contains the request after the resolution of stored requests and implicit information (e.g. site domain, device user agent).
```
"ext": {
@@ -1023,21 +1186,9 @@ The standard OpenRTB `test` flag triggers Prebid Server to dump additional debug
...
```
-
-##### Debugging
-
-`response.ext.debug.httpcalls.{bidder}` will be populated **only if** `request.test` **was set to 1**.
-
-This contains info about every request and response sent by the bidder to its server.
-It is only returned on `test` bids for performance reasons, but may be useful during debugging.
-
-`response.ext.debug.resolvedrequest` will be populated **only if** `request.test` **was set to 1**.
-
-This contains the request after the resolution of stored requests and implicit information (e.g. site domain, device user agent).
-
##### Original Bid CPM (PBS-Java only)
-`response.seatbid[].bid[].ext.origbidcpm` will contain the original bid price from the bidder.
+`response.seatbid[].bid[].ext.origbidcpm` and `response.seatbid[].bid[].ext.origbidcur` will contain the original bid price/currency from the bidder.
The value in seatbid[].bid[].price may be converted for currency and adjusted with a [bid adjustment factor](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bid-adjustments).
### OpenRTB Ambiguities
@@ -1047,7 +1198,6 @@ This section describes the ways in which Prebid Server **implements** OpenRTB sp
- `request.cur`: If `request.cur` is not specified in the bid request, Prebid Server will consider it as being `USD` whereas OpenRTB spec doesn't mention any default currency for bid request.
```request.cur: ['USD'] // Default value if not set```
-
### OpenRTB Differences
This section describes the ways in which Prebid Server **breaks** the OpenRTB spec.
@@ -1080,6 +1230,73 @@ In the OpenRTB spec, `request.imp[i].secure` says:
In Prebid Server, an `https` request which does not define `secure` will be forwarded to Bidders with a `1`.
Publishers who run `https` sites and want insecure ads can still set this to `0` explicitly.
+### HTTP Headers
+
+In order to facilitate compatibility and analytics, Prebid Server will add the x-prebid HTTP header to outgoing requests. Some examples:
+
+```
+x-prebid: pbs-go/0.155
+x-prebid: pbjs/4.39,pbs-go/0.155
+x-prebid: prebid-mobile/1.2.3,pbs-java/1.64
+```
+
+The PBJS version comes from ext.prebid.channel: `{name: "pbjs", version: "4.39"}`
+
+The Prebid SDK version comes from:
+```
+app.ext.prebid: {
+ source: "prebid-mobile"
+ version: "1.2.3"
+}
+```
+
+
+### Prebid Server ORTB2 Extension Summary
+
+{: .table .table-bordered .table-striped }
+| Req/Resp | Extension | Description | Type | Example | Adapter Sees? |
+| --- | --- | --- | --- | --- | --- |
+| req | imp[].ext.prebid. bidder.BIDDER | bidder parameters | object | imp[].ext. prebid.bidder. biddera: { placement: 123 } | They see the object as imp[].ext.bidder |
+| req | imp[].ext.BIDDER | DEPRECATED place to put bidder parameters | object | imp[].ext. prebid.bidder. biddera: { placement: 123 } | They see the object as imp[].ext.bidder |
+| req | imp[].ext.prebid. storedrequest.id | look up the defined stored request and merge the DB contents with this imp | object | see [stored requests](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-requests) | no |
+| req | imp[].ext.prebid. storedauctionresponse | PBS-Core skips the auction and uses the response in the DB instead | object | see [stored responses](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-responses-pbs-java-only) | no |
+| req | imp[].ext.prebid. is_rewarded_inventory | passed through to bid adapters | integer | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#rewarded-video-pbs-java-only) | yes |
+| req | imp[].ext.data.ATTR | Publisher-specific adunit-level first party data | any | "pmp_elig": true | yes |
+| req | app.ext.source | defined by Prebid SDK | string | "prebid-mobile" | yes |
+| req | app.ext.version | defined by Prebid SDK | string | "1.6" | yes |
+| req | ext.prebid.bidadjustmentfactors | Adjust the CPM value of bidrequests | object | See [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bid-adjustments) | no |
+| req | ext.prebid.targeting | defines the targeting values PBS-core places in seatbid.bid.ext.prebid.targeting | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#targeting) | no |
+| req | ext.prebid.adservertargeting | advanced targeting value rules | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#custom-targeting-pbs-java-only) | no |
+| req | ext.prebid.integration | host-dependent integration type passed through to events and analytics | string | "managed" | yes |
+| req | ext.prebid.channel | Generally "pbjs", "amp", or "app". Passed through to events and analytics | object | {name: "pbjs", version: "4.39"} | yes |
+| req | ext.prebid.aliases | defines alternate names for bidders | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bidder-aliases) | yes |
+| req | ext.prebid.debug | provides debug output in response | boolean | true | yes |
+| req | ext.prebid.cache | defines whether to put bid results in Prebid Cache | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#cache-bids) | no |
+| req | ext.prebid.schains | bidder-specific supply chains | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#supply-chain-support) | no |
+| req | ext.prebid.data.bidders | bidders in scope for bidder-specific first party data | array of strings | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#first-party-data-support-pbs-java-only) | no |
+| req | ext.prebid.bidderconfig | bidder-specific first party data | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#first-party-data-support-pbs-java-only) | no |
+| req | ext.prebid.currency | publisher-defined currency conversions | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#currency-support) | yes |
+| req | ext.prebid.no-sale | turns off CCPA processing for the named bidder(s) | array of strings | ["bidderA"] | no |
+| req | ext.prebid.interstitial | PBS-core will adjust the sizes on a request for interstitials | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#interstitial-support) | yes |
+| req | ext.prebid.auctiontimestamp | timestamp for use in correlating PBJS and PBS events | long int | 123456789 | yes |
+| req | ext.prebid.options. echovideoattrs | causes PBS-core to [echo video attributes](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#echo-storedrequest-video-attributes-pbs-java-only) on seatbid[].bid[].ext.prebid.storedrequestattributes so the player has access to them | boolean | true | yes |
+| req | ext.prebid.multibid | allows bidders to respond with more than one bid | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#multibid-pbs-java-only) | yes, but only their value |
+| resp | seatbid[].bid[].ext. prebid.targeting | ad server targeting values. Related to req ext.prebid.targeting. | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#ad-server-targeting) | n/a |
+| resp | seatbid[].bid[].ext.prebid. type | "banner", "video", "native" | string | "banner" | n/a |
+| resp | seatbid[].bid[].ext.prebid. cache.bids.url | URL location of the bid or VAST | string | URL | n/a |
+| resp | seatbid[].bid[].ext.prebid. cache.bids.cacheId | ID of the bid or VAST | string | "1234" | n/a |
+| resp | seatbid[].bid[].ext.prebid. events.win | URL for registering a BIDS_WON event for this bid | string | URL | n/a |
+| resp | seatbid[].bid[].ext.prebid. events.imp | URL for registering an impression event for this bid | string | URL | n/a |
+| resp | seatbid[].bid[].ext.prebid. bidid | defines a Prebid-generated id for this bid in case the bidder's ID isn't unique | string | UUID | n/a |
+| resp | seatbid[].bid[].ext.prebid. meta.ATTR | bidder-supplied metadata | object | see [docs](/prebid-server/developers/add-new-bidder-go.html) | n/a |
+| resp | seatbid[].bid[].ext.prebid. storedrequestattributes | results of the ext.prebid.options.echovideoattrs option above. | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#echo-storedrequest-video-attributes-pbs-java-only) | n/a |
+| resp | response.seatbid[].bid[].ext. origbidcpm | a copy of the unadjusted bid price | float | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#original-bid-cpm-pbs-java-only) | n/a |
+| resp | response.seatbid[].bid[].ext. origbidcur | a copy of the original bid currency | string | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#original-bid-cpm-pbs-java-only) | n/a |
+| resp | ext.responsetimemillis.BIDDER | debug mode: how long the named bidder took to respond with a bid | integer | 100 | n/a |
+| resp | ext.debug.httpcalls.BIDDER | debug mode: the HTTP request/response from the named bidder | object | | n/a |
+| resp | ext.errors.BIDDER | debug mode: errors from the named bidder | object | | n/a |
+| resp | ext.debug | debug mode: useful output | object | see [docs](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#debug-output)| n/a |
+
### Further Reading
- [The OpenRTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf)
diff --git a/prebid-server/features/pbs-currency.md b/prebid-server/features/pbs-currency.md
index 8b6201fb5f..3fe503fe98 100644
--- a/prebid-server/features/pbs-currency.md
+++ b/prebid-server/features/pbs-currency.md
@@ -80,7 +80,7 @@ Here are a couple examples showing the logic behind the currency converter:
## Request-Defined Conversion Rates
-Using PBS-Java, rates can be passed in on the request:
+Rates can be passed in on the request:
```
"ext": {
diff --git a/prebid-server/features/pbs-feature-idx.md b/prebid-server/features/pbs-feature-idx.md
index ccab2d7215..dec47eb023 100644
--- a/prebid-server/features/pbs-feature-idx.md
+++ b/prebid-server/features/pbs-feature-idx.md
@@ -14,6 +14,7 @@ title: Prebid Server | Features
| [Currency](/prebid-server/features/pbs-currency.html) | Request-Defined Rates | Allows the request to define its own currency rates. | |
|
| Currency | pbsConvertCurrency method | Allows adapters to convert bid floors to a different currency if needed. | |
|
| [Deals](/prebid-server/features/pbs-deals.html) | Core | Basic deal support, creating hb_deal targeting when appropriate. |
|
|
+| Deals | Deal prioritization | Supports the 'preferdeals' [targeting flag](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#targeting) to give deals the priority when PBS returns ad server targeting. |
|
|
| [AMP](/prebid-server/use-cases/pbs-amp.html) | Core | Reads and responds to the /openrtb2/amp endpoint |
|
|
| Targeting | Core | Request can specify `includewinners` and `includebidderkeys`. These cause PBS to emit seatbid[].bid[].ext.prebid.targeting values. |
|
|
| Targeting | Format | Request can specify `includeformat`, which causes PBS to emit hb_format along with other targeting values like hb_pb, etc. |
|
|
@@ -54,13 +55,14 @@ title: Prebid Server | Features
| Video | Outstream renderers | Support for bidders specifying their own renderers for outstream video. | | |
| Video | Long-form video | Support for the [long-form video endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-video.html). |
| |
| Video | IAB advertiser category mapping | Able to map IAB advertiser categories to a supplied mapping table. |
| |
-| Video | Echo video attributes | To support mobile video, copies stored request video attributes to the response. | |
|
+| Video | [Echo video attributes](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#echo-storedrequest-video-attributes-pbs-java-only) | To support mobile video, copies stored request video attributes to the response. | |
|
| [Interstitials](/prebid-server/features/pbs-interstitials.html) | Core | Support device.ext.prebid.interstitial.minwidthperc and device.ext.prebid.interstitial.minheightperc parameters, [dynamically updating the impression format object](https://github.com/prebid/prebid-server/issues/755) from a configurable list of sizes filtered by these parameters. |
|
|
| [Aliases](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bidder-aliases) | Core | Maps a biddercode on an incoming request to a specific server-side bid adapter named in the request or defined in config. |
|
|
| Aliases | [GVL ID support](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bidder-alias-gvl-ids-pbs-java-only) | Define the IAB GVL ID for an aliased biddercode. | |
|
| [User ID Sync](/prebid-server/developers/pbs-cookie-sync.html) | Core | Implements the /cookie_sync and /setuid endpoints. Bidders may choose either redirect or iframe method. |
|
|
| User ID Sync | Multi-Method | Bidders can supply both pixel redirects as well as iframe syncs. | |
|
| User ID Sync | Cooperative sync | Does a pixel sync with more than just the bidders on the page. | |
|
+| User ID Permissions | Extended ID Permissions | Allows publishers to determine which bidders are allowed to receive which extended ID. |
| |
| User ID Sync | Account override | Allows accounts to override the cooperative sync feature and bidder limits. | |
|
| User ID | [EID Permissions](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#eid-permissions) | The Publisher can define which bidders receive which extended user IDs. |
|
|
| [Events](https://docs.google.com/document/d/1ry0X4C2EV-R0pMrm1IQk9BstxaT395UCl3KKqTGa5c8/edit#heading=h.7w5yevygp2gz) | Events | Ability to process the /event endpoint, place /event URLs in the OpenRTB response, and place /event URLs in VAST XML. | |
|
@@ -77,4 +79,6 @@ title: Prebid Server | Features
| Operations | Circuit breaker | Protects system performance during fault scenarios by detecting problems with external and internal endpoints, turning them off temporarily when a problem occurs. | |
|
| Operations | [Server default request](/prebid-server/features/pbs-default-request.html) | Support global defaults for incoming requests. |
|
|
| Operations | IPv6 | Support taking IPv6 addresses and forwarding them to bidders. |
|
|
+| [Programmatic Guaranteed](/prebid-server/features/pg/pbs-pg-idx.html) | Integration and Targeting | Ability to load, target, and report PG line items | |
|
| Operations | [Request Logging Admin Endpoints](/troubleshooting/pbs-troubleshooting.html#request-logging) | Log a limited number of requests to understand the raw data clients are sending. | |
|
+| Metadata | [x-prebid header](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#http-headers) | Put version information in outgoing HTTP headers. | |
|
diff --git a/prebid-server/features/pbs-storedreqs.md b/prebid-server/features/pbs-storedreqs.md
index 966eace171..822b9b5237 100644
--- a/prebid-server/features/pbs-storedreqs.md
+++ b/prebid-server/features/pbs-storedreqs.md
@@ -8,27 +8,35 @@ title: Prebid Server | Features | Stored Requests
# Prebid Server | Features | Stored Requests
'Stored Requests' are blocks of OpenRTB stored on the server-side that are merged into
-OpenRTB requests in a couple of scenarios.
+OpenRTB requests for Mobile App and AMP scenarios.
The data source can be local files on Prebid Server, but more commonly it would be a relational
database distributed across all the Prebid Servers in the host company's installation.
## Mobile App
-Hardcoding bidders and parameters in a mobile app isn't ideal. Prebid Server allows Stored Request IDs to be
-used in two ways:
+We want to avoid hardcoding parameters into a mobile app like bidders and parameters. Because of this, Prebid Server allows host companies to store two types of JSON that are retrieved with a key called a 'Stored Request ID':
-1. Define cross-adunit parameters like currency and price granularity
-1. Define adunit-specific details: bidders and their parameters
+- "top-level" requests, also called "wrapper-level" requests. This block is merged into the root level of the incoming ORTB request. It's not expected to have an imp object.
+- "impression-level" requests are merged into a particular ORTB imp element.
+
+{: .pb-lg-img :}
+
+1. The SDK creates a 'skeleton' framework of the OpenRTB JSON that doesn't
+contain the bidders or any other parameter that might be changed by AdOps.
+2. Prebid Server merges all the stored requests into this template.
+3. Creating the final OpenRTB JSON just like Prebid.js would have sent using the PBS Bid Adapter.
See the [Mobile SDK Use Case reference](/prebid-server/use-cases/pbs-sdk.html) for specific examples.
## AMP
The AMP protocol is converted to OpenRTB primarily using Stored Requests: the `tag_id` is used to look up
-the base OpenRTB from the data source. After getting the bulk of the OpenRTB, AMP query string parameters
+a single base OpenRTB from the data source. After getting the bulk of the OpenRTB, AMP query string parameters
are used to inject and adjust parameters like size, url, etc. See the [AMP endpoint documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) for more details.
+{: .pb-lg-img :}
+
See the [AMP Use Case reference](/prebid-server/use-cases/pbs-amp.html) for specific examples.
## Creating Stored Requests
diff --git a/prebid-server/features/pg/pbs-pg-bidder.md b/prebid-server/features/pg/pbs-pg-bidder.md
new file mode 100644
index 0000000000..88e4dc53ec
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-bidder.md
@@ -0,0 +1,141 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Building a PG Bidder
+---
+
+# Building a Programmatic Guaranteed Bidder
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## What is a PG Bidder?
+
+The architecture of Prebid Programmatic Guaranteed (PG) is inherently multi-vendor. A PG `Host Company` runs a global distributed cluster of Prebid Servers. These servers handle the 'real-time' requests... those that need to have millisecond response times. They also run a couple of backend servers that help manage the PG line items. One of them
+is called the `General Planner`. The General Planner can connect out to multiple sources of PG Line Items, and that's where you come in -- as a PG Bidder, you can contribute PG Line Items into the auction ecosystem for the publishers who utilize the Host Company's installation.
+Here's a diagram from the [white paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf).
+
+{: .pb-lg-img :}
+
+1. The PG Host Company runs clusters of Prebid Servers that receive requests from publishers.
+2. Prebid Servers look up additional data for use in targeting.
+3. The General Planner queries your PG Bidder endpoint and allocates your line items across the Prebid Server clusters.
+4. The `Delivery Stats Service` is available for PG Bidders to obtain up-to-date reports on how line items are delivering.
+5. The `Dimension Value API` should be used by bidders to create targeting values.
+6. Each PG Bidder has it's own logic for pacing their line items in 1 or 5-minute increments called "plans".
+7. The publisher or a service team enter the PG Line Items into the PG Bidder's user interface.
+
+Notes:
+- It's possible that you could deliver PG Line Items through more than one PG Host Company.
+- It it the responsibility of the PG Bidder to manage their own finance arrangements with each Publisher.
+- It's possible that the Host Company may charge a fee to deliver PG Line Items through their infrastructure.
+
+## What's involved in building a PG Bidder?
+
+These are the high level steps for how to develop a PG Bidder and plug it into a Host Company's implementation.
+
+1. Contact a PG Host Company to make sure they're ready to incorporate a new PG Bidder. They may have additional requirements.
+1. Obtain access to the Host Company's Dimension Value API and Delivery Stats server. You will receive a "biddercode" similar to the codes used in Prebid.js. e.g. "pgExample".
+1. Develop a User Interface for the customer to enter PG info: date range, targeting details, price, and pacing details. The targeting information comes from the Host Company's Dimension Value API.
+1. Develop a pacing algorithm that uses data from the Host Company's Delivery Stats server and your own data stores.
+1. Develop a report that uses data from the Host Company's Delivery Stats server and your own data stores.
+1. Develop an external API that can respond to requests from the Host Company's General Planner for line item data.
+1. Develop a method for estimating inventory forecast and availability. The Host Company may have data available.
+1. Contact the Host Company to begin integration testing.
+
+### Obtain targeting dimensions
+
+The Host Company will give PG Bidders access to their Dimension Value API which will let them know what attributes and values their Prebid Servers can target at runtime for particular clients.
+The values used will differ between Host Companies and publishers. For example, there may be different geographic and device info services. Publisher AdSlot and First Party Data fields will also vary.
+
+Once granted authenticated access to the Dimension Value endpoint, you'll use the it to query it to get attribute names and values specific to the accounts you're working with. e.g.
+
+- GET /dim-val/api/v2/attr/names?account=1001
+- GET /dim-val/api/v2/attr/values?account=1001
+
+There are various options for filtering data. See the [Dimension Value API documentation](https://github.rp-core.com/ContainerTag/pg-dim-val-api/blob/master-rubicon/docs/server_endpoints.md) for more details.
+
+{: .alert.alert-info :}
+In order to access client-specific targeting data, you'll need to know the account ID the Host Company uses for each publisher.
+
+See [PG Targeting Syntax](/prebid-server/features/pg/pbs-pg-targeting.html) for a list of targeting attributes you may be able
+to get from the PG Host Company and how to format them as part of the [PG Plan](/prebid-server/features/pg/pbs-pg-plan.html).
+
+### Getting data from the Delivery Stats Service
+
+There are two reasons PG Bidders need data from the Host Company's PG Delivery Stats Service:
+
+1. **Line Item reporting**: detailed info is available about where in the delivery funnel each Line Item is getting attention or running into problems. See the [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html#metrics) for which statistics you can expect.
+1. **Inform the pacing algorithm**: in order to write a robust and responsive pacing algorithm, the PG Bidder is going to need fresh data. If the bidder's impression data stream is real-time, that may be enough. If not, the Host Company's Delivery Stats server can provide recent (5-minute) summaries of important metrics like tokens spend and bidsWon. See [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html) for more details.
+
+Some example Delivery Stats queries:
+
+- GET /del-stats-summ/api/v1/report/line-item-summary?startTime=YYYY-MM-DDT00:00:00.000Z -- this returns an hourly aggregration for all of your line items since the specified time. See the [Line Item Summary Report endpoint documentation](https://github.rp-core.com/ContainerTag/pg-del-stats-svc/blob/master-rubicon/docs/line_item_summary_endpoint.md) for more info.
+- GET /del-stats-pa/api/v2/report/delivery?bidderCode=pgExample&startTime=YYYY-MM-DDT00:00:00.000Z -- this returns 5-minute aggregations for all of your line items since the specified time. See the [Delivery Report endpoint documentation](https://github.rp-core.com/ContainerTag/pg-del-stats-svc/blob/master-rubicon/docs/delivery_report_endpoints.md)
+
+
+### Answering General Planner requests
+
+When the PG Bidder is ready for integration with the Host Company, they'll provide an authenticated secure endpoint that will answer requests from the Host Company's General Planner.
+The path of this endpoint can be anything you'd like. It will receive these query string parameters:
+
+{: .table .table-bordered .table-striped }
+| Parameter | Format | Required? | Description |
+| --- | --- | --- | --- |
+| since | string | no | Timestamp in ISO-8601 format. For example, 2019-02-01T03:00:00.000Z. Service should respond with all meta data for active or nearly-active line items and schedules that got updated since this timestamp. Absence of this parameter signals request to return all active or nearly-active line items. |
+| hours | string | no | Number of hours of plans desired i.e. provide the next 3 hours worth of plans |
+
+Here's an [example JSON response](https://github.rp-core.com/ContainerTag/pg-general-planner/blob/master-rubicon/docs/samples/pa_rsp.json) that might come from your bidder planner.
+
+At this point, your endpoint needs to respond quickly with the most recently calculated set of PG line item pacing plans. A `plan` is a set
+of instructions to Prebid Server that tells the system how often to serve
+a line item in a given period. e.g. "serve LineA 50 times from noon-12:05, 55 times from 12:05-12:10, ..."
+
+The General Planner will be configured to call your endpoint every 1-10 minutes depending on the Host Company.
+
+See [PG Plan Definition](/prebid-server/features/pg/pbs-pg-plan.html) for more details.
+
+### General notes on writing a pacing algorithm
+
+At a high level, pacing a line item seems like it might be simple:
+
+```
+NumberOfImpressionsEach5MinPeriod=TotalImpressionsRemaining+3percentBuffer / NumberOf5MinPeriodsRemaining
+```
+
+But this approach wouldn't perform well:
+- When the line falls behind, it won't take advantage of higher traffic periods to catch up. It will fall behind during normal low-traffic periods, saving all impressions for the last minute.
+- As covered in the description of [tokens](/prebid-server/features/pg/pbs-pg-plan.html#tokens), a PG line item cannot assume that it'll be chosen every time it's offered to the ad server. Prebid PG paces based on tokens, not impressions, so the pacing algorithm needs to estimate how many times each line item needs to be offered to the ad server in order to land a final certified impression.
+
+Likewise, another naive approach is to try and immediately catch up to the "even delivery" line:
+```
+ImpressionDeficit=TotalImpressions+3percentBuffer - TotalImpressionsShouldHaveByNow
+
+NumberOfImpressionsThis5MinPeriod=ImpressionDeficit * NoiseFactor
+```
+
+Potential problems with this algorithm:
+- If it falls far behind, it could be overly aggressive in trying to catch up, affecting the delivery of other line items.
+- If it gets ahead somehow, it will stop delivering entirely until time catches up to the delivery curve.
+
+Here are some examples of desirable delivery patterns:
+
+{: .pb-lg-img :}
+
+And these are examples of delivery patterns to avoid:
+
+{: .pb-lg-img :}
+
+For more information, see the "Plans" section of the [Intro to PG Whitepaper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf).
+
+{: .alert.alert-warning :}
+The PG Host Company may require periodic of testing with your pacing algorithm because undesirable
+token management from on PG Bidder could affect line item delivery from other PG Bidders.
+
+## Related Topics
+
+- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html)
+- [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html)
+- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html)
+- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html)
diff --git a/prebid-server/features/pg/pbs-pg-glossary.md b/prebid-server/features/pg/pbs-pg-glossary.md
new file mode 100644
index 0000000000..c4dd2df468
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-glossary.md
@@ -0,0 +1,80 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Programmatic Guaranteed Glossary
+---
+
+# Programmatic Guaranteed Glossary
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## Basic terminology
+
+- **Programmatic Ad** - an ad request that flows through the multi-vendor ad tech ecosystem
+- **Guaranteed** - A buyer and seller have entered into a contract: to deliver a certain amount of impressions to a particular target over a particular date range. If contract isn't met, there may be financial penalties or extra impressions.
+- **PG Host Company** - the entity running the Prebid PG software: Prebid Servers, General Planner, Delivery Stats, and Dimension Value API.
+- **Prebid Ad Slot** - the "hole in the page" that's requesting an ad (note: this is not currently standard Prebid.org terminology).
+- **Prebid Ad Unit** - a package of bidding parameters that defines which bidders and bid parameters are to be used for a specific "hole in the page".
+- **Client Requests** - OpenRTB-like network calls from a client to the Prebid Server requesting one or more auctions.
+- **Auction Requests** - a single OpenRTB ad request may contain 1 or more 'imp' blocks that define different auction scenarios. Each of these blocks is an "auction". Auctions are sent to one or more bidders and are associated with auction parameters for each bidder.
+- **PG Bidder** - the ad exchange, demand side platform, or other bid source that directly or indirectly connects the Auction Request to a bid. Example bidders include Magnite, Criteo, etc.
+- **Bidder Parameters** - the specific parameters required by the bidder describing the auction to take place. The Rubicon account, site, and zone are example parameters.
+- **PG Line Item** - the base unit of ad delivery has a goal, date range, target, creatives, deal ID, and pacing options.
+- **AdServer Line Item** - corresponding to the PG Line Item, the AdServer has a similar line item which prioritizes the PG Line Item in relation to other direct-sold agreements. It may also have a goal and date range, but the targeting will be just to the deal ID, not the full PG target. The creative is the Prebid-standard creative instead of the actual creative.
+- **Deal** - an agreement between a buyer and a seller. In the PG context, a Deal may be comprised of 1 or more line items for different media types, targets, date ranges, etc. Since most bidders won't understand "line items", a candidate Deal ID is likely to be what's passed to each bidder.
+- **Line Item Type** - sponsorship, guaranteed, non-guaranteed, house.
+- **Creative** - the actual ad that will be seen by an end user. May be an image, HTML, video, or native.
+- **Target** - a description of the specific sites, user, device, and geographic characteristics a line item is aimed at.
+- **Goal** - How many total impressions a campaign line needs to serve
+- **Bonus** - Extra impressions assigned to a campaign line to make sure it delivers at least the total goal. This may be stated as a percentage or a number of impressions. Bonus is important to make sure that impression counting discrepancies don't cause the campaign to be perceived as missing its goal.
+- **Goal Type** - which metric is used to meet the goal. (i.e. wins or views)
+- **Start and End Datetime** - the date range for the campaign could include starting and ending mid-day. Each campaign may also be associated with a timezone.
+- **Delivery Type** - defines the general shape of the desired delivery curve:
+ - even delivery - impressions are roughly equal each day of the campaign
+ - front-loaded delivery - there may be more impressions delivered in the early days of the campaign
+ - as-soon-as-possible - serve this thing whenever there's a chance
+- **Historic Delivery** - Number of impressions a line delivered until the end of previous day.
+- **Deficit** - The number of impressions a line is behind due to lack of overall inventory, existence of road-blocks, or other reason.
+- **Late Deficit** - Number of impressions that a line is behind due to trafficking reasons, normally late creative. We may choose to catch up on a late deficit differently than other kinds of deficits because it's the fault of the advertiser, and it could affect other campaigns.
+- **Priority** - a way of ranking competing line items against each other.
+- **Oversold** - one or more guaranteed line items are struggling and are unlikely to reach their goals. In some cases it may be better to let some of the line items finish at the expense of others, while in other scenarios it's better to distribute what's available.
+- **Underdelivery** - when a line item is not serving enough impressions to meet its goal.
+- **Overdelivery** - when a line item is serving too many impressions, or has met its delivery goal too early.
+- **Frequency Cap** - how often a given user is allowed to see the advertising message.
+- **Discrepancy** - impressions are counted by multiple systems which often different from each other by a few percent. The buyer and seller agree on which numbers are billable. The ad system needs to deliver enough impressions that the goal is met in the system-of-record.
+- **Ad Inventory** - the combined set of attributes supplied with an ad request, whether direct or indirect. e.g. page context, user info, device info, etc. Line Item 'Targets' inspect these inventory attributes for matching.
+- **Forecast** - how much inventory of a particular type is expected to come in over a specified time period. e.g. "how many 300x250 ad requests from example.com will come from Windows machines next week?"
+- **Commitment** - a guaranteed line item that the publisher has promised to deliver to an advertiser.
+- **Availability** - starts with the Projection, but removes traffic that's already sold to other committed line items.
+- **Availability Buffer** - a safety factor to recognize that projections are always an estimate, and only the most sophisticated delivery systems can properly support the juggling involved in tightly sold overlapping inventory.
+
+## Metrics
+
+The basic design of the metrics offered by the PG system is a funnel that allows us to see where a line item's chance to deliver may be struggling. Here are the metrics available:
+
+- **clientAuctions** - the total number of auction impression requests seen by the system across all accounts. A single HTTPS request to PBS may contain multiple auction requests – this number basically reflects all auctions taking place.
+- **accountAuctions** - the number of auctions taking place for the specific Rubicon Project account ID
+- **domainMatched** - the number of times the domain portion of this line item's target matched an impression request. e.g. "1000 auctions for example.com". If there is no domain targeting, this number should be the same as accountAuctions.
+- **targetMatched** - the number of times the line item's entire target matched a request.
+- **targetMatchedButFcapped** - the number of times the line item's entire target matched a request, but the user ad already reached their personal frequency cap limit for this line item.
+- **targetMatchedButFcapLookupFailed** - the number of times the line item's entire target matched a request, but was removed from consideration because the lines item has a frequency cap and the lookup to the Frequency Capping system failed.
+- **pacingDeferred** - Prebid has taken the line item out of consideration in order to make sure it's not delivering too often
+- **sentToBidder** - only the top few matching line items or deals will be sent to each bidder. This metric indicates whether the line item was in the top few.
+- **sentToBidderAsTopMatch** - if the line item was considered most ready to serve by Prebid Server before going to the bidder, this metric will be incremented.
+- **receivedFromBidder** - this metric indicates whether the bidder chose this deal/line item from the candidates sent to it. Bidders may reject any suggested Deal ID or fail to respond.
+- **receivedFromBidderInvalidated** - indicates the number of times this deal/line item was received from a bidder, but rejected by Prebid Server for any reason. Rejection reasons include: incorrect size for auction, target didn't match, ahead of pace and not ready to serve.
+- **sentToClient** - indicates how many times this line item was sent as the bidder's top match to the client, and therefore the ad server.
+- **sentToClientAsTopMatch** - indicates how many times this line item was sent to the client/ad server flagged by Prebid Server as the most eligible PG line item.
+- **lostToLineItems** - this array provides a measure of which competing line items have been considered more eligible to serve than this line item
+- **events** - how many times this line item received notification of the stated event type. For now only the only supported event type is "win", but eventually there may be other types like "click", "video 50% played", etc.
+
+Here's a graphical representation showing what point in the delivery funnel each of these metrics measures:
+
+{: .pb-xlg-img :}
+
+## Related Topics
+
+- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html)
+- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf)
diff --git a/prebid-server/features/pg/pbs-pg-host.md b/prebid-server/features/pg/pbs-pg-host.md
new file mode 100644
index 0000000000..3abf6b3d5e
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-host.md
@@ -0,0 +1,67 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Becoming a PG Host Company
+---
+
+# Becoming a PG Host Company
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## Overview
+
+Prebid PG is open source, so anyone can spin up the 4 different types of servers
+needed to offer a PG service.
+
+1. Prebid Servers handle the real-time mix of open market and PG auctions.
+1. The General Planner collects PG line items from one or more PG Bidders.
+1. The Delivery Stats Service provides pacing and reporting information.
+1. The Dimension Value API provides the user interface the details required to build targets.
+
+See [Adding a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) for the
+high level view of the components.
+
+As a PG Host Company, you will have expenses in running and maintaining a global high-performance cluster of servers and databases. You'll need at least one PG Bidder,
+which might be one you build on your own or partner with someone else. You're under
+no obligation to support other PG Bidders, but your publishers may request it.
+
+## Installing the Servers
+
+For now, the only information about building and running the servers is in
+the relevant GitHub repos:
+
+- [Prebid Server Java](https://github.com/prebid/prebid-server-java). Note that Prebid Server Go doesn't currently support Programmatic Guaranteed.
+- [General Planner](https://github.com/prebid/pg-general-planner)
+- [Delivery Stats Service](https://github.com/prebid/pg-del-stats)
+- [Dimension Value API](https://github.com/prebid/pg-dim-val-api)
+
+Prebid does not offer specific guidance about fault-tolerant architectures.
+It's left up to each Host Company to determine what will happen if one of the servers goes down. i.e. Will there be load-balancing, automatic failover, a warm stand-by, or no fault tolerance?
+
+## General notes on testing the service
+
+There are a fair number of moving parts in a Prebid PG installation. Prebid.org
+does not run a test cluster. Changes are made by Prebid member companies, which do
+have test clusters, but they may not test every possible configuration. e.g. different databases, geographic lookup vendors,
+
+We recommend that PG Host Companies commit to regular testing of software updates
+against their specific configuration.
+
+The testing of PG Bidders and their pacing algorithms may be important to you,
+as publishers and advertisers care about the delivery patterns of their ad campaigns
+in a variety of challenging scenarios. Prebid.org may have extended recommendations
+about PG Bidder testing in the future, but in the meantime, you should consider
+joining Prebid.org and chatting with the development teams involved.
+
+## Announcing your service
+
+When ready to open their doors for business, Prebid.org members can ask to
+have their contact info added to the list of [PG Managed Services](/prebid-server/features/pg/pbs-pg-idx.html#list-of-pg-managed-services).
+
+## Related Topics
+
+- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html)
+- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf)
+- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html)
diff --git a/prebid-server/features/pg/pbs-pg-idx.md b/prebid-server/features/pg/pbs-pg-idx.md
new file mode 100644
index 0000000000..391b4e0b38
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-idx.md
@@ -0,0 +1,67 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Prebid Programmatic Guaranteed
+---
+
+# Prebid Programmatic Guaranteed
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## Prebid Programmatic Guaranteed
+In general, Programmatic Guaranteed (PG) has existed for several years as an ad server-based function.
+While anchoring PG in the ad server is helpful from a deployment perspective,
+the lack of transparency and configurability in the ad server has slowed down product momentum
+and made it harder for buyers and sellers to flexibly adjust their strategy and
+configurations for PG deals. The introduction of open-source, standards-based
+Programmatic Guaranteed, anchored in Prebid Sever, helps both buyers and sellers in
+several key ways:
+
+- It allows publishers to utilize preferred partners and data in the Programmatic infrastructure.
+- It streamlines the traditional RFP and I/O process between buyers and sellers
+- It separates the pacing, capping and forecasting functions from the ad server so publishers can more easily control and modify deals
+- Enables a seamless, software-based negotiation process between buyers and sellers
+- Ensures easier interoperability with a wider universe of buy-side platforms
+
+At a high level, the system allows any **Host Company** running Prebid Server (only PBS-Java for now) to integrate open source components into their existing UIs and data delivery systems.
+
+In addition, the Host Company can support other **PG Bidders** connecting into their system to make their environment richer for publishers.
+
+{: .pb-sm-img :}
+
+We want to encourage an ecosystem where programmatic vendors can compete on their strengths: some companies may be excellent at hosting a technical infrastructure, while others may excel at usability, reporting, or delivery algorithms.
+
+
+## PG For Publishers
+
+Publishers interested in trying Programmatic Guaranteed through Prebid should
+contact one of the companies hosting a PG cluster. They'll explain how it all works and walk you through the setup process.
+
+### List of PG Managed Services
+
+If you're a publisher looking to try Programmatic Guaranteed or a PG bidder that wants to integrate into an existing cluster, here's a list of Prebid.org members to consider:
+
+- **Magnite** - contact your account representative or globalsupport@magnite.com
+
+## PG for Bidders
+
+If you have a demand source and are ready to implement a guaranteed delivery algorithm, learn how to [become a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html).
+
+## Hosting your own PG Cluster
+
+If you're ready to host a global high-performance cluster, learn how to [become a PG Host Company](/prebid-server/features/pg/pbs-pg-host.html).
+
+## Questions?
+
+Contact prebid-server@prebid.org.
+
+## Related Topics
+
+- Intro to PG: [video](https://files.prebid.org/pg/PG_in_Prebid.mp4), [pdf](https://files.prebid.org/pg/PG_in_Prebid_Overview.pdf)
+- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf)
+- [Becoming a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html)
+- [Becoming a PG Host Company](/prebid-server/features/pg/pbs-pg-host.html)
+- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html)
+- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html)
diff --git a/prebid-server/features/pg/pbs-pg-plan.md b/prebid-server/features/pg/pbs-pg-plan.md
new file mode 100644
index 0000000000..8c9c9e045e
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-plan.md
@@ -0,0 +1,284 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Programmatic Guaranteed Plans
+---
+
+# Programmatic Guaranteed Plans
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## What is a PG Plan?
+
+A `Plan` is a set of instructions to Prebid Server that tells it how often to serve a PG line item in a given period.
+
+1. Plans are created by each [PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) as an output of their bidder-specific pacing algorithm.
+1. The 'General Planner' run by the Host Company will spread the Plan out across the cluster of Prebid Servers.
+1. Each Prebid Server works to deliver its part of the Plan.
+
+Here's what one looks like at a high level:
+
+```
+[
+ {
+ "lineItemId": "2291",
+ ... other line item attributes ...
+ deliverySchedule: [{
+ "planId": "2656179",
+ "startTimeStamp": "2020-08-28T11:50:00.000Z",
+ "endTimeStamp": "2020-08-28T11:55:00.000Z",
+ "updatedTimeStamp": "2020-08-28T10:04:12.000Z",
+ "tokens": [{
+ "class": 1,
+ "total": 50
+ }]
+ },{
+ ... next delivery schedule ...
+ }]
+ },
+ ... next line item ...
+ }
+]
+```
+
+The key parts of the Plan are:
+- Line item details. (See [example](#annotated-plan-example) below)
+- An array of Delivery Schedules broken into 5-minute periods
+- Each 5-minute period defines a number of `tokens` that need to be delivered
+
+### Tokens
+
+A `token` is an ad impression scaled up to overcome delivery obstacles.
+
+When Prebid Server (PBS) sends a PG line item to the ad server, it might be
+chosen to win, or maybe not. In either case, the act of sending a
+line item to the ad server causes PBS to create a "cool down" period for that
+line item. This is what pacing is all about -- making sure that delivery of the
+daily impression goal doesn't complete 20 minutes after midnight. PG delivery
+needs to be spread through the day, through the hour, and through each 5-minute period.
+
+If we could guarantee that the ad server would choose the PG line item to win every time,
+we wouldn't need tokens... PG could just use impressions. But that's not the case. There are several reasons why a candidate PG line item might not end up
+getting a final certified ad impression:
+- competing line items in the ad server
+- competing PG line items from another vendor
+- user leaves the page before ad render
+- the impression may be discounted as non-human traffic
+
+Basically, the pacing algorithms are working in a "noisy" environment. Not only are there
+many things that can get in the way of delivering a certified an ad impression,
+conditions can change rapidly, e.g. competing line items may start or stop, or the DSP may change its bidding pattern.
+
+So a "token" is Prebid PG's way of dealing with noise in the system.
+Instead of being satifisfied with offering a PG line item to the ad server
+and assuming that it will become a certified impression, PG operates in tokens instead, knowing that some of those opportunities won't materialize.
+You can think of it in terms of this basic formula:
+
+```
+Tokens = ImpressionsNeeded * Noise
+```
+
+Where the "noise" factor is how many tokens it's currently taking to get an ad
+impression through the gauntlet of challenges. Determining this noise factor
+is part of what the pacing algorithm needs to do -- adjusting it in real time
+as needed. e.g. if it's been taking 2 trips to the ad server to get a "bid won", the noise factor is 2, so in a plan that requires 50 impressions, there would be 100 tokens.
+You might wonder "why doesn't Prebid Server just take care of this?" Because Prebid Server is stateless... useful statistics are forwarded from hundreds of front-end servers and it's the job of the backend servers to aggregate and use that data.
+
+Of course noise could be infinite. For example, if there's a 'roadblock'
+ad in the ad server, it's possible that a PG line item will just stop delivering
+entirely for a day or more, and that's ok. But even though noise can be infinite,
+tokens cannot be. The Host Company will cap tokens at some reasonable level,
+but the best strategy for the infinite noise scenario is to give up and use a
+very small token count, waiting for when the problem has lifted.
+
+A good real-time way to monitor noise is to compare two fields
+in the Delivery Stats reports: sentToClientAsTopMatch vs events.bidsWon. (See the [glossary.](/prebid-server/features/pg/pbs-pg-glossary.html#metrics)) These values
+are indications of how many times the line item was offered to the ad server
+and accepted. But this value may also be tempered with data from your
+clean financial pipeline that compares certified impressions with events.bidsWon.
+
+### Plan Attributes
+
+These are the attributes that are part of a Plan. See below for an [annotated example](#annotated-plan-example).
+
+{: .table .table-bordered .table-striped }
+| Attribute | Required? | Description | Data Type |
+| --- | --- |--- |--- |
+| lineItemId | yes | Bidder-specific ID for this line item | string |
+| source | yes | Your PG bidder code. e.g. "pgBidderA" | string |
+| status | yes | Whether this line item is currently "active" or not. The only value that matters to the General Planner is "active". Any other value will cause the line item to be ignored. | string |
+| dealId | yes | Bidder-specific deal ID. Note that a Deal ID may be used by multiple line items. | string |
+| accountId | yes | Host Company-specific value for the publisher. | string |
+| price.cpm | yes | The CPM of the line item. | float |
+| price.currency | yes | The currency for the CPM of the line item. | string |
+| relativePriority | yes | Relative ranking specific to your pacing algorithm. You can put every line item at the same priority, or create 1000 different levels managed by your pacing algorithm. | integer |
+| sizes | yes | An array of creative sizes associated with the line item. e.g. `[{"w": 468,"h": 60},{"w": 728,"h": 90}]` | array of objects |
+| frequencyCaps.fcapId | no | Bidder-specific frequency cap ID. Needs to be uniqueo within your line items. | string |
+| frequencyCaps.count | no | How many impressions can be served | integer |
+| frequencyCaps.periods | no | Over how many periods | integer |
+| frequencyCaps.periodType | no | Period length. E.g. "day" or "hour" | string |
+| targeting | yes | Defines which ad requests are of interest to this line item. See [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html) | object |
+| startTimeStamp | yes | Line start time in UTC. e.g. 2020-08-28T07:22:14.000Z | string |
+| endTimeStamp | yes | Line end time in UTC. | string |
+| updatedTimeStamp | no | When this plan was last modified. | string |
+| deliverySchedules | yes | array of objects |
+| deliverySchedules.planId | yes? | Bidder-specific ID for use in debugging. Should be unique. | string |
+| deliverySchedules.startTimeStamp | yes | Start time of plan period in UTC | string |
+| deliverySchedules.endTimeStamp | yes | End time of plan period in UTC | string |
+| deliverySchedules.updatedTimeStamp | no | When this plan period was last modified.| string |
+| deliverySchedules.tokens.class | no | For future use. Set to 1 for now. | integer |
+| deliverySchedules.tokens.total | yes | Token count (Impressions * Noise) for this plan period. | integer |
+
+## Plans and the General Planner
+
+The General Planner will poll the PG Bidder endpoint frequently - e.g. every minute or every 5-minutes. The exact period will be determined between you and the Host Company, but it needs to be often because pacing line items is a dynamic business.
+Even though it will be contacted frequently, they should still generate
+several hours worth of the delivery schedule in case communication breaks down somehow.
+
+Once it receives the Plan, the General Planner will split up the tokens across
+Prebid Servers. When a line item first starts, it does this in a really blunt way: just divides them evenly across the servers. But it will soon start adjusting for geographic differences
+in line item delivery. e.g. if a line item only serves tokens in Europe, the Prebid Servers in Europe will get all the tokens within a few cycles.
+
+## Plans and Prebid Server
+
+Each PBS polls the General Planner once per minute, getting new and updated Plans.
+Here's how it works:
+
+1. When an auction request comes in, check to see if the account has any active PG line items. If it doesn't, process the request normally.
+2. If it is an account with active PG line items, enhance the request with geographic, device, user, and frequency capping information
+3. Find out which PG line items have targets that match the current request
+4. Loop through the matching line items
+ 1. Increment the "targetMatched" metric.
+ 1. If the PG line item has a frequency cap and there's no user ID or the lookup failed, increment the "targetMatchedButFcapLookupFailed" metric and take it off the list.
+ 1. If the PG line item has a frequency cap and it's met the cap, increment the "targetMatchedButFcapped" metric and take it off the list.
+ 1. If the PG line item is in "cool-down", increment the "pacingDeferred" metric and take it off the list
+5. Sort the remaining line items into priority order based on the PG-bidder-provided "relative priority", with a random secondary sort.
+6. Take the first 3 PG line items for each PG Bidder and send them the relevant bid adapter, incrementing the "sentToBidder" metric for each, and the "sentToBidderAsTopMatch" metric for one of them.
+7. Wait for the auction delay for the results. Increment "receivedFromBidder" and "receivedFromBidderInvalidated" metrics as appropriate.
+8. Take the highest priority bid from each PG Bidder and prepare ad server targeting. Increment the "sentToClient" metric.
+9. If there's more than one bid from a PG Bidder, randomly choose one to be the overall winner and increment the "sentToClientAsTopMatch" metric. Only this line item is considered to have spent a token and is put into "cool-down": PBS calculates how many milliseconds it needs to wait before offering this line item to the ad server again.
+
+{: .alert.alert-info :}
+Random numbers are used at a couple of points in the PG algorithm. This is to avoid choosing the same aggressive-but-blocked line item every time.
+
+## Annotated Plan Example
+
+Here's a complete example of a Plan with all line item and delivery schedule fields.
+
+```
+[ // each line item has a plan entry
+ {
+ "lineItemId": "2291", // this is specific to your internal systems
+ "dealId": "710216", // also specific to your internal systems
+ "accountId": "1001", // the Host Company's account ID for the publisher
+ "price": {
+ "cpm": 7.29,
+ "currency": "EUR"
+ },
+ "relativePriority": 2, // relative stacking specific to your pacing algorithm
+ "sizes": [{ // creative sizes
+ "w": 468,
+ "h": 60
+ },
+ {
+ "w": 728,
+ "h": 90
+ }
+ ],
+ "frequencyCaps": [{ // Host Company may support multiple cap levels
+ "fcapId": "LI-2291", // ID specific to your system
+ "count": 2, // show no more than 2 times per 1 day
+ "periods": 1,
+ "periodType": "day"
+ }
+ ],
+ "targeting": { // Line Item targeting
+ "$and": [{
+ "adunit.size": {
+ "$intersects": [{
+ "h": 60,
+ "w": 468
+ },
+ {
+ "h": 90,
+ "w": 728
+ }
+ ]
+ }
+ },{
+ "adunit.mediatype": {
+ "$intersects": [
+ "banner"
+ ]
+ }
+ },{
+ "device.ext.deviceatlas.browser": {
+ "$in": [
+ "Chrome",
+ "Firefox"
+ ]
+ }
+ },{
+ "device.geo.ext.netacuity.country": {
+ "$in": [
+ "us",
+ "jp"
+ ]
+ }
+ },{
+ "adunit.adslot": {
+ "$in": [
+ "/1111/QA_Tests"
+ ]
+ }
+ }
+ ]
+ },
+ "startTimeStamp": "2020-08-28T07:22:14.000Z", // line start time in UTC
+ "endTimeStamp": "2020-08-30T17:22:14.000Z", // line end time in UTC
+ "updatedTimeStamp": "2020-08-28T06:22:15.000Z",
+ "deliverySchedules": [ // now starts the plans
+ {
+ "planId": "2656177", // ID is specific to your system
+ "startTimeStamp": "2020-08-28T11:40:00.000Z", // UTC 11:40 to 11:45
+ "endTimeStamp": "2020-08-28T11:45:00.000Z",
+ "updatedTimeStamp": "2020-08-28T11:36:30.000Z",
+ "tokens": [
+ {
+ "class": 1, // always 1 for now
+ "total": 8 // number of tokens
+ }
+ ]
+ },
+ {
+ "planId": "2656178",
+ "startTimeStamp": "2020-08-28T11:45:00.000Z", // UTC 11:45 to 11:50
+ "endTimeStamp": "2020-08-28T11:50:00.000Z",
+ "updatedTimeStamp": "2020-08-28T11:38:19.000Z",
+ "tokens": [
+ {
+ "class": 1,
+ "total": 10
+ }
+ ]
+ },{
+ ... more plans ...
+ }
+ ],
+ "source": "pgBidderCode",
+ "status": "active"
+ },
+ {
+ ... next line item ...
+ }
+]
+```
+
+## Related Topics
+
+- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html)
+- [Becoming a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html)
+- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html)
+- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html)
diff --git a/prebid-server/features/pg/pbs-pg-targeting.md b/prebid-server/features/pg/pbs-pg-targeting.md
new file mode 100644
index 0000000000..dd8157733a
--- /dev/null
+++ b/prebid-server/features/pg/pbs-pg-targeting.md
@@ -0,0 +1,177 @@
+---
+layout: page_v2
+sidebarType: 5
+title: Programmatic Guaranteed Targeting Syntax
+---
+
+# Programmatic Guaranteed Targeting Syntax
+{: .no_toc}
+
+* TOC
+{:toc}
+
+## Overview
+
+Targeting is the ability for Prebid Server (PBS) to match PG line items with
+incoming OpenRTB auction requests.
+
+Here's a simple example target that says this line item will match any request for a 300x250 banner:
+
+```
+{
+ "$and": [
+ {
+ "adunit.size": {"$intersects": [{"w": 300,"h": 250}]}
+ },
+ {
+ "adunit.mediatype": {"$intersects": ["banner"]}
+ }
+ ]
+}
+```
+
+In general, the syntax is:
+```
+{
+ "$and/$or": [
+ { "ATTRIBUTE": { "OPERATOR": CONDITION } },
+ "$and/$or": [ ... ],
+ "$not": { "ATTRIBUTE": { "OPERATOR": CONDITION } }
+ ]
+}
+```
+Here are the supported OPERATORs:
+
+{: .table .table-bordered .table-striped }
+| Operator | Description | Attribute Datatype | Condition Datatype | Example |
+| --- | --- | --- | --- |
+| $matches | True if the scalar ATTRIBUTE is the same as the CONDITION, or matches with an asterisk wildcard. | string | string | "$matches": "{::nomarkdown}*sports*{:/}" |
+| $in | True if the scalar ATTRIBUTE is on the CONDITION's array. | string | array of strings | "$in": ["a","b"] |
+| $intersects | True if at least one value from the ATTRIBUTE's array is on the CONDITION's array | array of strings | array of strings | "$intersects": ["hockey","soccer"] |
+| $within | True if user's lat/long are available and within the circle defined by the CONDITION. | from geolookup service | object with attributes: lat, lon, and radiusMiles | "$within": {"lat": 123.456,"lon": 789.123,"radiusMiles": 50} |
+
+## Targeting Attributes
+
+The full list of attributes supported by Prebid Server may differ by PG Host Company because they might use different geographic and device information services. But here's an example list:
+
+{: .table .table-bordered .table-striped }
+| Attribute | Description | Encoding | PBS Source | OpenRTB path | Operators |
+| --- | --- | --- | --- | --- | --- |
+| adunit.size | Ad Sizes | [{w: 300, h: 250},...] | OpenRTB | imp[].banner.format[] | intersects |
+| adunit.mediatype | Mediatype | string | OpenRTB | mediatype="banner" if imp.banner exists. mediatype="video-instream" if imp.video exists and placement is 1. mediatype="video-outstream" if imp.video exists and placement is <> 1. mediatype="native" if imp.native exists | intersects |
+| adunit.adslot | The ad server slot name | string | OpenRTB | imp[].ext.context.data.pbadslot | in, matches |
+| site.domain | Site domain | string | OpenRTB | site.domain | in, matches |
+| site.referrer | Referring URL | string | OpenRTB | site.page | in, matches |
+| app.bundle | Mobile application bundle | string | OpenRTB | app.bundle | in, matches |
+| pos | Page position | 0=unknown, 1=ATF, 3=BTF | OpenRTB | imp.banner.pos | in |
+| geo.distance | User's lat/lon is within a defined circle | none | Geo vendor | device.geo.lat, device.geo.lon | within |
+| device.geo.ext.VENDOR.country | Country | string | Geo vendor | device.geo.ext.VENDOR.country | in|
+| device.geo.ext.VENDOR.region | Region | string | Geo vendor | device.geo.ext.VENDOR.region | in|
+| device.geo.ext.VENDOR.metro | Metro (DMA) | string | Geo vendor | device.geo.ext.VENDOR.metro | in|
+| device.geo.ext.VENDOR.city | City | string | Geo vendor | device.geo.ext.VENDOR.city | in|
+| device.geo.ext.VENDOR.zip | Postal Code | string | Geo vendor | device.geo.ext.VENDOR.zip | in|
+| device.ext.VENDOR.connspeed | Connection Speed | string | Device vendor | device.ext.VENDOR.connspeed | in|
+| device.ext.VENDOR.type | Device Type | string | Device vendor | device.ext.VENDOR.type | in|
+| device.ext.VENDOR.make | Device Make | string | Device vendor | device.ext.VENDOR.make | in|
+| device.ext.VENDOR.model | Device Model | string | Device vendor | device.ext.VENDOR.model | in|
+| device.ext.VENDOR.os | Operating System | string | Device vendor | device.ext.VENDOR.os | in|
+| device.ext.VENDOR.browser | Browser | string | Device vendor | device.ext.VENDOR.browser | in|
+| device.ext.VENDOR.browserver | Browser Version | string | Device vendor | device.ext.VENDOR.browserver | in|
+| device.ext.VENDOR.language | Device Language | string | Device vendor | device.ext.VENDOR.language | in|
+| device.ext.VENDOR.osver | Operating System Version | string | Device vendor | device.ext.VENDOR.osver | in|
+| device.ext.VENDOR.carrier | Internet Carrier | string | Device vendor | device.ext.VENDOR.carrier | in|
+| user.ext.time.userdow | User Day of Week | 1=sun, 7=sat | Geo vendor + clock | user.ext.time.userdow | in|
+| user.ext.time.userhour | User Hour | 0-23 |Geo vendor + clock | user.ext.time.userhour | in|
+| ufpd.ATTR | User First Party Data | string | OpenRTB | user.ATTR or user.ext.data.ATTR | in, matches, intersects |
+| sfpd.ATTR | Site First Party Data | string | OpenRTB | imp[].ext.context.data.ATTR=VAL OR site.ext.data.ATTR=VAL OR app.ext.data.ATTR=VAL | in, matches, intersects |
+| segment.SOURCE | User Segment Data | string | OpenRTB | user.data[].id=SOURCE AND VALUE in user.data[].segment[].id | intersects |
+| bidp.BIDDER.ATTR | Bid Parameter Data | string | OpenRTB | imp[].ext.BIDDER.ATTR | in, matches, intersects|
+
+## Targeting Syntax
+
+Here's an example of a ridiculously specific target that uses most of the
+attributes and specific geographic and device info services:
+
+```
+{
+ "$and": [
+ {
+ "adunit.size": {"$intersects": [{"w": 300,"h": 250},{"w": 300,"h": 600}]}
+ },
+ {
+ "adunit.mediatype": {"$intersects": ["banner"]}
+ },
+ {
+ "$or": [
+ {"site.ext.domain": {"$matches": "*.example.com"}},
+ {"site.ext.domain": {"$in": ["prebid.org"]}}
+ ]
+ },
+ {
+ "$or": [
+ {"site.referrer": {"$matches": "*sports*"}},
+ {"site.referrer": {"$matches": "*prebid*"}}
+ ]
+ },
+ {
+ "$or": [
+ {"adunit.adslot": {"$matches": "/home/top*"}},
+ {"adunit.adslot": {"$in": ["/home/bottom"]}}
+ ]
+ },
+ {
+ "pos": {"$in": [1,3]}
+ },
+ {
+ "device.geo.ext.netacuity.country": {"$in": ["us","de"]}
+ },
+ {
+ "device.geo.ext.netacuity.region": {"$in": ["de-bw","de-by"]}
+ },
+ {
+ "device.geo.ext.netacuity.metro": {"$in": ["111","222"]}
+ },
+ {
+ "device.geo.ext.netacuity.city": {"$in": ["444","555"]}
+ },
+ {
+ "geo.distance": {"$within": {"lat": 123.456,"lon": 789.123,"radiusMiles": 50}}
+ },
+ {
+ "device.ext.deviceatlas.type": {"$in": ["tablet","phone"]}
+ },
+ {
+ "$or": [
+ {"bidp.rubicon.siteId": {"$in": [123,321]}},
+ {"bidp.appnexus.placementName": {"$matches": "*99999*"}},
+ ]
+ },
+ {
+ "$or": [
+ {"segment.rp": {"$intersects": [123,234,345]}},
+ {"segment.bluekai": {"$intersects": [123,234,345]}}
+ ]
+ },
+ {
+ "sfpd.sport": {"$intersects": ["hockey","soccer"]}
+ },
+ {
+ "user.ext.time.userdow": {"$in": [5,6]}
+ },
+ {
+ "user.ext.time.userhour": {"$in": [10,11,12,13,14]}
+ },
+ {
+ "$not": {
+ "ufpd.registered": {"$matches": ["false"]}
+ }
+ }
+ ]
+}
+```
+
+
+## Related Topics
+
+- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html)
+- [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html)
diff --git a/prebid-server/use-cases/pbs-amp.md b/prebid-server/use-cases/pbs-amp.md
index ecd191ed02..d5ec56c52e 100644
--- a/prebid-server/use-cases/pbs-amp.md
+++ b/prebid-server/use-cases/pbs-amp.md
@@ -47,7 +47,7 @@ There are two basic ways of invoking AMP RTC:
data-slot="/11111/amp_test"
data-multi-size-validation="false"
rtc-config='{"vendors": {"prebidrubicon": {"REQUEST_ID": "14062-amp-AMP_Test-300x250"}, "ACCOUNT_ID": "1001"}}'
- json='{ "targeting": {"site":{"keywords":"article, las vegas","cat":{"blah":"1"},"other-attribute":"other-value","ext":{"data":{"entry_group":["front-page","featured-stories"],"page_type":"AMP"}}},"user":{"gender":"m"},"bidders":["bidderA","bidderB"],"keywords":"las vegas hospitality employees","foo":{"bar":"baz"}}' >
+ json='{ "targeting": {"attr1": "val1", "attr2": "val2"}}' >
```
@@ -61,13 +61,10 @@ There are two basic ways of invoking AMP RTC:
type="doubleclick"
data-slot="/000/amp_test"
data-multi-size-validation="false"
- rtc-config='{"urls": ["https://prebid-server-qa.example.com/openrtb2/amp?tag_id=11111&w=300&h=50&slot=%2F000%2Famp_test&targeting=%7B%22site%22%3A%20%7B%22key1%22%3A%20%22val1%22%7D%2C%20%22user%22%3A%20%7B%22key2%22%3A%20%22val2%22%7D%7D%7D&purl=encoded_page_url&account=333&gdpr_consent=encoded_cmp_consent_string"]
+ rtc-config='{"urls": ["https://prebid-server-qa.example.com/openrtb2/amp?tag_id=11111&w=300&h=50&slot=%2F000%2Famp_test&purl=encoded_page_url&account=333&gdpr_consent=encoded_cmp_consent_string"]
```
-{: .alert.alert-info :}
-First party data may be passed in on the "targeting" field. See the [`/openrtb2/amp` endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) documentation for more details.
-
### Prebid Server Receives the AMP Request
Prebid Server's first job on the [/openrtb2/amp endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) is to create an OpenRTB block to pass to the adapters.
@@ -76,15 +73,8 @@ Prebid Server's first job on the [/openrtb2/amp endpoint](/prebid-server/endpoin
The `tag_id` in the AMP URL is used to look up the bulk of the request. If the lookup fails, the request can't proceed. If it's successful, the
next step is to parse the AMP query string parameters and place them
-in the appropriate OpenRTB locations:
-
-- w added into the openrtb packet at imp.banner.format[0].w
-- h added into the openrtb packet at imp.banner.format[0].h
-- ms (multiple-sizes) - takes values like "970x90, 728x90". Parse sizes and add to imp.banner.format array
-- ow, oh - override width, override height
-- curl added as site.page
-- slot added as imp.tagid
-- timeout added as tmax
+in the appropriate OpenRTB locations. See the [AMP endpoint documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html)
+for details.
So for the /openrtb2/amp URL above, the resulting OpenRTB might be:
```
@@ -116,17 +106,7 @@ So for the /openrtb2/amp URL above, the resulting OpenRTB might be:
"id": "0000"
},
"ext": {
- "amp": 1,
- "data": {
- "key1": "val1"
- }
- }
- },
- "user": {
- "ext": {
- "data": {
- "key2": "val2"
- }
+ "amp": 1
}
},
"device": {
@@ -169,7 +149,7 @@ Only a few dynamic parameters on the query string are integrated into the result
#### First Party Data Support
Ad Server targeting data passed in through the [`/openrtb2/amp`](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) endpoint is merged
-into the OpenRTB JSON in imp[].ext.data for each bidder if permissions allow.
+into the OpenRTB JSON in imp[].ext.data.
#### Auction and Response
@@ -180,7 +160,6 @@ From here, the header bidding auction is mostly the same as it is for Prebid.js:
1. Collect responses
1. Prepare the response
-
### AMP Gets the Response
AMP RTC endpoints can only respond with targeting, not OpenRTB. The
@@ -216,4 +195,5 @@ into an iframe for display.
## Further Reading
-- [AMP Support](/formats/amp.html)
+- [Prebid AMP Support](/formats/amp.html)
+- [PBS AMP endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html)
diff --git a/prebid-video/video-getting-started.md b/prebid-video/video-getting-started.md
index 491b156c3c..82bc941d97 100644
--- a/prebid-video/video-getting-started.md
+++ b/prebid-video/video-getting-started.md
@@ -71,7 +71,11 @@ Setting up Prebid ad units is almost the same whether you’re working with inst
mediaTypes: {
video: {
context: 'instream', //or 'outstream'
- playerSize: [640, 480]
+ playerSize: [640, 480],
+ mimes: ['video/mp4'], // required for Prebid Server
+ protocols: [1, 2, 3, 4, 5, 6, 7, 8],
+ playbackmethod: [2],
+ skip: 1
}
```
@@ -80,14 +84,6 @@ The mediaTypes.video.playerSize field is where you define the player size that w
Prebid Server
If you’re using Prebid Server, you must also include the mediaTypes.video.mimes field, as this is required by OpenRTB.
-
-
- mediaTypes: {
- video: {
- context: 'instream', // or 'outstream'
- playerSize: [640, 480],
- mimes: ['video/mp4']
-
In your ad unit you also need to define your list of bidders. For example, including AppNexus as a bidder would look something like this:
diff --git a/prebid/native-implementation.md b/prebid/native-implementation.md
index 704fc5f89a..9e4c8985ac 100644
--- a/prebid/native-implementation.md
+++ b/prebid/native-implementation.md
@@ -77,7 +77,7 @@ The Prebid.js AdUnit needs to defines a native mediatype object to tell bidders
| Attribute | Scope | Description | Example | Type |
| --- | --- | --- | --- | --- |
| sendTargetingKeys | optional | Defines whether or not to send the hb_native_ASSET targeting keys to the ad server. Defaults to `true` for now, though we recommend setting this to `false` and utilizing one of the ways to define a native template. | `false` | boolean |
-| adTemplate | optional | Used in the ‘AdUnit-Defined Creative Scenario’, this value controls the Native template right in the page. | See [example](#5-implementing-adunit-defined-creative) below. | escaped ES5 string |
+| adTemplate | optional | Used in the ‘AdUnit-Defined Creative Scenario’, this value controls the Native template right in the page. | See [example](#42-implementing-adunit-defined-template) below. | escaped ES5 string |
| rendererUrl | optional | Used in the ‘Custom Renderer Scenario’, this points to javascript code that will produce the Native template. | 'https://host/path.js' | string |
| type | optional | A “type” is like a macro that defines a group of assets. The only value currently supported is ‘image’, which implies the following assets: image, title, sponsoredBy, clickUrl, body, icon, and cta. The first 4 are required attributes. | `image` | string |
| ASSETCODE. required | optional | Defines whether native bids must include this asset. Defaults to `false`. | `true` | boolean |
@@ -136,9 +136,9 @@ In the native template, simply access the custom value with the normal Prebid ##
## 4. Implementing the Native Template
-- If you want to manage your creative within the ad server (e.g. Google Ad Manager), follow the instructions for [AdServer-Defined Creative](#4-implementing-adserver-defined-creative).
-- If you’d prefer to manage your creative within the Prebid.js AdUnit, follow the instructions for [AdUnit-Defined Creative](#5-implementing-adunit-defined-creative)
-- If you’d prefer to manage your creative from a separate piece of JavaScript, follow the instructions for the [Custom Renderer](#6-implementing-the-custom-renderer-scenario).
+- If you want to manage your creative within the ad server (e.g. Google Ad Manager), follow the instructions for [AdServer-Defined Creative](#41-implementing-adserver-defined-template).
+- If you’d prefer to manage your creative within the Prebid.js AdUnit, follow the instructions for [AdUnit-Defined Creative](#42-implementing-adunit-defined-template)
+- If you’d prefer to manage your creative from a separate piece of JavaScript, follow the instructions for the [Custom Renderer](#43-implementing-the-custom-renderer-scenario).
### 4.1. Implementing AdServer-Defined Template
@@ -356,7 +356,7 @@ In this scenario, the body of the native creative is managed from an external Ja
When the Native AdUnit is defined in the page:
- Declare`sendTargetingKeys: false` in the Native Object. This will prevent Prebid.js from sending all the native-related ad server targeting variables.
-- Define the `rendererUrl` as a URL that defines a `window.renderAd` function in the creative iframe. Any CSS definitions need to be defined in the body (e.g.