diff --git a/dev-docs/add-rtd-submodule.md b/dev-docs/add-rtd-submodule.md
index f97b848a0c..da83ba9677 100644
--- a/dev-docs/add-rtd-submodule.md
+++ b/dev-docs/add-rtd-submodule.md
@@ -176,17 +176,34 @@ submodule('realTimeData', subModuleObj);
This is the function that will allow RTD sub-modules to modify the AdUnit object for each auction. It's called as part of the requestBids hook.
1. RTD-core will call this function with:
- - reqBidsConfigObj: the object that's passed to [`pbjs.requestBids`](). Note that several auctions can happen concurrently, so the sub-module must be ready to support this.
+ - reqBidsConfigObj: a slightly modified version of the object that's passed to `pbjs.requestBids` (see [below](#reqBidsConfigObj)). Note that several auctions can happen concurrently, so the sub-module must be ready to support this.
- callback: lets RTD-core know which auction the sub-module is done with.
- config: the sub-module's config params provided by the publisher
- userConsent object (see above)
2. Your sub-module may update the reqBidsConfigObj and hit the callback. To inject data into the bid requests, you should follow one of these conventions:
- Recommended: use one of these [First Party Data](/features/firstPartyData.html) conventions:
- For AdUnit-specific first party data, set AdUnit.ortb2Imp.ext.data.ATTRIBUTES
- - For global first party data, call 'pbjs.[mergeConfig](/dev-docs/publisher-api-reference/mergeConfig.html)()'
- - If the data is not meant to go to all bidders, the module should use 'pbjs.[mergeBidderConfig](/dev-docs/publisher-api-reference/mergeBidderConfig.html)()' and support a parameter to allow the publisher to define which bidders are to receive the data.
+ - For global first party data, including bidder-specific data, modify the `reqBidsConfigObj` as shown [below](#reqBidsConfigObj)
- Not recommended: Place your data in bidRequest.rtd.RTDPROVIDERCODE.ATTRIBUTES and then get individual adapters to specifically read that location. Note that this method won't pass data to Prebid Server adapters.
+
+
+The `reqBidsConfigObj` parameter is a copy of the object passed to [`requestBids`](/dev-docs/publisher-api-reference/requestBids.html), except for:
+
+- `adUnits` and `timeout` are always defined (if the publisher didn't provide them, the default values are filled in - `pbjs.adUnits` and `getConfig('bidderTimeout')` respectively)
+- `ortb2` is replaced with an `ortb2Fragments` object, intended to be inspected and / or modified by your module.
+
+The `ortb2Fragments` parameter is an object containing two properties:
+
+- `global`, an object containing global (not bidder-specific) first party data in the same OpenRTB format used by `setConfig({ortb2})`
+- `bidder`, a map from bidder code to bidder-specific, OpenRTB-formatted first party data.
+
+Your module may modify either or both with additional data. If adding bidder-specific data in `ortb2Fragments.bidder`, it should also support a parameter to allow the publisher to define which bidders are to receive the data.
+
+{: .alert.alert-warning :}
+Before version 7, the pattern for first party data inspection and enrichment by RTD modules was `getConfig({ortb2])` / `mergeConfig({ortb2})`. With the introduction of [auction-specific data](/features/firstPartyData.html#supplying-auction-specific-data) in 7, the global `getConfig('ortb2')` is "frozen"
+at the time `requestBids` is called, and RTD submodules that wish to modify it are required to work on `ortb2Fragments` instead - as any additional call to `mergeConfig` will only take effect on the *next* auction.
+
**Code Example**
{% highlight text %}
@@ -205,7 +222,12 @@ function init(config, userConsent) {
function alterBidRequests(reqBidsConfigObj, callback, config, userConsent) {
// do stuff
- // put data in AdUnit.ortb2Imp.ext.data.* or rtd.RTDPROVIDERCODE.*
+ // put data in adUnits' ortb2Imp:
+ reqBidsConfigObj.adUnits.forEach((adUnit) => mergeDeep(adUnit, 'ortb2Imp.ext', myCustomData);
+ // or in global first party data:
+ mergeDeep(reqBidsConfigObj.ortb2Fragments.global, myCustomData);
+ // or in bidder-specific first party data:
+ config.bidders.forEach((bidderCode) => mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, {[bidderCode]: myCustomData});
callback();
}
diff --git a/dev-docs/bidder-adaptor.md b/dev-docs/bidder-adaptor.md
index dc52de5eb3..c75644fc8a 100644
--- a/dev-docs/bidder-adaptor.md
+++ b/dev-docs/bidder-adaptor.md
@@ -225,7 +225,7 @@ buildRequests: function(validBidRequests, bidderRequest) {
Building the request will use data from several places:
* **Ad Unit Params**: The arguments provided by the page are in `validBidRequests[]`.
-* **BidRequest Params**: Several important parameters such as userId, GDPR, USP, and supply chain values are on the `bidderRequest` object.
+* **BidRequest Params**: Several important parameters such as first-party data, userId, GDPR, USP, and supply chain values are on the `bidderRequest` object.
* **Prebid Config**: Publishers can set a number of config values that bid adapters should consider reading.
@@ -235,19 +235,20 @@ Here is a sample array entry for `validBidRequests[]`:
{% highlight js %}
[{
- adUnitCode: "test-div"
- auctionId: "b06c5141-fe8f-4cdf-9d7d-54415490a917"
- bidId: "22c4871113f461"
- bidder: "rubicon"
- bidderRequestId: "15246a574e859f"
- bidRequestsCount: 1
- bidderRequestsCount: 1
- bidderWinsCount: 0
- userId: {...}
- schain: {...}
- mediaTypes: {banner: {...}}
- params: {...}
- src: "client"
+ adUnitCode: "test-div",
+ auctionId: "b06c5141-fe8f-4cdf-9d7d-54415490a917",
+ bidId: "22c4871113f461",
+ bidder: "rubicon",
+ bidderRequestId: "15246a574e859f",
+ bidRequestsCount: 1,
+ bidderRequestsCount: 1,
+ bidderWinsCount: 0,
+ userId: {...},
+ userIdAsEid: {...},
+ schain: {...},
+ mediaTypes: {banner: {...}},
+ params: {...},
+ src: "client",
transactionId: "54a58774-7a41-494e-9aaf-fa7b79164f0c"
}]
{% endhighlight %}
@@ -260,6 +261,8 @@ Other notes:
- **Bid Request Count** is the number of times `requestBids()` has been called for this ad unit.
- **Bidder Request Count** is the number of times `requestBids()` has been called for this ad unit and bidder.
- **userId** is where bidders can look for IDs offered by the various [User ID modules](/dev-docs/modules/userId.html#prebidjs-adapters).
+- **userIdAsEid** is the EID-formatted version of `userId`.
+- **ortb2** a copy of `bidderRequest.ortb2` (see below), provided here for convenience.
- **schain** is where bidders can look for any [Supply Chain](/dev-docs/modules/schain.html) data that they should pass through to the endpoint.
#### bidderRequest Parameters
@@ -274,6 +277,7 @@ Here is a sample bidderRequest object:
bidderRequestId: "15246a574e859f",
bids: [{...}],
gdprConsent: {consentString: "BOtmiBKOtmiBKABABAENAFAAAAACeAAA", vendorData: {...}, gdprApplies: true},
+ ortb2: {...},
refererInfo: {
canonicalUrl: undefined,
numIframes: 0,
@@ -287,7 +291,8 @@ Notes on parameters in the bidderRequest object:
- **auctionID** is unique per call to `requestBids()`, but is the same across ad units.
- **refererInfo** is provided so you don't have to call any utils functions. See below for more information.
- **gdprConsent** is the object containing data from the [GDPR ConsentManagement](/dev-docs/modules/consentManagement.html) module. For TCF2+, it will contain both the tcfString and the addtlConsent string if the CMP sets the latter as part of the TCData object.
-- **uspConsent** is the object containing data from the [US Privacy ConsentManagement](/dev-docs/modules/consentManagementUsp.html) module
+- **uspConsent** is the object containing data from the [US Privacy ConsentManagement](/dev-docs/modules/consentManagementUsp.html) module.
+- **ortb2** is the global (not specific to any adUnit) [first party data](/features/firstPartyData.html) to use for all requests in this auction. Note that Prebid allows any standard ORTB field or extension as first party data - including items that typically wouldn't be considered as such, for example user agent client hints (`device.sua`) or information on the regulatory environment (`regs.ext.gpc`).
@@ -301,7 +306,7 @@ There are a number of important values that a publisher expects to be handled in
| Ad Server Currency | If your endpoint supports responding in different currencies, read this value. | config.getConfig('currency.adServerCurrency') |
| Bidder Timeout | Use if your endpoint needs to know how long the page is allowing the auction to run. | config.getConfig('bidderTimeout'); |
| COPPA | If your endpoint supports the Child Online Privacy Protection Act, you should read this value. | config.getConfig('coppa'); |
-| First Party Data | The publisher may provide [first party data](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd) (e.g. page type). | config.getConfig('fpd'); |
+| First Party Data | The publisher, as well as a number of modules, may provide [first party data](/features/firstPartyData.html) (e.g. page type). | bidderRequest.ortb2; validBidRequests[].ortb2Imp|
| Floors | Adapters that accept a floor parameter must also support the [floors module](https://docs.prebid.org/dev-docs/modules/floors.html) | [`getFloor()`](/dev-docs/modules/floors.html#bid-adapter-interface) |
| Page Referrer | Intead of building your own function to find the page referrer, look in the standard bidRequest location. | bidderRequest.refererInfo.referer |
| Publisher Domain | The page may declare its domain, useful in cross-iframe scenarios. | config.getConfig('publisherDomain') |
diff --git a/dev-docs/modules/enrichmentFpdModule.md b/dev-docs/modules/enrichmentFpdModule.md
index 857c4f2129..3a8d60a0c1 100644
--- a/dev-docs/modules/enrichmentFpdModule.md
+++ b/dev-docs/modules/enrichmentFpdModule.md
@@ -32,22 +32,16 @@ pbjs.setConfig({
## How it works
-When the first auction on the page is run, this module merges a number of values into the `ortb2` object. Specific details below.
-
-If the publisher needs to refresh the enriched FPD after the first auction, this can be done using a function provided by this module:
-
-```
-pbjs.refreshFpd();
-```
+At the beginning of each auction, this module merges a number of values into the `ortb2` [requestBids parameter](/dev-docs/publisher-api-reference/requestBids.html). Specific details below.
## Enrichments
{: .table .table-bordered .table-striped }
| Page Source | ortb2 field | Notes |
|---+---+---|
-| page URL | site.page | Uses pbjs getRefererInfo().canonicalUrl |
-| referer URL | site.ref | Uses pbjs getRefererInfo().referer |
-| host domain | site.domain | Pulled from the getRefererInfo().canonicalUrl the host domain is used with the www component dropped. |
+| page URL | site.page | Uses pbjs getRefererInfo().page |
+| referer URL | site.ref | Uses pbjs getRefererInfo().ref |
+| host domain | site.domain | Pulled from the getRefererInfo().page the host domain is used with the www component dropped. |
| aggregated domain | site.publisher.domain | The highest level domain in which cookies can be set. |
| viewport width | device.w | Hunts for window.innerWidth, window.document.documentElement.clientWidth, window.document.body.clientWidth |
| viewport height | device.w | Hunts for window.innerHeight, window.document.documentElement.clientHeight, window.document.body.clientHeight |
diff --git a/dev-docs/modules/validationFpdModule.md b/dev-docs/modules/validationFpdModule.md
index 571eb26f7f..635647034b 100644
--- a/dev-docs/modules/validationFpdModule.md
+++ b/dev-docs/modules/validationFpdModule.md
@@ -33,7 +33,7 @@ pbjs.setConfig({
## Validations
-This module does its checks only once at the first auction. The checks can be re-run anytime by calling `pbjs.refreshFpd()`.
+This module does its checks at the beginning of each auction.
When a data field doesn't meet the defined validations, it will be removed. In addition, the module will look for the _pubcid_optout cookie (or local storage),
and if it exists, certain fields will be removed.
diff --git a/dev-docs/publisher-api-reference/requestBids.md b/dev-docs/publisher-api-reference/requestBids.md
index 103b2db8d2..92ef42eb1c 100644
--- a/dev-docs/publisher-api-reference/requestBids.md
+++ b/dev-docs/publisher-api-reference/requestBids.md
@@ -20,6 +20,7 @@ Request bids. When `adUnits` or `adUnitCodes` are not specified, request bids fo
| requestObj.bidsBackHandler | Optional | `function` | Callback to execute when all the bid responses are back or the timeout hits. Callback will be passed three parameters, the [bidResponses](#module_pbjs.getBidResponses) themselves, a `timedOut` flag (true if any bidders timed out) and the `auctionId`. |
| requestObj.labels | Optional | `Array of strings` | Defines [labels](#labels) that may be matched on ad unit targeting conditions. |
| requestObj.auctionId | Optional | `String` | Defines an auction ID to be used rather than having the system generate one. This can be useful if there are multiple wrappers on a page and a single auction ID is desired to tie them together in analytics. |
+| requestObj.ortb2 | Optional | `Object` | Additional [first-party data](/features/firstPartyData.html) to use for this auction only |
Example call
```
diff --git a/dev-docs/publisher-api-reference/setConfig.md b/dev-docs/publisher-api-reference/setConfig.md
index 5872de8c96..2b38a9aa2c 100644
--- a/dev-docs/publisher-api-reference/setConfig.md
+++ b/dev-docs/publisher-api-reference/setConfig.md
@@ -1052,11 +1052,15 @@ The `ortb2` JSON structure reflects the OpenRTB standard:
- Segments should go in site.content.data[] or user.data[].
- Any other OpenRTB 2.5 field could be added here as well, e.g. site.content.language.
-**Scenario 2** - Global (cross-adunit) First Party Data open only to a subset of bidders
+**Scenario 2** - Auction (cross-adunit) First Party Data open to all bidders
+
+If a page needs to specify multiple different sets of top-level data (`site`, `user`, or `app`), use the `ortb2` parameter of [`requestBids`](/dev-docs/publisher-api-reference/setConfig.html) ([example](/features/firstPartyData.html#supplying-auction-specific-data)
+
+**Scenario 3** - Global (cross-adunit) First Party Data open only to a subset of bidders
If a publisher only wants certain bidders to receive the data, use the [setBidderConfig](/dev-docs/publisher-api-reference/setBidderConfig.html) function.
-**Scenario 3** - AdUnit-specific First Party Data
+**Scenario 4** - AdUnit-specific First Party Data
See the [AdUnit Reference](/dev-docs/adunit-reference.html) for AdUnit-specific first party data.
diff --git a/features/firstPartyData.md b/features/firstPartyData.md
index 6dee0ff456..79fb7fdd50 100644
--- a/features/firstPartyData.md
+++ b/features/firstPartyData.md
@@ -31,9 +31,10 @@ which can be used for more than just First Party Data.
Publishers supply First Party Data (FPD) by specifying attributes as
configuration or on a Prebid.js AdUnit:
-- Global site or user data that applies to all AdUnits and all bidders. Use [`setConfig()`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd)
-- AdUnit-specific data that applies to all bidders. Define [AdUnit.ortb2Imp](/dev-docs/adunit-reference.html#first-party-data)
-- Bidder-specific site or user data that applies to all AdUnits. Use [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html)
+- Global site or user data that applies to all AdUnits, bidders, and auctions. Use [`setConfig()`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd)
+- Auction-specific site or user data that applies to all AdUnits and bidders in that auction. Use the `ortb2` parameter of [`requestBids()`](/dev-docs/publisher-api-reference/requestBids.html)
+- AdUnit-specific data that applies to all bidders and auctions. Define [AdUnit.ortb2Imp](/dev-docs/adunit-reference.html#first-party-data)
+- Bidder-specific site or user data that applies to all AdUnits and auctions. Use [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html)
## In-Page Examples
@@ -110,6 +111,36 @@ of user data as part of its GDPR or CCPA modules.
{: .alert.alert-warning :}
If you're using PBJS version 4.29 or before, replace the following in the example above: 'ortb' with 'fpd', 'site' with 'context' and 'site.ext.data' with 'context.data'.
+### Supplying Auction-Specific Data
+
+In some situations the same page may wish to supply different `site` data for some of its sections,
+for example in infinite scroll or instream video scenarios where multiple pieces of content that would benefit from different contexts are served together.
+
+To support this use case, Prebid version 7 and above accepts auction-specific first-party data as a parameter to `requestBids`. For example:
+
+{% highlight js %}
+pbjs.requestBids({
+ ortb2: {
+ site: {
+ content: {
+ data: [{
+ name: 'www.iris.com',
+ ext: {
+ segtax: 500,
+ cids: ['iris_c73g5jq96mwso4d8']
+ },
+ segment: [
+ {id: '687'},
+ {id: '123'}
+ ]
+ }]
+ }
+ }
+ }
+});
+{% endhighlight %}
+
+
### Supplying AdUnit-Specific Data
If an attribute is specific to an AdUnit, it can be passed this way:
@@ -293,10 +324,12 @@ segment taxonomies they support.
## How Bid Adapters Should Read First Party Data
-To access global data, a Prebid.js bid adapter needs only to call [`getConfig()`](/dev-docs/publisher-api-reference/getConfig.html), like this:
+Prebid.js bid adapters are supplied global data in the `ortb2` property of [bid requests](/dev-docs/bidder-adaptor.html#building-the-request):
{% highlight js %}
-config.getConfig('ortb2'))
+buildRequests: function(validBidRequests, bidderRequest) {
+ const firstPartyData = bidderRequest.ortb2;
+}
{% endhighlight %}
AdUnit-specific values must be parsed out of the AdUnit object.