Skip to content

Commit

Permalink
Pass CCPA consent string to all endpoints (prebid#4536)
Browse files Browse the repository at this point in the history
  • Loading branch information
slimkrazy authored and Isaac A. Dettman committed Dec 11, 2019
1 parent 01450f5 commit 04c775f
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 40 deletions.
47 changes: 25 additions & 22 deletions modules/aolBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ export const spec = {
return isMarketplaceBid(bid) || isMobileBid(bid);
},
buildRequests(bids, bidderRequest) {
let consentData = bidderRequest ? bidderRequest.gdprConsent : null;
const consentData = {};
if (bidderRequest) {
consentData.gdpr = bidderRequest.gdprConsent;
consentData.uspConsent = bidderRequest.uspConsent;
}

return bids.map(bid => {
const endpointCode = resolveEndpointCode(bid);
Expand Down Expand Up @@ -230,7 +234,7 @@ export const spec = {
}
return (url.indexOf('//') === 0) ? `${DEFAULT_PROTO}:${url}` : `${DEFAULT_PROTO}://${url}`;
},
formatMarketplaceDynamicParams(params = {}, consentData) {
formatMarketplaceDynamicParams(params = {}, consentData = {}) {
let queryParams = {};

if (params.bidFloor) {
Expand All @@ -247,7 +251,7 @@ export const spec = {

return paramsFormatted;
},
formatOneMobileDynamicParams(params = {}, consentData) {
formatOneMobileDynamicParams(params = {}, consentData = {}) {
if (this.isSecureProtocol()) {
params.secure = NUMERIC_VALUES.TRUE;
}
Expand All @@ -261,32 +265,27 @@ export const spec = {

return paramsFormatted;
},
buildOpenRtbRequestData(bid, consentData) {
buildOpenRtbRequestData(bid, consentData = {}) {
let openRtbObject = {
id: bid.params.id,
imp: bid.params.imp
};

if (this.isConsentRequired(consentData)) {
openRtbObject.regs = {
ext: {
gdpr: NUMERIC_VALUES.TRUE
}
};

if (consentData.consentString) {
openRtbObject.user = {
ext: {
consent: consentData.consentString
}
};
if (this.isEUConsentRequired(consentData)) {
utils.deepSetValue(openRtbObject, 'regs.ext.gdpr', NUMERIC_VALUES.TRUE);
if (consentData.gdpr.consentString) {
utils.deepSetValue(openRtbObject, 'user.ext.consent', consentData.gdpr.consentString);
}
}

if (consentData.uspConsent) {
utils.deepSetValue(openRtbObject, 'regs.ext.us_privacy', consentData.uspConsent);
}

return openRtbObject;
},
isConsentRequired(consentData) {
return !!(consentData && consentData.gdprApplies);
isEUConsentRequired(consentData) {
return !!(consentData && consentData.gdpr && consentData.gdpr.gdprApplies);
},
formatKeyValues(keyValues) {
let keyValuesHash = {};
Expand All @@ -300,14 +299,18 @@ export const spec = {
formatConsentData(consentData) {
let params = {};

if (this.isConsentRequired(consentData)) {
if (this.isEUConsentRequired(consentData)) {
params.gdpr = NUMERIC_VALUES.TRUE;

if (consentData.consentString) {
params.euconsent = consentData.consentString;
if (consentData.gdpr.consentString) {
params.euconsent = consentData.gdpr.consentString;
}
}

if (consentData.uspConsent) {
params.us_privacy = consentData.uspConsent;
}

return params;
},
parsePixelItems(pixels) {
Expand Down
168 changes: 150 additions & 18 deletions test/spec/modules/aolBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,94 @@ describe('AolAdapter', function () {
});
});

describe('buildOpenRtbRequestData', () => {
const bid = {
params: {
id: 'bid-id',
imp: []
}
};
let euConsentRequiredStub;

beforeEach(function () {
euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired');
});

afterEach(function () {
euConsentRequiredStub.restore();
});

it('returns the basic bid info when regulation data is omitted', () => {
expect(spec.buildOpenRtbRequestData(bid)).to.deep.equal({
id: 'bid-id',
imp: []
});
});

it('returns the basic bid info with gdpr data when gdpr consent data is included', () => {
let consentData = {
gdpr: {
consentString: 'someEUConsent'
}
};
euConsentRequiredStub.returns(true);
expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({
id: 'bid-id',
imp: [],
regs: {
ext: {
gdpr: 1
}
},
user: {
ext: {
consent: 'someEUConsent'
}
}
});
});

it('returns the basic bid info with CCPA data when CCPA consent data is included', () => {
let consentData = {
uspConsent: 'someUSPConsent'
};
expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({
id: 'bid-id',
imp: [],
regs: {
ext: {
us_privacy: 'someUSPConsent'
}
}
});
});

it('returns the basic bid info with GDPR and CCPA data when GDPR and CCPA consent data is included', () => {
let consentData = {
gdpr: {
consentString: 'someEUConsent'
},
uspConsent: 'someUSPConsent'
};
euConsentRequiredStub.returns(true);
expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({
id: 'bid-id',
imp: [],
regs: {
ext: {
gdpr: 1,
us_privacy: 'someUSPConsent'
}
},
user: {
ext: {
consent: 'someEUConsent'
}
}
});
});
});

describe('getUserSyncs()', function () {
let serverResponses;
let bidResponse;
Expand Down Expand Up @@ -545,36 +633,42 @@ describe('AolAdapter', function () {
});
});

describe('isConsentRequired()', function () {
describe('isEUConsentRequired()', function () {
it('should return false when consentData object is not present', function () {
expect(spec.isConsentRequired(null)).to.be.false;
expect(spec.isEUConsentRequired(null)).to.be.false;
});

it('should return true when gdprApplies equals true and consentString is not present', function () {
let consentData = {
consentString: null,
gdprApplies: true
gdpr: {
consentString: null,
gdprApplies: true
}
};

expect(spec.isConsentRequired(consentData)).to.be.true;
expect(spec.isEUConsentRequired(consentData)).to.be.true;
});

it('should return false when consentString is present and gdprApplies equals false', function () {
let consentData = {
consentString: 'consent-string',
gdprApplies: false
gdpr: {
consentString: 'consent-string',
gdprApplies: false
}
};

expect(spec.isConsentRequired(consentData)).to.be.false;
expect(spec.isEUConsentRequired(consentData)).to.be.false;
});

it('should return true when consentString is present and gdprApplies equals true', function () {
let consentData = {
consentString: 'consent-string',
gdprApplies: true
gdpr: {
consentString: 'consent-string',
gdprApplies: true
}
};

expect(spec.isConsentRequired(consentData)).to.be.true;
expect(spec.isEUConsentRequired(consentData)).to.be.true;
});
});

Expand All @@ -596,14 +690,31 @@ describe('AolAdapter', function () {
expect(spec.formatMarketplaceDynamicParams()).to.be.equal('');
});

it('should return formatted params when formatConsentData returns data', function () {
it('should return formatted EU consent params when formatConsentData returns GDPR data', function () {
formatConsentDataStub.returns({
euconsent: 'test-consent',
gdpr: 1
});
expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;');
});

it('should return formatted US privacy params when formatConsentData returns USP data', function () {
formatConsentDataStub.returns({
us_privacy: 'test-usp-consent'
});
expect(spec.formatMarketplaceDynamicParams()).to.be.equal('us_privacy=test-usp-consent;');
});

it('should return formatted EU and USP consent params when formatConsentData returns all data', function () {
formatConsentDataStub.returns({
euconsent: 'test-consent',
gdpr: 1,
us_privacy: 'test-usp-consent'
});
expect(spec.formatMarketplaceDynamicParams()).to.be.equal(
'euconsent=test-consent;gdpr=1;us_privacy=test-usp-consent;');
});

it('should return formatted params when formatKeyValues returns data', function () {
formatKeyValuesStub.returns({
param1: 'val1',
Expand All @@ -622,16 +733,16 @@ describe('AolAdapter', function () {
});

describe('formatOneMobileDynamicParams()', function () {
let consentRequiredStub;
let euConsentRequiredStub;
let secureProtocolStub;

beforeEach(function () {
consentRequiredStub = sinon.stub(spec, 'isConsentRequired');
euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired');
secureProtocolStub = sinon.stub(spec, 'isSecureProtocol');
});

afterEach(function () {
consentRequiredStub.restore();
euConsentRequiredStub.restore();
secureProtocolStub.restore();
});

Expand All @@ -648,14 +759,35 @@ describe('AolAdapter', function () {
expect(spec.formatOneMobileDynamicParams(params)).to.contain('&param1=val1&param2=val2&param3=val3');
});

it('should return formatted gdpr params when isConsentRequired returns true', function () {
it('should return formatted gdpr params when isEUConsentRequired returns true', function () {
let consentData = {
consentString: 'test-consent'
gdpr: {
consentString: 'test-consent'
}
};
consentRequiredStub.returns(true);
euConsentRequiredStub.returns(true);
expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent');
});

it('should return formatted US privacy params when consentData contains USP data', function () {
let consentData = {
uspConsent: 'test-usp-consent'
};
expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal('us_privacy=test-usp-consent;');
});

it('should return formatted EU and USP consent params when consentData contains gdpr and usp values', function () {
euConsentRequiredStub.returns(true);
let consentData = {
gdpr: {
consentString: 'test-consent'
},
uspConsent: 'test-usp-consent'
};
expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal(
'gdpr=1;euconsent=test-consent;us_privacy=test-usp-consent;');
});

it('should return formatted secure param when isSecureProtocol returns true', function () {
secureProtocolStub.returns(true);
expect(spec.formatOneMobileDynamicParams()).to.be.equal('&secure=1');
Expand Down

0 comments on commit 04c775f

Please sign in to comment.