-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new userId module - neustar's fabrick (#5802)
* submitting userId module for neustar's fabrick - https://www.home.neustar/fabrick * fixing 'gulp test' errors * fixing another test issue (related to ie) * removing another (last) repeat * - expose full user id config (including storage) to user id modules (#5803 - removing TODO from test * - updates to test Co-authored-by: Anderson, Ben <Ben.Anderson@team.neustar>
- Loading branch information
1 parent
16fabf4
commit f907ee6
Showing
5 changed files
with
282 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/** | ||
* This module adds neustar's fabrickId to the User ID module | ||
* The {@link module:modules/userId} module is required | ||
* @module modules/fabrickIdSystem | ||
* @requires module:modules/userId | ||
*/ | ||
|
||
import * as utils from '../src/utils.js' | ||
import { ajax } from '../src/ajax.js'; | ||
import { submodule } from '../src/hook.js'; | ||
import { getRefererInfo } from '../src/refererDetection.js'; | ||
|
||
/** @type {Submodule} */ | ||
export const fabrickIdSubmodule = { | ||
/** | ||
* used to link submodule with config | ||
* @type {string} | ||
*/ | ||
name: 'fabrickId', | ||
|
||
/** | ||
* decode the stored id value for passing to bid requests | ||
* @function decode | ||
* @param {(Object|string)} value | ||
* @returns {(Object|undefined)} | ||
*/ | ||
decode(value) { | ||
if (value && value.fabrickId) { | ||
return { 'fabrickId': value.fabrickId }; | ||
} else { | ||
return undefined; | ||
} | ||
}, | ||
|
||
/** | ||
* performs action to obtain id and return a value in the callback's response argument | ||
* @function getId | ||
* @param {SubmoduleConfig} [config] | ||
* @param {ConsentData} | ||
* @param {Object} cacheIdObj - existing id, if any consentData] | ||
* @returns {IdResponse|undefined} | ||
*/ | ||
getId(config, consentData, cacheIdObj) { | ||
try { | ||
const configParams = (config && config.params) || {}; | ||
if (window.fabrickMod1) { | ||
window.fabrickMod1(configParams, consentData, cacheIdObj); | ||
} | ||
if (!configParams || typeof configParams.apiKey !== 'string') { | ||
utils.logError('fabrick submodule requires an apiKey.'); | ||
return; | ||
} | ||
try { | ||
let url = _getBaseUrl(configParams); | ||
let keysArr = Object.keys(configParams); | ||
for (let i in keysArr) { | ||
let k = keysArr[i]; | ||
if (k === 'url' || k === 'refererInfo') { | ||
continue; | ||
} | ||
let v = configParams[k]; | ||
if (Array.isArray(v)) { | ||
for (let j in v) { | ||
url += `${k}=${v[j]}&`; | ||
} | ||
} else { | ||
url += `${k}=${v}&`; | ||
} | ||
} | ||
// pull off the trailing & | ||
url = url.slice(0, -1) | ||
const referer = _getRefererInfo(configParams); | ||
const urls = new Set(); | ||
url = truncateAndAppend(urls, url, 'r', referer.referer); | ||
if (referer.stack && referer.stack[0]) { | ||
url = truncateAndAppend(urls, url, 'r', referer.stack[0]); | ||
} | ||
url = truncateAndAppend(urls, url, 'r', referer.canonicalUrl); | ||
url = truncateAndAppend(urls, url, 'r', window.location.href); | ||
|
||
const resp = function (callback) { | ||
const callbacks = { | ||
success: response => { | ||
if (window.fabrickMod2) { | ||
return window.fabrickMod2( | ||
callback, response, configParams, consentData, cacheIdObj); | ||
} else { | ||
let responseObj; | ||
if (response) { | ||
try { | ||
responseObj = JSON.parse(response); | ||
} catch (error) { | ||
utils.logError(error); | ||
responseObj = {}; | ||
} | ||
} | ||
callback(responseObj); | ||
} | ||
}, | ||
error: error => { | ||
utils.logError(`fabrickId fetch encountered an error`, error); | ||
callback(); | ||
} | ||
}; | ||
ajax(url, callbacks, null, {method: 'GET', withCredentials: true}); | ||
}; | ||
return {callback: resp}; | ||
} catch (e) { | ||
utils.logError(`fabrickIdSystem encountered an error`, e); | ||
} | ||
} catch (e) { | ||
utils.logError(`fabrickIdSystem encountered an error`, e); | ||
} | ||
} | ||
}; | ||
|
||
function _getRefererInfo(configParams) { | ||
if (configParams.refererInfo) { | ||
return configParams.refererInfo; | ||
} else { | ||
return getRefererInfo(); | ||
} | ||
} | ||
|
||
function _getBaseUrl(configParams) { | ||
if (configParams.url) { | ||
return configParams.url; | ||
} else { | ||
return `https://fid.agkn.com/f?`; | ||
} | ||
} | ||
|
||
function truncateAndAppend(urls, url, paramName, s) { | ||
if (s && url.length < 2000) { | ||
if (s.length > 200) { | ||
s = s.substring(0, 200); | ||
} | ||
// Don't send the same url in multiple params | ||
if (!urls.has(s)) { | ||
urls.add(s); | ||
return `${url}&${paramName}=${s}` | ||
} | ||
} | ||
return url; | ||
} | ||
|
||
submodule('userId', fabrickIdSubmodule); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
## Neustar Fabrick User ID Submodule | ||
|
||
Fabrick ID Module - https://www.home.neustar/fabrick | ||
Product and Sales Inquiries: 1-855-898-0036 | ||
|
||
## Example configuration for publishers: | ||
``` | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [{ | ||
name: 'fabrickId', | ||
storage: { | ||
name: 'pbjs_fabrickId', | ||
type: 'cookie', | ||
expires: 7 | ||
}, | ||
params: { | ||
apiKey: 'your apiKey', // provided to you by Neustar | ||
e: '31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66' // example hash identifier (sha256) | ||
} | ||
}] | ||
} | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"fabrickId": 1980 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import * as utils from '../../../src/utils.js'; | ||
import {server} from '../../mocks/xhr.js'; | ||
|
||
import * as fabrickIdSystem from 'modules/fabrickIdSystem.js'; | ||
|
||
const defaultConfigParams = { | ||
apiKey: '123', | ||
e: 'abc', | ||
p: ['def', 'hij'], | ||
url: 'http://localhost:9999/test/mocks/fabrickId.json?' | ||
}; | ||
const responseHeader = {'Content-Type': 'application/json'} | ||
const fabrickIdSubmodule = fabrickIdSystem.fabrickIdSubmodule; | ||
|
||
describe('Fabrick ID System', function() { | ||
let logErrorStub; | ||
|
||
beforeEach(function () { | ||
logErrorStub = sinon.stub(utils, 'logError'); | ||
}); | ||
|
||
afterEach(function () { | ||
logErrorStub.restore(); | ||
fabrickIdSubmodule.getRefererInfoOverride = null; | ||
}); | ||
|
||
it('should log an error if no configParams were passed into getId', function () { | ||
fabrickIdSubmodule.getId(); | ||
expect(logErrorStub.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should error on json parsing', function() { | ||
let submoduleCallback = fabrickIdSubmodule.getId({ | ||
name: 'fabrickId', | ||
params: defaultConfigParams | ||
}).callback; | ||
let callBackSpy = sinon.spy(); | ||
submoduleCallback(callBackSpy); | ||
let request = server.requests[0]; | ||
request.respond( | ||
200, | ||
responseHeader, | ||
'] this is not json {' | ||
); | ||
expect(callBackSpy.calledOnce).to.be.true; | ||
expect(logErrorStub.calledOnce).to.be.true; | ||
}); | ||
|
||
it('should truncate the params', function() { | ||
let r = ''; | ||
for (let i = 0; i < 300; i++) { | ||
r += 'r'; | ||
} | ||
let configParams = Object.assign({}, defaultConfigParams, { | ||
refererInfo: { | ||
referer: r, | ||
stack: ['s-0'], | ||
canonicalUrl: 'cu-0' | ||
} | ||
}); | ||
let submoduleCallback = fabrickIdSubmodule.getId({ | ||
name: 'fabrickId', | ||
params: configParams | ||
}).callback; | ||
let callBackSpy = sinon.spy(); | ||
submoduleCallback(callBackSpy); | ||
let request = server.requests[0]; | ||
r = ''; | ||
for (let i = 0; i < 200; i++) { | ||
r += 'r'; | ||
} | ||
expect(request.url).to.match(new RegExp(`r=${r}&r=`)); | ||
request.respond( | ||
200, | ||
responseHeader, | ||
JSON.stringify({}) | ||
); | ||
expect(callBackSpy.calledOnce).to.be.true; | ||
expect(logErrorStub.calledOnce).to.be.false; | ||
}); | ||
|
||
it('should complete successfully', function() { | ||
let configParams = Object.assign({}, defaultConfigParams, { | ||
refererInfo: { | ||
referer: 'r-0', | ||
stack: ['s-0'], | ||
canonicalUrl: 'cu-0' | ||
} | ||
}); | ||
let submoduleCallback = fabrickIdSubmodule.getId({ | ||
name: 'fabrickId', | ||
params: configParams | ||
}).callback; | ||
let callBackSpy = sinon.spy(); | ||
submoduleCallback(callBackSpy); | ||
let request = server.requests[0]; | ||
expect(request.url).to.match(/r=r-0&r=s-0&r=cu-0&r=http/); | ||
request.respond( | ||
200, | ||
responseHeader, | ||
JSON.stringify({}) | ||
); | ||
expect(callBackSpy.calledOnce).to.be.true; | ||
expect(logErrorStub.calledOnce).to.be.false; | ||
}); | ||
}); |