Skip to content

Commit

Permalink
Conversant: add new Publink user id module
Browse files Browse the repository at this point in the history
  • Loading branch information
johnwier committed Aug 19, 2021
1 parent a437b05 commit 0737780
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 0 deletions.
102 changes: 102 additions & 0 deletions modules/publinkIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* This module adds the PublinkId to the User ID module
* The {@link module:modules/userId} module is required
* @module modules/conversantIdSystem
* @requires module:modules/userId
*/

import {submodule} from '../src/hook.js';
import {getStorageManager} from '../src/storageManager.js';
import {ajax} from '../src/ajax.js';
import * as utils from '../src/utils.js';
import {uspDataHandler} from '../src/adapterManager.js';

const MODULE_NAME = 'publink';
const GVLID = 24;

export const storage = getStorageManager(GVLID);

function publinkIdUrl(params, consentData) {
let url = utils.parseUrl('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink');
url.search = {
deh: params.e,
mpn: 'Prebid.js',
mpv: '$prebid.version$',
};
if (consentData) {
url.search.gdpr = (consentData.gdprApplies) ? 1 : 0;
url.search.gdpr_consent = consentData.consentString;
}

const usPrivacyString = uspDataHandler.getConsentData();
if (usPrivacyString && typeof usPrivacyString === 'string') {
url.search.us_privacy = usPrivacyString;
}

return utils.buildUrl(url);
}

function makeCallback(config = {}, consentData) {
return function(prebidCallback) {
const options = {method: 'GET', withCredentials: true};
let handleResponse = function(responseText, xhr) {
if (xhr.status === 200) {
let response = JSON.parse(responseText);
if (response) {
prebidCallback(response.publink);
}
}
};
if (window.coreid && typeof window.coreid.getPublinkId === 'function') {
window.coreid.getPublinkId((newId) => {
if (newId) {
prebidCallback(newId);
} else {
if (config.params && config.params.e) {
ajax(publinkIdUrl(config.params, consentData), handleResponse, undefined, options);
}
}
});
} else {
if (config.params && config.params.e) {
ajax(publinkIdUrl(config.params, consentData), handleResponse, undefined, options);
}
}
};
}

/** @type {Submodule} */
export const publinkIdSubmodule = {
/**
* used to link submodule with config
* @type {string}
*/
name: MODULE_NAME,
gvlid: GVLID,

/**
* decode the stored id value for passing to bid requests
* @function
* @param {string} id encrypted userid
* @returns {{publinkId: string} | undefined}
*/
decode(publinkId) {
return {publink: publinkId};
},

/**
* performs action to obtain id
* @function
* @param {SubmoduleConfig} [config] Config object with params and storage properties
* @returns {IdResponse}
*/
getId: function(config, consentData, storedId) {
let result = {};
if (storedId) {
result.id = storedId;
}
result.callback = makeCallback(config, consentData);
return result;
}
};
submodule('userId', publinkIdSubmodule);
28 changes: 28 additions & 0 deletions modules/publinkIdSystem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Publink User ID Submodule

Publink user id module

## Configuration Descriptions for the `userId` Configuration Section

| Param Name | Required | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Yes | String | module identifier | `"publinkId"` |
| params.e | Yes | String | hashed email address | `"e80b5017098950fc58aad83c8c14978e"` |

