Skip to content

Commit ea17034

Browse files
kyrylenkoPavlo
andauthored
anonymisedRtdProvider: can load Anonymised Marketing Tag external script (prebid#12882)
* Can load Anonymised Marketing Tag external script * using clientId alias * introduced tagUrl param * added info about obtaining publisher's clientId * corrected URLs to anonymised support portal * review: ensure correct `clientId` type * test added "should not load external script when params.tagConfig is not defined" * better description --------- Co-authored-by: Pavlo <pavlo@id-ward.com>
1 parent b2f1df8 commit ea17034

File tree

5 files changed

+171
-20
lines changed

5 files changed

+171
-20
lines changed

integrationExamples/gpt/anonymised_segments_example.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@
5656
params: {
5757
cohortStorageKey: "cohort_ids",
5858
bidders: ['smartadserver', 'appnexus'],
59-
segtax: 1000
59+
segtax: 1000,
60+
tagConfig: {
61+
clientId: 'testId'
62+
}
6063
}
6164
}
6265
]

modules/anonymisedRtdProvider.js

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
*/
88
import {getStorageManager} from '../src/storageManager.js';
99
import {submodule} from '../src/hook.js';
10-
import {isPlainObject, mergeDeep, logMessage, logError} from '../src/utils.js';
10+
import {isPlainObject, mergeDeep, logMessage, logWarn, logError} from '../src/utils.js';
1111
import {MODULE_TYPE_RTD} from '../src/activities/modules.js';
12+
import {loadExternalScript} from '../src/adloader.js';
1213
/**
1314
* @typedef {import('../modules/rtdModule/index.js').RtdSubmodule} RtdSubmodule
1415
*/
1516
export function createRtdProvider(moduleName) {
1617
const MODULE_NAME = 'realTimeData';
1718
const SUBMODULE_NAME = moduleName;
1819
const GVLID = 1116;
20+
const MARKETING_TAG_URL = 'https://static.anonymised.io/light/loader.js';
1921

2022
const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: SUBMODULE_NAME });
2123
/**
@@ -42,17 +44,43 @@ export function createRtdProvider(moduleName) {
4244
return null;
4345
}
4446
}
47+
/**
48+
* Load the Anonymised Marketing Tag script
49+
* @param {Object} config
50+
*/
51+
function tryLoadMarketingTag(config) {
52+
const clientId = config?.params?.tagConfig?.clientId;
53+
if (typeof clientId !== 'string' || !clientId.trim()) {
54+
logWarn(`${SUBMODULE_NAME}RtdProvider: clientId missing or invalid; Marketing Tag not loaded.`);
55+
return;
56+
}
57+
logMessage(`${SUBMODULE_NAME}RtdProvider: Loading Marketing Tag`);
58+
// Check if the script is already loaded
59+
if (document.querySelector(`script[src*="${config.params.tagUrl ?? MARKETING_TAG_URL}"]`)) {
60+
logMessage(`${SUBMODULE_NAME}RtdProvider: Marketing Tag already loaded`);
61+
return;
62+
}
63+
const tagConfig = config.params?.tagConfig ? {...config.params.tagConfig, idw_client_id: config.params.tagConfig.clientId} : {};
64+
delete tagConfig.clientId;
65+
66+
const tagUrl = config.params.tagUrl ? config.params.tagUrl : `${MARKETING_TAG_URL}?ref=prebid`;
67+
68+
loadExternalScript(tagUrl, MODULE_TYPE_RTD, SUBMODULE_NAME, () => {
69+
logMessage(`${SUBMODULE_NAME}RtdProvider: Marketing Tag loaded successfully`);
70+
}, document, tagConfig);
71+
}
72+
4573
/**
4674
* Real-time data retrieval from Anonymised
4775
* @param {Object} reqBidsConfigObj
4876
* @param {function} onDone
49-
* @param {Object} rtdConfig
77+
* @param {Object} config
5078
* @param {Object} userConsent
5179
*/
52-
function getRealTimeData(reqBidsConfigObj, onDone, rtdConfig, userConsent) {
53-
if (rtdConfig && isPlainObject(rtdConfig.params)) {
54-
const cohortStorageKey = rtdConfig.params.cohortStorageKey;
55-
const bidders = rtdConfig.params.bidders;
80+
function getRealTimeData(reqBidsConfigObj, onDone, config, userConsent) {
81+
if (config && isPlainObject(config.params)) {
82+
const cohortStorageKey = config.params.cohortStorageKey;
83+
const bidders = config.params.bidders;
5684

5785
if (cohortStorageKey !== 'cohort_ids') {
5886
logError(`${SUBMODULE_NAME}RtdProvider: 'cohortStorageKey' should be 'cohort_ids'`)
@@ -70,7 +98,7 @@ export function createRtdProvider(moduleName) {
7098
const udSegment = {
7199
name: 'anonymised.io',
72100
ext: {
73-
segtax: rtdConfig.params.segtax
101+
segtax: config.params.segtax
74102
},
75103
segment: segments.map(x => ({id: x}))
76104
}
@@ -93,17 +121,17 @@ export function createRtdProvider(moduleName) {
93121
}
94122

95123
addRealTimeData(reqBidsConfigObj.ortb2Fragments?.global, data.rtd);
96-
onDone();
97124
}
98125
}
99126
}
100127
/**
101128
* Module init
102-
* @param {Object} provider
129+
* @param {Object} config
103130
* @param {Object} userConsent
104131
* @return {boolean}
105132
*/
106-
function init(provider, userConsent) {
133+
function init(config, userConsent) {
134+
tryLoadMarketingTag(config);
107135
return true;
108136
}
109137
/** @type {RtdSubmodule} */

modules/anonymisedRtdProvider.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ Anonymised’s Real-time Data Provider automatically obtains segment IDs from th
2525
params: {
2626
cohortStorageKey: "cohort_ids",
2727
bidders: ["appnexus", "onetag", "pubmatic", "smartadserver", ...],
28-
segtax: 1000
28+
segtax: 1000,
29+
tagConfig: {
30+
clientId: 'testId'
31+
//The rest of the Anonymised Marketing Tag parameters goes here
32+
}
2933
}
3034
}
3135
]
@@ -36,14 +40,19 @@ Anonymised’s Real-time Data Provider automatically obtains segment IDs from th
3640
### Config Syntax details
3741
| Name |Type | Description | Notes |
3842
| :------------ | :------------ | :------------ |:------------ |
39-
| name | String | Anonymised Rtd module name | 'anonymised' always|
40-
| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false |
41-
| params.cohortStorageKey | String | the `localStorage` key, under which Anonymised Marketing Tag stores the segment IDs | 'cohort_ids' always |
42-
| params.bidders | Array | Bidders with which to share segment information | Optional |
43-
| params.segtax | Integer | The taxonomy for Anonymised | '1000' always |
44-
45-
Please note that anonymisedRtdProvider should be integrated into the publisher website along with the [Anonymised Marketing Tag](https://support.anonymised.io/integrate/marketing-tag).
46-
Please reach out to Anonymised [representative](mailto:support@anonymised.io) if you have any questions or need further help to integrate Prebid, anonymisedRtdProvider, and Anonymised Marketing Tag
43+
| name | `String` | Anonymised Rtd module name | 'anonymised' always|
44+
| waitForIt | `Boolean` | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false |
45+
| params.cohortStorageKey | `String` | the `localStorage` key, under which Anonymised Marketing Tag stores the segment IDs | 'cohort_ids' always |
46+
| params.bidders | `Array` | Bidders with which to share segment information | Optional |
47+
| params.segtax | `Integer` | The taxonomy for Anonymised | '1000' always |
48+
| params.tagConfig | `Object` | Configuration for the Anonymised Marketing Tag | Optional. Defaults to `{}`. |
49+
| params.tagUrl | `String` | The URL of the Anonymised Marketing Tag script | Optional. Defaults to `https://static.anonymised.io/light/loader.js`. |
50+
51+
The `anonymisedRtdProvider` must be integrated into the publisher's website along with the [Anonymised Marketing Tag](https://support.anonymised.io/integrate/marketing-tag?t=LPukVCXzSIcRoal5jggyeg). One way to install the Marketing Tag is through `anonymisedRtdProvider` by specifying the required [parameters](https://support.anonymised.io/integrate/optional-anonymised-tag-parameters?t=LPukVCXzSIcRoal5jggyeg) in the `tagConfig` object.
52+
53+
The `tagConfig.clientId` parameter is mandatory for the Marketing Tag to initialize. If `tagConfig` is undefined or empty or `tagConfig.clientId` is undefined, the `anonymisedRtdProvider` will not initialize the Marketing Tag. The publisher's `clientId` is [provided by Anonymised](https://support.anonymised.io/integrate/install-the-anonymised-tag-natively#InstalltheAnonymisedtagnatively-Instructions?t=LPukVCXzSIcRoal5jggyeg).
54+
55+
For any questions or assistance with integrating Prebid, `anonymisedRtdProvider`, or the Anonymised Marketing Tag, please contact an [Anonymised representative](mailto:support@anonymised.io).
4756

4857
### Testing
4958
To view an example of available segments returned by Anonymised:

src/adloader.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const _approvedLoadExternalJSList = [
3737
'symitridap',
3838
'wurfl',
3939
'nodalsAi',
40+
'anonymised',
4041
// UserId Submodules
4142
'justtag',
4243
'tncId',

test/spec/modules/anonymisedRtdProvider_spec.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {config} from 'src/config.js';
22
import {getRealTimeData, anonymisedRtdSubmodule, storage} from 'modules/anonymisedRtdProvider.js';
3+
import { loadExternalScript } from '../../../src/adloader.js';
34

45
describe('anonymisedRtdProvider', function() {
56
let getDataFromLocalStorageStub;
@@ -34,6 +35,115 @@ describe('anonymisedRtdProvider', function() {
3435
it('successfully instantiates', function () {
3536
expect(anonymisedRtdSubmodule.init()).to.equal(true);
3637
});
38+
it('should load external script when params.tagConfig.clientId is set', function () {
39+
const rtdConfig = {
40+
params: {
41+
tagConfig: {
42+
clientId: 'testId'
43+
}
44+
}
45+
};
46+
anonymisedRtdSubmodule.init(rtdConfig, {});
47+
expect(loadExternalScript.called).to.be.true;
48+
});
49+
it('should not load external script when params.tagConfig.clientId is not set', function () {
50+
const rtdConfig = {
51+
params: {
52+
tagConfig: {}
53+
}
54+
};
55+
anonymisedRtdSubmodule.init(rtdConfig, {});
56+
expect(loadExternalScript.called).to.be.false;
57+
});
58+
it('should not load external script when params.tagConfig is not defined', function () {
59+
const rtdConfig = {
60+
params: {}
61+
};
62+
anonymisedRtdSubmodule.init(rtdConfig, {});
63+
expect(loadExternalScript.called).to.be.false;
64+
});
65+
it('should not load external script when params.tagConfig.clientId is empty string', function () {
66+
const rtdConfig = {
67+
params: {
68+
tagConfig: {
69+
clientId: ' '
70+
}
71+
}
72+
};
73+
anonymisedRtdSubmodule.init(rtdConfig, {});
74+
expect(loadExternalScript.called).to.be.false;
75+
});
76+
it('should not load external script when params.tagConfig.clientId is not a string', function () {
77+
const rtdConfig = {
78+
params: {
79+
tagConfig: {
80+
clientId: 123
81+
}
82+
}
83+
};
84+
anonymisedRtdSubmodule.init(rtdConfig, {});
85+
expect(loadExternalScript.called).to.be.false;
86+
});
87+
it('should load external script with correct attributes', function () {
88+
const rtdConfig = {
89+
params: {
90+
tagConfig: {
91+
clientId: 'testId'
92+
}
93+
}
94+
};
95+
anonymisedRtdSubmodule.init(rtdConfig, {});
96+
const expected = 'https://static.anonymised.io/light/loader.js?ref=prebid';
97+
const expectedTagConfig = {
98+
idw_client_id: 'testId'
99+
};
100+
101+
expect(loadExternalScript.args[0][0]).to.deep.equal(expected);
102+
expect(loadExternalScript.args[0][5]).to.deep.equal(expectedTagConfig);
103+
});
104+
it('should not load external script when it is already loaded', function () {
105+
const rtdConfig = {
106+
params: {
107+
tagConfig: {
108+
clientId: 'testId'
109+
}
110+
}
111+
};
112+
const script = document.createElement('script');
113+
script.src = 'https://static.anonymised.io/light/loader.js?random=quary';
114+
document.body.appendChild(script);
115+
anonymisedRtdSubmodule.init(rtdConfig, {});
116+
expect(loadExternalScript.called).to.be.false;
117+
});
118+
it('should load external script from tagUrl when it is set', function () {
119+
const rtdConfig = {
120+
params: {
121+
tagUrl: 'https://example.io/loader.js',
122+
tagConfig: {
123+
clientId: 'testId'
124+
}
125+
}
126+
};
127+
anonymisedRtdSubmodule.init(rtdConfig, {});
128+
const expected = 'https://example.io/loader.js';
129+
130+
expect(loadExternalScript.args[0][0]).to.deep.equal(expected);
131+
});
132+
it('should not load external script from tagUrl when it is already loaded', function () {
133+
const rtdConfig = {
134+
params: {
135+
tagUrl: 'https://example.io/loader.js',
136+
tagConfig: {
137+
clientId: 'testId'
138+
}
139+
}
140+
};
141+
const script = document.createElement('script');
142+
script.src = 'https://example.io/loader.js';
143+
document.body.appendChild(script);
144+
anonymisedRtdSubmodule.init(rtdConfig, {});
145+
expect(loadExternalScript.called).to.be.false;
146+
});
37147
});
38148

39149
describe('Get Real-Time Data', function() {

0 commit comments

Comments
 (0)