Skip to content

Commit

Permalink
Create Id Submodule for OneKey
Browse files Browse the repository at this point in the history
  • Loading branch information
RomainLofaso committed Jul 13, 2022
1 parent 91aa018 commit b8810b3
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 0 deletions.
1 change: 1 addition & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"naveggIdSystem",
"netIdSystem",
"novatiqIdSystem",
"oneKeyIdSystem",
"parrableIdSystem",
"pubProvidedIdSystem",
"publinkIdSystem",
Expand Down
78 changes: 78 additions & 0 deletions modules/oneKeyIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* This module adds Onekey data to the User ID module
* The {@link module:modules/userId} module is required
* @module modules/oneKeyIdSystem
* @requires module:modules/userId
*/

import {submodule} from '../src/hook.js';
import { logError, logMessage } from '../src/utils.js';

// Pre-init OneKey if it has not load yet.
window.OneKey = window.OneKey || {};
window.OneKey.queue = window.OneKey.queue || [];

const logPrefix = 'OneKey.Id-Module';

/**
* Generate callback that deserializes the result of getIdsAndPreferences.
*/
const onIdsAndPreferencesResult = (callback) => {
return (result) => {
logMessage(logPrefix, `Has got Ids and Prefs with status: `, result);
callback(result.data);
};
};

/**
* Call OneKey once it is loaded for retrieving
* the ids and the preferences.
*/
const getIdsAndPreferences = (callback) => {
logMessage(logPrefix, 'Queue getIdsAndPreferences call');
// Call OneKey in a queue so that we are sure
// it will be called when fully load and configured
// within the page.
window.OneKey.queue.push(() => {
logMessage(logPrefix, 'Get Ids and Prefs');
window.OneKey.getIdsAndPreferences()
.then(onIdsAndPreferencesResult(callback))
.catch(() => {
logError(logPrefix, 'Cannot retrieve the ids and preferences from OneKey.');
callback(undefined);
});
});
};

/** @type {Submodule} */
export const oneKeyIdSubmodule = {
/**
* used to link submodule with config
* @type {string}
*/
name: 'oneKeyData',
/**
* 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) {
return {
callback: getIdsAndPreferences
};
}
};

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

The OneKey real-time data module in Prebid has been built so that publishers
can quickly and easily setup the OneKey Addressability Framework.
This module is used along with the oneKeyRtdProvider to pass OneKey data to your partners.
Both modules are required. This module will pass oneKeyData to your partners
while the oneKeyRtdProvider 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)

## OneKey Configuration

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

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

`gulp build --modules=userId,oneKeyIdSystem,rtdModule,oneKeyRtdProvider,appnexusBidAdapter`

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

```javascript
pbjs.setConfig({
userSync: {
userIds: [{
name: "oneKeyData",
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 @@ -323,6 +323,32 @@ export const USER_IDS_CONFIG = {
'cpexId': {
source: 'czechadid.cz',
atype: 1
},

// OneKey Data
'oneKeyData': {
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
};
}
}
}
};

Expand Down
107 changes: 107 additions & 0 deletions test/spec/modules/oneKeyIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { oneKeyIdSubmodule } from 'modules/oneKeyIdSystem'

const defaultConf = {
params: {
proxyHostName: 'proxy.com'
}
};

const defaultIdsAndPreferences = {
identifiers: [
{
version: '0.1',
type: 'paf_browser_id',
value: 'df0a5664-987d-4074-bbd9-e9b12ebae6ef',
source: {
domain: 'crto-poc-1.onekey.network',
timestamp: 1657100291,
signature: 'ikjV6WwpcroNB5XyLOr3MgYHLpS6UjICEOuv/jEr00uVrjZm0zluDSWh11OeGDZrMhxMBPeTabtQ4U2rNk3IzQ=='
}
}
],
preferences: {
version: '0.1',
data: {
use_browsing_for_personalization: true
},
source: {
domain: 'cmp.pafdemopublisher.com',
timestamp: 1657100294,
signature: 'aAbMThxyeKpe/EgT5ARI1xecjCwwh0uRagsTuPXNY2fzh7foeW31qljDZf6h8UwOd9M2bAN7XNtM2LYBbJzskQ=='
}
}
};

const defaultIdsAndPreferencesResult = {
status: 'PARTICIPATING',
data: defaultIdsAndPreferences
};

describe('oneKeyData module', () => {
describe('getId function', () => {
beforeEach(() => {
setUpOneKey();
});

it('return a callback for handling asynchron results', () => {
const moduleIdResponse = oneKeyIdSubmodule.getId(defaultConf);

expect(moduleIdResponse.callback).to.be.an('function');
});

it(`return a callback that waits for OneKey to be loaded`, () => {
const moduleIdResponse = oneKeyIdSubmodule.getId(defaultConf);

moduleIdResponse.callback(function() {})

expect(window.OneKey.queue.length).to.equal(1);
});

it('return a callback that gets ids and prefs', () => {
const moduleIdResponse = oneKeyIdSubmodule.getId(defaultConf);

// Act
return new Promise((resolve) => {
moduleIdResponse.callback(resolve);
executeOneKeyQueue();
})

// Assert
.then((idsAndPrefs) => {
expect(idsAndPrefs).to.equal(defaultIdsAndPreferences);
});
});

it('return a callback with undefined if impossible to get ids and prefs', () => {
window.OneKey.getIdsAndPreferences = () => {
return Promise.reject(new Error(`Impossible to get ids and prefs`));
};
const moduleIdResponse = oneKeyIdSubmodule.getId(defaultConf);

// Act
return new Promise((resolve) => {
moduleIdResponse.callback(resolve);
executeOneKeyQueue();
})

// Assert
.then((idsAndPrefs) => {
expect(idsAndPrefs).to.be.undefined;
});
});
});
});

const setUpOneKey = () => {
window.OneKey.queue = [];
window.OneKey.getIdsAndPreferences = () => {
return Promise.resolve(defaultIdsAndPreferencesResult);
};
}

const executeOneKeyQueue = () => {
while (window.OneKey.queue.length > 0) {
window.OneKey.queue[0]();
window.OneKey.queue.shift();
}
}

0 comments on commit b8810b3

Please sign in to comment.