### Example configuration for Publink
```
pbjs.setConfig({
userSync: {
userIds: [{
name: "publinkId",
storage: {
name: "pbjs_publink",
type: "html5"
},
params: {
e: "e80b5017098950fc58aad83c8c14978e", // example hashed email (md5)
}
}],
}
});
```
4 changes: 4 additions & 0 deletions modules/userId/eids.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ const USER_IDS_CONFIG = {
source: 'amxrtb.com',
atype: 1,
},
'publink': {
source: 'epsilon.com',
atype: 3
},
'kpuid': {
source: 'kpuid.com',
atype: 3
Expand Down
125 changes: 125 additions & 0 deletions test/spec/modules/publinkIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {publinkIdSubmodule} from 'modules/publinkIdSystem.js';
import {getStorageManager} from '../../../src/storageManager';
import {server} from 'test/mocks/xhr.js';
import sinon from 'sinon';
import {uspDataHandler} from '../../../src/adapterManager';

export const storage = getStorageManager(24);
const TEST_COOKIE_VALUE = 'cookievalue';
describe('PublinkIdSystem', () => {
describe('decode', () => {
it('decode', () => {
const result = publinkIdSubmodule.decode(TEST_COOKIE_VALUE);
expect(result).deep.equals({publink: TEST_COOKIE_VALUE});
});
});

describe('getId', () => {
const serverResponse = {publink: 'ec0xHT3yfAOnykP64Qf0ORSi7LjNT1wju04ZSCsoPBekOJdBwK-0Zl_lXKDNnzhauC4iszBc-PvA1Be6IMlh1QocA'};
it('no config', () => {
const result = publinkIdSubmodule.getId();
expect(result).to.exist;
expect(result.callback).to.be.a('function');
});
it('Use local id', () => {
const result = publinkIdSubmodule.getId({}, undefined, TEST_COOKIE_VALUE);
expect(result).to.exist;
expect(result.id).to.equal(TEST_COOKIE_VALUE);
expect(result.callback).to.be.a('function');
});

describe('callout for id', () => {
let callbackSpy = sinon.spy();

beforeEach(() => {
callbackSpy.resetHistory();
});

it('Fetch with consent data', () => {
const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}};
const consentData = {gdprApplies: 1, consentString: 'myconsentstring'};
let submoduleCallback = publinkIdSubmodule.getId(config, consentData).callback;
submoduleCallback(callbackSpy);

let request = server.requests[0];
expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$&gdpr=1&gdpr_consent=myconsentstring');

request.respond(200, {}, JSON.stringify(serverResponse));
expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink);
});

it('server doesnt respond', () => {
const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}};
let submoduleCallback = publinkIdSubmodule.getId(config).callback;
submoduleCallback(callbackSpy);

let request = server.requests[0];
expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$');

request.respond(204, {}, JSON.stringify(serverResponse));
expect(callbackSpy.calledOnce).to.be.false;
});
});

describe('usPrivacy', () => {
let callbackSpy = sinon.spy();
const oldPrivacy = uspDataHandler.getConsentData();
before(() => {
uspDataHandler.setConsentData('1YNN');
});
after(() => {
uspDataHandler.setConsentData(oldPrivacy);
callbackSpy.resetHistory();
});

it('Fetch with usprivacy data', () => {
const config = {storage: {type: 'cookie'}, params: {e: 'hashedemailvalue'}};
let submoduleCallback = publinkIdSubmodule.getId(config).callback;
submoduleCallback(callbackSpy);

let request = server.requests[0];
expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$&us_privacy=1YNN');

request.respond(200, {}, JSON.stringify(serverResponse));
expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink);
});
});
describe('fetch from coreid', () => {
let callbackSpy = sinon.spy();
afterEach(() => {
callbackSpy.resetHistory();
delete window.coreid;
});
it('get id', () => {
window.coreid = {};
window.coreid.getPublinkId = (cb) => { cb(TEST_COOKIE_VALUE) };
const submoduleCallback = publinkIdSubmodule.getId({}).callback;
submoduleCallback(callbackSpy);
expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg).to.equal(TEST_COOKIE_VALUE);
});
it('coreid fails', () => {
window.coreid = {};
window.coreid.getPublinkId = (cb) => { cb() };
const submoduleCallback = publinkIdSubmodule.getId({params: {e: 'hashedemailvalue'}}).callback;
submoduleCallback(callbackSpy);
let request = server.requests[0];
expect(request.url).to.equal('https://proc.ad.cpe.dotomi.com/cvx/client/sync/publink?deh=hashedemailvalue&mpn=Prebid.js&mpv=$prebid.version$');
request.respond(200, {}, JSON.stringify(serverResponse));
expect(callbackSpy.calledOnce).to.be.true;
expect(callbackSpy.lastCall.lastArg).to.equal(serverResponse.publink);
});
it('no hashed email param', () => {
window.coreid = {};
window.coreid.getPublinkId = (cb) => { cb() };
const submoduleCallback = publinkIdSubmodule.getId({params: {}}).callback;
submoduleCallback(callbackSpy);
let request = server.requests[0];
expect(request).to.be.undefined;
expect(callbackSpy.calledOnce).to.be.false;
});
});
});
});

0 comments on commit 0737780

Please sign in to comment.