diff --git a/_data/sidebar.yml b/_data/sidebar.yml index f067a78785..d7e99973c8 100644 --- a/_data/sidebar.yml +++ b/_data/sidebar.yml @@ -596,6 +596,14 @@ sectionTitle: subgroup: 8 +- sbSecId: 1 + title: First Party Data + link: /features/firstPartyData.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + #--------------Prebid Mobile--------------| @@ -1770,6 +1778,14 @@ sectionTitle: subgroup: 3 +- sbSecId: 5 + title: First Party Data + link: /prebid-server/features/pbs-fpd.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + - sbSecId: 5 title: Developers link: diff --git a/assets/images/flowcharts/FirstPartyData-Detailed.png b/assets/images/flowcharts/FirstPartyData-Detailed.png new file mode 100644 index 0000000000..1e4125ffb8 Binary files /dev/null and b/assets/images/flowcharts/FirstPartyData-Detailed.png differ diff --git a/assets/images/flowcharts/FirstPartyData-Summary.png b/assets/images/flowcharts/FirstPartyData-Summary.png new file mode 100644 index 0000000000..cd9ac8cd84 Binary files /dev/null and b/assets/images/flowcharts/FirstPartyData-Summary.png differ diff --git a/dev-docs/publisher-api-reference.md b/dev-docs/publisher-api-reference.md index aebe9b1ff5..3245cc5547 100644 --- a/dev-docs/publisher-api-reference.md +++ b/dev-docs/publisher-api-reference.md @@ -2278,14 +2278,13 @@ pbjs.setConfig({coppa: true}); #### First Party Data -A number of adapters support taking key/value pairs as arguments, but they're all different. For example: +Historically, a number of adapters supported taking key/value pairs as arguments, but they were all different. For example: -- RubiconProject takes `keywords`, `inventory` and `visitor` parameters -- AppNexus takes `keywords` and `user` -- OpenX takes `customParams` +- RubiconProject took `keywords`, `inventory` and `visitor` parameters +- AppNexus took `keywords` and `user` +- OpenX took `customParams` -This feature allows publishers a way to specify key/value data in one place where each compatible bid adapter -can read it. +First party data allows publishers to specify key/value data in one place where each compatible bid adapter can read it. {: .alert.alert-warning :} Not all bid adapters currently support reading first party data in this way, but support should increase over time. @@ -2352,6 +2351,8 @@ pbjs.setBidderConfig({ +See [Prebid Server First Party Data](/prebid-server/features/pbs-fpd.html) for details about passing data server-side. + #### Client-side Caching of VAST XML When serving video ads, VAST XML creatives must be cached on the network so the diff --git a/features/firstPartyData.md b/features/firstPartyData.md new file mode 100644 index 0000000000..c1786fbfa2 --- /dev/null +++ b/features/firstPartyData.md @@ -0,0 +1,160 @@ +--- +layout: page_v2 +title: Prebid.js First Party Data +description: First Party Data - Prebid.js +sidebarType: 1 +--- + +# First Party Data - Prebid.js +{: .no_toc} + +* TOC +{:toc} + +Prebid allows publishers to supply attributes related to their content +and users, and to apply permissions so only certain bidders are allowed +to access those attributes. + +{: .alert.alert-warning :} +These conventions aren't implemented by all adapters. Please +check with each of your bidders to make sure they're reading first +party data from the standard Prebid locations. + +## How It Works + +Here's a summary of how first party data (FPD) works: + +![First Party Data Summary](/assets/images/flowcharts/FirstPartyData-Summary.png){: .pb-lg-img :} + +This diagram shows a page that can provide: + +- Global context (site) data that applies to all AdUnits and all bidders +- Global user data that applies to all AdUnits and all bidders +- AdUnit-specific data that applies to all bidders +- Bidder-specific context data that applies to all AdUnits +- Bidder-specific user data that applies to all AdUnits + +## In-Page Examples + +The Prebid First Party Data JSON structure reflects the OpenRTB standard. +Arbitrary values should go in fpd.context.data or fpd.user.data. Fields +that are meant to be standard [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) values should be in fpd.context or fpd.user. Specfically, the standard values for `site` are: name, domain, cat, sectioncat, pagecat, page, ref, search, keywords. For `user` these are: yob, gender, keywords. + +{: .alert.alert-info :} +'Context' corresponds to the OpenRTB 'site' object. + +### Supplying Global Data + +Here's how a publisher can let all bid adapters have access +to first party data that might be useful in ad targeting: +{% highlight js %} +pbjs.setConfig({ + fpd: { + context: { + keywords: "power tools", // keywords is a standard OpenRTB field + search: "drill", // same with search and content + content: { userrating: 4 }, + data: { + pageType: "article", + category: "tools" + } + }, + user: { + keywords: "a,b", // keywords is a standard OpenRTB field + data: { + registered: true, + interests: ["cars"] + } + } + } +}); +{% endhighlight %} + +{: .alert.alert-warning :} +Note that supplying first party **user** data may require special +consent in certain regions. Prebid does **not** police the passing +of user data as part of its GDPR or CCPA modules. + +### Supplying AdUnit-Specific Data + +If an attribute is specific to an AdUnit, it can be passed this way: + +{% highlight js %} +pbjs.addAdUnits({ + code: "test-div", + mediaTypes: { + banner: { + sizes: [[300,250]] + } + }, + fpd: { + context: { + pbAdSlot: "homepage-top-rect", + adUnitSpecificContextAttribute: "123" + } + }, + ... +}); +{% endhighlight %} + +{: .alert.alert-info :} +Prebid does not support AdUnit-Specific **user** data. + +### Supplying Bidder-Specific Data + +Use the [`setBidderConfig()`](/dev-docs/publisher-api-reference.html#module_pbjs.setBidderConfig) function to supply bidder-specific data. In this example, only bidderA and bidderB will get access to the supplied +global data. + +{% highlight js %} +pbjs.setBidderConfig({ + bidders: ['bidderA', 'bidderB'], + config: { + fpd: { + context: { + data: { + pageType: "article", + category: "tools" + } + }, + user: { + data: { + registered: true, + interests: ["cars"] + } + } + } + } +}); + +pbjs.setBidderConfig({ // different bidders can receive different data + bidders: ['bidderC'], + config: { + fpd: { ... } + } +}); +{% endhighlight %} + +{: .alert.alert-info :} +Applying permissions to AdUnit-specific First Party Data has +to be done manually by using an event handler -- [pbjs.onEvent('beforeRequestBids', function())](/dev-docs/publisher-api-reference.html#module_pbjs.onEvent) + +## 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.html#module_pbjs.getConfig), like this: + +{% highlight js %} +config.getConfig('fpd.context')) +config.getConfig('fpd.user')) +{% endhighlight %} + +AdUnit-specific values must be parsed out of the AdUnit object. + +The assumption is that bid adapters will copy the values to the appropriate protocol location for their endpoint. + +See [Prebid Server First Party Data](/prebid-server/features/pbs-fpd.html) for a discussion of this feature for Prebid Server bid adapters. + +## Further Reading + +- The [Prebid.js Publisher API](/dev-docs/publisher-api-reference.html) +- The [AdUnit Reference](/dev-docs/adunit-reference.html) +- [Prebid Server First Party Data support](/prebid-server/features/pbs-fpd.html) diff --git a/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md b/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md index 493c7b37aa..6dd89dfe28 100644 --- a/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md +++ b/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.md @@ -27,7 +27,7 @@ For a more general reference, see the [Prebid AMP Implementation Guide | 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 | +| targeting | optional | `String` | First Party Data (PBS-Java only) | | gdpr_consent | optional | `String` | Consent string passed from CMP. Note this is used for both GDPR and CCPA. | | 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. | @@ -80,6 +80,84 @@ An example Stored Request is given below: } ``` +#### First Party Data + +(Currently only supported in PBS-Java) + +You can send first party data into an AMP request by encoding a JSON +targeting block like this: + +``` +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... +``` + +Prebid Server will expand the targeting value and merge the data into +the resulting OpenRTB JSON for the appropriate bidders. + +For example, if this AMP targeting is provided: +``` +{ + "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 numbered elements from the raw targeting data above are merged into the resulting OpenRTB like this: +``` +{ + "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": [ + ... + "ext": { + "context": { + "data": { + "keywords": "las vegas hospitality employees", // (6) + "foo": { // (7) + "bar": "baz" + } + } + } + } + ] +} +``` + ### Response A sample response payload looks like this: @@ -198,3 +276,4 @@ Specifically: ## 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) diff --git a/prebid-server/features/pbs-feature-idx.md b/prebid-server/features/pbs-feature-idx.md index 6ba375ee3e..18683d93b4 100644 --- a/prebid-server/features/pbs-feature-idx.md +++ b/prebid-server/features/pbs-feature-idx.md @@ -35,8 +35,8 @@ title: Prebid Server | Features | [Stored Requests](/prebid-server/features/pbs-storedreqs.html) | Core | Accepts a stored request ID in the OpenRTB, looks it up against a local data store, and merges with the OpenRTB request record. | | | | Stored Responses | Stored Responses | Accepts a stored response ID in the OpenRTB, looks it up against a local data store, and merges with the OpenRTB response record. | | | | First Party Data | Core | Accepts core first party data attributes and supports ext.prebid.data.bidders. | | | -| First Party Data | Bidder-specific data | Accepts bidder-specific first party data attributes. | | | -| First Party Data | AMP first party data | Accepts first party data attributes on an AMP request. | | | +| First Party Data | Bidder-specific data | Accepts bidder-specific first party data attributes. | | | +| First Party Data | AMP first party data | Accepts first party data attributes on an AMP request. | | | | [Supply Chain](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#supply-chain-support) | Bidder-specific schains | Accepts bidder-specific schain | | | | Publisher Accounts | Core | Ability to enforce that requests coming in have a valid account ID. | | | | Publisher Accounts | AMP account parameter | Accept the account parameter on the AMP request. | | | diff --git a/prebid-server/features/pbs-fpd.md b/prebid-server/features/pbs-fpd.md new file mode 100644 index 0000000000..a488c46dac --- /dev/null +++ b/prebid-server/features/pbs-fpd.md @@ -0,0 +1,130 @@ +--- +layout: page_v2 +sidebarType: 5 +title: First Party Data - Prebid Server +--- + +# First Party Data - Prebid Server +{: .no_toc} + +* TOC +{:toc} + +Prebid allows publishers to supply attributes related to their content +and users, and to apply permissions so only certain bidders are allowed +to access those attributes. + +{: .alert.alert-warning :} +For now, this feature is only supported in PBS-Java and these conventions aren't implemented by all adapters. Please +check with each of your bidders to make sure they're reading first +party data from the standard Prebid locations. + +## How It Works + +Each of the three main sources of Prebid Server traffic will place +First Party Data in the OpenRTB JSON in several places: + +{: .table .table-bordered .table-striped } +| OpenRTB Attribute | Description | PBJS Source | SDK Source | AMP Source | +| --- | --- | --- | --- | --- | +| site.ATTR | Only standard OpenRTB attributes should be here: name, domain, cat, sectioncat, pagecat, page, ref, search, keywords. | config.fpd.context.ATTR | n/a | site.ATTR | +| site.ext.data.ATTR | Any other site-related attributes should go here. | config.fpd.context.data | n/a | site.ext.data.ATTR | +| app.ext.data.ATTR | Any app-related attributes should go here. | n/a | Targeting addContextData() | n/a | +| user.ATTR | Only standard OpenRTB attributes should be here: yob, gender, keywords. | config.fpd.user.ATTR | n/a | user.ATTR | +| user.ext.data.ATTR | Any other user-related attributes should go here. | config.fpd.user.data.ATTR | Targeting addUserData() | user.ext.data.ATTR | +| imp[].ext.context.data.ATTR | AdUnit-specific attributes should go here. | AdUnit.fpd.context | AdUnit addContextData() | n/a | +| ext.prebid.data.bidders[] | If specified, only these bidders are allowed to see fields in {site/app/user}.ext.data. | n/a | addBidderToAccessControlList() | bidders | +| ext.prebid.bidderconfig | Bidder-specific config | [setBidderConfig()](/dev-docs/publisher-api-reference.html#module_pbjs.setBidderConfig) | n/a | n/a | + +This diagram summarizes how first party data flows into the OpenRTB JSON: + +![First Party Data Summary](/assets/images/flowcharts/FirstPartyData-Detailed.png){: .pb-lg-img :} + +{: .alert.alert-info :} +Note that Prebid.js supports the [`setBidderConfig`](/dev-docs/publisher-api-reference.html#module_pbjs.setBidderConfig) method of defining +bidder-specific first party data, while SDK and AMP only support the `ext.prebid.data.bidders[]` approach. + +## OpenRTB Examples + +In this example, only BidderA has access to the global first party data: +``` +{ + ext: { + prebid: { + data: { bidders: [ "bidderA" ] } // limit bidders that receive global data + } + }, + site: { + keywords: "", + search: "", + ext: { + data: { + // only seen by bidderA as named in ext.prebid.data.bidders[] + GLOBAL CONTEXT DATA + } + } + }, + user: { + keywords: "", + gender: "", + yob: 1999, + geo: {}, + ext: { + data: { + // only seen by bidderA as named in ext.prebid.data.bidders[] + GLOBAL USER DATA + } + } + }, + imp: [ + ... + ext: { + context: { + keywords: "", + search: "", + data: { + // everyone sees this data + ADUNIT SPECIFIC CONTEXT DATA + } + } + } + ] +} +``` + +This example shows an array of bidder-specific config: +``` +{ + ext: { + prebid: { + bidderconfig: [ { + bidders: [ 'bidderA', 'bidderB' ], + config: { + fpd: { site: { ... }, user: { ...} } + } + },{ + bidders: [ 'bidderC' ], + config: { + fpd: { site: { ... }, user: { ...} } + } + }] + } + } +} +``` + +## How Server-Side Bid Adapters Read First Party Data + +Bid adapters don't need to worry about whether the request came from +Prebid.js, the SDK, or AMP -- everything is merged into the OpenRTB JSON. If a bid adapter receives first party data on any of the fields noted in +the table above, they can simply pass that data to their endpoint in +the expected way. + +In other words, just be aware of site.ext.data.ATTR, app.ext.data.ATTR, user.ext.data.ATTR, +and imp[].ext.context.data.ATTR and either pass them straight through or map +attributes to where your endpoints expect them. + +## Further Reading + +- [Prebid.js First Party Data](/features/firstPartyData.html) +- [Prebid Server and AMP](/prebid-server/use-cases/pbs-amp.html) diff --git a/prebid-server/use-cases/pbs-amp.md b/prebid-server/use-cases/pbs-amp.md index 98ae98d184..cfa2db3d5d 100644 --- a/prebid-server/use-cases/pbs-amp.md +++ b/prebid-server/use-cases/pbs-amp.md @@ -6,6 +6,10 @@ title: Prebid Server | Use Cases | AMP --- # Use Case: Prebid Server | AMP +{: .no_toc} + +* TOC +{:toc} [Accelerated Mobile Pages (AMP)](https://ampproject.org/) is an alternate web technology that can speed page performance, but as part of the tradeoff, header bidding wrappers like Prebid.js don't work well. Instead, AMP supports a method of header bidding called Real Time Configuration(RTC), which is implemented by Prebid Server. @@ -43,11 +47,12 @@ 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": {"tags": "autoestima","url": "/amp/familia/materias/33559-princesa-africana-da-disney-lembra-por-que-toda-crianca-precisa-se-sentir-representada"}}}' > + 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"}}' > ``` -**Note:** the `prebidrubicon` and `prebidappnexus` AMP vendors define different parameters. AppNexus uses "PLACEMENT_ID" as the argument to rtc-config while Rubicon uses "REQUEST_ID". +{: .alert.alert-info :} +**Note:** the `prebidrubicon` and `prebidappnexus` AMP vendor strings define slightly different parameters; AppNexus uses "PLACEMENT_ID" as the argument to rtc-config while Rubicon uses "REQUEST_ID". They both translate to `tag_id` when passed to Prebid Server. - The other option is to construct a direct URL from component pieces: w, h, slot, targeting, gdpr_consent, account, page url (purl), etc. @@ -60,6 +65,9 @@ There are two basic ways of invoking AMP RTC: ``` +{: .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. @@ -158,6 +166,11 @@ So for the /openrtb2/amp URL above, the resulting OpenRTB might be: Note that most of the above OpenRTB was prepared offline and stored in the Prebid Server database indexed by the `tag_id`. Only a few dynamic parameters on the query string are integrated into the results from the database. +#### First Party Data Support + +Any targeting data passed in through the [`/openrtb2/amp`](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) endpoint is merged +into the OpenRTB JSON and permissions, if defined, are applied to each bidder. + #### Auction and Response From here, the header bidding auction is mostly the same as it is for Prebid.js: diff --git a/prebid-server/use-cases/pbs-lfv.md b/prebid-server/use-cases/pbs-lfv.md index 164dd35ed8..f61c5e085e 100644 --- a/prebid-server/use-cases/pbs-lfv.md +++ b/prebid-server/use-cases/pbs-lfv.md @@ -6,6 +6,10 @@ title: Prebid Server | Use Cases | Long Form Video --- # Use Case: Prebid Server | Long Form Video +{: .no_toc} + +* TOC +{:toc} Prebid Server (PBS) supports filling _pods_ of multiple video advertisements, including support for competitve separation. diff --git a/prebid-server/use-cases/pbs-pbjs.md b/prebid-server/use-cases/pbs-pbjs.md index da9b6a888c..414d745f3c 100644 --- a/prebid-server/use-cases/pbs-pbjs.md +++ b/prebid-server/use-cases/pbs-pbjs.md @@ -6,6 +6,10 @@ title: Prebid Server | Use Cases | Prebid.js --- # Use Case: Prebid Server | Prebid.js +{: .no_toc} + +* TOC +{:toc} When publishers specify bidders in [Prebid.js `s2sConfig`](/dev-docs/publisher-api-reference.html#setConfig-Server-to-Server), the browser connects to Prebid Server to coordinate the header bidding auction for those bidders. diff --git a/prebid-server/use-cases/pbs-sdk.md b/prebid-server/use-cases/pbs-sdk.md index 37daa28bdb..f1500f8b2e 100644 --- a/prebid-server/use-cases/pbs-sdk.md +++ b/prebid-server/use-cases/pbs-sdk.md @@ -6,6 +6,10 @@ title: Prebid Server | Use Cases | Mobile SDK --- # Use Case: Prebid Server | Prebid Mobile SDK +{: .no_toc} + +* TOC +{:toc} Unlike Prebid.js, the [Prebid Mobile SDK](/prebid-mobile/prebid-mobile.html) doesn't make requests to demand sources directly. Instead, it relies entirely on Prebid Server to handle the bidder communication.