From 13733136ec651dd4a0411e2764dcb22daf55f613 Mon Sep 17 00:00:00 2001 From: Mike Groh Date: Tue, 21 Jan 2020 13:20:50 -0500 Subject: [PATCH] Trion gdpr and usp consent (#4740) * Adding files associated with the trion adapter update to the newest prebid version(1.0). * Updating pull request with safer checks for user sync and general clean up/consistency of tests. * removing a call to bidder code for pull request review. also removing the test that requires it * there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params. * Revert "there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params." This reverts commit 324d15785fb61c92db9c0a37f1001f47721e3a25. * there were some changes to the bid factory after our initial release that we didn't account for. Changing adapter to account for response body and required params. * adding safety checks to Trion adapter * Sending up to trion endpoint if there is bot traffic or the browser tab is not visible. * sending the wrong param in the test. * Trion test cleanup. returning document and window states to their original form after tests. * Trion test cleanup. using before and after to alter window and document objects in tests. * re-adding trion adapter to prebid project to stop using deprecated function for page url for 3.0 release * minor formatting change * accept size array from media types banner over the sizes array from pubs. * updating trion bid adapter to be us privacy and gdpr compliant * encoding consent strings for test --- modules/trionBidAdapter.js | 37 +++++++++++---- test/spec/modules/trionBidAdapter_spec.js | 56 +++++++++++++++++++++++ 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/modules/trionBidAdapter.js b/modules/trionBidAdapter.js index f31a460b0fe..6d564a66e2d 100644 --- a/modules/trionBidAdapter.js +++ b/modules/trionBidAdapter.js @@ -11,13 +11,13 @@ export const spec = { isBidRequestValid: function (bid) { return !!(bid && bid.params && bid.params.pubId && bid.params.sectionId); }, - buildRequests: function (validBidRequests) { + buildRequests: function (validBidRequests, bidderRequest) { var bidRequests = []; for (var i = 0; i < validBidRequests.length; i++) { var bid = validBidRequests[i]; - var trionUrlParams = buildTrionUrlParams(bid); + var trionUrlParams = buildTrionUrlParams(bid, bidderRequest); bidRequests.push({ method: 'GET', @@ -56,12 +56,12 @@ export const spec = { return bidResponses; }, - getUserSyncs: function getUserSyncs(syncOptions) { + getUserSyncs: function getUserSyncs(syncOptions, serverResponses, gdprConsent, usPrivacy) { if (syncOptions.iframeEnabled) { handlePostMessage(); return [{ type: 'iframe', - url: getSyncUrl() + url: getSyncUrl(gdprConsent, usPrivacy) }]; } } @@ -69,13 +69,23 @@ export const spec = { }; registerBidder(spec); -function getSyncUrl() { +function getSyncUrl(gdprConsent, usPrivacy) { var unParsedPubAndSection = getStorageData(BASE_KEY + 'lps') || ':'; var pubSectionArray = unParsedPubAndSection.split(':') || []; var pubId = pubSectionArray[0] || -1; var sectionId = pubSectionArray[1] || -1; var url = getPublisherUrl(); - return USER_SYNC_URL + `?p=${pubId}&s=${sectionId}&u=${url}`; + var consentParams = ''; + if (gdprConsent) { + if (gdprConsent.consentString) { + consentParams += '&gc=' + encodeURIComponent(gdprConsent.consentString); + } + consentParams += '&g=' + (gdprConsent.gdprApplies ? 1 : 0); + } + if (usPrivacy) { + consentParams = '&up=' + encodeURIComponent(usPrivacy); + } + return USER_SYNC_URL + `?p=${pubId}&s=${sectionId}${consentParams}&u=${url}`; } function getPublisherUrl() { @@ -95,7 +105,7 @@ function getPublisherUrl() { return url } -function buildTrionUrlParams(bid) { +function buildTrionUrlParams(bid, bidderRequest) { var pubId = utils.getBidIdParameter('pubId', bid.params); var sectionId = utils.getBidIdParameter('sectionId', bid.params); var re = utils.getBidIdParameter('re', bid.params); @@ -132,7 +142,18 @@ function buildTrionUrlParams(bid) { trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_wd', isAutomated); trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_hd', isHidden); trionUrl = utils.tryAppendQueryString(trionUrl, 'tr_vs', visibilityState); - + if (bidderRequest && bidderRequest.gdprConsent) { + var gdpr = bidderRequest.gdprConsent; + if (gdpr) { + if (gdpr.consentString) { + trionUrl = utils.tryAppendQueryString(trionUrl, 'gdprc', encodeURIComponent(gdpr.consentString)); + } + trionUrl = utils.tryAppendQueryString(trionUrl, 'gdpr', (gdpr.gdprApplies ? 1 : 0)); + } + } + if (bidderRequest && bidderRequest.uspConsent) { + trionUrl = utils.tryAppendQueryString(trionUrl, 'usp', encodeURIComponent(bidderRequest.uspConsent)); + } // remove the trailing "&" if (trionUrl.lastIndexOf('&') === trionUrl.length - 1) { trionUrl = trionUrl.substring(0, trionUrl.length - 1); diff --git a/test/spec/modules/trionBidAdapter_spec.js b/test/spec/modules/trionBidAdapter_spec.js index dc6bfb14a30..9a57f79e24f 100644 --- a/test/spec/modules/trionBidAdapter_spec.js +++ b/test/spec/modules/trionBidAdapter_spec.js @@ -27,6 +27,13 @@ const TRION_BID = { const TRION_BID_REQUEST = [TRION_BID]; +const TRION_BIDDER_REQUEST = { + 'bidderCode': 'trion', + 'auctionId': '12345', + 'bidderRequestId': 'abc1234', + 'bids': TRION_BID_REQUEST +}; + const TRION_BID_RESPONSE = { bidId: 'test-bid-id', sizes: [[300, 250], [300, 600]], @@ -197,6 +204,30 @@ describe('Trion adapter tests', function () { expect(bidUrlParams).to.include('tr_vs=hidden'); }); }); + + describe('should call buildRequests with correct consent params', function () { + it('when gdpr is present', function () { + TRION_BIDDER_REQUEST.gdprConsent = { + consentString: 'test_gdpr_str', + gdprApplies: true + }; + let bidRequests = spec.buildRequests(TRION_BID_REQUEST, TRION_BIDDER_REQUEST); + let bidUrlParams = bidRequests[0].data; + let gcEncoded = encodeURIComponent(TRION_BIDDER_REQUEST.gdprConsent.consentString); + expect(bidUrlParams).to.include('gdprc=' + gcEncoded); + expect(bidUrlParams).to.include('gdpr=1'); + delete TRION_BIDDER_REQUEST.gdprConsent; + }); + + it('when us privacy is present', function () { + TRION_BIDDER_REQUEST.uspConsent = '1YYY'; + let bidRequests = spec.buildRequests(TRION_BID_REQUEST, TRION_BIDDER_REQUEST); + let bidUrlParams = bidRequests[0].data; + let uspEncoded = encodeURIComponent(TRION_BIDDER_REQUEST.uspConsent); + expect(bidUrlParams).to.include('usp=' + uspEncoded); + delete TRION_BIDDER_REQUEST.uspConsent; + }); + }); }); describe('interpretResponse', function () { @@ -275,6 +306,31 @@ describe('Trion adapter tests', function () { expect(syncs[0]).to.deep.equal({type: 'iframe', url: USER_SYNC_URL + syncString}); }); + it('should register trion user script with gdpr params', function () { + let gdprConsent = { + consentString: 'test_gdpr_str', + gdprApplies: true + }; + let syncs = spec.getUserSyncs({iframeEnabled: true}, null, gdprConsent); + let pageUrl = getPublisherUrl(); + let pubId = 1; + let sectionId = 2; + let gcEncoded = encodeURIComponent(gdprConsent.consentString); + let syncString = `?p=${pubId}&s=${sectionId}&gc=${gcEncoded}&g=1&u=${pageUrl}`; + expect(syncs[0]).to.deep.equal({type: 'iframe', url: USER_SYNC_URL + syncString}); + }); + + it('should register trion user script with us privacy params', function () { + let uspConsent = '1YYY'; + let syncs = spec.getUserSyncs({iframeEnabled: true}, null, null, uspConsent); + let pageUrl = getPublisherUrl(); + let pubId = 1; + let sectionId = 2; + let uspEncoded = encodeURIComponent(uspConsent); + let syncString = `?p=${pubId}&s=${sectionId}&up=${uspEncoded}&u=${pageUrl}`; + expect(syncs[0]).to.deep.equal({type: 'iframe', url: USER_SYNC_URL + syncString}); + }); + it('should except posted messages from user sync script', function () { let testId = 'testId'; let message = BASE_KEY + 'userId=' + testId;