From 96516958eea723fce7333cbb0d3d659aa73685f7 Mon Sep 17 00:00:00 2001 From: gmiedlar-ox Date: Thu, 17 Jul 2025 13:48:58 +0200 Subject: [PATCH] EXCH-13317 Provide GPP params for user sync --- modules/openxBidAdapter.js | 7 +- test/spec/modules/openxBidAdapter_spec.js | 129 ++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index e287ad38417..2da04ad3e38 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -207,9 +207,10 @@ function interpretResponse(resp, req) { * @param responses * @param gdprConsent * @param uspConsent + * @param gppConsent * @return {{type: (string), url: (*|string)}[]} */ -function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent) { +function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent, gppConsent) { if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) { const pixelType = syncOptions.iframeEnabled ? 'iframe' : 'image'; const queryParamStrings = []; @@ -221,6 +222,10 @@ function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent) { if (uspConsent) { queryParamStrings.push('us_privacy=' + encodeURIComponent(uspConsent)); } + if (gppConsent?.gppString && gppConsent?.applicableSections?.length) { + queryParamStrings.push('gpp=' + encodeURIComponent(gppConsent.gppString)); + queryParamStrings.push('gpp_sid=' + gppConsent.applicableSections.join(',')); + } if (responses.length > 0 && responses[0].body && responses[0].body.ext) { const ext = responses[0].body.ext; if (ext.delDomain) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 1fb85682e0e..66151fa2633 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -988,6 +988,35 @@ describe('OpenxRtbAdapter', function () { expect(request[1].data.imp[0].ext.consent).to.equal(undefined); }); }); + + describe('GPP', function () { + it('should send GPP string and GPP section IDs in bid request when available', async function () { + bidderRequest.bids = bidRequests; + bidderRequest.ortb2 = { + regs: { + gpp: 'test-gpp-string', + gpp_sid: [6] + } + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.regs.gpp).to.equal('test-gpp-string'); + expect(request[0].data.regs.gpp_sid).to.deep.equal([6]); + expect(request[1].data.regs.gpp).to.equal('test-gpp-string'); + expect(request[1].data.regs.gpp_sid).to.deep.equal([6]); + }); + + it('should not send GPP string and GPP section IDs in bid request when not available', async function () { + bidderRequest.bids = bidRequests; + bidderRequest.ortb2 = { + regs: {} + }; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].data.regs.gpp).to.not.exist; + expect(request[0].data.regs.gpp_sid).to.not.exist; + expect(request[1].data.regs.gpp).to.not.exist; + expect(request[1].data.regs.gpp_sid).to.not.exist; + }); + }); }); context('coppa', function() { @@ -2031,6 +2060,106 @@ describe('OpenxRtbAdapter', function () { }); }); + describe('when gpp applies', function () { + it('should send GPP query params when GPP consent object available', () => { + const gppConsent = { + gppString: 'gpp-pixel-consent', + applicableSections: [6, 7] + } + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], + undefined, + undefined, + gppConsent + ); + + expect(url).to.have.string(`gpp=gpp-pixel-consent`); + expect(url).to.have.string(`gpp_sid=6,7`); + }); + + it('should send GDPR and GPP query params when both consent objects available', () => { + const gdprConsent = { + consentString: 'gdpr-pixel-consent', + gdprApplies: true + } + const gppConsent = { + gppString: 'gpp-pixel-consent', + applicableSections: [6, 7] + } + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], + gdprConsent, + undefined, + gppConsent + ); + + expect(url).to.have.string(`gdpr_consent=gdpr-pixel-consent`); + expect(url).to.have.string(`gdpr=1`); + expect(url).to.have.string(`gpp=gpp-pixel-consent`); + expect(url).to.have.string(`gpp_sid=6,7`); + }); + + it('should not send GPP query params when GPP string not available', function () { + const gppConsent = { + applicableSections: [6, 7] + } + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], + undefined, + undefined, + gppConsent + ); + + expect(url).to.not.have.string('gpp='); + expect(url).to.not.have.string('gpp_sid='); + }); + + it('should not send GPP query params when GPP section IDs not available', function () { + const gppConsent = { + gppString: 'gpp-pixel-consent', + } + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], + undefined, + undefined, + gppConsent + ); + + expect(url).to.not.have.string('gpp='); + expect(url).to.not.have.string('gpp_sid='); + }); + + it('should not send GPP query params when GPP section IDs empty', function () { + const gppConsent = { + gppString: 'gpp-pixel-consent', + applicableSections: [] + } + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], + undefined, + undefined, + gppConsent + ); + + expect(url).to.not.have.string('gpp='); + expect(url).to.not.have.string('gpp_sid='); + }); + + it('should not send GPP query params when GPP consent object not available', function () { + const [{url}] = spec.getUserSyncs( + {iframeEnabled: true, pixelEnabled: true}, + [], undefined, undefined, undefined + ); + expect(url).to.not.have.string('gpp='); + expect(url).to.not.have.string('gpp_sid='); + }); + }); + describe('when ccpa applies', function () { let usPrivacyConsent; let uspPixelUrl;