From 50c9452a1a60d855427179e881e154c5796635a8 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 19 Apr 2023 11:14:50 -0700 Subject: [PATCH 01/10] Prebid.js: activity controls --- dev-docs/activity-controls.md | 182 ++++++++++++++++++ dev-docs/publisher-api-reference/setConfig.md | 7 + 2 files changed, 189 insertions(+) create mode 100644 dev-docs/activity-controls.md diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md new file mode 100644 index 0000000000..531e8a2662 --- /dev/null +++ b/dev-docs/activity-controls.md @@ -0,0 +1,182 @@ +--- +layout: page_v2 +title: Activity controls +description: How to stop Prebid from doing things you don't want +sidebarType: 1 +--- + +# Activity controls +{: .no_toc } + +Starting with version 7.48, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. +These are intended to serve as building blocks for more privacy protection mechanism, allowing module developers or publishers to directly specify what should be permitted or avoided in any given regulatory environment. + + +* TOC +{: toc } + + +#### Example + +The following disables storage for everything except the bid adapter `bidderX`: + +``` +pbjs.setConfig({ + allowActivities: { + accessDevice: { + default: false, + rules: [{ + condition(params) { + return params.componentName === 'bidderX' + }, + allow: true + }] + }` + } +}) +``` + + + +### Configuration + +```allowActivities``` is a map from activity name ([see full list below](#activities)) to a configuration object that contains: + +{: .table .table-bordered .table-striped } +| Name | Type | Description | +|------|------|-------------| +| `default` | Boolean | Whether the activity should be allowed if no other rule applies. Defaults to true. | +| `rules` | Array of objects | Rules for this activity | +| `rules[].condition` | Function | Condition function to use for this rule; the rule applies only if this returns true. Receives a single object that contains [activity parameters](#parameters) as input. If omitted, the rule always applies. +| `rules[].allow` | Boolean | Whether the activity should be allowed when this rule applies. Defaults to true. | +| `rules[].priority` | Number | Priority of this rule compared to other rules; a lower number means higher priority. See [note on rule priority](#priority) below. Defaults to 1. | + + + +### Activities + +{: .table .table-bordered .table-striped } +| Name | Description | Effect when denied | Additional parameters | +|----------------|-------------|---------------------------|--------------------------------| +| `accessDevice` | A component wants to use device storage | Storage is disabled | [`storageType`](#params-accessDevice) | +| `enrichEids` | A user ID or RTD submodule wants to add user IDs to outgoing requests | User IDs are discarded | None | +| `enrichUfpd` | An RTD submodule wants to add user first party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | +| `fetchBids` | A bid adapter wants to participate in an auction | Bidder is removed from the auction | [`configName`](#params-fetchBids) | +| `reportAnalytics` | An analytics adapter is being enabled through `pbjs.enableAnalytics` | Adapter remains disabled | None | +| `syncUser` | A bid adapter wants to fetch a [user sync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) | User sync is skipped | [`syncType`, `syncUrl`](#params-syncUser) | +| `transmitEids` | A bid adapter or RTD submodule wants to access and/or transmit user IDs to their endpoint | User IDs are hidden from the component | None | +| `transmitPreciseGeo` | A bid adapter or RTD submodule wants to access and/or transmit precise geolocation data to their endpoint | Component is allowed only 2-digit precision for latitude and longitude | None | +| `transmitUfpd` | A bid adapter or RTD submodule wants to access and/or transmit user FPD to their endpoint | User FPD is hidden from the component | None | + + + +### Activity parameters + +`condition` functions receive information about the activity that is about to be performed as _activity parameters_: + +{: .table .table-bordered .table-striped } +| Name | Type | Available for | Description | +|------|------|-------------|---------------| +| `componentType` | String | All activities | One of: `'bidder'`, `'userId'`, `'rtd'`, `'analytics'`, or `'prebid'`; identifies the type of component (usually a module) that wishes to perform the activity. `'prebid'` is reserved for Prebid core itself and a few "privileged" modules such as the [PBS adapter](/dev-docs/modules/prebidServer.html). | +| `componentName` | String | All activities | Name of the component; this is (depending on the type) either a bidder code, user ID or RTD submodule name, analytics provider code, or module name. | +| `component` | String | All activities | This is always a dot-separated concatenation of `componentType` and `componentName`; for example, with `{componentType: 'bidder', componentName: 'bidderX'}`, `component` is `'bidder.bidderX'`. | +| `adapterCode` | String | All activities | If `componentType` is `'bidder'`, and `componentName` is an [alias](/dev-docs/publisher-api-reference/aliasBidder.html), then `adapterCode` is the bidder code that was aliased; or identical to `componentName` if the bidder is not an alias. This is undefined when the component is not a bidder.| +| `configName` | String | `fetchBids` | When the Prebid Server adapter is part of an auction, this is the name given to its [s2s configuration](/dev-docs/modules/prebidServer.md), if any. | +| `storageType` | String | `accessDevice` | Either `'html5'` or `'cookie'` - the device storage mechanism being accessed. | +| `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | +| `syncUrl` | String | `syncUser` | URL of the user sync. | + + + +### How rule priority works + +By default, rules set through the `allowActivities` config have a priority of 1, and every other rule (set by, for example, `filterSettings`, `bidderSettings`, the [GPP](/dev-docs/modules/consentManagementGpp.html) or [GDPR](/dev-docs/modules/gdprEnforcement.html) modules, etc) have a less urgent priority of 10. +This means that when `priority` is omitted, `allowActivities` configuration acts as an override over all other control mechanisms. For example: + +```javascript +pbjs.setConfig({ + deviceAccess: false, // this would have the effect of disabling device storage, but... + allowActivities: { + accessDevice: { + rules: [ + {allow: true} // ... it's overridden by allowActivities with when priority is < 10 (or omitted) + ] + } + } +}) +``` + +If a priority number greater than 10 is specified, the rule only takes effect when all other controls have allowed the activity; for example: + +```javascript +pbjs.setConfig({ + allowActivities: { + accessDevice: { + // disable all storage except localStorage. + // because this is using priority > 10, it still requires all other controls to allow storage; + // deviceAccess should be true; bidders need `storageAllowed` to be set through `bidderSettings`; + // if the GDPR module is enabled, vendor consent needs to have been given, etc + default: false, + rules: [{ + condition({storageType}) { + return storageType === 'html5' + }, + allow: true, + priority: 20 + }] + } + } +}) +``` + +#### More examples + + +Disable all user syncs except for specific domains: + +```javascript +const WHITELIST = [ + 'https://example-domain.org', + 'https://other-domain.com', +]; + +pbjs.setConfig({ + allowActivities: { + syncUser: { + default: false, + rules: [{ + condition({syncUrl}) { + return WHITELIST.find(domain => syncUrl.startsWith(domain)) + }, + allow: true + }] + } + } +}) +``` + +Always include a particular bidder in auctions (vendor exception): + +```javascript +pbjs.setConfig({ + fetchBids: { + rules: [{ + condition: ({componentName}) => componentName === 'firstPartyBidder', + allow: true + }] + } +}) +``` + +Deny a particular vendor access to user IDs: + +```javascript +pbjs.setConfig({ + transmitEids: { + rules: [{ + condition: ({componentName}) => componentName === 'exampleVendor', + allow: false, + }] + } +}) +``` diff --git a/dev-docs/publisher-api-reference/setConfig.md b/dev-docs/publisher-api-reference/setConfig.md index eadf9a5fad..2d8617a83e 100644 --- a/dev-docs/publisher-api-reference/setConfig.md +++ b/dev-docs/publisher-api-reference/setConfig.md @@ -15,6 +15,7 @@ See below for usage examples. Core config: + [Debugging](#setConfig-Debugging) ++ [Allow activities](#setConfig-allow-activities) + [Device Access](#setConfig-deviceAccess) + [Bidder Timeouts](#setConfig-Bidder-Timeouts) + [Max Requests Per Origin](#setConfig-Max-Requests-Per-Origin) @@ -69,6 +70,12 @@ pbjs.setConfig({ debug: true }); {: .alert.alert-warning :} Note that turning on debugging for Prebid Server causes most server-side adapters to consider it a test request, meaning that they won't count on reports. + + +#### Allow activities + +Starting since Prebid 7.48, you can prevent Prebid, or individual modules, from performing certain activities through `allowActivities` configuration, which provides fine-grained control over a number privacy-related items, including access to device storage, first party data, or user IDs. For more information, see [activity controls](/dev-docs/activity-controls.html). + #### Device Access From ab74bdefa14804076a75db1d368db41a250f153a Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 26 Apr 2023 16:32:07 -0400 Subject: [PATCH 02/10] initial pass at wordsmithing added background and transitions. The example rules need some work IMO. Will tackle that later this week. --- dev-docs/activity-controls.md | 73 ++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 531e8a2662..fb5abd4fc1 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -9,16 +9,55 @@ sidebarType: 1 {: .no_toc } Starting with version 7.48, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. -These are intended to serve as building blocks for more privacy protection mechanism, allowing module developers or publishers to directly specify what should be permitted or avoided in any given regulatory environment. - +These controls are intended to serve as building blocks for privacy protection mechanisms, allowing module developers or publishers to directly specify what should be permitted or avoided in any given regulatory environment. * TOC {: toc } +## Overview + +There are many privacy regulations that Prebid publishers need to accomodate. Prebid supplies [modules](/dev-docs/faq.html#how-does-prebid-support-privacy-regulations) to help Publishers implement their legal policies, but there are scenarios where extra control is needed: + +- a Publisher's lawyers want to make a particular exception +- a module hasn't been built for a regulation the Publisher needs to support + +### Prebid Is a Toolkit + +{: .alert.alert-danger :} +Important: This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and /or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. + +1. Get a privacy lawyer. +2. Consider all the privacy regulations your content business is subject to. +3. Come up with a plan. +4. Use Prebid.js modules and these Activity Controls as ways to help implement your privacy plan with respect to header bidding. +5. Let us know if there are tools missing from the Prebid toolkit. + +### Model + +We did an analysis of the kinds of things Prebid does and identified those that might be of concern to privacy regulations. We call these things "potentially restricted activities", or just "activities" for short. Here are some activities: + +- Setting a cookie +- Syncing ID cookies +- Transmitting user first party data +- etc. + +The [full list of activities Prebid supports](#activities) is below. -#### Example +Think of an activity as a 'gatekeeper' that make an important decision: -The following disables storage for everything except the bid adapter `bidderX`: +- Should I allow this cookie to be set? +- Should I allow this usersync? +- Is it ok for this data to be passed to bidders? +- etc. + +This 'gatekeeper' in Prebid.js core checks with the Activity Controls to see whether that activity is allowed. The configuration for the activity can come from regulation modules, custom functions in the page, or a rule-based JSON config. + +### Example + +{: .alert.alert-info :} +Hey, Activity System! I'm the gatekeeper for device storage... bidderX wants to set a cookie, is that allowed? + +Here's an example JSON config that disables accessing local storage (including cookies) for everything except the bid adapter `bidderX`: ``` pbjs.setConfig({ @@ -38,9 +77,9 @@ pbjs.setConfig({ -### Configuration +## Configuration -```allowActivities``` is a map from activity name ([see full list below](#activities)) to a configuration object that contains: +`allowActivities` is a new option to [setConfig](/dev-docs/publisher-api-reference/setConfig.html). It contains a list of activity names -- see the [full list of activities below](#activities). Each activity is an object that can contain these attributes: {: .table .table-bordered .table-striped } | Name | Type | Description | @@ -51,16 +90,27 @@ pbjs.setConfig({ | `rules[].allow` | Boolean | Whether the activity should be allowed when this rule applies. Defaults to true. | | `rules[].priority` | Number | Priority of this rule compared to other rules; a lower number means higher priority. See [note on rule priority](#priority) below. Defaults to 1. | +`Rules` is an array of objects that a publisher can contruct to provide fine-grained control over a given activity. For instance, you could set up a series of rules that says: + +- Amongst the bid adapters, BidderA is always allowed to receive user first party data +- Always let analytics adapters receive user first party data +- otherwise, let the active privacy modules decide +- if they refuse to decide, then the overall default is to allow the transmitting of user first party data + +There's more about [rules](#parameters) below. + ### Activities +Here's the list of 'potentially restricted activities' that Prebid.js core can enforce for Publishers. + {: .table .table-bordered .table-striped } | Name | Description | Effect when denied | Additional parameters | |----------------|-------------|---------------------------|--------------------------------| | `accessDevice` | A component wants to use device storage | Storage is disabled | [`storageType`](#params-accessDevice) | | `enrichEids` | A user ID or RTD submodule wants to add user IDs to outgoing requests | User IDs are discarded | None | -| `enrichUfpd` | An RTD submodule wants to add user first party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | +| `enrichUfpd` | A RTD submodule wants to add user first party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | | `fetchBids` | A bid adapter wants to participate in an auction | Bidder is removed from the auction | [`configName`](#params-fetchBids) | | `reportAnalytics` | An analytics adapter is being enabled through `pbjs.enableAnalytics` | Adapter remains disabled | None | | `syncUser` | A bid adapter wants to fetch a [user sync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) | User sync is skipped | [`syncType`, `syncUrl`](#params-syncUser) | @@ -70,9 +120,14 @@ pbjs.setConfig({ -### Activity parameters +### Rule Parameters + + There are three parts to a rule: + 1. The condition + 2. The allow status + 3. The priority -`condition` functions receive information about the activity that is about to be performed as _activity parameters_: +A `condition` is a function that receives information about the activity that is about to be performed as _activity parameters_: {: .table .table-bordered .table-striped } | Name | Type | Available for | Description | From d1d6748f9b028d2cfd35c6a1da1bc4a218fb49d0 Mon Sep 17 00:00:00 2001 From: bretg Date: Wed, 26 Apr 2023 17:04:05 -0400 Subject: [PATCH 03/10] language. --- dev-docs/activity-controls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index fb5abd4fc1..998062650f 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -110,7 +110,7 @@ Here's the list of 'potentially restricted activities' that Prebid.js core can e |----------------|-------------|---------------------------|--------------------------------| | `accessDevice` | A component wants to use device storage | Storage is disabled | [`storageType`](#params-accessDevice) | | `enrichEids` | A user ID or RTD submodule wants to add user IDs to outgoing requests | User IDs are discarded | None | -| `enrichUfpd` | A RTD submodule wants to add user first party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | +| `enrichUfpd` | A Real Time Data (RTD) submodule wants to add user first party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | | `fetchBids` | A bid adapter wants to participate in an auction | Bidder is removed from the auction | [`configName`](#params-fetchBids) | | `reportAnalytics` | An analytics adapter is being enabled through `pbjs.enableAnalytics` | Adapter remains disabled | None | | `syncUser` | A bid adapter wants to fetch a [user sync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) | User sync is skipped | [`syncType`, `syncUrl`](#params-syncUser) | From ecb8c227de21fe08202ecd5b62757a723c2a8676 Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 1 May 2023 10:39:14 -0400 Subject: [PATCH 04/10] next round - added more on rules processing - annotated examples - added Further Reading --- dev-docs/activity-controls.md | 130 +++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 48 deletions(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 998062650f..a9d95dc6d9 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -1,11 +1,11 @@ --- layout: page_v2 -title: Activity controls +title: Activity Controls description: How to stop Prebid from doing things you don't want sidebarType: 1 --- -# Activity controls +# Activity Controls {: .no_toc } Starting with version 7.48, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. @@ -32,7 +32,7 @@ Important: This resource should not be construed as legal advice and Prebid.org 4. Use Prebid.js modules and these Activity Controls as ways to help implement your privacy plan with respect to header bidding. 5. Let us know if there are tools missing from the Prebid toolkit. -### Model +### Activity Model We did an analysis of the kinds of things Prebid does and identified those that might be of concern to privacy regulations. We call these things "potentially restricted activities", or just "activities" for short. Here are some activities: @@ -52,10 +52,10 @@ Think of an activity as a 'gatekeeper' that make an important decision: This 'gatekeeper' in Prebid.js core checks with the Activity Controls to see whether that activity is allowed. The configuration for the activity can come from regulation modules, custom functions in the page, or a rule-based JSON config. -### Example +### Example Activity Control {: .alert.alert-info :} -Hey, Activity System! I'm the gatekeeper for device storage... bidderX wants to set a cookie, is that allowed? +In this example, bidderX wants to set a cookie through StorageManager, which queries the Activity Control System to determine whether that's allowed. The publisher has set up configuration that specifically enables bidderX to do this. Here's an example JSON config that disables accessing local storage (including cookies) for everything except the bid adapter `bidderX`: @@ -103,7 +103,7 @@ There's more about [rules](#parameters) below. ### Activities -Here's the list of 'potentially restricted activities' that Prebid.js core can enforce for Publishers. +Here's the list of the 'potentially restricted activities' that Prebid.js core can restrict for Publishers. {: .table .table-bordered .table-striped } | Name | Description | Effect when denied | Additional parameters | @@ -123,30 +123,45 @@ Here's the list of 'potentially restricted activities' that Prebid.js core can e ### Rule Parameters There are three parts to a rule: - 1. The condition - 2. The allow status - 3. The priority - -A `condition` is a function that receives information about the activity that is about to be performed as _activity parameters_: + 1. The priority + 2. The condition + 3. The allow status -{: .table .table-bordered .table-striped } -| Name | Type | Available for | Description | -|------|------|-------------|---------------| -| `componentType` | String | All activities | One of: `'bidder'`, `'userId'`, `'rtd'`, `'analytics'`, or `'prebid'`; identifies the type of component (usually a module) that wishes to perform the activity. `'prebid'` is reserved for Prebid core itself and a few "privileged" modules such as the [PBS adapter](/dev-docs/modules/prebidServer.html). | -| `componentName` | String | All activities | Name of the component; this is (depending on the type) either a bidder code, user ID or RTD submodule name, analytics provider code, or module name. | -| `component` | String | All activities | This is always a dot-separated concatenation of `componentType` and `componentName`; for example, with `{componentType: 'bidder', componentName: 'bidderX'}`, `component` is `'bidder.bidderX'`. | -| `adapterCode` | String | All activities | If `componentType` is `'bidder'`, and `componentName` is an [alias](/dev-docs/publisher-api-reference/aliasBidder.html), then `adapterCode` is the bidder code that was aliased; or identical to `componentName` if the bidder is not an alias. This is undefined when the component is not a bidder.| -| `configName` | String | `fetchBids` | When the Prebid Server adapter is part of an auction, this is the name given to its [s2s configuration](/dev-docs/modules/prebidServer.md), if any. | -| `storageType` | String | `accessDevice` | Either `'html5'` or `'cookie'` - the device storage mechanism being accessed. | -| `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | -| `syncUrl` | String | `syncUser` | URL of the user sync. | + + For example: + ``` + rules: [{ + condition(params) { + return params.componentName === 'bidderX' + }, + allow: true, + priority: 10 // the default + }] +``` -### How rule priority works +#### Priority + +Activity control rules in Prebid.js can be injected by two main sources: + +- Publisher `setConfig({allowActivities})` as in the examples shown here. When set this way, rules are consider the highest priority value of 1. +- Modules can set activity control rules, e.g. [usersync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing), [bidderSettings](/dev-docs/publisher-api-reference/bidderSettings.html), the [GPP](/dev-docs/modules/consentManagementGpp.html) or [GDPR](/dev-docs/modules/gdprEnforcement.html) modules. Rules set by modules have a less urgent priority of 10. + +When rules are processed, they are sorted by priority, and all rules of the same priority are considered to happen at the same time. + +1. The highest priority is 1 +2. There's no defined lowest priority other than MAXINT +3. The module default priority is 10 +4. When processing, group the rules by priority +5. In descending order of priority: + 1. If any rule that matches the condition has allow: false, the activity is DENIED. + 2. Otherwise, if at least one rule that matches the condition has allow: true, the activity is ALLOWED. + 3. If any rule matched, break out of the priority loop. +6. If none of rules match, and the activity has default: false, the activity is DENIED. +7. Otherwise, the activity is ALLOWED. -By default, rules set through the `allowActivities` config have a priority of 1, and every other rule (set by, for example, `filterSettings`, `bidderSettings`, the [GPP](/dev-docs/modules/consentManagementGpp.html) or [GDPR](/dev-docs/modules/gdprEnforcement.html) modules, etc) have a less urgent priority of 10. -This means that when `priority` is omitted, `allowActivities` configuration acts as an override over all other control mechanisms. For example: +So this means that when `priority` is omitted from `allowActivities` configuration, it acts as an override over all other control mechanisms. For example: ```javascript pbjs.setConfig({ @@ -154,7 +169,7 @@ pbjs.setConfig({ allowActivities: { accessDevice: { rules: [ - {allow: true} // ... it's overridden by allowActivities with when priority is < 10 (or omitted) + {allow: true} // ... it's overridden by this conditionless rule with default priority of 1 ] } } @@ -167,10 +182,9 @@ If a priority number greater than 10 is specified, the rule only takes effect wh pbjs.setConfig({ allowActivities: { accessDevice: { - // disable all storage except localStorage. - // because this is using priority > 10, it still requires all other controls to allow storage; - // deviceAccess should be true; bidders need `storageAllowed` to be set through `bidderSettings`; - // if the GDPR module is enabled, vendor consent needs to have been given, etc + // the intent here is to disable cookies but allow HTML5 localStorage + // because this defines priority > 10, other controls will be checked first + // e.g. if GDPR is in-scope and there's no consent, this priority 20 rule won't be processed default: false, rules: [{ condition({storageType}) { @@ -184,13 +198,43 @@ pbjs.setConfig({ }) ``` -#### More examples +#### Conditions + +A `condition` is a function that receives information about the activity that is about to be performed as _activity parameters_. If a condition is specified, it will be evaluated and if true, the `allow` attribute of the rule will be utilized. + +{: .table .table-bordered .table-striped } +| Name | Type | Available for | Description | +|------|------|-------------|---------------| +| `componentType` | String | All activities | One of: `'bidder'`, `'userId'`, `'rtd'`, `'analytics'`, or `'prebid'`; identifies the type of component (usually a module) that wishes to perform the activity. `'prebid'` is reserved for Prebid core itself and a few "privileged" modules such as the [PBS adapter](/dev-docs/modules/prebidServer.html). | +| `componentName` | String | All activities | Name of the component; this is (depending on the type) either a bidder code, user ID or RTD submodule name, analytics provider code, or module name. | +| `component` | String | All activities | This is always a dot-separated concatenation of `componentType` and `componentName`; for example, with `{componentType: 'bidder', componentName: 'bidderX'}`, `component` is `'bidder.bidderX'`. | +| `adapterCode` | String | All activities | If `componentType` is `'bidder'`, and `componentName` is an [alias](/dev-docs/publisher-api-reference/aliasBidder.html), then `adapterCode` is the bidder code that was aliased; or identical to `componentName` if the bidder is not an alias. This is undefined when the component is not a bidder.| +| `configName` | String | `fetchBids` | When the Prebid Server adapter is part of an auction, this is the name given to its [s2s configuration](/dev-docs/modules/prebidServer.md), if any. | +| `storageType` | String | `accessDevice` | Either `'html5'` or `'cookie'` - the device storage mechanism being accessed. | +| `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | +| `syncUrl` | String | `syncUser` | URL of the user sync. | + +### More examples + +#### Always include a particular bidder in auctions +This is similiar to the 'vendor exception' feature of the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html). This would always allow bidderA to participate in the auction, even without explicit consent in GDPR scenarios. It might indicate, for instance, that this is a 'first party bidder'. + +```javascript +pbjs.setConfig({ + fetchBids: { + rules: [{ + condition: ({componentName}) => componentName === 'bidderA', + allow: true + }] + } +}) +``` -Disable all user syncs except for specific domains: +#### Disable all user syncs except for specific domains ```javascript -const WHITELIST = [ +const DOMAINLIST = [ 'https://example-domain.org', 'https://other-domain.com', ]; @@ -201,7 +245,7 @@ pbjs.setConfig({ default: false, rules: [{ condition({syncUrl}) { - return WHITELIST.find(domain => syncUrl.startsWith(domain)) + return DOMAINLIST.find(domain => syncUrl.startsWith(domain)) }, allow: true }] @@ -210,20 +254,7 @@ pbjs.setConfig({ }) ``` -Always include a particular bidder in auctions (vendor exception): - -```javascript -pbjs.setConfig({ - fetchBids: { - rules: [{ - condition: ({componentName}) => componentName === 'firstPartyBidder', - allow: true - }] - } -}) -``` - -Deny a particular vendor access to user IDs: +#### Deny a particular vendor access to user IDs ```javascript pbjs.setConfig({ @@ -235,3 +266,6 @@ pbjs.setConfig({ } }) ``` + +## Further Reading +- [FAQ: How does Prebid.js support privacy regulations](/dev-docs/faq.html#how-does-prebid-support-privacy-regulations) From 1b5d48d28847c7113b623c50773ba7e2b9be5bc8 Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 1 May 2023 10:44:23 -0400 Subject: [PATCH 05/10] adding reference to FAQ --- dev-docs/faq.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-docs/faq.md b/dev-docs/faq.md index a51d9eb800..9d69c2eb44 100644 --- a/dev-docs/faq.md +++ b/dev-docs/faq.md @@ -31,6 +31,7 @@ To get started, first talk to your lawyers to determine your legal obligations. After you’ve determined your legal obligations, consider the tools Prebid makes available to publishers so that their pages can determine what actions are needed based on their interpretation of the user’s actions and the company’s policies: +- Consider utilizing an [Activity Control](/dev-docs/activity-controls.html). These are available with Prebid.js 7.48 and may help cover a number of common privacy concerns. - Turn off Prebid.js usersync: - [for client-side adapters](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) - either completely or for certain bidders. - [for server-side adapters](/dev-docs/modules/prebidServer.html) - override the s2sConfig.syncEndpoint From 78aecc76488ebd5ac00060759cb04fb6f95adcae Mon Sep 17 00:00:00 2001 From: bretg Date: Mon, 1 May 2023 11:25:30 -0400 Subject: [PATCH 06/10] added rule allow status section ready for broader review --- dev-docs/activity-controls.md | 60 +++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index a9d95dc6d9..79f977aa35 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -43,14 +43,14 @@ We did an analysis of the kinds of things Prebid does and identified those that The [full list of activities Prebid supports](#activities) is below. -Think of an activity as a 'gatekeeper' that make an important decision: +Think of an activity control as a 'gatekeeper' that makes the decision about whether the activity should be allowed in this specific context: -- Should I allow this cookie to be set? -- Should I allow this usersync? -- Is it ok for this data to be passed to bidders? +- Should I allow this cookie to be set for bidderA? +- Should I allow this usersync for bidderB? +- Is it ok for this data to be passed to bidderC and analyticsD? - etc. -This 'gatekeeper' in Prebid.js core checks with the Activity Controls to see whether that activity is allowed. The configuration for the activity can come from regulation modules, custom functions in the page, or a rule-based JSON config. +Prebid.js core checks with the Activity Controls to see whether an activity is allowed. The configuration for the activity can come from modules, custom functions in the page, or a rule-based JSON config. ### Example Activity Control @@ -120,48 +120,50 @@ Here's the list of the 'potentially restricted activities' that Prebid.js core c -### Rule Parameters +### Rules + + There are three parts to an Activity Control's rule: - There are three parts to a rule: 1. The priority 2. The condition 3. The allow status - - For example: + For example, this rule would allow bidderX to perform the activity if no higher priority rules take precedence. ``` + ... rules: [{ + priority: 10, // average priority condition(params) { return params.componentName === 'bidderX' }, - allow: true, - priority: 10 // the default + allow: true }] + ... ``` -#### Priority +#### Rule Priority -Activity control rules in Prebid.js can be injected by two main sources: +Activity control rules in Prebid.js can be created by two main sources: - Publisher `setConfig({allowActivities})` as in the examples shown here. When set this way, rules are consider the highest priority value of 1. - Modules can set activity control rules, e.g. [usersync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing), [bidderSettings](/dev-docs/publisher-api-reference/bidderSettings.html), the [GPP](/dev-docs/modules/consentManagementGpp.html) or [GDPR](/dev-docs/modules/gdprEnforcement.html) modules. Rules set by modules have a less urgent priority of 10. -When rules are processed, they are sorted by priority, and all rules of the same priority are considered to happen at the same time. +When rules are processed, they are sorted by priority, and all rules of the same priority are considered to happen at the same time. The details: -1. The highest priority is 1 +1. The highest rule priority is 1 2. There's no defined lowest priority other than MAXINT -3. The module default priority is 10 +3. Default priority for rules defined with setConfig is 1. Default priority for other rules is 10. 4. When processing, group the rules by priority -5. In descending order of priority: - 1. If any rule that matches the condition has allow: false, the activity is DENIED. - 2. Otherwise, if at least one rule that matches the condition has allow: true, the activity is ALLOWED. +5. Then, in descending order of priority: + 1. If any rule that matching the condition defines `allow: false`, the activity is DENIED. + 2. Otherwise, if at least one rule that matches the condition defines `allow: true`, the activity is ALLOWED. 3. If any rule matched, break out of the priority loop. -6. If none of rules match, and the activity has default: false, the activity is DENIED. +6. If none of rules match, and the activity defines `default: false`, the activity is DENIED. 7. Otherwise, the activity is ALLOWED. -So this means that when `priority` is omitted from `allowActivities` configuration, it acts as an override over all other control mechanisms. For example: +So this means that when `priority` is omitted from `allowActivities` configuration, it acts as an override over other control mechanisms. For example: ```javascript pbjs.setConfig({ @@ -176,7 +178,7 @@ pbjs.setConfig({ }) ``` -If a priority number greater than 10 is specified, the rule only takes effect when all other controls have allowed the activity; for example: +If a priority number greater than 10 is specified, the rule only takes effect when all other controls have allowed the activity. For example: ```javascript pbjs.setConfig({ @@ -198,9 +200,11 @@ pbjs.setConfig({ }) ``` -#### Conditions +#### Rule Conditions -A `condition` is a function that receives information about the activity that is about to be performed as _activity parameters_. If a condition is specified, it will be evaluated and if true, the `allow` attribute of the rule will be utilized. +A `condition` in an Activity Control rule is a function that receives information about the activity that is about to be performed. If a condition evaluates to true, the `allow` attribute of the rule will be utilized. If there's no condition specified, the rule's `allow` attribute will always be utilized. + +These are are the parameters available to the condition function: {: .table .table-bordered .table-striped } | Name | Type | Available for | Description | @@ -214,6 +218,14 @@ A `condition` is a function that receives information about the activity that is | `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | | `syncUrl` | String | `syncUser` | URL of the user sync. | +#### Rule Allow Status + +If the rule's condition matches, this attribute defines whether the rule 'votes' to allow (true) or disallow (false) the activity in question. + +As noted in the priority section, **disallow** (false) takes precedence amongst rules at the same priority level. + +If `allow` is not defined, the rule is assumed to assert **true** (i.e. allow). + ### More examples #### Always include a particular bidder in auctions From 7f6906fc61e9f588ff5392363818719195294b3e Mon Sep 17 00:00:00 2001 From: bretg Date: Thu, 4 May 2023 14:13:40 -0400 Subject: [PATCH 07/10] Update activity-controls.md --- dev-docs/activity-controls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 79f977aa35..1a1b956c9a 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -1,11 +1,11 @@ --- layout: page_v2 title: Activity Controls -description: How to stop Prebid from doing things you don't want +description: How to stop Prebid.js from doing things you don't want sidebarType: 1 --- -# Activity Controls +# Prebid.js Activity Controls {: .no_toc } Starting with version 7.48, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. From 1c8a9c6a87d8e4955668bcc7217b0c8ae6a235a3 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 9 May 2023 16:07:03 -0400 Subject: [PATCH 08/10] wordsmithing updated a few things noticed while working on the PBS version of this doc --- dev-docs/activity-controls.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 1a1b956c9a..079307ac67 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -32,16 +32,16 @@ Important: This resource should not be construed as legal advice and Prebid.org 4. Use Prebid.js modules and these Activity Controls as ways to help implement your privacy plan with respect to header bidding. 5. Let us know if there are tools missing from the Prebid toolkit. -### Activity Model +### What is an Activity? -We did an analysis of the kinds of things Prebid does and identified those that might be of concern to privacy regulations. We call these things "potentially restricted activities", or just "activities" for short. Here are some activities: +We did an analysis of the things Prebid.js does and identified those related to privacy regulations. We call these things "potentially restricted activities", or just "activities" for short. Here are some: - Setting a cookie - Syncing ID cookies - Transmitting user first party data - etc. -The [full list of activities Prebid supports](#activities) is below. +The [full list of activities Prebid.js supports](#activities) is below. Think of an activity control as a 'gatekeeper' that makes the decision about whether the activity should be allowed in this specific context: @@ -86,7 +86,7 @@ pbjs.setConfig({ |------|------|-------------| | `default` | Boolean | Whether the activity should be allowed if no other rule applies. Defaults to true. | | `rules` | Array of objects | Rules for this activity | -| `rules[].condition` | Function | Condition function to use for this rule; the rule applies only if this returns true. Receives a single object that contains [activity parameters](#parameters) as input. If omitted, the rule always applies. +| `rules[].condition` | Function | Condition function to use for this rule; the rule applies only if this returns true. Receives a single object that contains [activity parameters](#parameters) as input. If omitted, the rule always applies. | | `rules[].allow` | Boolean | Whether the activity should be allowed when this rule applies. Defaults to true. | | `rules[].priority` | Number | Priority of this rule compared to other rules; a lower number means higher priority. See [note on rule priority](#priority) below. Defaults to 1. | @@ -103,7 +103,7 @@ There's more about [rules](#parameters) below. ### Activities -Here's the list of the 'potentially restricted activities' that Prebid.js core can restrict for Publishers. +Here's the list of the 'potentially restricted activities' that Prebid.js core can restrict for Publishers: {: .table .table-bordered .table-striped } | Name | Description | Effect when denied | Additional parameters | @@ -126,7 +126,7 @@ Here's the list of the 'potentially restricted activities' that Prebid.js core c 1. The priority 2. The condition - 3. The allow status + 3. The allow flag For example, this rule would allow bidderX to perform the activity if no higher priority rules take precedence. ``` @@ -202,9 +202,9 @@ pbjs.setConfig({ #### Rule Conditions -A `condition` in an Activity Control rule is a function that receives information about the activity that is about to be performed. If a condition evaluates to true, the `allow` attribute of the rule will be utilized. If there's no condition specified, the rule's `allow` attribute will always be utilized. +A `condition` is a javascript function that receives information about the activity that is about to be performed. If a condition evaluates to true, the `allow` attribute of the rule will be utilized. If there's no condition specified, the rule's `allow` attribute will always be utilized. -These are are the parameters available to the condition function: +These are the parameters available to the condition function: {: .table .table-bordered .table-striped } | Name | Type | Available for | Description | @@ -218,13 +218,13 @@ These are are the parameters available to the condition function: | `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | | `syncUrl` | String | `syncUser` | URL of the user sync. | -#### Rule Allow Status +#### Allow Flag If the rule's condition matches, this attribute defines whether the rule 'votes' to allow (true) or disallow (false) the activity in question. As noted in the priority section, **disallow** (false) takes precedence amongst rules at the same priority level. -If `allow` is not defined, the rule is assumed to assert **true** (i.e. allow). +If `allow` is not defined, the rule is assumed to assert **true** (i.e. allow the activity to take place). ### More examples From 7113d28c520e0a8b06a2bb1e1e8bf089cfa594fb Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 6 Jun 2023 11:53:04 -0400 Subject: [PATCH 09/10] fixed missing allowActivities object --- dev-docs/activity-controls.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 079307ac67..07915940d7 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -234,12 +234,14 @@ This is similiar to the 'vendor exception' feature of the [GDPR Enforcement Modu ```javascript pbjs.setConfig({ + allowActivities: { fetchBids: { rules: [{ condition: ({componentName}) => componentName === 'bidderA', allow: true }] } + } }) ``` @@ -270,12 +272,14 @@ pbjs.setConfig({ ```javascript pbjs.setConfig({ + allowActivities: { transmitEids: { rules: [{ condition: ({componentName}) => componentName === 'exampleVendor', allow: false, }] } + } }) ``` From 0f835c3fa7f4338cf78c1c899b5c4ec26a2ab317 Mon Sep 17 00:00:00 2001 From: bretg Date: Tue, 6 Jun 2023 14:14:31 -0400 Subject: [PATCH 10/10] updated version --- dev-docs/activity-controls.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md index 07915940d7..7767f62810 100644 --- a/dev-docs/activity-controls.md +++ b/dev-docs/activity-controls.md @@ -3,12 +3,13 @@ layout: page_v2 title: Activity Controls description: How to stop Prebid.js from doing things you don't want sidebarType: 1 +pbjs_version: 7.52 --- # Prebid.js Activity Controls {: .no_toc } -Starting with version 7.48, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. +Starting with version 7.52, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. These controls are intended to serve as building blocks for privacy protection mechanisms, allowing module developers or publishers to directly specify what should be permitted or avoided in any given regulatory environment. * TOC