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

GPP MSPA enforcement activity controls: invalidate covered = 0 returns from the CMP #10351

Closed
wants to merge 4 commits into from
Closed
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
4 changes: 3 additions & 1 deletion libraries/mspa/activityControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export function isBasicConsentDenied(cd) {
// minors 13+ who have not given consent
cd.KnownChildSensitiveDataConsents[0] === 1 ||
// minors under 13 cannot consent
isApplicable(cd.KnownChildSensitiveDataConsents[1]);
isApplicable(cd.KnownChildSensitiveDataConsents[1]) ||
// covered cannot be zero
cd.MspaCoveredTransaction === 0;
}

export function sensitiveNoticeIs(cd, value) {
Expand Down
18 changes: 5 additions & 13 deletions modules/fledgeForGpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,18 @@ function isFledgeSupported() {

export function markForFledge(next, bidderRequests) {
if (isFledgeSupported()) {
const globalFledgeConfig = config.getConfig('fledgeForGpt');
const bidders = globalFledgeConfig?.bidders ?? [];
bidderRequests.forEach((req) => {
const useGlobalConfig = globalFledgeConfig?.enabled && (bidders.length == 0 || bidders.includes(req.bidderCode));
Object.assign(req, config.runWithBidder(req.bidderCode, () => {
return {
fledgeEnabled: config.getConfig('fledgeEnabled') ?? (useGlobalConfig ? globalFledgeConfig.enabled : undefined),
defaultForSlots: config.getConfig('defaultForSlots') ?? (useGlobalConfig ? globalFledgeConfig?.defaultForSlots : undefined)
}
}));
});
req.fledgeEnabled = config.runWithBidder(req.bidderCode, () => config.getConfig('fledgeEnabled'))
})
}
next(bidderRequests);
}
getHook('makeBidRequests').after(markForFledge);

export function setImpExtAe(imp, bidRequest, context) {
const impExt = imp.ext ?? {};
impExt.ae = context.bidderRequest.fledgeEnabled ? (impExt.ae ?? context.bidderRequest.defaultForSlots) : undefined;
imp.ext = impExt;
if (!context.bidderRequest.fledgeEnabled) {
delete imp.ext?.ae;
}
}
registerOrtbProcessor({type: IMP, name: 'impExtAe', fn: setImpExtAe});

Expand Down
27 changes: 10 additions & 17 deletions modules/fledgeForGpt.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,24 @@ This is accomplished by adding the `fledgeForGpt` module to the list of modules
gulp build --modules=fledgeForGpt,...
```

Second, they must enable FLEDGE in their Prebid.js configuration.
This is done through module level configuration, but to provide a high degree of flexiblity for testing, FLEDGE settings also exist at the bidder level and slot level.
Second, they must enable FLEDGE in their Prebid.js configuration. To provide a high degree of flexiblity for testing, FLEDGE
settings exist at the module level, the bidder level, and the slot level.

### Module Configuration
This module exposes the following settings:

|Name |Type |Description |Notes |
| :------------ | :------------ | :------------ |:------------ |
|enabled | Boolean |Enable/disable the module |Defaults to `false` |
|bidders | Array[String] |Optional list of bidders |Defaults to all bidders |
|defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1 |

As noted above, FLEDGE support is disabled by default. To enable it, set the `enabled` value to `true` for this module and configure `defaultForSlots` to be `1` (meaning _Client-side auction_).
using the `setConfig` method of Prebid.js. Optionally, a list of
bidders to apply these settings to may be provided:
As noted above, FLEDGE support is disabled by default. To enable it, set the `enabled` value to `true` for this module
using the `setConfig` method of Prebid.js:

```js
pbjs.que.push(function() {
pbjs.setConfig({
fledgeForGpt: {
enabled: true,
bidders: ['openx', 'rtbhouse'],
defaultForSlots: 1
enabled: true
}
});
});
Expand All @@ -49,25 +44,23 @@ This module adds the following setting for bidders:
|Name |Type |Description |Notes |
| :------------ | :------------ | :------------ |:------------ |
| fledgeEnabled | Boolean | Enable/disable a bidder to participate in FLEDGE | Defaults to `false` |
|defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1|

Individual bidders may be further included or excluded here using the `setBidderConfig` method
In addition to enabling FLEDGE at the module level, individual bidders must also be enabled. This allows publishers to
selectively test with one or more bidders as they desire. To enable one or more bidders, use the `setBidderConfig` method
of Prebid.js:

```js
pbjs.setBidderConfig({
bidders: ["openx"],
config: {
fledgeEnabled: true,
defaultForSlots: 1
fledgeEnabled: true
}
});
```

### AdUnit Configuration
All adunits can be opted-in to FLEDGE in the global config via the `defaultForSlots` parameter.
If needed, adunits can be configured individually by setting an attribute of the `ortb2Imp` object for that
adunit. This attribute will take precedence over `defaultForSlots` setting.
Enabling an adunit for FLEDGE eligibility is accomplished by setting an attribute of the `ortb2Imp` object for that
adunit.

