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

Tnc id module: initial release #8435

Merged
merged 31 commits into from
Jun 18, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bfb41d2
- TNCID UserID Module
May 12, 2022
d6221b0
revert
May 12, 2022
a497bc7
- TNCID UserID Module
May 12, 2022
d848061
- TNCID UserID Module
May 13, 2022
3796588
Converted loadTNCScript to Promise
micheletnc May 13, 2022
ff1b883
Merge branch 'TNCID' of https://github.com/annavane/Prebid.js into TNCID
May 13, 2022
2f754ca
Added CacheID
micheletnc May 13, 2022
eb5ab8f
Merge branch 'TNCID' of https://github.com/annavane/Prebid.js into TNCID
May 13, 2022
015e0a6
- TNCID UserID module
May 19, 2022
85d543e
- Documentation updated
May 19, 2022
71e6314
- File naming fix
May 20, 2022
850dc77
- type fix
May 20, 2022
571ad11
Merge branch 'master' into TNCID
May 20, 2022
3ff4377
-no change
May 23, 2022
1f5daad
- space removed
May 23, 2022
950469b
new line removed
May 23, 2022
ad2b0d4
Merge branch 'master' into TNCID
annavane May 24, 2022
f1b5c46
Merge branch 'TNCID' of https://github.com/annavane/Prebid.js into TNCID
May 24, 2022
34505bf
- lint fix
May 24, 2022
bd60ddc
- eids fix
May 24, 2022
799f6c1
- .submodules.json: module name moved in alphabetical order
May 30, 2022
e185380
- tnc script loaded by loadExternalScript util function
Jun 7, 2022
38a51b1
Merge branch 'master' into TNCID
annavane Jun 7, 2022
58d7b23
-resolved lint errors
Jun 7, 2022
83b8984
Merge branch 'TNCID' of https://github.com/annavane/Prebid.js into TNCID
Jun 7, 2022
95c1c5c
- module name refactoring
Jun 9, 2022
038ccdb
- input parameter added to disable load of fallback script
Jun 9, 2022
dae17ef
Merge branch 'master' into TNCID
annavane Jun 14, 2022
0540994
- TNC fallback script is now input param
Jun 15, 2022
09b57a7
Merge branch 'TNCID' of https://github.com/annavane/Prebid.js into TNCID
Jun 15, 2022
6f0e847
- Added missing tests
Jun 15, 2022
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
3 changes: 2 additions & 1 deletion modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"unifiedIdSystem",
"verizonMediaIdSystem",
"zeotapIdPlusIdSystem",
"adqueryIdSystem",
"tncIdSystem",
annavane marked this conversation as resolved.
Show resolved Hide resolved
"adqueryIdSystem",
"gravitoIdSystem"
],
"adpod": [
Expand Down
85 changes: 85 additions & 0 deletions modules/tncIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { submodule } from '../src/hook.js';
import { logInfo } from '../src/utils.js';

const MODULE_NAME = 'tncId';
const FALLBACK_TNC_PROVIDERID = 'c8549079-f149-4529-a34b-3fa91ef257d1';
const FALLBACK_TNC_INSTANCE = '__tncPbjs';

const loadRemoteTNCScript = (providerId) => {
try {
let tncOptions = {
autostart: true,
tcf: true,
getFiles: {
cacheid: true, // true
options: false, // true
callback: false, // true
prepare: false, // false
scripts: false // true
}
};
let t = window;
let n = t.document;
let c = FALLBACK_TNC_INSTANCE;
let i = providerId;
let d = tncOptions;

t[c] = t[c] || {}; t[c].providerId = i; t[c].options = t[c].options || d;
var f = 'ready'; t[c][f] = t[c][f] || function (z) {
t[c][f].q = t[c][f].q || []; t[c][f].q.push(z);
return t[c];
}; var s = n.createElement('script'); s.setAttribute('global', c); s.async = !0;
s.defer = !0; s.id = 'tnc_route'; s.src = 'https://js.tncid.app/route.js';
n.querySelector('head,body').appendChild(s);
annavane marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) { }
}

const waitTNCScript = (tncNS) => {
return new Promise((resolve, reject) => {
var tnc = window[tncNS];
if (!tnc) reject(new Error('No TNC Object'));
if (tnc.tncid) resolve(tnc.tncid);
tnc.ready(() => {
tnc = window[tncNS];
if (tnc.tncid) resolve(tnc.tncid);
else tnc.on('data-sent', () => resolve(tnc.tncid));
});
});
}

const tncCallback = function (providerId, cb) {
let tncNS = '__tnc';
if (!window[tncNS]) {
tncNS = FALLBACK_TNC_INSTANCE;
loadRemoteTNCScript(providerId);
}

return waitTNCScript(tncNS).then(cb).catch(() => cb());
}

export const tncidSubModule = {
name: MODULE_NAME,
decode(id) {
return {
tncid: id
};
},
gvlid: 750,
getId(config, consentData) {
const gdpr = (consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies) ? 1 : 0;
const consentString = gdpr ? consentData.consentString : '';
let providerId = FALLBACK_TNC_PROVIDERID;
if (config && config.params && config.params.providerId)providerId = config.params.providerId;

if (gdpr && !consentString) {
logInfo('Consent string is required for TNCID module');
return;
}

return {
callback: function (cb) { return tncCallback(providerId, cb); }
}
}
}

submodule('userId', tncidSubModule)
34 changes: 34 additions & 0 deletions modules/tncIdSystem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# TNCID UserID Module

### Prebid Configuration

First, make sure to add the TNCID submodule to your Prebid.js package with:

```
gulp build --modules=tncIdSystem,userId
```

### TNCIDIdSystem module Configuration

You can configure this submodule in your `userSync.userIds[]` configuration:

```javascript
pbjs.setConfig({
userSync: {
userIds: [
{
name: 'tncId',
params: {
providerId: "c8549079-f149-4529-a34b-3fa91ef257d1" // Optional
}
annavane marked this conversation as resolved.
Show resolved Hide resolved
}
]
}
});
```
#### Configuration Params

| Param Name | Required | Type | Description |
| --- | --- | --- | --- |
| name | Required | String | ID value for the TNCID module: `"tncId"` |
| params.providerId | Optional | String | Provide TNC providerId if possible |
7 changes: 7 additions & 0 deletions modules/userId/eids.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,18 @@ export const USER_IDS_CONFIG = {
}
},

