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

OneKey userId module: initial release #8366

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"netIdSystem",
"nextrollIdSystem",
"novatiqIdSystem",
"pafIdSystem",
"parrableIdSystem",
"pubProvidedIdSystem",
"publinkIdSystem",
Expand Down
43 changes: 43 additions & 0 deletions modules/pafIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* This module adds pafData to the User ID module
* The {@link module:modules/userId} module is required
* @module modules/pafIdSystem
* @requires module:modules/userId
*/

import {submodule} from '../src/hook.js';

/** @type {Submodule} */
export const pafIdSubmodule = {
/**
* used to link submodule with config
* @type {string}
*/
name: 'pafData',
/**
* decode the stored data value for passing to bid requests
* @function decode
* @param {(Object|string)} value
* @returns {(Object|undefined)}
*/
decode(data) {
return { pafData: data };
},
/**
* performs action to obtain id and return a value in the callback's response argument
* @function
* @param {SubmoduleConfig} [config]
* @param {ConsentData} [consentData]
* @param {(Object|undefined)} cacheIdObj
* @returns {IdResponse|undefined}
*/
getId(config, consentData) {
if (window.PAF && window.PAF.getIdsAndPreferences()) {
return {id: window.PAF.getIdsAndPreferences()};
} else {
return undefined;
}
}
};

submodule('userId', pafIdSubmodule);
104 changes: 104 additions & 0 deletions modules/pafIdSystem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Prebid Addressability Framework (OneKey)

The PAF real-time data module in Prebid has been built so that publishers
can quickly and easily setup the Prebid Addressability Framework and utilize OneKey.
This module is used along with the pafRtdProvider to pass PAF data to your partners.
Both modules are required. This module will pass paData to your partners
while the pafRtdProvider will pass the transmission requests.

Background information:
- [prebid/addressability-framework](https://github.com/prebid/addressability-framework)
- [prebid/paf-mvp-implementation](https://github.com/prebid/paf-mvp-implementation)

## PAF Configuration

The pafData module depends on paf-lib.js existing in the page.

Compile the pafData module into your Prebid build.
You will also want to add the pafRtdProvider module as well.

`gulp build --modules=userId,pafIdSystem,rtdModule,pafRtdProvider,appnexusBidAdapter`

There are no custom configuration parameters for PAF. The module
will retrieve the PAF data from the page if available and pass the
information to bidders. Here is a configuration example:

```javascript
pbjs.setConfig({
userSync: {
userIds: [{
name: "pafData",
params: {}
}]
}],
auctionDelay: 50 // example auction delay, applies to all userId modules
}
});
```

Bidders will receive the data in the following format:

```json
{
"identifiers": [{
"version": "0.1",
"type": "paf_browser_id",
"value": "da135b3a-7d04-44bf-a0af-c4709f10420b",
"source": {
"domain": "crto-poc-1.onekey.network",
"timestamp": 1648836556881,
"signature": "+NF27bBvPM54z103YPExXuS834+ggAQe6JV0jPeGo764vRYiiBl5OmEXlnB7UZgxNe3KBU7rN2jk0SkI4uL0bg=="
}
}],
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.pafdemopublisher.com",
"timestamp": 1648836566468,
"signature": "ipbYhU8IbSFm2tCqAVYI2d5w4DnGF7Xa2AaiZScx2nmBPLfMmIT/FkBYGitR8Mi791DHtcy5MXr4+bs1aeZFqw=="
}
}
}
```


If the bidder elects to use pbjs.getUserIdsAsEids() then the format will be:

```json
"user": {
"ext": {
"eids": [{
"source": "paf",
"uids": [{
"id": "da135b3a-7d04-44bf-a0af-c4709f10420b",
"atype": 1,
"ext": {
"version": "0.1",
"type": "paf_browser_id",
"source": {
"domain": "crto-poc-1.onekey.network",
"timestamp": 1648836556881,
"signature": "+NF27bBvPM54z103YPExXuS834+ggAQe6JV0jPeGo764vRYiiBl5OmEXlnB7UZgxNe3KBU7rN2jk0SkI4uL0bg=="
}
}
}],
"ext": {
"preferences": {
"version": "0.1",
"data": {
"use_browsing_for_personalization": true
},
"source": {
"domain": "cmp.pafdemopublisher.com",
"timestamp": 1648836566468,
"signature": "ipbYhU8IbSFm2tCqAVYI2d5w4DnGF7Xa2AaiZScx2nmBPLfMmIT/FkBYGitR8Mi791DHtcy5MXr4+bs1aeZFqw=="
}
}
}
}]
}
}
```
26 changes: 26 additions & 0 deletions modules/userId/eids.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,32 @@ export const USER_IDS_CONFIG = {
return data.envelope;
}
},

// PAF Data
'pafData': {
getValue: function(data) {
if (data && Array.isArray(data.identifiers) && data.identifiers[0]) {
return data.identifiers[0].value;
}
},
source: 'paf',
atype: 1,
getEidExt: function(data) {
if (data && data.preferences) {
return {preferences: data.preferences};
}
},
getUidExt: function(data) {
if (data && Array.isArray(data.identifiers) && data.identifiers[0]) {
const id = data.identifiers[0];
return {
version: id.version,
type: id.type,
source: id.source
};
}
}
},
};

