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.