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

Deepintent ID System: add new ID module #6537

Merged
merged 26 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from 12 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 @@ -16,6 +16,7 @@
"zeotapIdPlusIdSystem",
"haloIdSystem",
"quantcastIdSystem",
"deepintentDpesIdSystem",
"nextrollIdSystem",
"idxIdSystem",
"fabrickIdSystem",
Expand Down
80 changes: 80 additions & 0 deletions modules/deepintentDpesIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* This module adds DPES to the User ID module
* The {@link module:modules/userId} module is required
* @module modules/deepintentDpesSystem
* @requires module:modules/userId
*/

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

const MODULE_NAME = 'deepintentId';
export const storage = getStorageManager(null, MODULE_NAME);
const DEEPINTENT_DPES_ID = 'di_dpes';

function readCookie(cookieName) {
const val = storage.cookiesAreEnabled ? storage.getCookie(cookieName) : null;
return JSON.parse(val);
}

function readFromLocalStorage() {
const val = storage.localStorageIsEnabled
? storage.getDataFromLocalStorage(DEEPINTENT_DPES_ID)
: null;
return JSON.parse(val);
}

/** @type {Submodule} */
export const deepintentDpesSubmodule = {
/**
* used to link submodule with config
* @type {string}
*/
name: MODULE_NAME,
/**
* decode the stored id value for passing to bid requests
* @function
* @param {{value:string}} value
* @returns {{deepintentId:Object}}
*/
decode(value, config) {
const configParams = (config && config.params) || {};
if (configParams && configParams.identityKey && configParams.siteId && value.siteId && configParams.siteId == value.siteId) {
if (configParams.identityKey === 'hashedEmail') {
value = {'deepintentId': value.email}
return value;
} else if (configParams.identityKey === 'hashedNPI') {
value = {'deepintentId': value.npi}
return value;
} else {
return undefined;
}
} else {
return undefined;
}
},
/**
* performs action to obtain id and return a value in the callback's response argument
* @function
* @param {SubmoduleConfig} config
* @return {{id: string | undefined} | undefined}
*/
getId(config) {
const configStorage = (config && config.storage) || {};

let id = null;
if (
configStorage &&
configStorage.name &&
configStorage.type === 'cookie'
) {
id = readCookie(configStorage.name);
sourabhg marked this conversation as resolved.
Show resolved Hide resolved
} else if (configStorage && configStorage.type === 'html5') {
id = readFromLocalStorage();
}

return id ? { id } : undefined;
},
};

submodule('userId', deepintentDpesSubmodule);
49 changes: 49 additions & 0 deletions modules/deepintentDpesIdSystem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Deepintent DPES ID

The Deepintent DPES ID or Healthcare Identity is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The Deepintent DPES ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain.
sourabhg marked this conversation as resolved.
Show resolved Hide resolved

## Deepintent DPES ID Registration

The Deepintent DPES ID is free to use, but requires a simple registration with Deepintent. Please contact your sales rep to get started


## Deepintent DPES ID Configuration
sourabhg marked this conversation as resolved.
Show resolved Hide resolved

First, make sure to add the Deepintent submodule to your Prebid.js package with:

```
gulp build --modules=deepintentDpesIdSystem,userId
```

The following configuration parameters are available:

```javascript
pbjs.setConfig({
userSync: {
userIds: [{
name: 'deepintentId',
params: {
siteId: 173, // change to the siteId number to the one you recieved from Deepintent.
identityKey: "hashedEmail" // HashedEmail or HashedNPI based on type of your integration
},
storage: {
type: 'cookie', // "html5" is the required storage type option is "html5"
name: '_di', // change to the cookie name you wish to read from, optional if storage type is html5
sourabhg marked this conversation as resolved.
Show resolved Hide resolved
expires: 90 // storage lasts for 90 days, optional if storage type is html5
}
}],
auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules
}
});
```

| Param under userSync.userIds[] | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Required | String | The name of this module: `"deepintentId"` | `"deepintentId"` |
| params | Required | Object | Details for the Deepinent DPES ID. | |
| params.siteId | Required | Number | This is the Deepintent site id obtained from registering with deepintent. | `10023` |
| params.identityKey | Required | String | This is identity type which healthcare identity will store by using healthcare identity module by deepintent it will be either "hashedEmail" or "hashedNPI" | `hashedEmai` |
| storage | Required | Object | Storage settings for how the User Id module will cache the Deepintent ID locally | |
| storage.type | Required | String | This is where the results of the user ID will be stored. Deepintent`"html5"` or `"cookie"`. | `"html5"` |
| storage.name | Optional | String | The name of the local storage where the user ID will be stored. Deepintent **required** for storage type `"cookie"`. | `"_di"` |
| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. Deepintent recommends `90`. | `90` |
5 changes: 4 additions & 1 deletion modules/userId/eids.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,10 @@ const USER_IDS_CONFIG = {
return data.id;
}
},

