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

Halo ID url params, RTD dupe protection, doc update #7204

Merged
merged 6 commits into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 20 additions & 1 deletion modules/haloIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ const AU_GVLID = 561;

export const storage = getStorageManager(AU_GVLID, 'halo');

/**
* Param or default.
* @param {String} param
* @param {String} defaultVal
*/
function paramOrDefault(param, defaultVal, arg) {
if (utils.isFn(param)) {
return param(arg);
} else if (utils.isStr(param)) {
return param;
}
return defaultVal;
}

/** @type {Submodule} */
export const haloIdSubmodule = {
/**
Expand Down Expand Up @@ -42,7 +56,12 @@ export const haloIdSubmodule = {
* @returns {IdResponse|undefined}
*/
getId(config) {
const url = `https://id.halo.ad.gt/api/v1/pbhid`;
if (!utils.isPlainObject(config.params)) {
config.params = {};
}
const url = paramOrDefault(config.params.url,
`https://id.halo.ad.gt/api/v1/pbhid`,
config.params.urlArg);
antlauzon marked this conversation as resolved.
Show resolved Hide resolved

const resp = function (callback) {
let haloId = storage.getDataFromLocalStorage('auHaloId');
Expand Down
3 changes: 3 additions & 0 deletions modules/haloIdSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ The below parameters apply only to the HaloID User ID Module integration.
| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"haloid"` |
| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` |
| value | Optional | Object | Used only if the page has a separate mechanism for storing the Halo ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"haloId": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}` |
| params | Optional | Object | Used to store params for the id system |
| params.url | Optional | String | Set an alternate GET url for HaloId with this parameter |
| params.urlArg | Optional | Object | Optional url parameter for params.url |
53 changes: 48 additions & 5 deletions modules/haloRtdProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {config} from '../src/config.js';
import {getGlobal} from '../src/prebidGlobal.js';
import {getStorageManager} from '../src/storageManager.js';
import {submodule} from '../src/hook.js';
import {isFn, isStr, isPlainObject, mergeDeep, logError} from '../src/utils.js';
import {isFn, isStr, isArray, deepEqual, isPlainObject, logError} from '../src/utils.js';

const MODULE_NAME = 'realTimeData';
const SUBMODULE_NAME = 'halo';
Expand All @@ -26,25 +26,67 @@ export const storage = getStorageManager(AU_GVLID, SUBMODULE_NAME);
* @param {String} path
* @param {Object} val
*/
const set = (obj, path, val) => {
function set(obj, path, val) {
const keys = path.split('.');
const lastKey = keys.pop();
const lastObj = keys.reduce((obj, key) => obj[key] = obj[key] || {}, obj);
lastObj[lastKey] = lastObj[lastKey] || val;
};
}

/**
* Deep object merging with array deduplication.
* @param {Object} target
* @param {Object} sources
*/
function mergeDeep(target, ...sources) {
if (!sources.length) return target;
const source = sources.shift();

if (isPlainObject(target) && isPlainObject(source)) {
for (const key in source) {
if (isPlainObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
mergeDeep(target[key], source[key]);
} else if (isArray(source[key])) {
if (!target[key]) {
Object.assign(target, { [key]: source[key] });
} else if (isArray(target[key])) {
source[key].forEach(obj => {
let e = 1;
for (let i = 0; i < target[key].length; i++) {
if (deepEqual(target[key][i], obj)) {
e = 0;
break;
}
}
if (e) {
target[key].push(obj);
}
});
}
} else {
Object.assign(target, { [key]: source[key] });
}
}
}

return mergeDeep(target, ...sources);
}

/**
* Lazy merge objects.
* @param {String} target
* @param {String} source
* @param {Object} target
* @param {Object} source
*/
function mergeLazy(target, source) {
if (!isPlainObject(target)) {
target = {};
}

if (!isPlainObject(source)) {
source = {};
}

return mergeDeep(target, source);
}

Expand Down Expand Up @@ -123,6 +165,7 @@ export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) {

let haloId = storage.getDataFromLocalStorage(HALOID_LOCAL_NAME);
if (isStr(haloId)) {
(getGlobal()).refreshUserIds({submoduleNames: 'haloId'});
userIds.haloId = haloId;
getRealTimeDataAsync(bidConfig, onDone, rtdConfig, userConsent, userIds);
} else {
Expand Down
29 changes: 18 additions & 11 deletions modules/haloRtdProvider.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
## Audigent Halo Real-time Data Submodule

Audigent is a next-generation data management platform and a first-of-a-kind
"data agency" containing some of the most exclusive content-consuming audiences
across desktop, mobile and social platforms.

This real-time data module provides quality first-party data, contextual data,
site-level data and more that can be injected into bid request objects destined
for different bidders in order to optimize targeting.
Audigent is a next-generation, 1st party data management platform and the
world’s first "data agency", powering the programmatic landscape and DTC
eCommerce with actionable 1st party audience and contextual data from the
world’s most influential retailers, lifestyle publishers, content creators,
athletes and artists.

The Halo real-time data module in Prebid has been built so that publishers
can maximize the power of their first-party audiences and contextual data.
This module provides both an integrated cookieless Halo identity with real-time
contextual and audience segmentation solution that seamlessly and easily
integrates into your existing Prebid deployment.

Users, devices, content, cohorts and other features are identified and utilized
to augment every bid request with targeted, 1st party data-derived segments
before being submitted to supply-side platforms. Enriching the bid request with
robust 1st party audience and contextual data, Audigent's Halo RTD module
optimizes targeting, increases the number of bids, increases bid value,
and drives additional incremental revenue for publishers.

### Publisher Usage

Expand Down Expand Up @@ -113,7 +124,3 @@ To view an example of available segments returned by Audigent's backends:
and then point your browser at:

`http://localhost:9999/integrationExamples/gpt/haloRtdProvider_example.html`




15 changes: 15 additions & 0 deletions test/spec/modules/haloIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,20 @@ describe('HaloIdSystem', function () {
callback(callbackSpy);
expect(callbackSpy.lastCall.lastArg).to.deep.equal({haloId: 'tstCachedHaloId1'});
});

it('allows configurable id url', function() {
const config = {
params: {
url: 'https://haloid.publync.com'
}
};
const callbackSpy = sinon.spy();
const callback = haloIdSubmodule.getId(config).callback;
callback(callbackSpy);
const request = server.requests[0];
expect(request.url).to.eq('https://haloid.publync.com');
request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ haloId: 'testHaloId1' }));
expect(callbackSpy.lastCall.lastArg).to.deep.equal({haloId: 'testHaloId1'});
});
});
});
Loading