Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update SharedId docs with Conversant content #3137

Merged
merged 20 commits into from
Jul 27, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions dev-docs/modules/userId.md
Original file line number Diff line number Diff line change
Expand Up @@ -1334,10 +1334,10 @@ pbjs.setConfig({

### SharedID

This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support Publisher Common ID will be able to pick up the user ID and return it for additional server-side cross device tracking.
This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support SharedId will be able to pick up the user ID and return it for additional server-side cross device tracking.
bretg marked this conversation as resolved.
Show resolved Hide resolved

There is no special registration or configuration for SharedID. Each publisher's privacy policy should take
SharedID into account.
SharedID into account. Prebid recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page. For more information check out Prebid's dedicated [identity page](/identity/sharedid.html)

Add it to your Prebid.js package with:

Expand All @@ -1354,8 +1354,12 @@ In addition to the parameters documented above in the Basic Configuration sectio
| name | Required | String | The name of this module. | `'pubCommonId'` |
| params | Optional | Object | Customized parameters | |
| params.create | Optional | Boolean | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` |
| params.pixelUrl | Optional | String | For publisher server support only. This is a URL of a pixel for updating cookies' expiration times. Fired after a new ID has been created or an existing ID is being extended. No default. | `'https://example.com/ping'`
| params.pixelUrl | Optional | String | For publisher server support only. Where to call out to for a server cookie -- see [Prebid Identity](/identity/sharedid.html) for more information. | `/wp-json/pubcid/v1/extend/`
| params.extend | Optional | Boolean | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `false` |
| storage | Required | Object | The publisher must specify some kind of local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. |
jdwieland8282 marked this conversation as resolved.
Show resolved Hide resolved
| storage.expires | Integer | Required | How long the user ID information will be stored. | `365` |
| storage.name | String | Required | The name of the cookie or html5 local storage where the user ID will be stored. | `_pubcid`
| storage.type | String | Required | This is where the results of the user ID will be stored. Must be either: Must be either: "cookie" or "html5". For server side implementations, which have the best identifier life and revenue impact, this must be a cookie. | `cookie`

#### SharedID Examples

Expand All @@ -1368,7 +1372,7 @@ pbjs.setConfig({
name: "pubCommonId",
storage: {
type: "cookie",
name: "_pubcid", // create a cookie with this name
name: `"_pubcid"`, // create a cookie with this name
expires: 365 // expires in 1 years
}
}]
Expand All @@ -1393,9 +1397,12 @@ pbjs.setConfig({
}
},{
name: "pubCommonId",
params: {
pixelUrl: "/wp-json/pubcid/v1/extend/"
jdwieland8282 marked this conversation as resolved.
Show resolved Hide resolved
},
storage: {
type: "cookie",
name: "_pubcid", // create a cookie with this name
name: `"_pubcid"`, // create a cookie with this name
expires: 180
}
}],
Expand All @@ -1404,6 +1411,26 @@ pbjs.setConfig({
});
{% endhighlight %}

3) Publisher supports SharedID and first party domain cookie storage initiated by a first party server

{% highlight javascript %}
pbjs.setConfig({
userSync: {
userIds: [{
name: "pubCommonId",
params: {
pixelUrl: "/wp-json/pubcid/v1/extend/" //pixelUrl should be specified when the server plugin is used
},
storage: {
type: "cookie",
name: `"_pubcid"`, // create a cookie with this name
expires: 365 // expires in 1 years
}
}]
}
});
{% endhighlight %}

### PubProvided ID

The PubProvided Id module allows publishers to set and pass a first party user id into the bid stream. This module has several unique characteristics:
Expand Down
229 changes: 224 additions & 5 deletions identity/sharedid.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,20 @@ As of Prebid.js 5.0, PubCommon ID is no longer supported -- it's been merged int

SharedId is a convenient Prebid-owned first party identifier within the [Prebid UserId Module framework](/dev-docs/modules/userId.html).

## How does it work?
There are multiple ways to integrate SharedId on your site. See the table below for a breakout of options, and the rest of this document for detailed integration instructions. Due to cookie life restrictions in Safari when the document.cookie javascript method is used, SharedId is most effective when a server side first party cookie is set.

{: .table .table-bordered .table-striped }
| Implementation | Description | Cookie Lifetime | SAFARI COOKIE LIFETIME | TECHNICAL DIFFICULTY | REVENUE BENEFIT |
| --- | --- | --- | --- | --- | --- |
| 3rd Party Cookie Only | No first party cookie solution. | Some Blocked | Blocked | None | Low |
| User Id Submodule | Including User Id Module in your Prebid.js installation. | 365 days | 7 days | Basic | Good |
| PubCID Script | Adding the legacy PubCID script; not maintained by Prebid.org. | 365 days | 7 days | High | Varies |
| SharedId Server | Writing cookie from your web server code directly. | 365 days | 365 days | Intermediate | Best |

## How does the Prebid UserId Module implementation work?

The SharedID ID system sets a user id cookie in the publisher’s domain.
Since the cookie is set in the publisher's first party domain it does not fall in scope of browser restrictions on third party cookies.
Since the cookie is set in the publisher's first party domain it does not fall in scope of browser restrictions on third party cookies. Safari has restrictions on first party cookies set via document.cookie. For this reason we recommend a server side installation for maximum effect.

### Prebid.js 5.x

Expand All @@ -33,9 +43,12 @@ the module:
pbjs.setConfig({
userSync: {
userIds: [{
name: 'sharedId',
name: 'sharedId', //"pubCommonId" as a name is supported for backwards compatibility,
params: {
pixelUrl: "/wp-json/pubcid/v1/extend/" // this parameter identifies your server side endpoint that will set a first party cookie if you have configued SharedId server'
},
storage: {
name: '_sharedID', // name of the 1st party cookie
name: '_sharedID', // name of the 1st party cookie, _pubcid is supported for backwards compatibility
type: 'cookie',
expires: 30
}
Expand Down Expand Up @@ -132,9 +145,215 @@ by the publisher.
Publishers that decide to build a first-party opt-out workflow might follow a process like this:
- User is presented with an option to turn off ad targeting
- If the user opts out, the page can do one of two things:
- set a _pbjs_id_optout first party cookie
- set a `_pbjs_id_optout` first party cookie
- avoid calling pbjs.setConfig to initialize the user ID modules

## Alternative Implementations

For those not using Prebid's header bidding solution, Sharedid can deployed via in inline script reference or from a web server.

### SharedId Script

For those interested in implementing Sharedid without prebid.js.
1. Clone the [SharedId script repository](https://github.com/prebid/Shared-id-v2)
2. Implement the pubcid.js script on the desired page by following the build instructions in the [readme.md](https://github.com/prebid/Shared-id-v2#readme)

Prebid also recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page.

If there are no custom configurations, then just include the script and it'll use the default values.

```
<script type="text/javascript" src="//myserver.com/pubcid.min.js"></script>
```

If custom configurations are needed, define the pubcid_options object before inclusion of the script. Below is an example to switch from using local storage to cookie:

```
<script type="text/javascript">
window.pubcid_options = {type: 'cookie'};
</script>
<script type="text/javascript" src="//myserver.com/pubcid.min.js"></script>
```

#### Configuration

Configuration
Below are the available configuration options for the PubCID script.

{: .table .table-bordered .table-striped }
| Parameter Name | Type | Description | Example |
| --- | --- | --- | --- |
| create | boolean | If true, then an id is created automatically by the script if it's missing. Default is true. If your server has a component that generates the id instead, then this should be set to false
| `TRUE` |
| expInterval | decimal | Expiration interval in minutes. Default is 525600, or 1 year
| `525600` |
| extend | boolean | If true, the the expiration time is automatically extended whenever the script is executed even if the id exists already. Default is true. If false, then the id expires from the time it was initially created. | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `TRUE` |
| params.pixelUrl | Optional | String | For publisher server support only. Where to call out to for a server cookie. | `/wp-json/pubcid/v1/extend/`
| type | string | Type of storage. It's possible to specify one of the following: 'html5', 'cookie'. Default is 'html5' priority, aka local storage, and fall back to cookie if local storage is unavailable. | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `cookie` |

#### Example Configurations

Always use cookies and create an ID that expires in 30 days after creation.

```
{
type: 'cookie',
extend: false,
expInterval: 43200
}
```

Using a SharedId Server implementation, create the cookie once, which will be allowed to expire before it is created again.

```
{
type: 'cookie',
pixelUrl: '/wp-json/pubcid/v1/extend/',
create: false,
extend: false
}

```

### SharedId Server

Add server-side support for SharedId to better handle the ever-increasing restrictions on cookies in modern web browsers by having the SharedId cookie written and extended by your web server.

#### CMS

Plugins are available for Wordpress and Drupal. Because CMS can cache pages to improve scalability, it's impractical to extend cookies during page generation. Instead the plugins add a dynamic endpoint that serves back a blank pixel, and updates cookies at the same time. The client side script therefore needs one additional
bretg marked this conversation as resolved.
Show resolved Hide resolved

1. Wordpress : Install directly from the [Wordpress admin page](https://wordpress.org/plugins/publisher-common-id/). Install from [GITHUB](https://github.com/prebid/sharedid-wordpress)
2. Drupal : Install from [Github](https://github.com/prebid/sharedid-drupal).

#### Server Implementations
Below are some examples for how to implement SharedId Server in various languages or platforms.

##### JAVA
```JAVA
public class PubCid {
private static final String pubcidCookieName = "_pubcid";
private static final int expireTime = (int) TimeUnit.DAYS.toSeconds(365); //store cookie for 1 year

/**
* Returns the pubcid cookie found in the user's list of cookies.
* Always update the expire time to another year so that the cookie persists.
*
* @param cookies User's list of cookies
* @return the pubcid cookie if found, null otherwise
*/
public static Cookie getPubcidCookie(Cookie[] cookies) {

Cookie pubcidCookie = fetchPubcidCookie(cookies);
if (pubcidCookie != null)
pubcidCookie.setMaxAge(expireTime);

return pubcidCookie;
}

/**
* Simple function to test if the user has a pubcid cookie
*
* @param cookies User's list of cookies
* @return true if the cookie is found, false otherwise
*/
public static boolean hasPubcidCookie(Cookie[] cookies) {
return fetchPubcidCookie(cookies) != null;
}

/**
* Local function to find the pubcid cookie within the user's list of cookie
*
* @param cookies User's list of cookies
* @return pubcid cookie if found, null otherwise
*/
private static Cookie fetchPubcidCookie(Cookie[] cookies) {
if (cookies == null) return null;
return Arrays.stream(cookies)
.filter(e -> e.getName().equals(pubcidCookieName))
.findFirst()
.orElse(null);
}
}
```
##### PHP
```PHP
$cookie_name = '_pubcid';
$cookie_path = '/';
$max_age = 365;

$value = NULL;

// See if the cookie exist already

if (isset($_COOKIE[$cookie_name ]))
$value = $_COOKIE[$cookie_name];

// Obtain site domain if defined
if (defined(COOKIE_DOMAIN))
$cookie_domain = COOKIE_DOMAIN;
else
$cookie_domain = "";

// Update the cookie
if (isset($value)) {
setcookie(
$cookie_name,
$value,
time() + $max_age * DAY_IN_SECONDS,
$cookie_path,
$cookie_domain
);
}
```
##### Node.js
```Node
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 3000;

app.use(cookieParser());

app.get('/', function(req, res) {

// Check for existence of _pubcid cookie
let value = req.cookies['_pubcid'];

// If pubcid exists, then update its expiration time
if (value) {
res.cookie('_pubcid', value, {domain: '.example.com', path: '/', expires: new Date(Date.now() + 1000*60*60*24*365)});
}

res.render('index');
});

app.listen(port, ()=>console.log(`App listening on port ${port}`));
```
##### Apache
```Apache
# Add to httpd.conf
# Requires mod_headers and mod_env

# Capture _pubcid cookie value if available
SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" PUBCID_VALUE=$2
SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" HAVE_PUBCID=1

# Add _pubcid cookie if it exists to the response with 1 year expiration time
Header add Set-Cookie "_pubcid=%{PUBCID_VALUE}e;Domain=.example.com;Path=/;Max-Age=31536000" env=HAVE_PUBCID
```
##### Nginx
```Nginx
# Add to a location directive

location /example {
set $pubcid_value $cookie__pubcid;
if ($pubcid_value) {
add_header Set-Cookie "_pubcid=$pubcid_value;Domain=.example.com;Path=/;Max-Age=31536000";
}
}
```

## Related Topics

- [Prebid Identity Overview](/identity/prebid-identity.html)
Expand Down