forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Operaads: add ID System sbumodule (prebid#10270)
Co-authored-by: hongxingp <hongxingp@opera.com>
- Loading branch information
1 parent
8df5e93
commit 49418b1
Showing
7 changed files
with
238 additions
and
6 deletions.
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
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,106 @@ | ||
/** | ||
* This module adds operaId to the User ID module | ||
* The {@link module:modules/userId} module is required | ||
* @module modules/operaadsIdSystem | ||
* @requires module:modules/userId | ||
*/ | ||
import * as ajax from '../src/ajax.js'; | ||
import { submodule } from '../src/hook.js'; | ||
import { logMessage, logError } from '../src/utils.js'; | ||
|
||
const MODULE_NAME = 'operaId'; | ||
const ID_KEY = MODULE_NAME; | ||
const version = '1.0'; | ||
const SYNC_URL = 'https://t.adx.opera.com/identity/'; | ||
const AJAX_TIMEOUT = 300; | ||
const AJAX_OPTIONS = {method: 'GET', withCredentials: true, contentType: 'application/json'}; | ||
|
||
function constructUrl(pairs) { | ||
const queries = []; | ||
for (let key in pairs) { | ||
queries.push(`${key}=${encodeURIComponent(pairs[key])}`); | ||
} | ||
return `${SYNC_URL}?${queries.join('&')}`; | ||
} | ||
|
||
function asyncRequest(url, cb) { | ||
ajax.ajaxBuilder(AJAX_TIMEOUT)( | ||
url, | ||
{ | ||
success: response => { | ||
try { | ||
const jsonResponse = JSON.parse(response); | ||
const { uid: operaId } = jsonResponse; | ||
cb(operaId); | ||
return; | ||
} catch (e) { | ||
logError(`${MODULE_NAME}: invalid response`, response); | ||
} | ||
cb(); | ||
}, | ||
error: (err) => { | ||
logError(`${MODULE_NAME}: ID error response`, err); | ||
cb(); | ||
} | ||
}, | ||
null, | ||
AJAX_OPTIONS | ||
); | ||
} | ||
|
||
export const operaIdSubmodule = { | ||
/** | ||
* used to link submodule with config | ||
* @type {string} | ||
*/ | ||
name: MODULE_NAME, | ||
|
||
/** | ||
* @type {string} | ||
*/ | ||
version, | ||
|
||
/** | ||
* decode the stored id value for passing to bid requests | ||
* @function | ||
* @param {string} id | ||
* @returns {{'operaId': string}} | ||
*/ | ||
decode: (id) => | ||
id != null && id.length > 0 | ||
? { [ID_KEY]: id } | ||
: undefined, | ||
|
||
/** | ||
* performs action to obtain id and return a value in the callback's response argument | ||
* @function | ||
* @param {SubmoduleConfig} [config] | ||
* @returns {IdResponse|undefined} | ||
*/ | ||
getId(config, consentData) { | ||
logMessage(`${MODULE_NAME}: start synchronizing opera uid`); | ||
const params = (config && config.params) || {}; | ||
if (typeof params.pid !== 'string' || params.pid.length == 0) { | ||
logError(`${MODULE_NAME}: submodule requires a publisher ID to be defined`); | ||
return; | ||
} | ||
|
||
const { pid, syncUrl = SYNC_URL } = params; | ||
const url = constructUrl(syncUrl, { publisherId: pid }); | ||
|
||
return { | ||
callback: (cb) => { | ||
asyncRequest(url, cb); | ||
} | ||
} | ||
}, | ||
|
||
eids: { | ||
'operaId': { | ||
source: 't.adx.opera.com', | ||
atype: 1 | ||
}, | ||
} | ||
}; | ||
|
||
submodule('userId', operaIdSubmodule); |
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,52 @@ | ||
# Opera ID System | ||
|
||
For help adding this module, please contact [adtech-prebid-group@opera.com](adtech-prebid-group@opera.com). | ||
|
||
### Prebid Configuration | ||
|
||
You should configure this module under your `userSync.userIds[]` configuration: | ||
|
||
```javascript | ||
pbjs.setConfig({ | ||
userSync: { | ||
userIds: [ | ||
{ | ||
name: "operaId", | ||
storage: { | ||
name: "operaId", | ||
type: "html5", | ||
expires: 14 | ||
}, | ||
params: { | ||
pid: "your-pulisher-ID-here" | ||
} | ||
} | ||
] | ||
} | ||
}) | ||
``` | ||
<br> | ||
|
||
| Param under `userSync.userIds[]` | Scope | Type | Description | Example | | ||
| -------------------------------- | -------- | ------ | ----------------------------- | ----------------------------------------- | | ||
| name | Required | string | ID for the operaId module | `"operaId"` | | ||
| storage | Optional | Object | Settings for operaId storage | See [storage settings](#storage-settings) | | ||
| params | Required | Object | Parameters for opreaId module | See [params](#params) | | ||
<br> | ||
|
||
### Params | ||
|
||
| Param under `params` | Scope | Type | Description | Example | | ||
| -------------------- | -------- | ------ | ------------------------------ | --------------- | | ||
| pid | Required | string | Publisher ID assigned by Opera | `"pub12345678"` | | ||
<br> | ||
|
||
### Storage Settings | ||
|
||
The following settings are suggested for the `storage` property in the `userSync.userIds[]` object: | ||
|
||
| Param under `storage` | Type | Description | Example | | ||
| --------------------- | ------------- | -------------------------------------------------------------------------------- | ----------- | | ||
| name | String | Where the ID will be stored | `"operaId"` | | ||
| type | String | For best performance, this should be `"html5"` | `"html5"` | | ||
| expires | Number <= 30 | number of days until the stored ID expires. **Must be less than or equal to 30** | `14` | |
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,53 @@ | ||
import { operaIdSubmodule } from 'modules/operaadsIdSystem' | ||
import * as ajaxLib from 'src/ajax.js' | ||
|
||
const TEST_ID = 'opera-test-id'; | ||
const operaIdRemoteResponse = { uid: TEST_ID }; | ||
|
||
describe('operaId submodule properties', () => { | ||
it('should expose a "name" property equal to "operaId"', () => { | ||
expect(operaIdSubmodule.name).to.equal('operaId'); | ||
}); | ||
}); | ||
|
||
function fakeRequest(fn) { | ||
const ajaxBuilderStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(() => { | ||
return (url, cbObj) => { | ||
cbObj.success(JSON.stringify(operaIdRemoteResponse)); | ||
} | ||
}); | ||
fn(); | ||
ajaxBuilderStub.restore(); | ||
} | ||
|
||
describe('operaId submodule getId', function() { | ||
it('request to the fake server to correctly extract test ID', function() { | ||
fakeRequest(() => { | ||
const moduleIdCallbackResponse = operaIdSubmodule.getId({ params: { pid: 'pub123' } }); | ||
moduleIdCallbackResponse.callback((id) => { | ||
expect(id).to.equal(operaIdRemoteResponse.operaId); | ||
}); | ||
}); | ||
}); | ||
|
||
it('request to the fake server without publiser ID', function() { | ||
fakeRequest(() => { | ||
const moduleIdCallbackResponse = operaIdSubmodule.getId({ params: {} }); | ||
expect(moduleIdCallbackResponse).to.equal(undefined); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('operaId submodule decode', function() { | ||
it('should respond with an object containing "operaId" as key with the value', () => { | ||
expect(operaIdSubmodule.decode(TEST_ID)).to.deep.equal({ | ||
operaId: TEST_ID | ||
}); | ||
}); | ||
|
||
it('should respond with undefined if the value is not a string or an empty string', () => { | ||
[1, 2.0, null, undefined, NaN, [], {}].forEach((value) => { | ||
expect(operaIdSubmodule.decode(value)).to.equal(undefined); | ||
}); | ||
}); | ||
}); |