|Name |Type |Description |Notes |
| :------------ | :------------ | :------------ |:------------ |
Expand Down
6 changes: 6 additions & 0 deletions test/spec/libraries/mspa/activityControls_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ describe('Consent interpretation', () => {
}));
expect(result).to.equal(true);
});
it('should be true (basic consent conditions do not pass) with covered set to zero (invalid state)', () => {
const result = isBasicConsentDenied(mkConsent({
MspaCoveredTransaction: 0
}));
expect(result).to.equal(true);
});
it('should not deny when consent for under-13 is null', () => {
expect(isBasicConsentDenied(mkConsent({
KnownChildSensitiveDataConsents: [0, null]
Expand Down
156 changes: 42 additions & 114 deletions test/spec/modules/fledge_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,131 +61,59 @@ describe('fledgeEnabled', function () {
config.resetConfig();
});

const adUnits = [{
'code': '/19968336/header-bid-tag1',
'mediaTypes': {
'banner': {
'sizes': [[728, 90]]
},
},
'bids': [
{
'bidder': 'appnexus',
},
{
'bidder': 'rubicon',
},
]
}];

describe('with setBidderConfig()', () => {
it('should set fledgeEnabled correctly per bidder', function () {
config.setConfig({bidderSequence: 'fixed'})
config.setBidderConfig({
bidders: ['appnexus'],
config: {
fledgeEnabled: true,
defaultForSlots: 1,
}
});

const bidRequests = adapterManager.makeBidRequests(
adUnits,
Date.now(),
utils.getUniqueIdentifierStr(),
function callback() {},
[]
);

expect(bidRequests[0].bids[0].bidder).equals('appnexus');
expect(bidRequests[0].fledgeEnabled).to.be.true;
expect(bidRequests[0].defaultForSlots).to.equal(1);

expect(bidRequests[1].bids[0].bidder).equals('rubicon');
expect(bidRequests[1].fledgeEnabled).to.be.undefined;
expect(bidRequests[1].defaultForSlots).to.be.undefined;
});
});

describe('with setConfig()', () => {
it('should set fledgeEnabled correctly per bidder', function () {
config.setConfig({
bidderSequence: 'fixed',
fledgeForGpt: {
enabled: true,
bidders: ['appnexus'],
defaultForSlots: 1,
}
});

const bidRequests = adapterManager.makeBidRequests(
adUnits,
Date.now(),
utils.getUniqueIdentifierStr(),
function callback() {},
[]
);

expect(bidRequests[0].bids[0].bidder).equals('appnexus');
expect(bidRequests[0].fledgeEnabled).to.be.true;
expect(bidRequests[0].defaultForSlots).to.equal(1);

expect(bidRequests[1].bids[0].bidder).equals('rubicon');
expect(bidRequests[1].fledgeEnabled).to.be.undefined;
expect(bidRequests[1].defaultForSlots).to.be.undefined;
it('should set fledgeEnabled correctly per bidder', function () {
config.setConfig({bidderSequence: 'fixed'})
config.setBidderConfig({
bidders: ['appnexus'],
config: {
fledgeEnabled: true,
}
});

it('should set fledgeEnabled correctly for all bidders', function () {
config.setConfig({
bidderSequence: 'fixed',
fledgeForGpt: {
enabled: true,
defaultForSlots: 1,
}
});

const bidRequests = adapterManager.makeBidRequests(
adUnits,
Date.now(),
utils.getUniqueIdentifierStr(),
function callback() {},
[]
);

expect(bidRequests[0].bids[0].bidder).equals('appnexus');
expect(bidRequests[0].fledgeEnabled).to.be.true;
expect(bidRequests[0].defaultForSlots).to.equal(1);

expect(bidRequests[1].bids[0].bidder).equals('rubicon');
expect(bidRequests[0].fledgeEnabled).to.be.true;
expect(bidRequests[0].defaultForSlots).to.equal(1);
});
const adUnits = [{
'code': '/19968336/header-bid-tag1',
'mediaTypes': {
'banner': {
'sizes': [[728, 90]]
},
},
'bids': [
{
'bidder': 'appnexus',
},
{
'bidder': 'rubicon',
},
]
}];

const bidRequests = adapterManager.makeBidRequests(
adUnits,
Date.now(),
utils.getUniqueIdentifierStr(),
function callback() {},
[]
);

expect(bidRequests[0].bids[0].bidder).equals('appnexus');
expect(bidRequests[0].fledgeEnabled).to.be.true;

expect(bidRequests[1].bids[0].bidder).equals('rubicon');
expect(bidRequests[1].fledgeEnabled).to.be.undefined;
});
});

describe('ortb processors for fledge', () => {
describe('when defaultForSlots is set', () => {
it('imp.ext.ae should be set if fledge is enabled', () => {
const imp = {};
setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true, defaultForSlots: 1}});
expect(imp.ext.ae).to.equal(1);
});
it('imp.ext.ae should be left intact if set on adunit and fledge is enabled', () => {
const imp = {ext: {ae: 2}};
setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true, defaultForSlots: 1}});
expect(imp.ext.ae).to.equal(2);
});
});
describe('when defaultForSlots is not defined', () => {
it('imp.ext.ae should be removed if fledge is not enabled', () => {
describe('imp.ext.ae', () => {
it('should be removed if fledge is not enabled', () => {
const imp = {ext: {ae: 1}};
setImpExtAe(imp, {}, {bidderRequest: {}});
expect(imp.ext.ae).to.not.exist;
})
it('imp.ext.ae should be left intact if fledge is enabled', () => {
const imp = {ext: {ae: 2}};
it('should be left intact if fledge is enabled', () => {
const imp = {ext: {ae: false}};
setImpExtAe(imp, {}, {bidderRequest: {fledgeEnabled: true}});
expect(imp.ext.ae).to.equal(2);
expect(imp.ext.ae).to.equal(false);
});
});
describe('parseExtPrebidFledge', () => {
Expand Down