'deepintentId': {
source: 'deepintent.com',
atype: 1
sourabhg marked this conversation as resolved.
Show resolved Hide resolved
},
// Admixer Id
'admixerId': {
source: 'admixer.net',
Expand Down
121 changes: 121 additions & 0 deletions test/spec/modules/deepintentDpesIdsystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { expect } from 'chai';
import find from 'core-js-pure/features/array/find.js';
import { storage, deepintentDpesSubmodule } from 'modules/deepintentDpesIdSystem.js';
import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js';
import { config } from 'src/config.js';

const DI_COOKIE_NAME = '_di';
const DI_LOCALSTORAGE_ID = 'di_dpes';
const DI_DUMMY_VALUE = '{"email":"2cf40748c4f7f60d343336e08f80dc99","siteId":"80088"}';
const DI_COOKIE_STORED = DI_DUMMY_VALUE;
const DI_EMAIL_DECODE_VALUE = {
email: '2cf40748c4f7f60d343336e08f80dc99',
siteId: '80088'
};
const DI_NPI_DECODE_VALUE = {
npi: '2cf40748c4f7f60d343336e08f80dc99',
siteId: '80088'
};
const DI_COOKIE_OBJECT = {
id: {
email: '2cf40748c4f7f60d343336e08f80dc99',
siteId: '80088'
}
};
const cookieConfig = {
name: 'deepintentId',
params: {
identityKey: 'hashedEmail',
siteId: '80088'
},
storage: {
type: 'cookie',
name: '_di',
expires: 28
}
};
const cookieNPIConfig = {
name: 'deepintentId',
params: {
identityKey: 'hashedNPI',
siteId: '80088'
},
storage: {
type: 'cookie',
name: '_di',
expires: 28
}
};

const html5Config = {
name: 'deepintentId',
params: {
identityKey: 'hashedEmail',
siteId: '80088'
},
storage: {
type: 'html5'
}
};

describe('Deepintent DPES System', () => {
let getDataFromLocalStorageStub, localStorageIsEnabledStub;
let getCookieStub, cookiesAreEnabledStub;

beforeEach(() => {
getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled');
getCookieStub = sinon.stub(storage, 'getCookie');
cookiesAreEnabledStub = sinon.stub(storage, 'cookiesAreEnabled');
});

afterEach(() => {
getDataFromLocalStorageStub.restore();
localStorageIsEnabledStub.restore();
getCookieStub.restore();
cookiesAreEnabledStub.restore();
});

describe('Deepintent Dpes Sytsem: test "getId" method', () => {
it('Wrong config should fail the tests', () => {
// no config
expect(deepintentDpesSubmodule.getId()).to.be.eq(undefined);
expect(deepintentDpesSubmodule.getId({ })).to.be.eq(undefined);

expect(deepintentDpesSubmodule.getId({params: {}, storage: {}})).to.be.eq(undefined);
expect(deepintentDpesSubmodule.getId({params: {}, storage: {type: 'cookie'}})).to.be.eq(undefined);
expect(deepintentDpesSubmodule.getId({params: {}, storage: {name: '_di'}})).to.be.eq(undefined);
});

it('Get value stored in cookie for getId', () => {
getCookieStub.withArgs(DI_COOKIE_NAME).returns(DI_COOKIE_STORED);
let diId = deepintentDpesSubmodule.getId(cookieConfig);
expect(diId).to.deep.equal(DI_COOKIE_OBJECT);
});

it('provides the stored deepintentId if cookie is absent but present in local storage', () => {
getDataFromLocalStorageStub.withArgs(DI_LOCALSTORAGE_ID).returns(DI_COOKIE_STORED);
let idx = deepintentDpesSubmodule.getId(html5Config);
expect(idx).to.deep.equal(DI_COOKIE_OBJECT);
});
});

describe('Deepintent Dpes System : test "decode" method', () => {
it('Wrong params passed via config', () => {
expect(deepintentDpesSubmodule.decode('test', {params: {}})).to.be.undefined;
expect(deepintentDpesSubmodule.decode('test', {params: {identityKey: 'hashedEmail'}})).to.be.undefined;
expect(deepintentDpesSubmodule.decode('test', {params: {identityKey: 'hashedNPI'}})).to.be.undefined;
expect(deepintentDpesSubmodule.decode('test', {params: {siteId: '80088'}})).to.be.undefined;
expect(deepintentDpesSubmodule.decode('test', {params: {siteId: '80088', identityKey: 'hello'}})).to.be.undefined;
});

it('Get the correct decoded value for dpes id', () => {
expect(deepintentDpesSubmodule.decode(DI_EMAIL_DECODE_VALUE, cookieConfig)).to.deep.equal({'deepintentId': '2cf40748c4f7f60d343336e08f80dc99'});
expect(deepintentDpesSubmodule.decode(DI_NPI_DECODE_VALUE, cookieNPIConfig)).to.deep.equal({'deepintentId': '2cf40748c4f7f60d343336e08f80dc99'});
});

it('Check for wrong siteId', () => {
expect(deepintentDpesSubmodule.decode(DI_EMAIL_DECODE_VALUE, {params: {siteId: '80090', identityKey: 'hashedEmail'}})).to.be.undefined;
});
});
});