// this function will create an eid object for the given UserId sub-module
Expand Down
114 changes: 114 additions & 0 deletions test/spec/modules/pafIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { pafIdSubmodule } from 'modules/pafIdSystem'
import { config } from 'src/config.js';
import {find} from 'src/polyfill.js';
import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js';

const idsAndPrefs = {
'identifiers': [
{
'version': '0.1',
'type': 'paf_browser_id',
'value': 'da135b3a-7d04-44bf-a0af-c4709f10420b',
'source': {
'domain': 'crto-poc-1.onekey.network',
'timestamp': 1648836556881,
'signature': '+NF27bBvPM54z103YPExXuS834+ggAQe6JV0jPeGo764vRYiiBl5OmEXlnB7UZgxNe3KBU7rN2jk0SkI4uL0bg=='
}
}
],
'preferences': {
'version': '0.1',
'data': {
'use_browsing_for_personalization': true
},
'source': {
'domain': 'cmp.pafdemopublisher.com',
'timestamp': 1648836566468,
'signature': 'ipbYhU8IbSFm2tCqAVYI2d5w4DnGF7Xa2AaiZScx2nmBPLfMmIT/FkBYGitR8Mi791DHtcy5MXr4+bs1aeZFqw=='
}
}
};

function getConfigMock() {
return {
userSync: {
syncDelay: 0,
userIds: [{
name: 'pafData'
}]
}
}
}

function getAdUnitMock(code = 'adUnit-code') {
return {
code,
mediaTypes: {banner: {}, native: {}},
sizes: [
[300, 200],
[300, 600]
],
bids: [{
bidder: 'sampleBidder',
params: { placementId: 'banner-only-bidder' }
}]
};
}

describe('pafData module', function () {
it('returns undefined if paf-lib is not found', function () {
const moduleIdResponse = pafIdSubmodule.getId();
expect(moduleIdResponse).to.be.undefined;
})
it('returns undefined if no Data', function () {
window.PAF = {
getIdsAndPreferences() {
return undefined;
}
}
const moduleIdResponse = pafIdSubmodule.getId();
expect(moduleIdResponse).to.be.undefined;
})
it('gets pafData from page context', function () {
window.PAF = {
getIdsAndPreferences() {
return idsAndPrefs;
}
}
const moduleIdResponse = pafIdSubmodule.getId();
expect(moduleIdResponse).to.deep.equal({id: idsAndPrefs});
})

// this test format was copied from other id module tests
// but it is failing on the hook and im not sure why, if someone
// knows why and can help i will fix, otherwise i will remove it
// describe('requestBids hook', function() {
// let adUnits;

// beforeEach(function() {
// adUnits = [getAdUnitMock()];
// window.PAF = {
// getIdsAndPreferences() {
// return idsAndPrefs;
// }
// }
// init(config);
// setSubmoduleRegistry([pafIdSubmodule]);
// config.setConfig(getConfigMock());
// });

// it('when pafData exists it is added to bids', function(done) {
// requestBidsHook(function() {
// adUnits.forEach(unit => {
// unit.bids.forEach(bid => {
// expect(bid).to.have.deep.nested.property('userId.pafData');
// expect(bid.userId.pafData).to.equal(idsAndPrefs);
// const pafDataAsEid = find(bid.userIdAsEids, e => e.source == 'paf');
// expect(pafDataAsEid.uids[0].id).to.equal('da135b3a-7d04-44bf-a0af-c4709f10420b');
// });
// });
// done();
// }, { adUnits });
// });
// });
})