// tncId
'tncid': {
source: 'thenewco.it',
atype: 3
},

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you appear to be missing changes to eids.md, user id spec and eids spec

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this was resolved without changes

// Gravito MP ID
'gravitompId': {
source: 'gravito.net',
atype: 1
},

};

// this function will create an eid object for the given UserId sub-module
Expand Down
108 changes: 108 additions & 0 deletions test/spec/modules/tncIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { tncidSubModule } from 'modules/tncIdSystem';

const consentData = {
gdprApplies: true,
consentString: 'GDPR_CONSENT_STRING'
};

describe('TNCID tests', function () {
describe('name', () => {
it('should expose the name of the submodule', () => {
expect(tncidSubModule.name).to.equal('tncId');
});
});

describe('gvlid', () => {
it('should expose the vendor id', () => {
expect(tncidSubModule.gvlid).to.equal(750);
});
});

describe('decode', () => {
it('should wrap the given value inside an object literal', () => {
expect(tncidSubModule.decode('TNCID_TEST_ID')).to.deep.equal({
tncid: 'TNCID_TEST_ID'
});
});
});

describe('getId', () => {
afterEach(function () {
Object.defineProperty(window, '__tnc', {value: undefined, configurable: true});
Object.defineProperty(window, '__tncPbjs', {value: undefined, configurable: true});
});

it('Should NOT give TNCID if GDPR applies but consent string is missing', function () {
const res = tncidSubModule.getId(null, { gdprApplies: true });
expect(res).to.be.undefined;
});

it('GDPR is OK and page has no TNC script on page, script goes in error, no TNCID is returned', function () {
const completeCallback = sinon.spy();
const {callback} = tncidSubModule.getId(null, consentData);

return callback(completeCallback).then(() => {
expect(completeCallback.calledOnce).to.be.true;
})
});

it('GDPR is OK and page has TNC script with ns: __tnc, present TNCID is returned', function () {
Object.defineProperty(window, '__tnc', {
value: {
ready: (readyFunc) => { readyFunc() },
on: (name, cb) => { cb() },
tncid: 'TNCID_TEST_ID_1',
providerId: 'TEST_PROVIDER_ID_1',
},
configurable: true
});

const completeCallback = sinon.spy();
const {callback} = tncidSubModule.getId(null, { gdprApplies: false });

return callback(completeCallback).then(() => {
expect(completeCallback.calledOnceWithExactly('TNCID_TEST_ID_1')).to.be.true;
})
});

it('GDPR is OK and page has TNC script with ns: __tnc but not loaded, TNCID is assigned and returned', function () {
Object.defineProperty(window, '__tnc', {
value: {
ready: (readyFunc) => { readyFunc() },
on: (name, cb) => { cb() },
providerId: 'TEST_PROVIDER_ID_1',
},
configurable: true
});

const completeCallback = sinon.spy();
const {callback} = tncidSubModule.getId(null, { gdprApplies: false });

return callback(completeCallback).then(() => {
expect(completeCallback.calledOnce).to.be.true;
})
});

it('GDPR is OK and page has TNC script with ns: __tncPbjs, TNCID is returned', function () {
Object.defineProperty(window, '__tncPbjs', {
value: {
ready: (readyFunc) => { readyFunc() },
on: (name, cb) => { cb() },
providerId: 'TEST_PROVIDER_ID_1',
options: {},
tncid: 'TNCID_TEST_ID_2'
},
configurable: true,
writable: true
});

const completeCallback = sinon.spy();
const {callback} = tncidSubModule.getId({params: {providerId: 'TEST_PROVIDER_ID_2'}}, consentData);

return callback(completeCallback).then(() => {
expect(completeCallback.calledOnceWithExactly('TNCID_TEST_ID_2')).to.be.true;
expect(window.__tncPbjs.providerId).to.be.eq('TEST_PROVIDER_ID_2');
})
});
});
});