From 274872dd1f711e12151e94e980aa84e0a44477af Mon Sep 17 00:00:00 2001 From: yagovelazquezfreestar <143502852+yagovelazquezfreestar@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:09:52 -0300 Subject: [PATCH] PFG-2579: prebid update to latest 8.30.0 (#169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Increment version to 8.28.0-pre * Support UID 2.0 pgamssp module (#10771) * new adapter PGAMSSP * upd * support UID 2.0 * del obj * ADSS-1756-pass-gpid-to-video-requests (#10809) Co-authored-by: John Bauzon * Browsi RTD : fix for targeting (#10814) * real time data module, browsi sub module for real time data, new hook bidsBackCallback, fix for config unsubscribe * change timeout&primary ad server only to auctionDelay update docs * support multiple providers * change promise to callbacks configure submodule on submodules.json * bug fixes * use Prebid ajax * tests fix * browsi real time data provider improvements * real time data module, browsi sub module for real time data, new hook bidsBackCallback, fix for config unsubscribe * change timeout&primary ad server only to auctionDelay update docs * support multiple providers * change promise to callbacks configure submodule on submodules.json * bug fixes * use Prebid ajax * tests fix * browsi real time data provider improvements * browsi-rtd-targeting-fix * nextMillennium Bid Adapter : add pbjs version and support for user.eids (#10812) * added support for gpp consent string * changed test for nextMillenniumBidAdapter * added some tests * added site.pagecat, site.content.cat and site.content.language to request * lint fix * formated code * formated code * formated code * pachage-lock with prebid * pachage-lock with prebid * formatted code * added device.sua, user.eids * formatted * fixed tests * fixed bug functio getSua * Update deepintentBidAdapter.js (#10818) * GC-158 When accessing the TCF it is pulling from the wrong location, use userConsent.gdpr.consentString (#10808) * Adagio Analytics Adapter: listen to AUCTION_END (#10798) * Adagio Analytics Adapter: add tracker on auction_end * Adagio Analytics Adapter: refacto metadata transfer * Adagio Analytics Adapter: update pba props --------- Co-authored-by: François Rotta * PubMaticAnalyticAdapter : Added new fields related to floors (fetch status, source of floor, provider and unique id) in analytics call (#10768) * Added floors field to logger call * Added sid in logger records * Pubmatic Analytics Adapter : skip duplicate data for pubmatic bids in logger and tracker (#10787) * Adding config for openwrap metadapter * Changed from http to https and timeout to 500 * Timeout value update * 1.Added safechecks for s2s metadapter case 2.Skipped firing client side tracker for pubmatic 3.Skipped adding pubmatic bid in logger * Analytics adapter changes to avoid duplicate data in case of OW S2S setup * Moved to bottom * kick off tests --------- Co-authored-by: Chris Huie * support ad unit name (#10825) * PBjs Core : new event fired before add bid response (#10685) * new event before add bid response * test new event is emit * change new event name * Revert "Pubmatic Analytics Adapter : skip duplicate data for pubmatic bids in logger and tracker (#10787)" (#10830) This reverts commit 048f735ccea9907ca72f068042bd35394c58689b. * Revert "support ad unit name (#10825)" (#10831) This reverts commit 947a487550e3fea398ae6887287635cf755bacb8. * Invibes Bid Adapter : infinite scroll tcf (#10764) * added prevent page view event param in order to differentiate from the first and following request on multi request; added disableUserSyncs in order to disable that functionality as default and added the option to activate it from the bidRequest * added infinite scroll and page refresh params, updated tcf, changed randomId to guid, updated the subdomain * reverted subdomain * Update invibesBidAdapter.js with code review suggestion * Moved new variables to invibes object * Update invibesBidAdapter.js add placementIds to invibes object * initialized window.invibes * Mediago Bid Adapter : switch domain name (#10833) * Mediago Bid Adapter:new adapter * remove console * change spec file to fix CircleCI * change spec file to fix CircleCI * change spec file * Update mediagoBidAdapter.js * Update mediagoBidAdapter.js * rerun CurcleCi * update mediagoBidAdapter * update discoveryBidAdapter * Discovery Bid Adapter : parameter updates * Mediago Bid Adapter : parameter updates * Mediago Bid Adapter : code style format * rerun circleci * rerun circleci * rerun circleci * rerun circleci * Update mediagoBidAdapter & discoveryBidAdapter:report eids to server * Update mediagoBidAdapter & discoveryBidAdapter:report eids to server * update Mediago & Discovery BidAdapter:remove size filter * update Mediago & Discovery BidAdapter:code format * update Mediago & Discovery BidAdapter:code format * update Mediago & Discovery BidAdapter:add param in banner format * update mediago & discovery:first party data * update mediago & discovery:first party data * update mediago & discovery:first party data * fix(mediago & discovery): update param tagid * fix(mediago & discovery): update param tagid * feat:add imp params for analysis * fix:add imp params for analysis * code format * test:add test data & test * format code * rerun circleci * feat: 1. add cookieSync 2. add gdpr * code format * rerun circleci * add gvlid * feat:add param 1.ppuid 2.content 3.cat 4.reqtime * fix: getUserSyncs param fixed * fix: getUserSyncs param fixed * feat: add param 1. adUnitCode 2. referrer * feat: Switch domain * rerun circle ci --------- Co-authored-by: BaronYu * Bizzclick Bid Adapter : update adapter, used ortbConverter lib (#10828) * update bizzclick adapter, used ortbConverter lib * fix: removed gdpr, ccpa, coppa * PubMatic Bid Adapter : passing a unique wiid to pubmatic ssp and logger call (#10821) * Added wiid as UUID * Handled undefined wiid in logger and tracker * updated test cases * updated test cases --------- Co-authored-by: pm-azhar-mulla * Criteo Bid Adapter: Add support for app.publisher.id in bid request (#10837) Co-authored-by: v.raybaud * providing visibility in case of adapter timeout and bidError (#10807) Co-authored-by: ahmadlob <109217988+ahmadlob@users.noreply.github.com> * Prebid 8.28.0 release * Increment version to 8.29.0-pre * Adding support for video.plcmt (#10841) * Bump github/codeql-action from 2 to 3 (#10856) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * HadronId Module: implementing user consent in backend calls (#10845) * Implementing user consent in HadronId module * fixing tests accepting just the start of url * Eids Docs : add missing EID examples (#10844) * Add missing brackets * Add missing examples * Add back missing ext * Admixer Bid Adaper: add admixerwl alias (#10859) * Update README.md update * Add admixerwl alias for admixerBidAdapter. --------- Co-authored-by: Yaroslav Masenko * AdagioAnalyticsAdapter: fix function param check (#10860) * NoBid Analytics Adapter: support for counting blocked requests for the Optimizer (#10842) * Enable supplyChain support * Added support for COPPA * rebuilt * Added support for Extended User IDs. * Added support for the "meta" attribute in bid response. * Delete nobidBidAdapter.js.orig * Delete a * Delete .jsdtscope * Delete org.eclipse.wst.jsdt.ui.superType.container * Delete org.eclipse.wst.jsdt.ui.superType.name * Delete .project * Added support for counting blocked requests for the Optimizer. * Added missing function for testing. * Added unit tests --------- Co-authored-by: Reda Guermas * consentManagementGpp: fix handling of CMP errors (#10811) * Taboola Bid Adapter: implement Iframe user sync (#10789) * iframe-sync * iframe-sync-add-tests * AMX bid adapter: fix timeout handler, bump version (#10744) * amx bid adapter: fix timeout handler, bump version * restore package-lock to master * remove sendbeacon, use mock xhr * add keepalive option for ajax * fix firefox test * CR changes * CR changes: restore files * CR changes * Ucfunnel Bid Adapter: add format support (#10862) * Add a new ucfunnel Adapter and test page * Add a new ucfunnel Adapter and test page * 1. Use prebid lib in the repo to keep updated 2. Replace var with let 3. Put JSON.parse(JSON.stringify()) into try catch block * utils.getTopWindowLocation is a function * Change to modules from adapters * Migrate to module design * [Dev Fix] Remove width and height which can be got from ad unit id * Update ucfunnelBidAdapter to fit into new spec * Correct the endpoint. Fix the error of query string * Add test case for ucfunnelBidAdapter * Fix lint error * Update version number * Combine all checks on bid request * Add GDPR support for ucfunnel adapter * Add in-stream video and native support for ucfunnel adapter * Remove demo page. Add more test cases. * Change request method from POST to GET * Remove unnecessary comment * Support vastXml and vastUrl for video request * update TTL to 30 mins * Avoid using arrow function which is not discuraged in mocha * ucfunnel tdid support * ucfunnel fix error message in debug mode * ucfunnel adapter add bidfloor parameter * ucfunnel adapter support CCPA * ucfunnel adapter native support clicktrackers * ucfunnel adapter change cookie sync setting * ucfunnel adapter update request parameter * Update ucfunnelBidAdapter * ucfunnel adapter add currency in ad response * ucfunnel adapter support uid2 * ucfunnel Bid Adapter: add support for FLoC and Verizon Media ConnectID * ucfunnel Bid Adapter: add support Price Floors Module * ucfunnel Bid Adapter: add GPID support and fix page and domain parameter. * ucfunnel Bid Adapter: add format support. --------- Co-authored-by: root Co-authored-by: Ryan Chou Co-authored-by: ucfunnel Co-authored-by: jack.hsieh * R2B2 Bid Adapter: Initial release (#10702) * R2B2 bidder adapter * R2B2 bid adapter: fix * conditional renderer --------- Co-authored-by: jenda * Core: fix headers in ortbConverter readme (#10874) * SparteoBidAdapter: Add UserSync (#10822) * Yandex Bid Adapter: Add rtt (roud trip time) tracking via nurl (#10846) * Add rtt (roud trip time) tracking via nurl in yandexBidAdapter * Yandex Bid Adapter: Fix let -> const --------- Co-authored-by: Konstantin Korobkov * AdMatic Bid Adapter : consent management features added (#10813) * Admatic Bidder Adaptor * Update admaticBidAdapter.md * Update admaticBidAdapter.md * remove floor parameter * Update admaticBidAdapter.js * Admatic Bid Adapter: alias and bid floor features activated * Admatic adapter: host param control changed * Alias name changed. * Revert "Admatic adapter: host param control changed" This reverts commit de7ac85981b1ba3ad8c5d1dc95c5dadbdf5b9895. * added alias feature and host param * Revert "added alias feature and host param" This reverts commit 6ec8f4539ea6be403a0d7e08dad5c7a5228f28a1. * Revert "Alias name changed." This reverts commit 661c54f9b2397e8f25c257144d73161e13466281. * Revert "Admatic Bid Adapter: alias and bid floor features activated" This reverts commit 7a2e0e29c49e2f876b68aafe886b336fe2fe6fcb. * Revert "Update admaticBidAdapter.js" This reverts commit 7a845b7151bbb08addfb58ea9bd5b44167cc8a4e. * Revert "remove floor parameter" This reverts commit 7a23b055ccd4ea23d23e73248e82b21bc6f69d90. * Admatic adapter: host param control && Add new Bidder * Revert "Admatic adapter: host param control && Add new Bidder" This reverts commit 3c797b120c8e0fe2b851381300ac5c4b1f92c6e2. * commit new features * Update admaticBidAdapter.js * updated for coverage * sync updated * Update adloader.js * AdMatic Bidder: development of user sync url * Update admaticBidAdapter.js * Set currency for AdserverCurrency: bug fix * Update admaticBidAdapter.js * update * admatic adapter video params update * Update admaticBidAdapter.js * update * Update admaticBidAdapter.js * update * update * Update admaticBidAdapter_spec.js * Update admaticBidAdapter.js * Update admaticBidAdapter.js * Revert "Update admaticBidAdapter.js" This reverts commit 1216892fe55e5ab24dda8e045ea007ee6bb40ff8. * Revert "Update admaticBidAdapter.js" This reverts commit b1929ece33bb4040a3bcd6b9332b50335356829c. * Revert "Update admaticBidAdapter_spec.js" This reverts commit 1ca659798b0c9b912634b1673e15e54e547b81e7. * Revert "update" This reverts commit 689ce9d21e08c27be49adb35c5fd5205aef5c35c. * Revert "update" This reverts commit f381a453f9389bebd58dcfa719e9ec17f939f338. * Revert "Update admaticBidAdapter.js" This reverts commit 38fd7abec701d8a4750f9e95eaeb40fb67e9f0e6. * Revert "update" This reverts commit a5316e74b612a5b2cd16cf42586334321fc87770. * Revert "Update admaticBidAdapter.js" This reverts commit 60a28cae302b711366dab0bff9f49b11862fb8ee. * Revert "admatic adapter video params update" This reverts commit 31e69e88fd9355e143f736754ac2e47fe49b65b6. * update * Update admaticBidAdapter.js * Update admaticBidAdapter_spec.js * mime_type add * add native adapter * AdMatic Adapter: Consent Management * Taboola Bid Adapter: Cookie Look Up Logic Fix (#10873) * cookie-look-up-logic-fix * cookie-look-up-logic-fix * cookie-look-up-logic-fix * ZetaGlobalSsp Bid Adapter : support topics module (#10803) * add getTopics() * provide get segments from ortb2 * rename const * additional check * fix test --------- Co-authored-by: Surovenko Alexey Co-authored-by: Alexey Surovenko * Adnuntius Bid Adapter: bugfix for storageFunction (#10869) * Removed linting issues * Fixed merge issues. * Bugfix on storageTool. * Prebid 8.29.0 release * Increment version to 8.30.0-pre * Yandex Bid Adapter: add support for topicsFpdModule (#10875) * Yandex Bid Adapter: add support for topicsFpdModule * add test * Yandex Bid Adapter: add jsdoc (#10884) * DxKulture Bid Adapter : user syncs improvements (#10738) * Initial implementation of kulturemedia bid adapter * Changing outstream to instream * Enriching md file with test examples * Changing nId to networkId * Cleaning up md file * Submitting rebranded dxkultureBidAdapter * dxkultureBidAdapter - Improve UserSyncs * Include gdpr/usp params in iframe usersync url * Add gdpr/usp data to iframe usync urls * Cleaning up testing html file * Adding outstream support * Updating exchange endpoint * Resolve requests test * Resolving iframe/pixel priority when iframeEnabled/pixelEnabled * Improving userSync filtering condition * Prioritize iframe user syncing --------- Co-authored-by: Danijel Predarski Co-authored-by: dani-nova <73398187+dani-nova@users.noreply.github.com> Co-authored-by: Slavisa Petkovic Co-authored-by: Slavisa Petkovic <32300768+spetkovic@users.noreply.github.com> * Mygaru Id System: Initial release (#10848) * Update viantOrtbBidAdapter_spec.js (#10888) Added a test case for native ads * Stv Bid Adapter: added user id support, adaptation of schain support (#10849) * initial commit * adapted buildRequests function * refinement pfilter and bcat * refinement * adapted tests for isBidRequestValid,buildRequests * adaptations for test * finished building stvBidAdapter.js * finished: ran tests, coverage 99% * update: rename w->srw, h->srh * adapt stvBidAdapter.md * remove dspx from stv adapters * some changes (missing: getUserSyncs, but is the same as in radsBidAdapter) * added checks in getUserSyncs; ran tests * added schain support (94.8% coverage) * correct schain encoding * added serializeUids and adapted serializeSChain --------- Co-authored-by: theo_ * Missena Bid Adapter: allow per page capping (#10863) * LiveIntent ID Module: Update live-connect version (#10894) * update lc version * fix typo * Do not require API for video requests (#10895) * Price Floors: Failure to Account for 'data.skipRate' (#10872) * Update skipRate handling in priceFloors.js and add unit tests for the changes. * Update wording on tests and remove unecessary spread. * Prebid 8.30.0 release * add prebid analyticsS --------- Signed-off-by: dependabot[bot] Co-authored-by: Prebid.js automated release Co-authored-by: PGAMSSP <142323401+PGAMSSP@users.noreply.github.com> Co-authored-by: John Ivan Bauzon Co-authored-by: John Bauzon Co-authored-by: Omer Dotan <54346241+omerBrowsi@users.noreply.github.com> Co-authored-by: Malkov Mikhail Co-authored-by: Patrick McCann Co-authored-by: Chris Southern <79725079+southern-growthcode@users.noreply.github.com> Co-authored-by: Olivier Co-authored-by: François Rotta Co-authored-by: kapil-tuptewar <91458408+kapil-tuptewar@users.noreply.github.com> Co-authored-by: pm-priyanka-deshmane <107103300+pm-priyanka-deshmane@users.noreply.github.com> Co-authored-by: Chris Huie Co-authored-by: Marco Muths Co-authored-by: matthieularere-msq <63732822+matthieularere-msq@users.noreply.github.com> Co-authored-by: gabrielIvbs <112690249+gabrielIvbs@users.noreply.github.com> Co-authored-by: BaronJHYu <254878848@qq.com> Co-authored-by: BaronYu Co-authored-by: BizzClick <73241175+BizzClick@users.noreply.github.com> Co-authored-by: pm-azhar-mulla <75726247+pm-azhar-mulla@users.noreply.github.com> Co-authored-by: pm-azhar-mulla Co-authored-by: Vincent Co-authored-by: v.raybaud Co-authored-by: barRubi <151519394+barRubi@users.noreply.github.com> Co-authored-by: ahmadlob <109217988+ahmadlob@users.noreply.github.com> Co-authored-by: Nayan Savla Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: joseluis laso Co-authored-by: Viktor Dreiling <34981284+3link@users.noreply.github.com> Co-authored-by: AdmixerTech <35560933+AdmixerTech@users.noreply.github.com> Co-authored-by: Yaroslav Masenko Co-authored-by: redaguermas Co-authored-by: Reda Guermas Co-authored-by: Demetrio Girardi Co-authored-by: Nick Jacob Co-authored-by: jackhsiehucf <77815341+jackhsiehucf@users.noreply.github.com> Co-authored-by: root Co-authored-by: Ryan Chou Co-authored-by: ucfunnel Co-authored-by: jack.hsieh Co-authored-by: alexalukr2b2 <136449554+alexalukr2b2@users.noreply.github.com> Co-authored-by: jenda Co-authored-by: Denis <7009699+someden@users.noreply.github.com> Co-authored-by: geoffray-viously <95097046+geoffray-viously@users.noreply.github.com> Co-authored-by: Konstantin Korobkov Co-authored-by: Konstantin Korobkov Co-authored-by: Fatih Kaya Co-authored-by: asurovenko-zeta <80847074+asurovenko-zeta@users.noreply.github.com> Co-authored-by: Surovenko Alexey Co-authored-by: Alexey Surovenko Co-authored-by: Mikael Lundin Co-authored-by: kmdevops <126434358+kmdevops@users.noreply.github.com> Co-authored-by: Danijel Predarski Co-authored-by: dani-nova <73398187+dani-nova@users.noreply.github.com> Co-authored-by: Slavisa Petkovic Co-authored-by: Slavisa Petkovic <32300768+spetkovic@users.noreply.github.com> Co-authored-by: Gena Co-authored-by: tkrishnaviant Co-authored-by: theo-stv <120092078+theo-stv@users.noreply.github.com> Co-authored-by: theo_ Co-authored-by: Petre Damoc Co-authored-by: Wiem Zine El Abidine Co-authored-by: Robert Ray Martinez III Co-authored-by: bbaresic <153560835+bbaresic@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +- libraries/ortbConverter/README.md | 9 +- modules/.submodules.json | 3 +- modules/adagioAnalyticsAdapter.js | 62 +- modules/admaticBidAdapter.js | 131 +- modules/admixerBidAdapter.js | 10 +- modules/admixerBidAdapter.md | 45 + modules/adnuntiusBidAdapter.js | 4 +- modules/amxBidAdapter.js | 116 +- modules/bizzclickBidAdapter.js | 355 +----- modules/bizzclickBidAdapter.md | 183 +-- modules/browsiRtdProvider.js | 4 +- modules/consentManagementGpp.js | 13 +- modules/criteoBidAdapter.js | 1 + modules/deepintentBidAdapter.js | 2 + modules/dxkultureBidAdapter.js | 111 +- modules/growthCodeRtdProvider.js | 4 +- modules/gumgumBidAdapter.js | 6 +- modules/hadronIdSystem.js | 34 +- modules/invibesBidAdapter.js | 56 +- modules/mediagoBidAdapter.js | 6 +- modules/missenaBidAdapter.js | 4 +- modules/mygaruIdSystem.js | 98 ++ modules/mygaruIdSystem.md | 24 + modules/nextMillenniumBidAdapter.js | 40 +- modules/nobidAnalyticsAdapter.js | 67 +- modules/pgamsspBidAdapter.js | 19 +- modules/priceFloors.js | 4 +- modules/pubmaticAnalyticsAdapter.js | 39 +- modules/pubmaticBidAdapter.js | 4 +- modules/r2b2BidAdapter.js | 309 +++++ modules/r2b2BidAdapter.md | 37 + modules/rtdModule/index.js | 3 +- modules/rubiconBidAdapter.js | 3 +- modules/sparteoBidAdapter.js | 42 +- modules/stvBidAdapter.js | 59 +- modules/taboolaBidAdapter.js | 28 +- modules/ucfunnelBidAdapter.js | 53 +- modules/userId/eids.md | 52 + modules/userId/userId.md | 3 + modules/yandexBidAdapter.js | 112 +- modules/yieldmoBidAdapter.js | 4 +- modules/zeta_global_sspBidAdapter.js | 20 + package-lock.json | 34 +- package.json | 4 +- prebid-analytics-8.30.0.js | 90 ++ src/auction.js | 2 +- src/constants.json | 7 +- .../modules/adagioAnalyticsAdapter_spec.js | 109 +- test/spec/modules/admaticBidAdapter_spec.js | 1057 +++++++++++------ test/spec/modules/admixerBidAdapter_spec.js | 43 +- test/spec/modules/amxBidAdapter_spec.js | 187 ++- test/spec/modules/bizzclickBidAdapter_spec.js | 569 ++++----- test/spec/modules/browsiRtdProvider_spec.js | 6 - .../spec/modules/consentManagementGpp_spec.js | 2 +- test/spec/modules/criteoBidAdapter_spec.js | 24 + test/spec/modules/dxkultureBidAdapter_spec.js | 79 +- test/spec/modules/gumgumBidAdapter_spec.js | 8 + test/spec/modules/hadronIdSystem_spec.js | 4 +- test/spec/modules/invibesBidAdapter_spec.js | 99 ++ .../modules/liveIntentIdMinimalSystem_spec.js | 4 +- test/spec/modules/liveIntentIdSystem_spec.js | 42 +- test/spec/modules/missenaBidAdapter_spec.js | 41 +- test/spec/modules/mygaruIdSystem_spec.js | 62 + .../modules/nextMillenniumBidAdapter_spec.js | 73 ++ .../modules/nobidAnalyticsAdapter_spec.js | 8 +- test/spec/modules/pgamsspBidAdapter_spec.js | 1 + test/spec/modules/priceFloors_spec.js | 86 +- .../modules/pubmaticAnalyticsAdapter_spec.js | 51 + test/spec/modules/pubmaticBidAdapter_spec.js | 8 + test/spec/modules/r2b2BidAdapter_spec.js | 689 +++++++++++ test/spec/modules/rubiconBidAdapter_spec.js | 10 - test/spec/modules/sparteoBidAdapter_spec.js | 26 + test/spec/modules/stvBidAdapter_spec.js | 44 +- test/spec/modules/taboolaBidAdapter_spec.js | 79 +- test/spec/modules/ucfunnelBidAdapter_spec.js | 18 +- test/spec/modules/viantOrtbBidAdapter_spec.js | 43 + test/spec/modules/yandexBidAdapter_spec.js | 105 +- test/spec/modules/yieldmoBidAdapter_spec.js | 18 +- .../modules/zeta_global_sspBidAdapter_spec.js | 28 +- test/spec/unit/pbjs_api_spec.js | 7 + 81 files changed, 4426 insertions(+), 1526 deletions(-) create mode 100644 modules/mygaruIdSystem.js create mode 100644 modules/mygaruIdSystem.md create mode 100644 modules/r2b2BidAdapter.js create mode 100644 modules/r2b2BidAdapter.md create mode 100644 prebid-analytics-8.30.0.js create mode 100644 test/spec/modules/mygaruIdSystem_spec.js create mode 100644 test/spec/modules/r2b2BidAdapter_spec.js diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 84c97376a3e..3bee8f7c947 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -57,7 +57,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -70,4 +70,4 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/libraries/ortbConverter/README.md b/libraries/ortbConverter/README.md index 31f56b4c754..751971eebdc 100644 --- a/libraries/ortbConverter/README.md +++ b/libraries/ortbConverter/README.md @@ -80,8 +80,7 @@ However, there are two restrictions (to avoid them, use the [other customization ) ``` - -### Fine grained customization - imp, request, bidResponse, response +### Fine grained customization - imp, request, bidResponse, response When invoked, `toORTB({bidRequests, bidderRequest})` first loops through each request in `bidRequests`, converting them into ORTB `imp` objects. It then packages them into a single ORTB request, adding other parameters that are not imp-specific (such as for example `request.tmax`). @@ -91,7 +90,7 @@ a single return value. You can customize each of these steps using the `ortbConverter` arguments `imp`, `request`, `bidResponse` and `response`: -### Customizing imps: `imp(buildImp, bidRequest, context)` +### Customizing imps: `imp(buildImp, bidRequest, context)` Invoked once for each input `bidRequest`; should return the ORTB `imp` object to include in the request. The arguments are: @@ -101,7 +100,7 @@ The arguments are: - `context`: a [context object](#context) that contains at least: - `bidderRequest`: the `bidderRequest` argument passed to `toORTB`. -#### Example: attaching custom bid params +#### Example: attaching custom bid params ```javascript const converter = ortbConverter({ @@ -351,7 +350,7 @@ const converter = ortbConverter({ - the `context` argument of `ortbConverter`: e.g. `ortbConverter({context: {ttl: 30}})`. This will set `context.ttl = 30` globally for the converter. - the `context` argument of `toORTB`: e.g. `converter.toORTB({bidRequests, bidderRequest, context: {ttl: 30}})`. This will set `context.ttl = 30` only for this request. -### Special `context` properties +### Special `context` properties For ease of use, the conversion logic gives special meaning to some context properties: diff --git a/modules/.submodules.json b/modules/.submodules.json index 830d3c9b2f3..d2a13a57330 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -47,7 +47,8 @@ "adqueryIdSystem", "gravitoIdSystem", "freepassIdSystem", - "operaadsIdSystem" + "operaadsIdSystem", + "mygaruIdSystem" ], "adpod": [ "freeWheelAdserverVideo", diff --git a/modules/adagioAnalyticsAdapter.js b/modules/adagioAnalyticsAdapter.js index 9c4c0e8fea7..807937ba3dd 100644 --- a/modules/adagioAnalyticsAdapter.js +++ b/modules/adagioAnalyticsAdapter.js @@ -22,6 +22,12 @@ const cache = { getAuction: function(auctionId, adUnitCode) { return this.auctions[auctionId][adUnitCode]; }, + getBiddersFromAuction: function(auctionId, adUnitCode) { + return this.getAuction(auctionId, adUnitCode).bdrs.split(','); + }, + getAllAdUnitCodes: function(auctionId) { + return Object.keys(this.auctions[auctionId]); + }, updateAuction: function(auctionId, adUnitCode, values) { this.auctions[auctionId][adUnitCode] = { ...this.auctions[auctionId][adUnitCode], @@ -74,7 +80,8 @@ const adagioEnqueue = function adagioEnqueue(action, data) { const guard = { adagio: (value) => isAdagio(value), - bidTracked: (auctionId, adUnitCode) => deepAccess(cache, `auctions.${auctionId}.${adUnitCode}`, false) + bidTracked: (auctionId, adUnitCode) => deepAccess(cache, `auctions.${auctionId}.${adUnitCode}`, false), + auctionTracked: (auctionId) => deepAccess(cache, `auctions.${auctionId}`, false) }; function removeDuplicates(arr, getKey) { @@ -90,6 +97,10 @@ function getAdapterNameForAlias(aliasName) { }; function isAdagio(value) { + if (!value) { + return false + } + return value.toLowerCase().includes('adagio') || getAdapterNameForAlias(value).toLowerCase().includes('adagio'); }; @@ -105,6 +116,19 @@ function getMediaTypeAlias(mediaType) { return mediaTypesMap[mediaType] || mediaType; }; +function addKeyPrefix(obj, prefix) { + return Object.keys(obj).reduce((acc, key) => { + // We don't want to prefix already prefixed keys. + if (key.startsWith(prefix)) { + acc[key] = obj[key]; + return acc; + } + + acc[`${prefix}${key}`] = obj[key]; + return acc; + }, {}); +} + /** * sendRequest to Adagio. It filter null values and encode each query param. * @param {Object} qp @@ -146,6 +170,7 @@ function getTargetedAuctionId(bid) { * HANDLERS * - handlerAuctionInit * - handlerBidResponse + * - handlerAuctionEnd * - handlerBidWon * - handlerAdRender * @@ -227,11 +252,10 @@ function handlerAuctionInit(event) { auct_id: adagioAuctionId, adu_code: adUnitCode, url_dmn: w.location.hostname, - dvc: params.environment, pgtyp: params.pagetype, plcmt: params.placement, - tname: params.testName || null, - tvname: params.testVariationName || null, + t_n: params.testName || null, + t_v: params.testVersion || null, mts: mediaTypesKeys.join(','), ban_szs: bannerSizes.join(','), bdrs: bidders.map(bidder => getAdapterNameForAlias(bidder.bidder)).sort().join(','), @@ -257,11 +281,33 @@ function handlerBidResponse(event) { return; } + if (!event.pba) { + return; + } + cache.updateAuction(event.auctionId, event.adUnitCode, { - adg_sid: event.seatId || null + ...addKeyPrefix(event.pba, 'e_') }); }; +function handlerAuctionEnd(event) { + const { auctionId } = event; + + if (!guard.auctionTracked(auctionId)) { + return; + } + + const adUnitCodes = cache.getAllAdUnitCodes(auctionId); + adUnitCodes.forEach(adUnitCode => { + const mapper = (bidder) => event.bidsReceived.find(bid => bid.adUnitCode === adUnitCode && bid.bidder === bidder) ? '1' : '0'; + + cache.updateAuction(auctionId, adUnitCode, { + bdrs_bid: cache.getBiddersFromAuction(auctionId, adUnitCode).map(mapper).join(',') + }); + sendNewBeacon(auctionId, adUnitCode); + }); +} + function handlerBidWon(event) { let auctionId = getTargetedAuctionId(event); @@ -340,10 +386,14 @@ let adagioAdapter = Object.assign(adapter({ emptyUrl, analyticsType }), { case CONSTANTS.EVENTS.BID_RESPONSE: handlerBidResponse(args); break; + case CONSTANTS.EVENTS.AUCTION_END: + handlerAuctionEnd(args); + break; case CONSTANTS.EVENTS.BID_WON: handlerBidWon(args); break; - case CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED: + // AD_RENDER_SUCCEEDED seems redundant with BID_WON. + // case CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED: case CONSTANTS.EVENTS.AD_RENDER_FAILED: handlerAdRender(args, eventType === CONSTANTS.EVENTS.AD_RENDER_SUCCEEDED); break; diff --git a/modules/admaticBidAdapter.js b/modules/admaticBidAdapter.js index fc5cf9c8f7b..236114f6396 100644 --- a/modules/admaticBidAdapter.js +++ b/modules/admaticBidAdapter.js @@ -1,4 +1,4 @@ -import {getValue, logError, isEmpty, deepAccess, isArray, getBidIdParameter} from '../src/utils.js'; +import {getValue, formatQS, logError, deepAccess, isArray, getBidIdParameter} from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; @@ -56,18 +56,16 @@ export const spec = { * @return {ServerRequest} */ buildRequests: (validBidRequests, bidderRequest) => { + const tmax = bidderRequest.timeout; const bids = validBidRequests.map(buildRequestObject); - const blacklist = bidderRequest.ortb2; + const ortb = bidderRequest.ortb2; const networkId = getValue(validBidRequests[0].params, 'networkId'); const host = getValue(validBidRequests[0].params, 'host'); const currency = config.getConfig('currency.adServerCurrency') || 'TRY'; const bidderName = validBidRequests[0].bidder; const payload = { - user: { - ua: navigator.userAgent - }, - blacklist: [], + ortb, site: { page: bidderRequest.refererInfo.page, ref: bidderRequest.refererInfo.page, @@ -80,17 +78,59 @@ export const spec = { ext: { cur: currency, bidder: bidderName - } + }, + schain: {}, + regs: { + ext: { + } + }, + user: { + ext: {} + }, + at: 1, + tmax: parseInt(tmax) }; - if (!isEmpty(blacklist.badv)) { - payload.blacklist = blacklist.badv; - }; + if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) { + const consentStr = (bidderRequest.gdprConsent.consentString) + ? bidderRequest.gdprConsent.consentString.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') : ''; + const gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; + payload.regs.ext.gdpr = gdpr; + payload.regs.ext.consent = consentStr; + } + + if (bidderRequest && bidderRequest.coppa) { + payload.regs.ext.coppa = bidderRequest.coppa === true ? 1 : (bidderRequest.coppa === false ? 0 : undefined); + } + + if (bidderRequest && bidderRequest.ortb2?.regs?.gpp) { + payload.regs.ext.gpp = bidderRequest.ortb2?.regs?.gpp; + } + + if (bidderRequest && bidderRequest.ortb2?.regs?.gpp_sid) { + payload.regs.ext.gpp_sid = bidderRequest.ortb2?.regs?.gpp_sid; + } + + if (bidderRequest && bidderRequest.uspConsent) { + payload.regs.ext.uspIab = bidderRequest.uspConsent; + } + + if (validBidRequests[0].schain) { + const schain = mapSchain(validBidRequests[0].schain); + if (schain) { + payload.schain = schain; + } + } + + if (validBidRequests[0].userIdAsEids) { + const eids = { eids: validBidRequests[0].userIdAsEids }; + payload.user.ext = { ...payload.user.ext, ...eids }; + } if (payload) { switch (bidderName) { case 'pixad': - SYNC_URL = 'https://static.pixad.com.tr/sync.html'; + SYNC_URL = 'https://static.cdn.pixad.com.tr/sync.html'; break; default: SYNC_URL = 'https://cdn.serve.admatic.com.tr/showad/sync.html'; @@ -101,12 +141,36 @@ export const spec = { } }, - getUserSyncs: function (syncOptions, responses) { - if (syncOptions.iframeEnabled) { - return [{ + getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent, gppConsent) { + if (!hasSynced && syncOptions.iframeEnabled) { + // data is only assigned if params are available to pass to syncEndpoint + let params = {}; + + if (gdprConsent) { + if (typeof gdprConsent.gdprApplies === 'boolean') { + params['gdpr'] = Number(gdprConsent.gdprApplies); + } + if (typeof gdprConsent.consentString === 'string') { + params['gdpr_consent'] = gdprConsent.consentString; + } + } + + if (uspConsent) { + params['us_privacy'] = encodeURIComponent(uspConsent); + } + + if (gppConsent?.gppString) { + params['gpp'] = gppConsent.gppString; + params['gpp_sid'] = gppConsent.applicableSections?.toString(); + } + + params = Object.keys(params).length ? `?${formatQS(params)}` : ''; + + hasSynced = true; + return { type: 'iframe', - url: SYNC_URL - }]; + url: SYNC_URL + params + }; } }, @@ -156,6 +220,41 @@ export const spec = { } }; +var hasSynced = false; + +export function resetUserSync() { + hasSynced = false; +} + +/** + * @param {object} schain object set by Publisher + * @returns {object} OpenRTB SupplyChain object + */ +function mapSchain(schain) { + if (!schain) { + return null; + } + if (!validateSchain(schain)) { + logError('AdMatic: required schain params missing'); + return null; + } + return schain; +} + +/** + * @param {object} schain object set by Publisher + * @returns {object} bool + */ +function validateSchain(schain) { + if (!schain.nodes) { + return false; + } + const requiredFields = ['asi', 'sid', 'hp']; + return schain.nodes.every(node => { + return requiredFields.every(field => node[field]); + }); +} + function isUrl(str) { try { URL(str); diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js index 6cbc36c1dcd..f5f0b5bf665 100644 --- a/modules/admixerBidAdapter.js +++ b/modules/admixerBidAdapter.js @@ -14,6 +14,7 @@ const ALIASES = [ {code: 'futureads', endpoint: 'https://ads.futureads.io/prebid.1.2.aspx'}, {code: 'smn', endpoint: 'https://ads.smn.rs/prebid.1.2.aspx'}, {code: 'admixeradx', endpoint: 'https://inv-nets.admixer.net/adxprebid.1.2.aspx'}, + {code: 'admixerwl', endpoint: 'https://inv-nets-adxwl.admixer.com/adxwlprebid.aspx'}, ]; export const spec = { code: BIDDER_CODE, @@ -23,7 +24,9 @@ export const spec = { * Determines whether or not the given bid request is valid. */ isBidRequestValid: function (bid) { - return !!bid.params.zone; + return bid.bidder === 'admixerwl' + ? !!bid.params.clientId && !!bid.params.endpointId + : !!bid.params.zone; }, /** * Make a server request from the list of BidRequests. @@ -76,10 +79,11 @@ export const spec = { imp.ortb2 && delete imp.ortb2; payload.imps.push(imp); }); + + let urlForRequest = endpointUrl || getEndpointUrl(bidderRequest.bidderCode) return { method: 'POST', - url: - endpointUrl || getEndpointUrl(bidderRequest.bidderCode), + url: bidderRequest.bidderCode === 'admixerwl' ? `${urlForRequest}?client=${payload.imps[0]?.params?.clientId}` : urlForRequest, data: payload, }; }, diff --git a/modules/admixerBidAdapter.md b/modules/admixerBidAdapter.md index 682f5629115..64f8dd64ee4 100644 --- a/modules/admixerBidAdapter.md +++ b/modules/admixerBidAdapter.md @@ -50,3 +50,48 @@ Please use ```admixer``` as the bidder code. }, ]; ``` + +### AdmixerWL Test Parameters +``` + var adUnits = [ + { + code: 'desktop-banner-ad-div', + sizes: [[300, 250]], // a display size + bids: [ + { + bidder: "admixer", + params: { + endpointId: 41512, + clientId: 62 + } + } + ] + },{ + code: 'mobile-banner-ad-div', + sizes: [[300, 50]], // a mobile size + bids: [ + { + bidder: "admixer", + params: { + endpointId: 41512, + clientId: 62 + } + } + ] + },{ + code: 'video-ad', + sizes: [[300, 50]], + mediaType: 'video', + bids: [ + { + bidder: "admixer", + params: { + endpointId: 41512, + clientId: 62 + } + } + ] + }, + ]; +``` + diff --git a/modules/adnuntiusBidAdapter.js b/modules/adnuntiusBidAdapter.js index 8f841006524..6f3ed6eb5b6 100644 --- a/modules/adnuntiusBidAdapter.js +++ b/modules/adnuntiusBidAdapter.js @@ -30,14 +30,14 @@ const storageTool = (function () { const getMetaInternal = function () { if (!storage.localStorageIsEnabled()) { - return {}; + return []; } let parsedJson; try { parsedJson = JSON.parse(storage.getDataFromLocalStorage(META_DATA_KEY)); } catch (e) { - return {}; + return []; } let filteredEntries = parsedJson ? parsedJson.filter((datum) => { diff --git a/modules/amxBidAdapter.js b/modules/amxBidAdapter.js index a773ac70559..6e14f65b0c8 100644 --- a/modules/amxBidAdapter.js +++ b/modules/amxBidAdapter.js @@ -14,20 +14,31 @@ import { } from '../src/utils.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; +import { fetch } from '../src/ajax.js'; const BIDDER_CODE = 'amx'; const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const SIMPLE_TLD_TEST = /\.com?\.\w{2,4}$/; const DEFAULT_ENDPOINT = 'https://prebid.a-mo.net/a/c'; -const VERSION = 'pba1.3.3'; +const VERSION = 'pba1.3.4'; const VAST_RXP = /^\s*<\??(?:vast|xml)/i; -const TRACKING_ENDPOINT = 'https://1x1.a-mo.net/hbx/'; +const TRACKING_BASE = 'https://1x1.a-mo.net/'; +const TRACKING_ENDPOINT = TRACKING_BASE + 'hbx/'; +const POST_TRACKING_ENDPOINT = TRACKING_BASE + 'e'; const AMUID_KEY = '__amuidpb'; function getLocation(request) { return parseUrl(request.refererInfo?.topmostLocation || window.location.href); } +function getTimeoutSize(timeoutData) { + if (timeoutData.sizes == null || timeoutData.sizes.length === 0) { + return [0, 0]; + } + + return timeoutData.sizes[0]; +} + const largestSize = (sizes, mediaTypes) => { const allSizes = sizes .concat(deepAccess(mediaTypes, `${BANNER}.sizes`, []) || []) @@ -149,7 +160,9 @@ function convertRequest(bid) { const tid = deepAccess(bid, 'params.tagId'); const au = - bid.params != null && typeof bid.params.adUnitId === 'string' && bid.params.adUnitId !== '' + bid.params != null && + typeof bid.params.adUnitId === 'string' && + bid.params.adUnitId !== '' ? bid.params.adUnitId : bid.adUnitCode; @@ -202,7 +215,10 @@ function isSyncEnabled(syncConfigP, syncType) { return false; } - if (syncConfig.bidders === '*' || (isArray(syncConfig.bidders) && syncConfig.bidders.indexOf('amx') !== -1)) { + if ( + syncConfig.bidders === '*' || + (isArray(syncConfig.bidders) && syncConfig.bidders.indexOf('amx') !== -1) + ) { return syncConfig.filter == null || syncConfig.filter === 'include'; } @@ -219,12 +235,17 @@ function getSyncSettings() { d: 0, l: 0, t: 0, - e: true + e: true, }; } - const settings = { d: syncConfig.syncDelay, l: syncConfig.syncsPerBidder, t: 0, e: syncConfig.syncEnabled } - const all = isSyncEnabled(syncConfig.filterSettings, 'all') + const settings = { + d: syncConfig.syncDelay, + l: syncConfig.syncsPerBidder, + t: 0, + e: syncConfig.syncEnabled, + }; + const all = isSyncEnabled(syncConfig.filterSettings, 'all'); if (all) { settings.t = SYNC_IMAGE & SYNC_IFRAME; @@ -256,12 +277,14 @@ function getGpp(bidderRequest) { return bidderRequest.gppConsent; } - return bidderRequest?.ortb2?.regs?.gpp ?? { gppString: '', applicableSections: '' }; + return ( + bidderRequest?.ortb2?.regs?.gpp ?? { gppString: '', applicableSections: '' } + ); } function buildReferrerInfo(bidderRequest) { if (bidderRequest.refererInfo == null) { - return { r: '', t: false, c: '', l: 0, s: [] } + return { r: '', t: false, c: '', l: 0, s: [] }; } const re = bidderRequest.refererInfo; @@ -272,7 +295,7 @@ function buildReferrerInfo(bidderRequest) { l: re.numIframes, s: re.stack, c: re.canonicalUrl, - } + }; } const isTrue = (boolValue) => @@ -358,28 +381,35 @@ export const spec = { return { data: payload, method: 'POST', + browsingTopics: true, url: deepAccess(bidRequests[0], 'params.endpoint', DEFAULT_ENDPOINT), withCredentials: true, }; }, - getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { + getUserSyncs( + syncOptions, + serverResponses, + gdprConsent, + uspConsent, + gppConsent + ) { const qp = { gdpr_consent: enc(gdprConsent?.consentString || ''), gdpr: enc(gdprConsent?.gdprApplies ? 1 : 0), us_privacy: enc(uspConsent || ''), gpp: enc(gppConsent?.gppString || ''), - gpp_sid: enc(gppConsent?.applicableSections || '') + gpp_sid: enc(gppConsent?.applicableSections || ''), }; const iframeSync = { url: `https://prebid.a-mo.net/isyn?${formatQS(qp)}`, - type: 'iframe' + type: 'iframe', }; if (serverResponses == null || serverResponses.length === 0) { if (syncOptions.iframeEnabled) { - return [iframeSync] + return [iframeSync]; } return []; @@ -394,7 +424,10 @@ export const spec = { const pixelType = syncPixel.indexOf('__st=iframe') !== -1 ? 'iframe' : 'image'; if (syncOptions.iframeEnabled || pixelType === 'image') { - hasFrame = hasFrame || (pixelType === 'iframe') || (syncPixel.indexOf('cchain') !== -1) + hasFrame = + hasFrame || + pixelType === 'iframe' || + syncPixel.indexOf('cchain') !== -1; output.push({ url: syncPixel, type: pixelType, @@ -405,7 +438,7 @@ export const spec = { }); if (!hasFrame && output.length < 2) { - output.push(iframeSync) + output.push(iframeSync); } return output; @@ -470,19 +503,58 @@ export const spec = { aud: targetingData.requestId, a: targetingData.adUnitCode, c2: nestedQs(targetingData.adserverTargeting), + cn3: targetingData.timeToRespond, }); }, onTimeout(timeoutData) { - if (timeoutData == null) { + if (timeoutData == null || !timeoutData.length) { return; } - trackEvent('pbto', { - A: timeoutData.bidder, - bid: timeoutData.bidId, - a: timeoutData.adUnitCode, - cn: timeoutData.timeout, + let common = null; + const events = timeoutData.map((timeout) => { + const params = timeout.params || {}; + const size = getTimeoutSize(timeout); + const { domain, page, ref } = + timeout.ortb2 != null && timeout.ortb2.site != null + ? timeout.ortb2.site + : {}; + + if (common == null) { + common = { + do: domain, + u: page, + U: getUIDSafe(), + re: ref, + V: '$prebid.version$', + vg: '$$PREBID_GLOBAL$$', + }; + } + + return { + A: timeout.bidder, + mid: params.tagId, + a: params.adunitId || timeout.adUnitCode, + bid: timeout.bidId, + n: 'g_pbto', + aud: timeout.transactionId, + w: size[0], + h: size[1], + cn: timeout.timeout, + cn2: timeout.bidderRequestsCount, + cn3: timeout.bidderWinsCount, + }; + }); + + const payload = JSON.stringify({ c: common, e: events }); + fetch(POST_TRACKING_ENDPOINT, { + body: payload, + keepalive: true, + withCredentials: true, + method: 'POST' + }).catch((_e) => { + // do nothing; ignore errors }); }, diff --git a/modules/bizzclickBidAdapter.js b/modules/bizzclickBidAdapter.js index dc7731231ab..d2eba3f0f81 100644 --- a/modules/bizzclickBidAdapter.js +++ b/modules/bizzclickBidAdapter.js @@ -1,322 +1,77 @@ -import {_map, deepAccess, deepSetValue, getDNT, logMessage, logWarn} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'bizzclick'; -const ACCOUNTID_MACROS = '[account_id]'; -const URL_ENDPOINT = `https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=${ACCOUNTID_MACROS}`; -const NATIVE_ASSET_IDS = { 0: 'title', 2: 'icon', 3: 'image', 5: 'sponsoredBy', 4: 'body', 1: 'cta' }; -const NATIVE_PARAMS = { - title: { - id: 0, - name: 'title' - }, - icon: { - id: 2, - type: 1, - name: 'img' - }, - image: { - id: 3, - type: 3, - name: 'img' +const SOURCE_ID_MACRO = '[sourceid]'; +const ACCOUNT_ID_MACRO = '[accountid]'; +const HOST_MACRO = '[host]'; +const URL = `https://${HOST_MACRO}.bizzclick.com/bid?rtb_seat_id=${SOURCE_ID_MACRO}&secret_key=${ACCOUNT_ID_MACRO}&integration_type=prebidjs`; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_HOST = 'us-e-node1'; + +const converter = ortbConverter({ + context: { + netRevenue: true, + ttl: 20, }, - sponsoredBy: { - id: 5, - name: 'data', - type: 1 + imp(buildImp, bidRequest, context) { + const imp = buildImp(bidRequest, context); + if (!imp.bidfloor) imp.bidfloor = bidRequest.params.bidfloor || 0; + imp.ext = { + [BIDDER_CODE]: { + accountId: bidRequest.params.accountId, + sourceId: bidRequest.params.sourceId, + host: bidRequest.params.host || DEFAULT_HOST, + } + } + return imp; }, - body: { - id: 4, - name: 'data', - type: 2 + request(buildRequest, imps, bidderRequest, context) { + const request = buildRequest(imps, bidderRequest, context); + const bid = context.bidRequests[0]; + request.test = config.getConfig('debug') ? 1 : 0; + if (!request.cur) request.cur = [bid.params.currency || DEFAULT_CURRENCY]; + return request; }, - cta: { - id: 1, - type: 12, - name: 'data' + bidResponse(buildBidResponse, bid, context) { + const bidResponse = buildBidResponse(bid, context); + bidResponse.cur = bid.cur || DEFAULT_CURRENCY; + return bidResponse; } -}; -const NATIVE_VERSION = '1.2'; +}); + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER, VIDEO, NATIVE], - /** - * Determines whether or not the given bid request is valid. - * - * @param {object} bid The bid to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ + isBidRequestValid: (bid) => { - return Boolean(bid.params.accountId) && Boolean(bid.params.placementId) + return Boolean(bid.params.sourceId) && Boolean(bid.params.accountId); }, - /** - * Make a server request from the list of BidRequests. - * - * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: (validBidRequests, bidderRequest) => { - // convert Native ORTB definition to old-style prebid native definition - validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); - if (validBidRequests && validBidRequests.length === 0) return [] - let accuontId = validBidRequests[0].params.accountId; - const endpointURL = URL_ENDPOINT.replace(ACCOUNTID_MACROS, accuontId); - let winTop = window; - let location; - try { - location = new URL(bidderRequest.refererInfo.page) - winTop = window.top; - } catch (e) { - location = winTop.location; - logMessage(e); - }; - let bids = []; - for (let bidRequest of validBidRequests) { - let impObject = prepareImpObject(bidRequest); - let data = { - id: bidRequest.bidId, - test: config.getConfig('debug') ? 1 : 0, - at: 1, - cur: ['USD'], - device: { - w: winTop.screen.width, - h: winTop.screen.height, - dnt: getDNT() ? 1 : 0, - language: (navigator && navigator.language) ? navigator.language.indexOf('-') != -1 ? navigator.language.split('-')[0] : navigator.language : '', - }, - site: { - page: location.pathname, - host: location.host - }, - source: { - tid: bidRequest.ortb2Imp?.ext?.tid, - ext: { - schain: {} - } - }, - regs: { - coppa: config.getConfig('coppa') === true ? 1 : 0, - ext: {} - }, - user: { - ext: {} - }, - ext: { - ts: Date.now() - }, - tmax: bidRequest.timeout, - imp: [impObject], - }; - - let connection = navigator.connection || navigator.webkitConnection; - if (connection && connection.effectiveType) { - data.device.connectiontype = connection.effectiveType; - } - if (bidRequest) { - if (bidRequest.schain) { - deepSetValue(data, 'source.ext.schain', bidRequest.schain); - } - - if (bidRequest.gdprConsent && bidRequest.gdprConsent.gdprApplies) { - deepSetValue(data, 'regs.ext.gdpr', bidRequest.gdprConsent.gdprApplies ? 1 : 0); - deepSetValue(data, 'user.ext.consent', bidRequest.gdprConsent.consentString); - } - - if (bidRequest.uspConsent !== undefined) { - deepSetValue(data, 'regs.ext.us_privacy', bidRequest.uspConsent); - } - } - bids.push(data) - } + buildRequests: (validBidRequests, bidderRequest) => { + if (validBidRequests && validBidRequests.length === 0) return []; + const { sourceId, accountId } = validBidRequests[0].params; + const host = validBidRequests[0].params.host || 'USE'; + const endpointURL = URL.replace(HOST_MACRO, host || DEFAULT_HOST) + .replace(ACCOUNT_ID_MACRO, accountId) + .replace(SOURCE_ID_MACRO, sourceId); + const request = converter.toORTB({ bidRequests: validBidRequests, bidderRequest }); return { method: 'POST', url: endpointURL, - data: bids + data: request }; }, - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: (serverResponse) => { - if (!serverResponse || !serverResponse.body) return [] - let bizzclickResponse = serverResponse.body; - let bids = []; - for (let response of bizzclickResponse) { - let mediaType = response.seatbid[0].bid[0].ext && response.seatbid[0].bid[0].ext.mediaType ? response.seatbid[0].bid[0].ext.mediaType : BANNER; - let bid = { - requestId: response.id, - cpm: response.seatbid[0].bid[0].price, - width: response.seatbid[0].bid[0].w, - height: response.seatbid[0].bid[0].h, - ttl: response.ttl || 1200, - currency: response.cur || 'USD', - netRevenue: true, - creativeId: response.seatbid[0].bid[0].crid, - dealId: response.seatbid[0].bid[0].dealid, - mediaType: mediaType - }; - - bid.meta = {}; - if (response.seatbid[0].bid[0].adomain && response.seatbid[0].bid[0].adomain.length > 0) { - bid.meta.advertiserDomains = response.seatbid[0].bid[0].adomain; - } - switch (mediaType) { - case VIDEO: - bid.vastXml = response.seatbid[0].bid[0].adm - bid.vastUrl = response.seatbid[0].bid[0].ext.vastUrl - break - case NATIVE: - bid.native = parseNative(response.seatbid[0].bid[0].adm) - break - default: - bid.ad = response.seatbid[0].bid[0].adm - } - bids.push(bid); + interpretResponse: (response, request) => { + if (response?.body) { + const bids = converter.fromORTB({ response: response.body, request: request.data }).bids; + return bids; } - return bids; + return []; }, }; -/** - * Determine type of request - * - * @param bidRequest - * @param type - * @returns {boolean} - */ -const checkRequestType = (bidRequest, type) => { - return (typeof deepAccess(bidRequest, `mediaTypes.${type}`) !== 'undefined'); -} -const parseNative = admObject => { - const { assets, link, imptrackers, jstracker } = admObject.native; - const result = { - clickUrl: link.url, - clickTrackers: link.clicktrackers || undefined, - impressionTrackers: imptrackers || undefined, - javascriptTrackers: jstracker ? [ jstracker ] : undefined - }; - assets.forEach(asset => { - const kind = NATIVE_ASSET_IDS[asset.id]; - const content = kind && asset[NATIVE_PARAMS[kind].name]; - if (content) { - result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h }; - } - }); - return result; -} -const prepareImpObject = (bidRequest) => { - let impObject = { - id: bidRequest.transactionId, - secure: 1, - ext: { - placementId: bidRequest.params.placementId - } - }; - if (checkRequestType(bidRequest, BANNER)) { - impObject.banner = addBannerParameters(bidRequest); - } - if (checkRequestType(bidRequest, VIDEO)) { - impObject.video = addVideoParameters(bidRequest); - } - if (checkRequestType(bidRequest, NATIVE)) { - impObject.native = { - ver: NATIVE_VERSION, - request: addNativeParameters(bidRequest) - }; - } - return impObject -}; -const addNativeParameters = bidRequest => { - let impObject = { - // TODO: top-level ID is not in ORTB native 1.2, is this intentional? - // (despite the name, this appears to be an ORTB native request - not an imp - object) - id: bidRequest.bidId, - ver: NATIVE_VERSION, - }; - const assets = _map(bidRequest.mediaTypes.native, (bidParams, key) => { - const props = NATIVE_PARAMS[key]; - const asset = { - required: bidParams.required & 1, - }; - if (props) { - asset.id = props.id; - let wmin, hmin; - let aRatios = bidParams.aspect_ratios; - if (aRatios && aRatios[0]) { - aRatios = aRatios[0]; - wmin = aRatios.min_width || 0; - hmin = aRatios.ratio_height * wmin / aRatios.ratio_width | 0; - } - if (bidParams.sizes) { - const sizes = flatten(bidParams.sizes); - wmin = sizes[0]; - hmin = sizes[1]; - } - asset[props.name] = {}; - if (bidParams.len) asset[props.name]['len'] = bidParams.len; - if (props.type) asset[props.name]['type'] = props.type; - if (wmin) asset[props.name]['wmin'] = wmin; - if (hmin) asset[props.name]['hmin'] = hmin; - return asset; - } - }).filter(Boolean); - impObject.assets = assets; - return impObject -} -const addBannerParameters = (bidRequest) => { - let bannerObject = {}; - const size = parseSizes(bidRequest, 'banner'); - bannerObject.w = size[0]; - bannerObject.h = size[1]; - return bannerObject; -}; -const parseSizes = (bid, mediaType) => { - let mediaTypes = bid.mediaTypes; - if (mediaType === 'video') { - let size = []; - if (mediaTypes.video && mediaTypes.video.w && mediaTypes.video.h) { - size = [ - mediaTypes.video.w, - mediaTypes.video.h - ]; - } else if (Array.isArray(deepAccess(bid, 'mediaTypes.video.playerSize')) && bid.mediaTypes.video.playerSize.length === 1) { - size = bid.mediaTypes.video.playerSize[0]; - } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0 && Array.isArray(bid.sizes[0]) && bid.sizes[0].length > 1) { - size = bid.sizes[0]; - } - return size; - } - let sizes = []; - if (Array.isArray(mediaTypes.banner.sizes)) { - sizes = mediaTypes.banner.sizes[0]; - } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { - sizes = bid.sizes - } else { - logWarn('no sizes are setup or found'); - } - return sizes -} -const addVideoParameters = (bidRequest) => { - let videoObj = {}; - let supportParamsList = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'placement', 'skip', 'skipafter', 'minbitrate', 'maxbitrate', 'delivery', 'playbackmethod', 'api', 'linearity'] - for (let param of supportParamsList) { - if (bidRequest.mediaTypes.video[param] !== undefined) { - videoObj[param] = bidRequest.mediaTypes.video[param]; - } - } - const size = parseSizes(bidRequest, 'video'); - videoObj.w = size[0]; - videoObj.h = size[1]; - return videoObj; -} -const flatten = arr => { - return [].concat(...arr); -} + registerBidder(spec); diff --git a/modules/bizzclickBidAdapter.md b/modules/bizzclickBidAdapter.md index 6fc1bebf546..ad342f34e07 100644 --- a/modules/bizzclickBidAdapter.md +++ b/modules/bizzclickBidAdapter.md @@ -11,94 +11,99 @@ Maintainer: support@bizzclick.com Module that connects to BizzClick SSP demand sources # Test Parameters -``` - var adUnits = [{ - code: 'placementId', - mediaTypes: { - banner: { - sizes: [[300, 250], [300,600]] - } - }, - bids: [{ - bidder: 'bizzclick', - params: { - placementId: 'hash', - accountId: 'accountId' - } - }] - }, - { - code: 'native_example', - // sizes: [[1, 1]], - mediaTypes: { - native: { - title: { - required: true, - len: 800 - }, - image: { - required: true, - len: 80 - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - }, - privacyLink: { - required: false - }, - body: { - required: true - }, - icon: { - required: true, - sizes: [50, 50] - } - } - }, - bids: [ { - bidder: 'bizzclick', - params: { - placementId: 'hash', - accountId: 'accountId' - } - }] - }, - { - code: 'video1', - sizes: [640,480], - mediaTypes: { video: { - minduration:0, - maxduration:999, - boxingallowed:1, - skip:0, - mimes:[ - 'application/javascript', - 'video/mp4' - ], - w:1920, - h:1080, - protocols:[ - 2 - ], - linearity:1, - api:[ - 1, - 2 - ] - } }, +```js +const adUnits = [ + { + code: "placementId", + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600], + ], + }, + }, + bids: [ + { + bidder: "bizzclick", + params: { + placementId: "hash", + accountId: "accountId", + host: "host", + }, + }, + ], + }, + { + code: "native_example", + // sizes: [[1, 1]], + mediaTypes: { + native: { + title: { + required: true, + len: 800, + }, + image: { + required: true, + len: 80, + }, + sponsoredBy: { + required: true, + }, + clickUrl: { + required: true, + }, + privacyLink: { + required: false, + }, + body: { + required: true, + }, + icon: { + required: true, + sizes: [50, 50], + }, + }, + }, bids: [ - { - bidder: 'bizzclick', - params: { - placementId: 'hash', - accountId: 'accountId' - } - } - ] - } - ]; -``` \ No newline at end of file + { + bidder: "bizzclick", + params: { + placementId: "hash", + accountId: "accountId", + host: "host", + }, + }, + ], + }, + { + code: "video1", + sizes: [640, 480], + mediaTypes: { + video: { + minduration: 0, + maxduration: 999, + boxingallowed: 1, + skip: 0, + mimes: ["application/javascript", "video/mp4"], + w: 1920, + h: 1080, + protocols: [2], + linearity: 1, + api: [1, 2], + }, + }, + bids: [ + { + bidder: "bizzclick", + params: { + placementId: "hash", + accountId: "accountId", + host: "host", + }, + }, + ], + }, +]; +``` diff --git a/modules/browsiRtdProvider.js b/modules/browsiRtdProvider.js index 4a61f40600d..1f37c7c5bc0 100644 --- a/modules/browsiRtdProvider.js +++ b/modules/browsiRtdProvider.js @@ -88,6 +88,7 @@ export function collectData() { let predictorData = { ...{ sk: _moduleParams.siteKey, + pk: _moduleParams.pubKey, sw: (win.screen && win.screen.width) || -1, sh: (win.screen && win.screen.height) || -1, url: `${doc.location.protocol}//${doc.location.host}${doc.location.pathname}`, @@ -134,7 +135,6 @@ function getRTD(auc) { const adSlot = getSlotByCode(uc); const identifier = adSlot ? getMacroId(_browsiData['pmd'], adSlot) : uc; const _pd = _bp[identifier]; - rp[uc] = getKVObject(-1); if (!_pd) { return rp } @@ -275,7 +275,7 @@ function getPredictionsFromServer(url) { if (req.status === 200) { try { const data = JSON.parse(response); - if (data && data.p && data.kn) { + if (data) { setData({p: data.p, kn: data.kn, pmd: data.pmd, bet: data.bet}); } else { setData({}); diff --git a/modules/consentManagementGpp.js b/modules/consentManagementGpp.js index 8160ee2378c..f696ce25902 100644 --- a/modules/consentManagementGpp.js +++ b/modules/consentManagementGpp.js @@ -70,13 +70,18 @@ export class GPPClient { * - a promise to GPP data. */ static init(mkCmp = cmpClient) { - if (this.INST == null) { - this.INST = this.ping(mkCmp).catch(e => { - this.INST = null; + let inst = this.INST; + if (!inst) { + let err; + const reset = () => err && (this.INST = null); + inst = this.INST = this.ping(mkCmp).catch(e => { + err = true; + reset(); throw e; }); + reset(); } - return this.INST.then(([client, pingData]) => [ + return inst.then(([client, pingData]) => [ client, client.initialized ? client.refresh() : client.init(pingData) ]); diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 45769edaf61..4fe9ca7d0f4 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -607,6 +607,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { }; request.user = bidderRequest.ortb2?.user || {}; request.site = bidderRequest.ortb2?.site || {}; + request.app = bidderRequest.ortb2?.app || {}; if (bidderRequest && bidderRequest.ceh) { request.user.ceh = bidderRequest.ceh; } diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js index e062686b320..7c24cd6a8f6 100644 --- a/modules/deepintentBidAdapter.js +++ b/modules/deepintentBidAdapter.js @@ -2,6 +2,7 @@ import { generateUUID, deepSetValue, deepAccess, isArray, isInteger, logError, l import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; const BIDDER_CODE = 'deepintent'; +const GVL_ID = 541; const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid'; const USER_SYNC_URL = 'https://cdn.deepintent.com/syncpixel.html'; const DI_M_V = '1.0.0'; @@ -32,6 +33,7 @@ export const ORTB_VIDEO_PARAMS = { }; export const spec = { code: BIDDER_CODE, + gvlid: GVL_ID, supportedMediaTypes: [BANNER, VIDEO], aliases: [], diff --git a/modules/dxkultureBidAdapter.js b/modules/dxkultureBidAdapter.js index 9e4768d12bb..282b54e0823 100644 --- a/modules/dxkultureBidAdapter.js +++ b/modules/dxkultureBidAdapter.js @@ -1,5 +1,6 @@ import { logInfo, + logWarn, logError, logMessage, deepAccess, @@ -8,13 +9,14 @@ import { } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js' const BIDDER_CODE = 'dxkulture'; const DEFAULT_BID_TTL = 300; const DEFAULT_NET_REVENUE = true; const DEFAULT_CURRENCY = 'USD'; -const SYNC_URL = 'https://ads.kulture.media/usync'; +const DEFAULT_OUTSTREAM_RENDERER_URL = 'https://cdn.dxkulture.com/players/dxOutstreamPlayer.js'; const converter = ortbConverter({ context: { @@ -55,20 +57,14 @@ const converter = ortbConverter({ }, bidResponse(buildBidResponse, bid, context) { let resMediaType; + const {bidRequest} = context; + if (bid.adm?.trim().startsWith(' { + const value = userSync[key]; + if (value.syncs && value.syncs.length) { + syncDetails = syncDetails.concat(value.syncs); + } + }); + syncDetails.forEach(syncDetails => { + let queryParamStrings = []; + let syncUrl = syncDetails.url; + + if (syncDetails.type === 'iframe') { + if (gdprConsent) { + queryParamStrings.push('gdpr=' + (gdprConsent.gdprApplies ? 1 : 0)); + queryParamStrings.push('gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || '')); + } + if (uspConsent) { + queryParamStrings.push('us_privacy=' + encodeURIComponent(uspConsent)); + } + syncUrl = `${syncDetails.url}${queryParamStrings.length > 0 ? '?' + queryParamStrings.join('&') : ''}` + } + + syncs.push({ + type: syncDetails.type === 'iframe' ? 'iframe' : 'image', + url: syncUrl + }); + }); + + if (syncOptions.iframeEnabled) { + syncs = syncs.filter(s => s.type == 'iframe'); + } else if (syncOptions.pixelEnabled) { + syncs = syncs.filter(s => s.type == 'image'); + } } + }); + logInfo('dxkulture.getUserSyncs result=%o', syncs); + return syncs; + }, - return [{ - type: pixelType, - url: `${syncUrl}${queryParamStrings.length > 0 ? '?' + queryParamStrings.join('&') : ''}` - }]; - } +}; + +function outstreamRenderer(bid) { + const rendererConfig = { + width: bid.width, + height: bid.height, + vastTimeout: 5000, + maxAllowedVastTagRedirects: 3, + allowVpaid: false, + autoPlay: true, + preload: true, + mute: false } -}; + const renderer = Renderer.install({ + id: bid.adId, + url: DEFAULT_OUTSTREAM_RENDERER_URL, + config: rendererConfig, + loaded: false, + targetId: bid.adUnitCode, + adUnitCode: bid.adUnitCode + }); + + try { + renderer.setRender(function (bid) { + bid.renderer.push(() => { + const { id, config } = bid.renderer; + window.dxOutstreamPlayer(bid, id, config); + }); + }); + } catch (err) { + logWarn('dxkulture: Prebid Error calling setRender on renderer', err); + } + + return renderer; +} /* ======================================= * Util Functions diff --git a/modules/growthCodeRtdProvider.js b/modules/growthCodeRtdProvider.js index e7dce81f7d0..b12b25a0951 100644 --- a/modules/growthCodeRtdProvider.js +++ b/modules/growthCodeRtdProvider.js @@ -81,8 +81,8 @@ function callServer(configParams, items, expiresAt, userConsent) { url = tryAppendQueryString(url, 'pid', configParams.pid); url = tryAppendQueryString(url, 'u', window.location.href); url = tryAppendQueryString(url, 'gcid', gcid); - if ((userConsent !== null) && (userConsent.gdpr !== null) && (userConsent.gdpr.consentData.getTCData.tcString)) { - url = tryAppendQueryString(url, 'tcf', userConsent.gdpr.consentData.getTCData.tcString) + if ((userConsent !== null) && (userConsent.gdpr !== null) && (userConsent.gdpr.consentString)) { + url = tryAppendQueryString(url, 'tcf', userConsent.gdpr.consentString) } ajax.ajaxBuilder()(url, { diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 83fd726fde5..deee906298e 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -345,9 +345,6 @@ function buildRequests(validBidRequests, bidderRequest) { // ADTS-134 Retrieve ID envelopes for (const eid in eids) data[eid] = eids[eid]; - // ADJS-1024 & ADSS-1297 & ADTS-175 - gpid && (data.gpid = gpid); - if (mediaTypes.banner) { sizes = mediaTypes.banner.sizes; } else if (mediaTypes.video) { @@ -355,6 +352,9 @@ function buildRequests(validBidRequests, bidderRequest) { data = _getVidParams(mediaTypes.video); } + // ADJS-1024 & ADSS-1297 & ADTS-175 + gpid && (data.gpid = gpid); + if (pageViewId) { data.pv = pageViewId; } diff --git a/modules/hadronIdSystem.js b/modules/hadronIdSystem.js index c60f0f812a4..4141e9a01f8 100644 --- a/modules/hadronIdSystem.js +++ b/modules/hadronIdSystem.js @@ -9,8 +9,11 @@ import {ajax} from '../src/ajax.js'; import {getStorageManager} from '../src/storageManager.js'; import {submodule} from '../src/hook.js'; import {isFn, isStr, isPlainObject, logError, logInfo} from '../src/utils.js'; +import { config } from '../src/config.js'; import {MODULE_TYPE_UID} from '../src/activities/modules.js'; +import { gdprDataHandler, uspDataHandler, gppDataHandler } from '../src/adapterManager.js'; +const LOG_PREFIX = '[hadronIdSystem]'; const HADRONID_LOCAL_NAME = 'auHadronId'; const MODULE_NAME = 'hadronId'; const AU_GVLID = 561; @@ -42,6 +45,8 @@ const urlAddParams = (url, params) => { return url + (url.indexOf('?') > -1 ? '&' : '?') + params } +const isDebug = config.getConfig('debug') || false; + /** @type {Submodule} */ export const hadronIdSubmodule = { /** @@ -88,7 +93,7 @@ export const hadronIdSubmodule = { } catch (error) { logError(error); } - logInfo(`Response from backend is ${responseObj}`); + logInfo(LOG_PREFIX, `Response from backend is ${response}`, responseObj); hadronId = responseObj['hadronId']; storage.setDataInLocalStorage(HADRONID_LOCAL_NAME, hadronId); responseObj = {id: {hadronId}}; @@ -100,13 +105,34 @@ export const hadronIdSubmodule = { callback(); } }; - logInfo('HadronId not found in storage, calling backend...'); - const url = urlAddParams( + let url = urlAddParams( // config.params.url and config.params.urlArg are not documented // since their use is for debugging purposes only paramOrDefault(config.params.url, DEFAULT_HADRON_URL_ENDPOINT, config.params.urlArg), - `partner_id=${partnerId}&_it=prebid` + `partner_id=${partnerId}&_it=prebid&t=1&src=id` // src=id => the backend was called from getId ); + if (isDebug) { + url += '&debug=1' + } + const gdprConsent = gdprDataHandler.getConsentData() + if (gdprConsent) { + url += `${gdprConsent.consentString ? '&gdprString=' + encodeURIComponent(gdprConsent.consentString) : ''}`; + url += `&gdpr=${gdprConsent.gdprApplies === true ? 1 : 0}`; + } + + const usPrivacyString = uspDataHandler.getConsentData(); + if (usPrivacyString) { + url += `&us_privacy=${encodeURIComponent(usPrivacyString)}`; + } + + const gppConsent = gppDataHandler.getConsentData(); + if (gppConsent) { + url += `${gppConsent.gppString ? '&gpp=' + encodeURIComponent(gppConsent.gppString) : ''}`; + url += `${gppConsent.applicableSections ? '&gpp_sid=' + encodeURIComponent(gppConsent.applicableSections) : ''}`; + } + + logInfo(LOG_PREFIX, `hadronId not found in storage, calling home (${url})`); + ajax(url, callbacks, undefined, {method: 'GET'}); }; return {callback: resp}; diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js index 0c0d1cdef87..1d608d7136b 100644 --- a/modules/invibesBidAdapter.js +++ b/modules/invibesBidAdapter.js @@ -9,7 +9,7 @@ const CONSTANTS = { SYNC_ENDPOINT: 'https://k.r66net.com/GetUserSync', TIME_TO_LIVE: 300, DEFAULT_CURRENCY: 'EUR', - PREBID_VERSION: 10, + PREBID_VERSION: 11, METHOD: 'GET', INVIBES_VENDOR_ID: 436, USERID_PROVIDERS: ['pubcid', 'pubProvidedId', 'uid2', 'zeotapIdPlus', 'id5id'], @@ -49,14 +49,36 @@ registerBidder(spec); // some state info is required: cookie info, unique user visit id const topWin = getTopMostWindow(); let invibes = topWin.invibes = topWin.invibes || {}; -invibes.purposes = invibes.purposes || [false, false, false, false, false, false, false, false, false, false]; -invibes.legitimateInterests = invibes.legitimateInterests || [false, false, false, false, false, false, false, false, false, false]; +invibes.purposes = invibes.purposes || [false, false, false, false, false, false, false, false, false, false, false]; +invibes.legitimateInterests = invibes.legitimateInterests || [false, false, false, false, false, false, false, false, false, false, false]; invibes.placementBids = invibes.placementBids || []; invibes.pushedCids = invibes.pushedCids || {}; let preventPageViewEvent = false; +let isInfiniteScrollPage = false; +let isPlacementRefresh = false; let _customUserSync; let _disableUserSyncs; +function updateInfiniteScrollFlag() { + const { scrollHeight } = document.documentElement; + + if (invibes.originalURL === undefined) { + invibes.originalURL = window.location.href; + return; + } + + if (invibes.originalScrollHeight === undefined) { + invibes.originalScrollHeight = scrollHeight; + return; + } + + const currentURL = window.location.href; + + if (scrollHeight > invibes.originalScrollHeight && invibes.originalURL !== currentURL) { + isInfiniteScrollPage = true; + } +} + function isBidRequestValid(bid) { if (typeof bid.params !== 'object') { return false; @@ -87,10 +109,24 @@ function buildRequest(bidRequests, bidderRequest) { const _placementIds = []; const _adUnitCodes = []; let _customEndpoint, _userId, _domainId; - let _ivAuctionStart = bidderRequest.auctionStart || Date.now(); + let _ivAuctionStart = Date.now(); + window.invibes = window.invibes || {}; + window.invibes.placementIds = window.invibes.placementIds || []; + + if (isInfiniteScrollPage == false) { + updateInfiniteScrollFlag(); + } bidRequests.forEach(function (bidRequest) { bidRequest.startTime = new Date().getTime(); + + if (window.invibes.placementIds.includes(bidRequest.params.placementId)) { + isPlacementRefresh = true; + } + + window.invibes.placementIds.push(bidRequest.params.placementId); + + _placementIds.push(bidRequest.params.placementId); _placementIds.push(bidRequest.params.placementId); _adUnitCodes.push(bidRequest.adUnitCode); _domainId = _domainId || bidRequest.params.domainId; @@ -138,6 +174,8 @@ function buildRequest(bidRequests, bidderRequest) { tc: invibes.gdpr_consent, isLocalStorageEnabled: storage.hasLocalStorage(), preventPageViewEvent: preventPageViewEvent, + isPlacementRefresh: isPlacementRefresh, + isInfiniteScrollPage: isInfiniteScrollPage, }; let lid = readFromLocalStorage('ivbsdid'); @@ -368,7 +406,9 @@ function addMeta(bidModelMeta) { } function generateRandomId() { - return (Math.round(Math.random() * 1e12)).toString(36).substring(0, 10); + return '10000000100040008000100000000000'.replace(/[018]/g, c => + (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) + ); } function getDocumentLocation(bidderRequest) { @@ -568,7 +608,7 @@ function readGdprConsent(gdprConsent) { } let legitimateInterests = getLegitimateInterests(gdprConsent.vendorData); - tryCopyValueToArray(legitimateInterests, invibes.legitimateInterests, 10); + tryCopyValueToArray(legitimateInterests, invibes.legitimateInterests, purposesLength); let invibesVendorId = CONSTANTS.INVIBES_VENDOR_ID.toString(10); let vendorConsents = getVendorConsents(gdprConsent.vendorData); @@ -621,6 +661,10 @@ function tryCopyValueToArray(value, target, length) { function getPurposeConsentsCounter(vendorData) { if (vendorData.purpose && vendorData.purpose.consents) { + if (vendorData.tcfPolicyVersion >= 4) { + return 11; + } + return 10; } diff --git a/modules/mediagoBidAdapter.js b/modules/mediagoBidAdapter.js index 72b06dfe7ed..a9c670f35d8 100644 --- a/modules/mediagoBidAdapter.js +++ b/modules/mediagoBidAdapter.js @@ -10,10 +10,8 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'mediago'; // const PROTOCOL = window.document.location.protocol; -const ENDPOINT_URL = - // ((PROTOCOL === 'https:') ? 'https' : 'http') + - 'https://rtb-us.mediago.io/api/bid?tn='; -const COOKY_SYNC_URL = 'https://trace.mediago.io/ju/cs/eplist'; +const ENDPOINT_URL = 'https://gbid.mediago.io/api/bid?tn='; +const COOKY_SYNC_URL = 'https://gtrace.mediago.io/ju/cs/eplist'; const COOKY_SYNC_IFRAME_URL = 'https://cdn.mediago.io/js/cookieSync.html'; const TIME_TO_LIVE = 500; diff --git a/modules/missenaBidAdapter.js b/modules/missenaBidAdapter.js index a06ba1ce29c..5e68f56ed1c 100644 --- a/modules/missenaBidAdapter.js +++ b/modules/missenaBidAdapter.js @@ -59,9 +59,11 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { const capKey = `missena.missena.capper.remove-bubble.${validBidRequests[0]?.params.apiKey}`; const capping = safeJSONParse(storage.getDataFromLocalStorage(capKey)); + const referer = bidderRequest?.refererInfo?.topmostLocation; if ( typeof capping?.expiry === 'number' && - new Date().getTime() < capping?.expiry + new Date().getTime() < capping?.expiry && + (!capping?.referer || capping?.referer == referer) ) { logInfo('Missena - Capped'); return []; diff --git a/modules/mygaruIdSystem.js b/modules/mygaruIdSystem.js new file mode 100644 index 00000000000..4d50de16d48 --- /dev/null +++ b/modules/mygaruIdSystem.js @@ -0,0 +1,98 @@ +/** + * This module adds MyGaru Real Time User Sync to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/mygaruIdSystem + * @requires module:modules/userId + */ + +import { ajax } from '../src/ajax.js'; +import { submodule } from '../src/hook.js'; + +const bidderCode = 'mygaruId'; +const syncUrl = 'https://ident.mygaru.com/v2/id'; + +export function buildUrl(opts) { + const queryPairs = []; + for (let key in opts) { + if (opts[key] !== undefined) { + queryPairs.push(`${key}=${encodeURIComponent(opts[key])}`); + } + } + return `${syncUrl}?${queryPairs.join('&')}`; +} + +function requestRemoteIdAsync(url) { + return new Promise((resolve) => { + ajax( + url, + { + success: response => { + try { + const jsonResponse = JSON.parse(response); + const { iuid } = jsonResponse; + resolve(iuid); + } catch (e) { + resolve(); + } + }, + error: () => { + resolve(); + }, + }, + undefined, + { + method: 'GET', + contentType: 'application/json' + } + ); + }); +} + +/** @type {Submodule} */ +export const mygaruIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: bidderCode, + /** + * decode the stored id value for passing to bid requests + * @function + * @returns {{id: string} | null} + */ + decode(id) { + return id; + }, + /** + * get the MyGaru Id from local storages and initiate a new user sync + * @function + * @param {SubmoduleConfig} [config] + * @param {ConsentData} [consentData] + * @returns {{id: string | undefined}} + */ + getId(config, consentData) { + const gdprApplies = consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies ? 1 : 0; + const gdprConsentString = gdprApplies ? consentData.consentString : undefined; + const url = buildUrl({ + gdprApplies, + gdprConsentString + }); + + return { + url, + callback: function (done) { + return requestRemoteIdAsync(url).then((id) => { + done({ mygaruId: id }); + }) + } + } + }, + eids: { + 'mygaruId': { + source: 'mygaru.com', + atype: 1 + }, + } +}; + +submodule('userId', mygaruIdSubmodule); diff --git a/modules/mygaruIdSystem.md b/modules/mygaruIdSystem.md new file mode 100644 index 00000000000..92724f99469 --- /dev/null +++ b/modules/mygaruIdSystem.md @@ -0,0 +1,24 @@ +## Mygaru User ID Submodule + +MyGaru provides single use tokens as a UserId for SSPs and DSP that consume telecom DMP data. + +## Building Prebid with Mygaru ID Support + +First, make sure to add submodule to your Prebid.js package with: + +``` +gulp build --modules=userId,mygaruIdSystem +``` +Params configuration is not required. +Also mygaru is async, in order to get ids for initial ad auctions you need to add auctionDelay param to userSync config. + +```javascript +pbjs.setConfig({ + userSync: { + auctionDelay: 100, + userIds: [{ + name: 'mygaruId', + }] + } +}); +``` diff --git a/modules/nextMillenniumBidAdapter.js b/modules/nextMillenniumBidAdapter.js index 9c6c0c648c6..0475b662bc9 100644 --- a/modules/nextMillenniumBidAdapter.js +++ b/modules/nextMillenniumBidAdapter.js @@ -14,6 +14,7 @@ import { triggerPixel, } from '../src/utils.js'; +import {getGlobal} from '../src/prebidGlobal.js'; import CONSTANTS from '../src/constants.json'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -22,7 +23,7 @@ import * as events from '../src/events.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {getRefererInfo} from '../src/refererDetection.js'; -const NM_VERSION = '3.0.0'; +const NM_VERSION = '3.1.0'; const GVLID = 1060; const BIDDER_CODE = 'nextMillennium'; const ENDPOINT = 'https://pbs.nextmillmedia.com/openrtb2/auction'; @@ -47,6 +48,7 @@ const ALLOWED_ORTB2_PARAMETERS = [ 'site.pagecat', 'site.content.cat', 'site.content.language', + 'device.sua', ]; const sendingDataStatistic = initSendingDataStatistic(); @@ -96,6 +98,7 @@ export const spec = { nextMillennium: { nm_version: NM_VERSION, + pbjs_version: getGlobal()?.version || undefined, refresh_count: window.nmmRefreshCounts[bid.adUnitCode]++, elOffsets: getBoundingClient(bid), scrollTop: window.pageYOffset || document.documentElement.scrollTop, @@ -110,6 +113,7 @@ export const spec = { postBody.imp.push(getImp(bid, id)); setConsentStrings(postBody, bidderRequest); setOrtb2Parameters(postBody, bidderRequest?.ortb2); + setEids(postBody, bid); const urlParameters = parseUrl(getWindowTop().location.href).search; const isTest = urlParameters['pbs'] && urlParameters['pbs'] === 'test'; @@ -315,6 +319,12 @@ export function setOrtb2Parameters(postBody, ortb2 = {}) { } } +export function setEids(postBody, bid) { + if (!isArray(bid.userIdAsEids) || !bid.userIdAsEids.length) return; + + deepSetValue(postBody, 'user.eids', bid.userIdAsEids); +} + export function replaceUsersyncMacros(url, gdprConsent = {}, uspConsent = '', gppConsent = {}, type = '') { const { consentString = '', gdprApplies = false } = gdprConsent; const gdpr = Number(gdprApplies); @@ -394,7 +404,7 @@ function getAd(bid) { } else if (bid.nurl) { adUrl = bid.nurl; }; - } + }; return {ad, adUrl, vastXml, vastUrl}; } @@ -402,10 +412,21 @@ function getAd(bid) { function getSiteObj() { const refInfo = (getRefererInfo && getRefererInfo()) || {}; + let language = navigator.language; + let content; + if (language) { + // get ISO-639-1-alpha-2 (2 character language) + language = language.split('-')[0]; + content = { + language, + }; + }; + return { page: refInfo.page, ref: refInfo.ref, - domain: refInfo.domain + domain: refInfo.domain, + content, }; } @@ -413,6 +434,19 @@ function getDeviceObj() { return { w: window.innerWidth || window.document.documentElement.clientWidth || window.document.body.clientWidth || 0, h: window.innerHeight || window.document.documentElement.clientHeight || window.document.body.clientHeight || 0, + ua: window.navigator.userAgent || undefined, + sua: getSua(), + }; +} + +function getSua() { + let {brands, mobile, platform} = (window?.navigator?.userAgentData || {}); + if (!(brands && platform)) return undefined; + + return { + brands, + mobile: Number(!!mobile), + platform: (platform && {brand: platform}) || undefined, }; } diff --git a/modules/nobidAnalyticsAdapter.js b/modules/nobidAnalyticsAdapter.js index 27ec1cd9451..3a7912c37e1 100644 --- a/modules/nobidAnalyticsAdapter.js +++ b/modules/nobidAnalyticsAdapter.js @@ -6,10 +6,10 @@ import CONSTANTS from '../src/constants.json'; import adapterManager from '../src/adapterManager.js'; import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js'; -const VERSION = '1.0.4'; +const VERSION = '1.1.0'; const MODULE_NAME = 'nobidAnalyticsAdapter'; -const ANALYTICS_DATA_NAME = 'analytics.nobid.io'; -const RETENTION_SECONDS = 7 * 24 * 3600; +const ANALYTICS_OPT_FLUSH_TIMEOUT_SECONDS = 5 * 1000; +const RETENTION_SECONDS = 1 * 24 * 3600; const TEST_ALLOCATION_PERCENTAGE = 5; // dont block 5% of the time; window.nobidAnalyticsVersion = VERSION; const analyticsType = 'endpoint'; @@ -148,7 +148,7 @@ nobidAnalytics = { return isExpired(data, this.retentionSeconds); }, isAnalyticsDisabled () { - let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME); + let stored = storage.getDataFromLocalStorage(this.ANALYTICS_DATA_NAME); if (!isJson(stored)) return false; stored = JSON.parse(stored); if (this.isExpired(stored)) return false; @@ -157,8 +157,10 @@ nobidAnalytics = { processServerResponse (response) { if (!isJson(response)) return; const resp = JSON.parse(response); - storage.setDataInLocalStorage(ANALYTICS_DATA_NAME, JSON.stringify({ ...resp, ts: Date.now() })); - } + storage.setDataInLocalStorage(this.ANALYTICS_DATA_NAME, JSON.stringify({ ...resp, ts: Date.now() })); + }, + ANALYTICS_DATA_NAME: 'analytics.nobid.io', + ANALYTICS_OPT_NAME: 'analytics.nobid.io.optData' } adapterManager.registerAnalyticsAdapter({ @@ -166,33 +168,74 @@ adapterManager.registerAnalyticsAdapter({ code: 'nobidAnalytics', gvlid: GVLID }); +nobidAnalytics.originalAdUnits = {}; window.nobidCarbonizer = { getStoredLocalData: function () { - return storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME); + const a = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_DATA_NAME); + const b = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_OPT_NAME); + const ret = {}; + if (a) ret[nobidAnalytics.ANALYTICS_DATA_NAME] = a; + if (b) ret[nobidAnalytics.ANALYTICS_OPT_NAME] = b + return ret; }, isActive: function () { - let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME); + let stored = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_DATA_NAME); if (!isJson(stored)) return false; stored = JSON.parse(stored); if (isExpired(stored, nobidAnalytics.retentionSeconds)) return false; return stored.carbonizer_active || false; }, carbonizeAdunits: function (adunits, skipTestGroup) { + function processBlockedBidders (blockedBidders) { + function sendOptimizerData() { + let optData = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_OPT_NAME); + storage.removeDataFromLocalStorage(nobidAnalytics.ANALYTICS_OPT_NAME); + if (isJson(optData)) { + optData = JSON.parse(optData); + if (Object.getOwnPropertyNames(optData).length > 0) { + const event = { o_bidders: optData }; + if (nobidAnalytics.topLocation) event.topLocation = nobidAnalytics.topLocation; + sendEvent(event, 'optData'); + } + } + } + if (blockedBidders && blockedBidders.length > 0) { + let optData = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_OPT_NAME); + optData = isJson(optData) ? JSON.parse(optData) : {}; + const bidders = blockedBidders.map(rec => rec.bidder); + if (bidders && bidders.length > 0) { + bidders.forEach(bidder => { + if (!optData[bidder]) optData[bidder] = 1; + else optData[bidder] += 1; + }); + storage.setDataInLocalStorage(nobidAnalytics.ANALYTICS_OPT_NAME, JSON.stringify(optData)); + if (window.nobidAnalyticsOptTimer) return; + window.nobidAnalyticsOptTimer = setInterval(sendOptimizerData, ANALYTICS_OPT_FLUSH_TIMEOUT_SECONDS); + } + } + } function carbonizeAdunit (adunit) { - let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME); + let stored = storage.getDataFromLocalStorage(nobidAnalytics.ANALYTICS_DATA_NAME); if (!isJson(stored)) return; stored = JSON.parse(stored); if (isExpired(stored, nobidAnalytics.retentionSeconds)) return; const carbonizerBidders = stored.bidders || []; - const allowedBidders = adunit.bids.filter(rec => carbonizerBidders.includes(rec.bidder)); + let originalAdUnit = null; + if (nobidAnalytics.originalAdUnits && nobidAnalytics.originalAdUnits[adunit.code]) originalAdUnit = nobidAnalytics.originalAdUnits[adunit.code]; + const allowedBidders = originalAdUnit.bids.filter(rec => carbonizerBidders.includes(rec.bidder)); + const blockedBidders = originalAdUnit.bids.filter(rec => !carbonizerBidders.includes(rec.bidder)); + processBlockedBidders(blockedBidders); adunit.bids = allowedBidders; } + for (const adunit of adunits) { + if (!nobidAnalytics.originalAdUnits[adunit.code]) nobidAnalytics.originalAdUnits[adunit.code] = JSON.parse(JSON.stringify(adunit)); + }; if (this.isActive()) { // 5% of the time do not block; if (!skipTestGroup && Math.floor(Math.random() * 101) <= TEST_ALLOCATION_PERCENTAGE) return; - adunits.forEach(adunit => { + for (const adunit of adunits) { carbonizeAdunit(adunit); - }); + }; } } }; diff --git a/modules/pgamsspBidAdapter.js b/modules/pgamsspBidAdapter.js index 7d285daf3c6..b38131c1c18 100644 --- a/modules/pgamsspBidAdapter.js +++ b/modules/pgamsspBidAdapter.js @@ -35,9 +35,14 @@ function getPlacementReqData(bid) { const placement = { bidId, schain, - bidfloor + bidfloor, + eids: [] }; + if (bid.userId) { + getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com'); + } + if (placementId) { placement.placementId = placementId; placement.type = 'publisher'; @@ -91,6 +96,18 @@ function getBidFloor(bid) { return 0; } } +function getUserId(eids, id, source, uidExt) { + if (id) { + var uid = { id }; + if (uidExt) { + uid.ext = uidExt; + } + eids.push({ + source, + uids: [ uid ] + }); + } +} export const spec = { code: BIDDER_CODE, diff --git a/modules/priceFloors.js b/modules/priceFloors.js index 4ec8a8e4b7e..3837f56366c 100644 --- a/modules/priceFloors.js +++ b/modules/priceFloors.js @@ -347,7 +347,7 @@ export function updateAdUnitsForAuction(adUnits, floorData, auctionId) { bid.auctionId = auctionId; bid.floorData = { skipped: floorData.skipped, - skipRate: floorData.skipRate, + skipRate: deepAccess(floorData, 'data.skipRate') ?? floorData.skipRate, floorMin: floorData.floorMin, modelVersion: deepAccess(floorData, 'data.modelVersion'), modelWeight: deepAccess(floorData, 'data.modelWeight'), @@ -396,7 +396,7 @@ export function createFloorsDataForAuction(adUnits, auctionId) { resolvedFloorsData.skipped = true; } else { // determine the skip rate now - const auctionSkipRate = getParameterByName('pbjs_skipRate') || resolvedFloorsData.skipRate; + const auctionSkipRate = getParameterByName('pbjs_skipRate') || (deepAccess(resolvedFloorsData, 'data.skipRate') ?? resolvedFloorsData.skipRate); const isSkipped = Math.random() * 100 < parseFloat(auctionSkipRate); resolvedFloorsData.skipped = isSkipped; } diff --git a/modules/pubmaticAnalyticsAdapter.js b/modules/pubmaticAnalyticsAdapter.js index a8f2b8d20ee..9b910caa992 100755 --- a/modules/pubmaticAnalyticsAdapter.js +++ b/modules/pubmaticAnalyticsAdapter.js @@ -1,4 +1,4 @@ -import {_each, isArray, isStr, logError, logWarn, pick} from '../src/utils.js'; +import {_each, isArray, isStr, logError, logWarn, pick, generateUUID} from '../src/utils.js'; import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import adapterManager from '../src/adapterManager.js'; import CONSTANTS from '../src/constants.json'; @@ -286,7 +286,7 @@ function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestBid) { 'ocpm': bid.bidResponse ? (bid.bidResponse.originalCpm || 0) : 0, 'ocry': bid.bidResponse ? (bid.bidResponse.originalCurrency || CURRENCY_USD) : CURRENCY_USD, 'piid': bid.bidResponse ? (bid.bidResponse.partnerImpId || EMPTY_STRING) : EMPTY_STRING, - 'frv': (bid.bidResponse ? (bid.bidResponse.floorData ? bid.bidResponse.floorData.floorRuleValue : undefined) : undefined), + 'frv': bid.bidResponse ? bid.bidResponse.floorData?.floorRuleValue : undefined, 'md': bid.bidResponse ? getMetadata(bid.bidResponse.meta) : undefined }); }); @@ -337,11 +337,11 @@ function executeBidsLoggerCall(e, highestCpmBids) { let auctionId = e.auctionId; let referrer = config.getConfig('pageUrl') || cache.auctions[auctionId].referer || ''; let auctionCache = cache.auctions[auctionId]; - let floorData = auctionCache.floorData; + let wiid = auctionCache?.wiid || auctionId; + let floorData = auctionCache?.floorData; + let floorFetchStatus = getFloorFetchStatus(auctionCache?.floorData); let outputObj = { s: [] }; let pixelURL = END_POINT_BID_LOGGER; - // will return true if floor data is present. - let fetchStatus = getFloorFetchStatus(auctionCache.floorData); if (!auctionCache) { return; @@ -353,7 +353,7 @@ function executeBidsLoggerCall(e, highestCpmBids) { pixelURL += 'pubid=' + publisherId; outputObj['pubid'] = '' + publisherId; - outputObj['iid'] = '' + auctionId; + outputObj['iid'] = '' + wiid; outputObj['to'] = '' + auctionCache.timeout; outputObj['purl'] = referrer; outputObj['orig'] = getDomainFromUrl(referrer); @@ -364,7 +364,7 @@ function executeBidsLoggerCall(e, highestCpmBids) { outputObj['tgid'] = getTgId(); outputObj['pbv'] = getGlobal()?.version || '-1'; - if (floorData && fetchStatus) { + if (floorData && floorFetchStatus) { outputObj['fmv'] = floorData.floorRequestData ? floorData.floorRequestData.modelVersion || undefined : undefined; outputObj['ft'] = floorData.floorResponseData ? (floorData.floorResponseData.enforcements.enforceJS == false ? 0 : 1) : undefined; } @@ -379,8 +379,25 @@ function executeBidsLoggerCall(e, highestCpmBids) { 'mt': getAdUnitAdFormats(origAdUnit), 'sz': getSizesForAdUnit(adUnit, adUnitId), 'ps': gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestCpmBids.filter(bid => bid.adUnitCode === adUnitId)), - 'fskp': (floorData && fetchStatus) ? (floorData.floorRequestData ? (floorData.floorRequestData.skipped == false ? 0 : 1) : undefined) : undefined, + 'fskp': floorData && floorFetchStatus ? (floorData.floorRequestData ? (floorData.floorRequestData.skipped == false ? 0 : 1) : undefined) : undefined, + 'sid': generateUUID() }; + if (floorData?.floorRequestData) { + const { location, fetchStatus, floorProvider } = floorData?.floorRequestData; + slotObject.ffs = { + [CONSTANTS.FLOOR_VALUES.SUCCESS]: 1, + [CONSTANTS.FLOOR_VALUES.ERROR]: 2, + [CONSTANTS.FLOOR_VALUES.TIMEOUT]: 4, + undefined: 0 + }[fetchStatus]; + slotObject.fsrc = { + [CONSTANTS.FLOOR_VALUES.FETCH]: 2, + [CONSTANTS.FLOOR_VALUES.NO_DATA]: 2, + [CONSTANTS.FLOOR_VALUES.AD_UNIT]: 1, + [CONSTANTS.FLOOR_VALUES.SET_CONFIG]: 1 + }[location]; + slotObject.fp = floorProvider; + } slotsArray.push(slotObject); return slotsArray; }, []); @@ -412,6 +429,7 @@ function executeBidWonLoggerCall(auctionId, adUnitId) { let origAdUnit = getAdUnit(cache.auctions[auctionId].origAdUnits, adUnitId) || {}; let auctionCache = cache.auctions[auctionId]; let floorData = auctionCache.floorData; + let wiid = cache.auctions[auctionId]?.wiid || auctionId; let referrer = config.getConfig('pageUrl') || cache.auctions[auctionId].referer || ''; let adv = winningBid.bidResponse ? getAdDomain(winningBid.bidResponse) || undefined : undefined; let fskp = floorData ? (floorData.floorRequestData ? (floorData.floorRequestData.skipped == false ? 0 : 1) : undefined) : undefined; @@ -420,7 +438,7 @@ function executeBidWonLoggerCall(auctionId, adUnitId) { pixelURL += 'pubid=' + publisherId; pixelURL += '&purl=' + enc(config.getConfig('pageUrl') || cache.auctions[auctionId].referer || ''); pixelURL += '&tst=' + Math.round((new window.Date()).getTime() / 1000); - pixelURL += '&iid=' + enc(auctionId); + pixelURL += '&iid=' + enc(wiid); pixelURL += '&bidid=' + enc(winningBidId); pixelURL += '&pid=' + enc(profileId); pixelURL += '&pdvid=' + enc(profileVersionId); @@ -484,6 +502,9 @@ function bidRequestedHandler(args) { dimensions: bid.sizes }; } + if (bid.bidder === 'pubmatic' && !!bid?.params?.wiid) { + cache.auctions[args.auctionId].wiid = bid.params.wiid; + } cache.auctions[args.auctionId].adUnitCodes[bid.adUnitCode].bids[bid.bidId] = [copyRequiredBidDetails(bid)]; if (bid.floorData) { cache.auctions[args.auctionId].floorData['floorRequestData'] = bid.floorData; diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index ee80de03c03..a6c7dda510c 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,4 +1,4 @@ -import { getBidRequest, logWarn, isBoolean, isStr, isArray, inIframe, mergeDeep, deepAccess, isNumber, deepSetValue, logInfo, logError, deepClone, uniques, isPlainObject, isInteger } from '../src/utils.js'; +import { getBidRequest, logWarn, isBoolean, isStr, isArray, inIframe, mergeDeep, deepAccess, isNumber, deepSetValue, logInfo, logError, deepClone, uniques, isPlainObject, isInteger, generateUUID } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO, NATIVE, ADPOD } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; @@ -1081,8 +1081,10 @@ export const spec = { var bid; var blockedIabCategories = []; var allowedIabCategories = []; + var wiid = generateUUID(); validBidRequests.forEach(originalBid => { + originalBid.params.wiid = originalBid.params.wiid || bidderRequest.auctionId || wiid; bid = deepClone(originalBid); bid.params.adSlot = bid.params.adSlot || ''; _parseAdSlot(bid); diff --git a/modules/r2b2BidAdapter.js b/modules/r2b2BidAdapter.js new file mode 100644 index 00000000000..15a65e3924c --- /dev/null +++ b/modules/r2b2BidAdapter.js @@ -0,0 +1,309 @@ +import {logWarn, logError, triggerPixel, deepSetValue, getParameterByName} from '../src/utils.js'; +import {ortbConverter} from '../libraries/ortbConverter/converter.js' +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {Renderer} from '../src/Renderer.js'; +import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; +import {pbsExtensions} from '../libraries/pbsExtensions/pbsExtensions.js'; +import {bidderSettings} from '../src/bidderSettings.js'; + +const ADAPTER_VERSION = '1.0.0'; +const BIDDER_CODE = 'r2b2'; +const GVL_ID = 1235; + +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_TTL = 360; +const DEFAULT_NET_REVENUE = true; +const DEBUG_PARAM = 'pbjs_test_r2b2'; +const RENDERER_URL = 'https://delivery.r2b2.io/static/rendering.js'; + +const ENDPOINT = bidderSettings.get(BIDDER_CODE, 'endpoint') || 'hb.r2b2.cz'; +const SERVER_URL = 'https://' + ENDPOINT; +const URL_BID = SERVER_URL + '/openrtb2/bid'; +const URL_SYNC = SERVER_URL + '/cookieSync'; +const URL_EVENT = SERVER_URL + '/event'; + +const URL_EVENT_ON_BIDDER_ERROR = URL_EVENT + '/bidError'; +const URL_EVENT_ON_TIMEOUT = URL_EVENT + '/timeout'; + +const R2B2_TEST_UNIT = 'selfpromo'; + +export const internal = { + placementsToSync: [], + mappedParams: {} +} + +let r2b2Error = function(message, params) { + logError(message, params, BIDDER_CODE) +} + +function getIdParamsFromPID(pid) { + // selfpromo test creative + if (pid === R2B2_TEST_UNIT) { + return { d: 'test', g: 'test', p: 'selfpromo', m: 0, selfpromo: 1 } + } + if (!isNaN(pid)) { + return { pid: Number(pid) } + } + if (typeof pid === 'string') { + const params = pid.split('/'); + if (params.length === 3 || params.length === 4) { + const paramNames = ['d', 'g', 'p', 'm']; + return paramNames.reduce((p, paramName, index) => { + let param = params[index]; + if (paramName === 'm') { + param = ['desktop', 'classic', '0'].includes(param) ? 0 : Number(!!param) + } + p[paramName] = param; + return p + }, {}); + } + } +} + +function pickIdFromParams(params) { + if (!params) return null; + const { d, g, p, m, pid } = params; + return d ? { d, g, p, m } : { pid }; +} + +function getIdsFromBids(bids) { + return bids.reduce((ids, bid) => { + const params = internal.mappedParams[bid.bidId]; + const id = pickIdFromParams(params); + if (id) { + ids.push(id); + } + return ids + }, []); +} + +function triggerEvent(eventUrl, ids) { + if (ids && !ids.length) return; + const timeStamp = new Date().getTime(); + const symbol = (eventUrl.indexOf('?') === -1 ? '?' : '&'); + const url = eventUrl + symbol + `p=${btoa(JSON.stringify(ids))}&cb=${timeStamp}`; + triggerPixel(url) +} + +const converter = ortbConverter({ + imp(buildImp, bidRequest, context) { + const imp = buildImp(bidRequest, context); + const idParams = getIdParamsFromPID(bidRequest.params.pid); + deepSetValue(imp, 'ext.r2b2', idParams); + internal.placementsToSync.push(idParams); + internal.mappedParams[imp.id] = Object.assign({}, bidRequest.params, idParams); + return imp; + }, + request(buildRequest, imps, bidderRequest, context) { + const request = buildRequest(imps, bidderRequest, context); + deepSetValue(request, 'ext.version', ADAPTER_VERSION); + request.cur = [DEFAULT_CURRENCY]; + const test = getParameterByName(DEBUG_PARAM) === '1' ? 1 : 0; + deepSetValue(request, 'test', test); + return request; + }, + context: { + netRevenue: DEFAULT_NET_REVENUE, + ttl: DEFAULT_TTL + }, + processors: pbsExtensions +}); + +function setUpRenderer(adUnitCode, bid) { + // let renderer load once in main window, but pass the renderDocument + let renderDoc; + const config = { + documentResolver: (bid, sourceDocument, renderDocument) => { + renderDoc = renderDocument; + return sourceDocument; + } + } + let renderer = Renderer.install({ + url: RENDERER_URL, + config: config, + id: bid.requestId, + adUnitCode + }); + + renderer.setRender(function (bid, doc) { + doc = renderDoc || doc; + window.R2B2 = window.R2B2 || {}; + let main = window.R2B2; + main.HB = main.HB || {}; + main.HB.Render = main.HB.Render || {}; + main.HB.Render.queue = main.HB.Render.queue || []; + main.HB.Render.queue.push(() => { + const id = pickIdFromParams(internal.mappedParams[bid.requestId]) + main.HB.Renderer.render(id, bid, null, doc) + }) + }) + + return renderer +} + +function getExtMediaType(bidMediaType, responseBid) { + switch (bidMediaType) { + case BANNER: + return { + type: 'banner', + settings: { + chd: null, + width: responseBid.w, + height: responseBid.h, + ad: { + type: 'content', + data: responseBid.adm + } + } + }; + case NATIVE: + break; + case VIDEO: + break; + default: + break; + } +} + +function createPrebidResponseBid(requestImp, bidResponse, serverResponse, bids) { + const bidId = requestImp.id; + const adUnitCode = bids[0].adUnitCode; + const mediaType = bidResponse.ext.prebid.type; + let bidOut = { + requestId: bidId, + cpm: bidResponse.price, + creativeId: bidResponse.crid, + width: bidResponse.w, + height: bidResponse.h, + ttl: bidResponse.ttl ?? DEFAULT_TTL, + netRevenue: serverResponse.netRevenue ?? DEFAULT_NET_REVENUE, + currency: serverResponse.cur ?? DEFAULT_CURRENCY, + ad: bidResponse.adm, + mediaType: mediaType, + winUrl: bidResponse.nurl, + ext: { + cid: bidResponse.ext?.r2b2?.cid, + cdid: bidResponse.ext?.r2b2?.cdid, + mediaType: getExtMediaType(mediaType, bidResponse), + adUnit: adUnitCode, + dgpm: internal.mappedParams[bidId], + events: bidResponse.ext?.r2b2?.events + } + }; + if (bidResponse.ext?.r2b2?.useRenderer) { + bidOut.renderer = setUpRenderer(adUnitCode, bidOut); + } + return bidOut; +} + +export const spec = { + code: BIDDER_CODE, + gvlid: GVL_ID, + supportedMediaTypes: [BANNER], + + isBidRequestValid: function(bid) { + if (!bid.params || !bid.params.pid) { + logWarn('Bad params, "pid" required.'); + return false + } + const id = getIdParamsFromPID(bid.params.pid); + if (!id || !(id.pid || (id.d && id.g && id.p))) { + logWarn('Bad params, "pid" has to be either a number or a correctly assembled string.'); + return false + } + return true + }, + buildRequests: function(validBidRequests, bidderRequest) { + const data = converter.toORTB({ + bidRequests: validBidRequests, + bidderRequest + }); + return [{ + method: 'POST', + url: URL_BID, + data, + bids: bidderRequest.bids + }] + }, + + interpretResponse: function(serverResponse, request) { + // r2b2Error('error message', {params: 1}); + let prebidResponses = []; + + const response = serverResponse.body; + if (!response || !response.seatbid || !response.seatbid[0] || !response.seatbid[0].bid) { + return prebidResponses; + } + let requestImps = request.data.imp || []; + try { + response.seatbid.forEach(seat => { + let bids = seat.bid; + + for (let responseBid of bids) { + let responseImpId = responseBid.impid; + let requestCurrentImp = requestImps.find((requestImp) => requestImp.id === responseImpId); + if (!requestCurrentImp) { + r2b2Error('Cant match bid response.', {impid: Boolean(responseBid.impid)}); + continue;// Skip this iteration if there's no match + } + prebidResponses.push(createPrebidResponseBid(requestCurrentImp, responseBid, response, request.bids)); + } + }) + } catch (e) { + r2b2Error('Error while interpreting response:', {msg: e.message}); + } + return prebidResponses; + }, + getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { + const syncs = []; + + if (!syncOptions.iframeEnabled) { + logWarn('Please enable iframe based user sync.'); + return syncs; + } + + let plString; + try { + plString = btoa(JSON.stringify(internal.placementsToSync || [])); + } catch (e) { + logWarn('User sync failed: ' + e.message); + return syncs + } + + let url = URL_SYNC + `?p=${plString}`; + + if (gdprConsent) { + url += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}` + } + + if (uspConsent) { + url += `&us_privacy=${uspConsent}` + } + + syncs.push({ + type: 'iframe', + url: url + }) + return syncs; + }, + onBidWon: function(bid) { + const url = bid.ext?.events?.onBidWon; + if (url) { + triggerEvent(url) + } + }, + onSetTargeting: function(bid) { + const url = bid.ext?.events?.onSetTargeting; + if (url) { + triggerEvent(url) + } + }, + onTimeout: function(bids) { + triggerEvent(URL_EVENT_ON_TIMEOUT, getIdsFromBids(bids)) + }, + onBidderError: function(params) { + let { bidderRequest } = params; + triggerEvent(URL_EVENT_ON_BIDDER_ERROR, getIdsFromBids(bidderRequest.bids)) + } +} +registerBidder(spec); diff --git a/modules/r2b2BidAdapter.md b/modules/r2b2BidAdapter.md new file mode 100644 index 00000000000..43b59133215 --- /dev/null +++ b/modules/r2b2BidAdapter.md @@ -0,0 +1,37 @@ +# Overview + +``` +Module Name: R2B2 Bid Adapter +Module Type: Bidder Adapter +Maintainer: dev@r2b2.cz +``` + +## Description + +Module that integrates R2B2 demand sources. To get your bidder configuration reach out to our account team on partner@r2b2.io + + + +## Test unit + +```javascript + var adUnits = [ + { + code: 'test-r2b2', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], + } + }, + bids: [{ + bidder: 'r2b2', + params: { + pid: 'selfpromo' + } + }] + } + ]; +``` +## Rendering + +Our adapter can feature a custom renderer specifically for display ads, tailored to enhance ad presentation and functionality. This is particularly beneficial for non-standard ad formats that require more complex logic. It's important to note that our rendering process operates outside of SafeFrames. For additional information, not limited to rendering aspects, please feel free to contact us at partner@r2b2.io diff --git a/modules/rtdModule/index.js b/modules/rtdModule/index.js index 633c4f4cdc1..fb6e65e8a65 100644 --- a/modules/rtdModule/index.js +++ b/modules/rtdModule/index.js @@ -215,7 +215,8 @@ const setEventsListeners = (function () { [CONSTANTS.EVENTS.AUCTION_INIT]: ['onAuctionInitEvent'], [CONSTANTS.EVENTS.AUCTION_END]: ['onAuctionEndEvent', getAdUnitTargeting], [CONSTANTS.EVENTS.BID_RESPONSE]: ['onBidResponseEvent'], - [CONSTANTS.EVENTS.BID_REQUESTED]: ['onBidRequestEvent'] + [CONSTANTS.EVENTS.BID_REQUESTED]: ['onBidRequestEvent'], + [CONSTANTS.EVENTS.BID_ACCEPTED]: ['onBidAcceptedEvent'] }).forEach(([ev, [handler, preprocess]]) => { events.on(ev, (args) => { preprocess && preprocess(args); diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index bff7661455a..226950875e2 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -1183,8 +1183,7 @@ export function hasValidVideoParams(bid) { var requiredParams = { mimes: arrayType, protocols: arrayType, - linearity: numberType, - api: arrayType + linearity: numberType } // loop through each param and verify it has the correct Object.keys(requiredParams).forEach(function(param) { diff --git a/modules/sparteoBidAdapter.js b/modules/sparteoBidAdapter.js index 93353c5dda7..bfb527d46f2 100644 --- a/modules/sparteoBidAdapter.js +++ b/modules/sparteoBidAdapter.js @@ -8,6 +8,8 @@ const GVLID = 1028; const TTL = 60; const HTTP_METHOD = 'POST'; const REQUEST_URL = 'https://bid.sparteo.com/auction'; +const USER_SYNC_URL_IFRAME = 'https://sync.sparteo.com/sync/iframe.html?from=prebidjs'; +let isSynced = window.sparteoCrossfire?.started || false; const converter = ortbConverter({ context: { @@ -60,7 +62,7 @@ export const spec = { * @param {BidRequest} bid The bid params to validate. * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { let bannerParams = deepAccess(bid, 'mediaTypes.banner'); let videoParams = deepAccess(bid, 'mediaTypes.video'); @@ -106,7 +108,7 @@ export const spec = { return true; }, - buildRequests: function(bidRequests, bidderRequest) { + buildRequests: function (bidRequests, bidderRequest) { const payload = converter.toORTB({bidRequests, bidderRequest}) return { @@ -116,23 +118,49 @@ export const spec = { }; }, - interpretResponse: function(serverResponse, requests) { + interpretResponse: function (serverResponse, requests) { const bids = converter.fromORTB({response: serverResponse.body, request: requests.data}).bids; return bids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {}, + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { + let syncurl = ''; - onTimeout: function(timeoutData) {}, + if (!isSynced && !window.sparteoCrossfire?.started) { + // Attaching GDPR Consent Params in UserSync url + if (gdprConsent) { + syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&gdpr_consent=' + encodeURIComponent(gdprConsent.consentString || ''); + } + if (uspConsent && uspConsent.consentString) { + syncurl += `&usp_consent=${uspConsent.consentString}`; + } + + if (syncOptions.iframeEnabled) { + isSynced = true; + + window.sparteoCrossfire = { + started: true + }; + + return [{ + type: 'iframe', + url: USER_SYNC_URL_IFRAME + syncurl + }]; + } + } + }, + + onTimeout: function (timeoutData) {}, - onBidWon: function(bid) { + onBidWon: function (bid) { if (bid && bid.nurl) { triggerPixel(bid.nurl, null); } }, - onSetTargeting: function(bid) {} + onSetTargeting: function (bid) {} }; registerBidder(spec); diff --git a/modules/stvBidAdapter.js b/modules/stvBidAdapter.js index 8d368b996fc..0dacf389955 100644 --- a/modules/stvBidAdapter.js +++ b/modules/stvBidAdapter.js @@ -51,6 +51,7 @@ export const spec = { bid_id: bidId, pbver: '$prebid.version$', schain: '', + uids: '', }; if (!isVideoRequest(bidRequest)) { payload._f = 'html'; @@ -61,6 +62,11 @@ export const spec = { delete payload.schain; } + payload.uids = serializeUids(bidRequest); + if (payload.uids == '') { + delete payload.uids; + } + payload.pfilter = { ...params }; delete payload.pfilter.placement; if (params.bcat !== undefined) { delete payload.pfilter.bcat; } @@ -201,7 +207,7 @@ function objectToQueryString(obj, prefix) { let v = obj[p]; str.push((v !== null && typeof v === 'object') ? objectToQueryString(v, k) - : (k == 'schain' ? k + '=' + v : encodeURIComponent(k) + '=' + encodeURIComponent(v))); + : (k == 'schain' || k == 'uids' ? k + '=' + v : encodeURIComponent(k) + '=' + encodeURIComponent(v))); } } return str.join('&'); @@ -227,13 +233,60 @@ function serializeSChain(schain) { ret += encodeURIComponent(node.name ?? ''); ret += ','; ret += encodeURIComponent(node.domain ?? ''); - ret += ','; - ret += encodeURIComponent(node.ext ?? ''); + if (node.ext) { + ret += ','; + ret += encodeURIComponent(node.ext ?? ''); + } } return ret; } +function serializeUids(bidRequest) { + let uids = []; + + let id5 = deepAccess(bidRequest, 'userId.id5id.uid'); + if (id5) { + uids.push(encodeURIComponent('id5:' + id5)); + let id5Linktype = deepAccess(bidRequest, 'userId.id5id.ext.linkType'); + if (id5Linktype) { + uids.push(encodeURIComponent('id5_linktype:' + id5Linktype)); + } + } + let netId = deepAccess(bidRequest, 'userId.netId'); + if (netId) { + uids.push(encodeURIComponent('netid:' + netId)); + } + let uId2 = deepAccess(bidRequest, 'userId.uid2.id'); + if (uId2) { + uids.push(encodeURIComponent('uid2:' + uId2)); + } + let sharedId = deepAccess(bidRequest, 'userId.sharedid.id'); + if (sharedId) { + uids.push(encodeURIComponent('sharedid:' + sharedId)); + } + let liverampId = deepAccess(bidRequest, 'userId.idl_env'); + if (liverampId) { + uids.push(encodeURIComponent('liverampid:' + liverampId)); + } + let criteoId = deepAccess(bidRequest, 'userId.criteoId'); + if (criteoId) { + uids.push(encodeURIComponent('criteoid:' + criteoId)); + } + // documentation missing... + let utiqId = deepAccess(bidRequest, 'userId.utiq.id'); + if (utiqId) { + uids.push(encodeURIComponent('utiq:' + utiqId)); + } else { + utiqId = deepAccess(bidRequest, 'userId.utiq'); + if (utiqId) { + uids.push(encodeURIComponent('utiq:' + utiqId)); + } + } + + return uids.join(','); +} + /** * Check if it's a banner bid request * diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 0d56d6daec7..7402b725fd2 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -12,9 +12,13 @@ const GVLID = 42; const CURRENCY = 'USD'; export const END_POINT_URL = 'https://display.bidder.taboola.com/OpenRTB/TaboolaHB/auction'; export const USER_SYNC_IMG_URL = 'https://trc.taboola.com/sg/prebidJS/1/cm'; +export const USER_SYNC_IFRAME_URL = 'https://cdn.taboola.com/scripts/prebid_iframe_sync.html'; const USER_ID = 'user-id'; const STORAGE_KEY = `taboola global:${USER_ID}`; const COOKIE_KEY = 'trc_cookie_storage'; +const TGID_COOKIE_KEY = 't_gid'; +const TBLA_ID_COOKIE_KEY = 'tbla_id'; +export const EVENT_ENDPOINT = 'https://beacon.bidder.taboola.com'; /** * extract User Id by that order: @@ -38,10 +42,18 @@ export const userData = { const {cookiesAreEnabled, getCookie} = userData.storageManager; if (cookiesAreEnabled()) { const cookieData = getCookie(COOKIE_KEY); - const userId = userData.getCookieDataByKey(cookieData, USER_ID); + let userId = userData.getCookieDataByKey(cookieData, USER_ID); if (userId) { return userId; } + userId = getCookie(TGID_COOKIE_KEY); + if (userId) { + return userId; + } + const tblaId = getCookie(TBLA_ID_COOKIE_KEY); + if (tblaId) { + return tblaId; + } } }, getCookieDataByKey(cookieData, key) { @@ -182,6 +194,13 @@ export const spec = { queryParams.push('gpp=' + encodeURIComponent(gppConsent)); } + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: USER_SYNC_IFRAME_URL + (queryParams.length ? '?' + queryParams.join('&') : '') + }); + } + if (syncOptions.pixelEnabled) { syncs.push({ type: 'image', @@ -190,6 +209,13 @@ export const spec = { } return syncs; }, + onTimeout: (timeoutData) => { + ajax(EVENT_ENDPOINT + '/timeout', null, JSON.stringify(timeoutData), {method: 'POST'}); + }, + + onBidderError: ({ error, bidderRequest }) => { + ajax(EVENT_ENDPOINT + '/bidError', null, JSON.stringify(error, bidderRequest), {method: 'POST'}); + }, }; function getSiteProperties({publisherId}, refererInfo, ortb2) { diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index 2225deaa900..67f3cebdce8 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -68,7 +68,6 @@ export const spec = { interpretResponse: function (ucfunnelResponseObj, request) { const bidRequest = request.bidRequest; const ad = ucfunnelResponseObj ? ucfunnelResponseObj.body : {}; - const videoPlayerSize = parseSizes(bidRequest); let bid = { requestId: bidRequest.bidId, @@ -117,10 +116,10 @@ export const spec = { vastXml: ad.vastXml }); - if (videoPlayerSize && videoPlayerSize.length === 2) { + if (bidRequest.sizes && bidRequest.sizes.length > 0) { Object.assign(bid, { - width: videoPlayerSize[0], - height: videoPlayerSize[1] + width: bidRequest.sizes[0][0], + height: bidRequest.sizes[0][1] }); } break; @@ -128,8 +127,8 @@ export const spec = { default: var size = parseSizes(bidRequest); Object.assign(bid, { - width: ad.width || size[0], - height: ad.height || size[1], + width: ad.width || size[0][0], + height: ad.height || size[0][1], ad: ad.adm || '' }); } @@ -156,12 +155,6 @@ export const spec = { }; registerBidder(spec); -function transformSizes(requestSizes) { - if (typeof requestSizes === 'object' && requestSizes.length) { - return requestSizes[0]; - } -} - function getCookieSyncParameter(gdprApplies, apiVersion, consentString, uspConsent) { let param = '?'; if (gdprApplies == '1') { @@ -187,11 +180,10 @@ function parseSizes(bid) { params.video.playerWidth, params.video.playerHeight ]; - return size; + return [size]; } } - - return transformSizes(bid.sizes); + return bid.sizes; } function getSupplyChain(schain) { @@ -244,6 +236,20 @@ function getFloor(bid, size, mediaTypes) { return undefined; } +function addBidData(bidData, key, value) { + if (value) { + bidData[key] = value; + } +} + +function getFormat(size) { + let formatList = [] + for (var i = 0; i < size.length; i++) { + formatList.push(size[i].join(',')); + } + return (formatList.length > 0) ? formatList.join(';') : ''; +} + function getRequestData(bid, bidderRequest) { const size = parseSizes(bid); const language = navigator.language; @@ -264,14 +270,8 @@ function getRequestData(bid, bidderRequest) { schain: supplyChain }; - if (bidFloor) { - bidData.fp = bidFloor; - } - - if (gpid) { - bidData.gpid = gpid; - } - + addBidData(bidData, 'fp', bidFloor); + addBidData(bidData, 'gpid', gpid); addUserId(bidData, bid.userId); bidData.u = bidderRequest.refererInfo.page || bidderRequest.refererInfo.topmostLocation; @@ -293,10 +293,11 @@ function getRequestData(bid, bidderRequest) { } } - if (size != undefined && size.length == 2) { - bidData.w = size[0]; - bidData.h = size[1]; + if (size != undefined && size.length > 0 && size[0].length == 2) { + bidData.w = size[0][0]; + bidData.h = size[0][1]; } + addBidData(bidData, 'format', getFormat(size)); if (bidderRequest && bidderRequest.uspConsent) { Object.assign(bidData, { diff --git a/modules/userId/eids.md b/modules/userId/eids.md index 04073923ed1..c8d27cc9d52 100644 --- a/modules/userId/eids.md +++ b/modules/userId/eids.md @@ -77,6 +77,7 @@ userIdAsEids = [ uids: [{ id: 'the-ids-object-stringified', atype: 1 + }] }, { @@ -117,6 +118,50 @@ userIdAsEids = [ }] }, + { + source: 'liveintent.indexexchange.com', + uids: [{ + id: 'some-random-id-value', + atype: 3, + ext: { + provider: 'liveintent.com' + } + }] + }, + + { + source: 'liveintent.sovrn.com'', + uids: [{ + id: 'some-random-id-value', + atype: 3, + ext: { + provider: 'liveintent.com' + } + }] + }, + + { + source: 'openx.net'', + uids: [{ + id: 'some-random-id-value', + atype: 3, + ext: { + provider: 'liveintent.com' + } + }] + }, + + { + source: 'pubmatic.com'', + uids: [{ + id: 'some-random-id-value', + atype: 3, + ext: { + provider: 'liveintent.com' + } + }] + }, + { source: 'media.net', uids: [{ @@ -279,6 +324,13 @@ userIdAsEids = [ id: 'some-random-id-value', atype: 3 }] + }, + { + source: 'mygaru.com', + uids: [{ + id: 'some-random-id-value', + atype: 1 + }] } ] ``` diff --git a/modules/userId/userId.md b/modules/userId/userId.md index 01930a67dda..7a01e128814 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -158,6 +158,9 @@ pbjs.setConfig({ }, { name: "gravitompId" + }, + { + name: "mygaruId" } ], syncDelay: 5000, diff --git a/modules/yandexBidAdapter.js b/modules/yandexBidAdapter.js index 9ca989b2259..cc4a8c18241 100644 --- a/modules/yandexBidAdapter.js +++ b/modules/yandexBidAdapter.js @@ -4,10 +4,55 @@ import { BANNER, NATIVE } from '../src/mediaTypes.js' import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { config } from '../src/config.js'; +/** + * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid + * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest + * @typedef {import('../src/adapters/bidderFactory.js').BidderSpec} BidderSpec + * @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest + * @typedef {import('../src/adapters/bidderFactory.js').ServerResponse} ServerResponse + * @typedef {import('../src/adapters/bidderFactory.js').SyncOptions} SyncOptions + * @typedef {import('../src/adapters/bidderFactory.js').UserSync} UserSync + * @typedef {import('../src/auction.js').BidderRequest} BidderRequest + * @typedef {import('../src/mediaTypes.js').MediaType} MediaType + * @typedef {import('../src/utils.js').MediaTypes} MediaTypes + * @typedef {import('../modules/priceFloors.js').getFloor} GetFloor + */ + +/** + * @typedef {Object} CustomServerRequestFields + * @property {BidRequest} bidRequest + */ + +/** + * @typedef {ServerRequest & CustomServerRequestFields} YandexServerRequest + */ + +/** + * Yandex bidder-specific params which the publisher used in their bid request. + * + * @typedef {Object} YandexBidRequestParams + * @property {string} placementId Possible formats: `R-I-123456-2`, `R-123456-1`, `123456-789`. + * @property {number} [pageId] Deprecated. Please use `placementId` instead. + * @property {number} [impId] Deprecated. Please use `placementId` instead. + */ + +/** + * @typedef {Object} AdditionalBidRequestFields + * @property {GetFloor} [getFloor] + * @property {MediaTypes} [mediaTypes] + */ + +/** + * @typedef {BidRequest & AdditionalBidRequestFields} ExtendedBidRequest + */ + const BIDDER_CODE = 'yandex'; const BIDDER_URL = 'https://bs.yandex.ru/prebid'; const DEFAULT_TTL = 180; const DEFAULT_CURRENCY = 'EUR'; +/** + * @type {MediaType[]} + */ const SUPPORTED_MEDIA_TYPES = [ BANNER, NATIVE ]; const SSP_ID = 10500; @@ -42,11 +87,18 @@ export const NATIVE_ASSETS = { const NATIVE_ASSETS_IDS = {}; _each(NATIVE_ASSETS, (asset, key) => { NATIVE_ASSETS_IDS[asset[0]] = key }); +/** @type BidderSpec */ export const spec = { code: BIDDER_CODE, aliases: ['ya'], // short code supportedMediaTypes: SUPPORTED_MEDIA_TYPES, + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid request to validate. + * @returns {boolean} True if this is a valid bid, and false otherwise. + */ isBidRequestValid: function(bid) { const { params } = bid; if (!params) { @@ -59,6 +111,13 @@ export const spec = { return true; }, + /** + * Make a server request from the list of BidRequests. + * + * @param {ExtendedBidRequest[]} validBidRequests An array of bids. + * @param {BidderRequest} bidderRequest Bidder request object. + * @returns {YandexServerRequest[]} Objects describing the requests to the server. + */ buildRequests: function(validBidRequests, bidderRequest) { validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); @@ -131,6 +190,11 @@ export const spec = { deepSetValue(data, 'user.ext.eids', eids); } + const userData = deepAccess(bidRequest, 'ortb2.user.data'); + if (userData && userData.length) { + deepSetValue(data, 'user.data', userData); + } + const queryParamsString = formatQS(queryParams); return { method: 'POST', @@ -146,8 +210,12 @@ export const spec = { interpretResponse: interpretResponse, - onBidWon: function (bid) { - const nurl = bid['nurl']; + /** + * Register bidder specific code, which will execute if a bid from this bidder won the auction. + * @param {Bid} bid The bid that won the auction. + */ + onBidWon: function(bid) { + const nurl = addRTT(bid['nurl'], bid.timeToRespond); if (!nurl) { return; @@ -157,6 +225,9 @@ export const spec = { } } +/** + * @param {YandexBidRequestParams} bidRequestParams + */ function extractPlacementIds(bidRequestParams) { const { placementId } = bidRequestParams; const result = { pageId: null, impId: null }; @@ -191,6 +262,9 @@ function extractPlacementIds(bidRequestParams) { return result; } +/** + * @param {ExtendedBidRequest} bidRequest + */ function getBidfloor(bidRequest) { const floors = []; @@ -210,6 +284,9 @@ function getBidfloor(bidRequest) { return floors.sort((a, b) => b.floor - a.floor)[0]; } +/** + * @param {ExtendedBidRequest} bidRequest + */ function mapBanner(bidRequest) { if (deepAccess(bidRequest, 'mediaTypes.banner')) { const sizes = bidRequest.sizes || bidRequest.mediaTypes.banner.sizes; @@ -227,6 +304,9 @@ function mapBanner(bidRequest) { } } +/** + * @param {ExtendedBidRequest} bidRequest + */ function mapNative(bidRequest) { const adUnitNativeAssets = deepAccess(bidRequest, 'mediaTypes.native'); if (adUnitNativeAssets) { @@ -299,6 +379,13 @@ function mapImageAsset(adUnitImageAssetParams, nativeAssetType) { return img; } +/** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @param {YandexServerRequest} yandexServerRequest + * @return {Bid[]} An array of bids which were nested inside the server. + */ function interpretResponse(serverResponse, { bidRequest }) { let response = serverResponse.body; if (!response.seatbid) { @@ -313,6 +400,7 @@ function interpretResponse(serverResponse, { bidRequest }) { return bidsReceived.map(bidReceived => { const price = bidReceived.price; + /** @type {Bid} */ let prBid = { requestId: bidRequest.bidId, cpm: price, @@ -385,4 +473,24 @@ function replaceAuctionPrice(url, price, currency) { .replace(/\${AUCTION_CURRENCY}/, currency); } +function addRTT(url, rtt) { + if (!url) return; + + if (url.indexOf(`\${RTT}`) > -1) { + return url.replace(/\${RTT}/, rtt ?? -1); + } + + const urlObj = new URL(url); + + if (Number.isInteger(rtt)) { + urlObj.searchParams.set('rtt', rtt); + } else { + urlObj.searchParams.delete('rtt'); + } + + url = urlObj.toString(); + + return url; +} + registerBidder(spec); diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index e72a671ac74..9109c6e2a80 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -29,7 +29,7 @@ const VIDEO_PATH = '/exchange/prebidvideo'; const STAGE_DOMAIN = 'https://ads-stg.yieldmo.com'; const PROD_DOMAIN = 'https://ads.yieldmo.com'; const OUTSTREAM_VIDEO_PLAYER_URL = 'https://prebid-outstream.yieldmo.com/bundle.js'; -const OPENRTB_VIDEO_BIDPARAMS = ['mimes', 'startdelay', 'placement', 'startdelay', 'skipafter', 'protocols', 'api', +const OPENRTB_VIDEO_BIDPARAMS = ['mimes', 'startdelay', 'placement', 'plcmt', 'skipafter', 'protocols', 'api', 'playbackmethod', 'maxduration', 'minduration', 'pos', 'skip', 'skippable']; const OPENRTB_VIDEO_SITEPARAMS = ['name', 'domain', 'cat', 'keywords']; const LOCAL_WINDOW = getWindowTop(); @@ -449,7 +449,7 @@ function openRtbImpression(bidRequest) { imp.video.skip = 1; delete imp.video.skippable; } - if (imp.video.placement !== 1) { + if (imp.video.plcmt !== 1 || imp.video.placement !== 1) { imp.video.startdelay = DEFAULT_START_DELAY; imp.video.playbackmethod = [ DEFAULT_PLAYBACK_METHOD ]; } diff --git a/modules/zeta_global_sspBidAdapter.js b/modules/zeta_global_sspBidAdapter.js index db31791d86f..0c5db541286 100644 --- a/modules/zeta_global_sspBidAdapter.js +++ b/modules/zeta_global_sspBidAdapter.js @@ -163,6 +163,7 @@ export const spec = { } provideEids(validBidRequests[0], payload); + provideSegments(bidderRequest, payload); const url = params.sid ? ENDPOINT_URL.concat('?sid=', params.sid) : ENDPOINT_URL; return { method: 'POST', @@ -335,6 +336,25 @@ function provideEids(request, payload) { } } +function provideSegments(bidderRequest, payload) { + const data = bidderRequest.ortb2?.user?.data; + if (isArray(data)) { + const segments = data.filter(d => d?.segment).map(d => d.segment).filter(s => isArray(s)).flatMap(s => s).filter(s => s?.id); + if (segments.length > 0) { + if (!payload.user) { + payload.user = {}; + } + if (!isArray(payload.user.data)) { + payload.user.data = []; + } + const payloadData = { + segment: segments + }; + payload.user.data.push(payloadData); + } + } +} + function provideMediaType(zetaBid, bid, bidRequest) { if (zetaBid.ext && zetaBid.ext.prebid && zetaBid.ext.prebid.type) { bid.mediaType = zetaBid.ext.prebid.type === VIDEO ? VIDEO : BANNER; diff --git a/package-lock.json b/package-lock.json index 3aed00f6b76..577b65c74f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "prebid.js", - "version": "8.27.0", + "version": "8.30.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "prebid.js", - "version": "8.24.0", + "version": "8.30.0-pre", "license": "Apache-2.0", "dependencies": { "@babel/core": "^7.16.7", @@ -22,7 +22,7 @@ "express": "^4.15.4", "fun-hooks": "^0.9.9", "just-clone": "^1.0.2", - "live-connect-js": "^6.3.0" + "live-connect-js": "^6.3.2" }, "devDependencies": { "@babel/eslint-parser": "^7.16.5", @@ -16336,19 +16336,19 @@ "dev": true }, "node_modules/live-connect-common": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.0.2.tgz", - "integrity": "sha512-K3LNKd9CpREDJbXGdwKqPojjQaxd4G6c7OAD6Yzp3wsCWTH2hV8xNAbUksSOpOcVyyOT9ilteEFXIJQJrbODxQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.0.3.tgz", + "integrity": "sha512-ZPycT04ROBUvPiksnLTunrKC3ROhBSeO99fQ+4qMIkgKwP2CvS44L7fK+0WFV4nAi+65KbzSng7JWcSlckfw8w==", "engines": { "node": ">=18" } }, "node_modules/live-connect-js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.3.0.tgz", - "integrity": "sha512-1SnXQZq9gxHIb0scXPX1Da1rQ0oY2sloMGgeRreTAwhCtdQEuip/IYwgOh3/ZeZ6yT6iG9FLb7+AjORC4pO46g==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.3.3.tgz", + "integrity": "sha512-njpWQgoJuXhxm+XBJQvT672wR20/qROPUfUKwIXPwEtGXznJYlrUDPJDChEknBiKIo7P4jOeirAMwcZWPCN4ow==", "dependencies": { - "live-connect-common": "^v3.0.2", + "live-connect-common": "^v3.0.3", "tiny-hashes": "1.0.1" }, "engines": { @@ -38079,16 +38079,16 @@ "dev": true }, "live-connect-common": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.0.2.tgz", - "integrity": "sha512-K3LNKd9CpREDJbXGdwKqPojjQaxd4G6c7OAD6Yzp3wsCWTH2hV8xNAbUksSOpOcVyyOT9ilteEFXIJQJrbODxQ==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/live-connect-common/-/live-connect-common-3.0.3.tgz", + "integrity": "sha512-ZPycT04ROBUvPiksnLTunrKC3ROhBSeO99fQ+4qMIkgKwP2CvS44L7fK+0WFV4nAi+65KbzSng7JWcSlckfw8w==" }, "live-connect-js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.3.0.tgz", - "integrity": "sha512-1SnXQZq9gxHIb0scXPX1Da1rQ0oY2sloMGgeRreTAwhCtdQEuip/IYwgOh3/ZeZ6yT6iG9FLb7+AjORC4pO46g==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-6.3.3.tgz", + "integrity": "sha512-njpWQgoJuXhxm+XBJQvT672wR20/qROPUfUKwIXPwEtGXznJYlrUDPJDChEknBiKIo7P4jOeirAMwcZWPCN4ow==", "requires": { - "live-connect-common": "^v3.0.2", + "live-connect-common": "^v3.0.3", "tiny-hashes": "1.0.1" } }, diff --git a/package.json b/package.json index fa0e61a6805..aced4d29868 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "8.27.0", + "version": "8.30.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { @@ -134,7 +134,7 @@ "express": "^4.15.4", "fun-hooks": "^0.9.9", "just-clone": "^1.0.2", - "live-connect-js": "^6.3.0" + "live-connect-js": "^6.3.2" }, "optionalDependencies": { "fsevents": "^2.3.2" diff --git a/prebid-analytics-8.30.0.js b/prebid-analytics-8.30.0.js new file mode 100644 index 00000000000..0f3a977393c --- /dev/null +++ b/prebid-analytics-8.30.0.js @@ -0,0 +1,90 @@ +/* prebid.js v8.30.0 +Updated: 2024-01-10 +Modules: videoModule, adpod, 33acrossBidAdapter, adprimeBidAdapter, apacdexBidAdapter, appnexusBidAdapter, atsAnalyticsAdapter, colossussspBidAdapter, concertBidAdapter, consentManagement, consentManagementUsp, conversantBidAdapter, criteoBidAdapter, enrichmentFpdModule, gptPreAuction, gridBidAdapter, gumgumBidAdapter, hadronRtdProvider, ixBidAdapter, justpremiumBidAdapter, kargoBidAdapter, mantisBidAdapter, medianetBidAdapter, openxBidAdapter, permutiveRtdProvider, prebidServerBidAdapter, pubmaticBidAdapter, priceFloors, rtdModule, rubiconBidAdapter, schain, sharethroughBidAdapter, sonobiBidAdapter, sovrnBidAdapter, teadsBidAdapter, tripleliftBidAdapter, userId, undertoneBidAdapter, unrulyBidAdapter, yahoosspBidAdapter, yieldmoBidAdapter, ttdBidAdapter, adyoulikeBidAdapter, sizeMappingV2, videojsVideoProvider, dfpAdServerVideo, taboolaBidAdapter, criteoIdSystem, fabrickIdSystem, hadronIdSystem, identityLinkIdSystem, intentIqIdSystem, lotamePanoramaIdSystem, pubProvidedIdSystem, sharedIdSystem, uid2IdSystem, liveIntentIdSystem, unifiedIdSystem, pairIdSystem, connectIdSystem */ +if(window.fsprebid&&window.fsprebid.libLoaded)try{window.fsprebid.getConfig("debug")&&console.warn("Attempted to load a copy of Prebid.js that clashes with the existing 'fsprebid' instance. Load aborted.")}catch(e){}else (function(){ +!function(){var n,e={5706:function(n,e,t){t.d(e,{Pd:function(){return d},Th:function(){return s},_U:function(){return f}});var r=t(5730),i=t(4358),o=t(265),a=t(4614),u=(0,t(8640).R)(),c="outstream";function s(n){var e=this,t=n.url,o=n.config,a=n.id,u=n.callback,s=n.loaded,d=n.adUnitCode,f=n.renderNow;this.url=t,this.config=o,this.handlers={},this.id=a,this.renderNow=f,this.loaded=s,this.cmd=[],this.push=function(n){"function"==typeof n?e.loaded?n.call():e.cmd.push(n):(0,i.H)("Commands given to Renderer.push must be wrapped in a function")},this.callback=u||function(){e.loaded=!0,e.process()},this.render=function(){var n=this,e=arguments,o=function(){n._render?n._render.apply(n,e):(0,i.yN)("No render function was provided, please use .setRender on the renderer")};l(d)?((0,i.yN)("External Js not loaded by Renderer since renderer url and callback is already defined on adUnit ".concat(d)),o()):f?o():(this.cmd.unshift(o),(0,r.B)(t,c,this.callback,this.documentContext))}.bind(this)}function d(n){return!(!n||!n.url&&!n.renderNow)}function f(n,e,t){var r=null;n.config&&n.config.documentResolver&&(r=n.config.documentResolver(e,document,t)),r||(r=document),n.documentContext=r,n.render(e,n.documentContext)}function l(n){var e=u.adUnits,t=(0,a.sE)(e,(function(e){return e.code===n}));if(!t)return!1;var r=(0,o.Z)(t,"renderer"),i=!!(r&&r.url&&r.render),c=(0,o.Z)(t,"mediaTypes.video.renderer"),s=!!(c&&c.url&&c.render);return!!(i&&!0!==r.backupOnly||s&&!0!==c.backupOnly)}s.install=function(n){return new s({url:n.url,config:n.config,id:n.id,callback:n.callback,loaded:n.loaded,adUnitCode:n.adUnitCode,renderNow:n.renderNow})},s.prototype.getConfig=function(){return this.config},s.prototype.setRender=function(n){this._render=n},s.prototype.setEventHandlers=function(n){this.handlers=n},s.prototype.handleVideoEvent=function(n){var e=n.id,t=n.eventName;"function"==typeof this.handlers[t]&&this.handlers[t](),(0,i.ji)("Prebid Renderer event for id ".concat(e," type ").concat(t))},s.prototype.process=function(){for(;this.cmd.length>0;)try{this.cmd.shift().call()}catch(n){(0,i.H)("Error processing Renderer command: ",n)}}},4947:function(n,e,t){t.d(e,{EL:function(){return a},Jt:function(){return l},K$:function(){return i},S1:function(){return r},S5:function(){return o},UE:function(){return u},e:function(){return s},g0:function(){return f},oK:function(){return d},x$:function(){return c}});var r="accessDevice",i="syncUser",o="enrichUfpd",a="enrichEids",u="fetchBids",c="reportAnalytics",s="transmitEids",d="transmitUfpd",f="transmitPreciseGeo",l="transmitTid"},286:function(n,e,t){t.d(e,{T:function(){return i}});var r=t(6104),i=(0,t(6310).Oj)((function(n){return r.ZP.resolveAlias(n)}))},9633:function(n,e,t){t.d(e,{UL:function(){return i},XG:function(){return a},_U:function(){return u},wu:function(){return r},y2:function(){return o}});var r="prebid",i="bidder",o="userId",a="rtd",u="analytics"},6310:function(n,e,t){t.d(e,{$k:function(){return u},Hw:function(){return v},IV:function(){return g},JR:function(){return a},Ki:function(){return s},Oj:function(){return p},Qf:function(){return f},bL:function(){return d},bp:function(){return c},cx:function(){return l}});var r=t(4942),i=t(9633),o=t(2797),a="component",u=a+"Type",c=a+"Name",s="adapterCode",d="storageType",f="configName",l="syncType",g="syncUrl",v="_config";function p(n){return function(e,t,o){var d,f=(d={},(0,r.Z)(d,u,e),(0,r.Z)(d,c,t),(0,r.Z)(d,a,"".concat(e,".").concat(t)),d);return e===i.UL&&(f[s]=n(t)),h(Object.assign(f,o))}}var h=(0,o.z3)("sync",(function(n){return n}))},1087:function(n,e,t){t.d(e,{$8:function(){return f},Db:function(){return p},Mp:function(){return w},RD:function(){return h},ZZ:function(){return l},a:function(){return m},hb:function(){return A},js:function(){return y}});var r=t(1002),i=t(3324),o=t(265),a=t(3193),u=t(571),c=t(4947);function s(n,e){var t="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(!t){if(Array.isArray(n)||(t=function(n,e){if(!n)return;if("string"==typeof n)return d(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);"Object"===t&&n.constructor&&(t=n.constructor.name);if("Map"===t||"Set"===t)return Array.from(n);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return d(n,e)}(n))||e&&n&&"number"==typeof n.length){t&&(n=t);var r=0,i=function(){};return{s:i,n:function(){return r>=n.length?{done:!0}:{done:!1,value:n[r++]}},e:function(n){throw n},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){t=t.call(n)},n:function(){var n=t.next();return a=n.done,n},e:function(n){u=!0,o=n},f:function(){try{a||null==t.return||t.return()}finally{if(u)throw o}}}}function d(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t0?e.join("."):null,t]}))})),function(e,t){for(var r=[],a=arguments.length,u=new Array(a>2?a-2:0),c=2;c1?e-1:0),r=1;r0)}function y(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:u.xD;return function(t){return!e(n,t)}}function b(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:u.xD;return[{name:c.e,paths:["userId","userIdAsEids"],applies:y(c.e,n)},{name:c.Jt,paths:["ortb2Imp.ext.tid"],applies:y(c.Jt,n)}].map(v)}function w(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:u.xD;return[{name:c.oK,paths:f,applies:y(c.oK,n)},{name:c.e,paths:l,applies:y(c.e,n)},{name:c.g0,paths:g,applies:y(c.g0,n),get:function(n){return Math.round(100*(n+Number.EPSILON))/100}},{name:c.Jt,paths:["source.tid"],applies:y(c.Jt,n)}].map(v)}var A=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:u.xD,e=p(w(n)),t=p(b(n));return function(n){var r={};return{ortb2:function(t){return e(r,t,n),t},bidRequest:function(e){return t(r,e,n),e}}}}();(0,u.oB)(c.Jt,"enableTIDs config",(function(){if(!a.vc.getConfig("enableTIDs"))return{allow:!1,reason:"TIDs are disabled"}}))},571:function(n,e,t){t.d(e,{oB:function(){return d},xD:function(){return f}});var r=t(3324),i=t(4358),o=t(6310);function a(n,e){var t="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(!t){if(Array.isArray(n)||(t=function(n,e){if(!n)return;if("string"==typeof n)return u(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);"Object"===t&&n.constructor&&(t=n.constructor.name);if("Map"===t||"Set"===t)return Array.from(n);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return u(n,e)}(n))||e&&n&&"number"==typeof n.length){t&&(n=t);var r=0,i=function(){};return{s:i,n:function(){return r>=n.length?{done:!0}:{done:!1,value:n[r++]}},e:function(n){throw n},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,c=!1;return{s:function(){t=t.call(n)},n:function(){var n=t.next();return a=n.done,n},e:function(n){c=!0,o=n},f:function(){try{a||null==t.return||t.return()}finally{if(c)throw o}}}}function u(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t0&&void 0!==arguments[0]?arguments[0]:(0,i.qp)("Activity control:"),e={};function t(n){return e[n]=e[n]||[]}function u(e,t,r,i){var a;try{a=r(i)}catch(r){n.logError("Exception in rule ".concat(t," for '").concat(e,"'"),r),a={allow:!1,reason:r}}return a&&Object.assign({activity:e,name:t,component:i[o.JR]},a)}var c={},s=1e3;function d(e){var t=e.activity,r=e.name,i=e.allow,o=e.reason,a=e.component,u="".concat(r," ").concat(i?"allowed":"denied"," '").concat(t,"' for '").concat(a,"'").concat(o?":":""),d=c.hasOwnProperty(u);if(d&&clearTimeout(c[u]),c[u]=setTimeout((function(){return delete c[u]}),s),!d){var f=[u];o&&f.push(o),(i?n.logInfo:n.logWarn).apply(n,f)}}return[function(n,e,i){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:10,a=t(n),u=a.findIndex((function(n){var e=(0,r.Z)(n,1)[0];return o=0&&a.splice(n,1)}},function(n,e){var i,o,c,s=a(t(n));try{for(s.s();!(c=s.n()).done;){var f=(0,r.Z)(c.value,3),l=f[0],g=f[1],v=f[2];if(i!==l&&o)break;i=l;var p=u(n,g,v,e);if(p){if(!p.allow)return d(p),!1;o=p}}}catch(n){s.e(n)}finally{s.f()}return o&&d(o),!0}]}(),s=(0,r.Z)(c,2),d=s[0],f=s[1]},3667:function(n,e,t){t.d(e,{Pm:function(){return h},XD:function(){return y},bL:function(){return m}});var r=t(4358),i=t(265),o=t(2021),a=t(5644),u=t(3193),c=t(5706),s=t(4679),d=t(8653),f=a.FP,l=f.AD_RENDER_FAILED,g=f.AD_RENDER_SUCCEEDED,v=f.STALE_RENDER,p=f.BID_WON;function h(n){var e=n.reason,t=n.message,i=n.bid,a=n.id,u={reason:e,message:t};i&&(u.bid=i),a&&(u.adId=a),(0,r.H)("Error rendering ad (id: ".concat(a,"): ").concat(t)),o.emit(l,u)}function m(n){var e=n.doc,t=n.bid,r=n.id,i={doc:e};t&&(i.bid=t),r&&(i.adId=r),o.emit(g,i)}function y(n,e){var t=e.adId,f=e.options,l=e.bidResponse;if(null!=l){if(l.status!==a.UE.fe||((0,r.yN)("Ad id ".concat(t," has been rendered before")),o.emit(v,l),!(0,i.Z)(u.vc.getConfig("auctionOptions"),"suppressStaleRender"))){try{var g=l.adId,m=l.ad,y=l.adUrl,b=l.width,w=l.height,A=l.renderer,C=l.cpm,T=l.originalCpm,O=l.mediaType;if((0,c.Pd)(A))(0,c._U)(A,l);else if(g){if(O===s.pX)return void h({reason:a.q_.Sn,message:"Cannot render video ad",bid:l,id:g});var E={AUCTION_PRICE:T||C,CLICKTHROUGH:(null==f?void 0:f.clickUrl)||""};n({ad:(0,r.No)(m,E),adUrl:(0,r.No)(y,E),adId:g,width:b,height:w})}}catch(n){return void h({reason:a.q_.XW,message:n.message,id:t,bid:l})}d.K.addWinningBid(l),o.emit(p,l)}}else h({reason:a.q_.WT,message:"Cannot find ad '".concat(t,"'"),id:t})}},875:function(n,e,t){t.d(e,{f:function(){return a}});var r=t(265),i={};function o(n,e,t){var r=function(n,e){var t=i[n]=i[n]||{bidders:{}};return e?t.bidders[e]=t.bidders[e]||{}:t}(n,t);return r[e]=(r[e]||0)+1,r[e]}var a={incrementRequestsCounter:function(n){return o(n,"requestsCounter")},incrementBidderRequestsCounter:function(n,e){return o(n,"requestsCounter",e)},incrementBidderWinsCounter:function(n,e){return o(n,"winsCounter",e)},getRequestsCounter:function(n){return(0,r.Z)(i,"".concat(n,".requestsCounter"))||0},getBidderRequestsCounter:function(n,e){return(0,r.Z)(i,"".concat(n,".bidders.").concat(e,".requestsCounter"))||0},getBidderWinsCounter:function(n,e){return(0,r.Z)(i,"".concat(n,".bidders.").concat(e,".winsCounter"))||0}}},8525:function(n,e,t){function r(n){var e=n;return{callBids:function(){},setBidderCode:function(n){e=n},getBidderCode:function(){return e}}}t.d(e,{Z:function(){return r}})},6104:function(n,e,t){t.d(e,{O6:function(){return N},uV:function(){return z}});var r=t(9062),i=t(3324),o=t(4942),a=t(4358),u=t(265),c=t(59),s=t(4699),d=t(8928),f=t(3193),l=t(2797),g=t(4614),v=t(875),p=t(5102),h=t(2513),m=t(2021),y=t(5644),b=t(9128),w=t(8653),A=t(9633),C=t(571),T=t(4947),O=t(6310),E=t(1087);function k(n,e){var t=Object.keys(n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(n);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),t.push.apply(t,r)}return t}function I(n){for(var e=1;e2&&void 0!==arguments[2]?arguments[2]:{},r=t.getS2SBidders,i=void 0===r?z:r;if(null==e)return n;var o=i(e);return n.filter((function(n){return o.has(n.bidder)}))}),"filterBidsForAdUnit");function M(n,e){var t=(0,a.I8)(n),r=!1;return t.forEach((function(n){var t=n.bids.filter((function(n){var t;return n.module===B&&(null===(t=n.params)||void 0===t?void 0:t.configName)===e.configName}));1===t.length?(n.s2sBid=t[0],r=!0,n.ortb2Imp=(0,a.Ee)({},n.s2sBid.ortb2Imp,n.ortb2Imp)):t.length>1&&(0,a.yN)('Multiple "module" bids for the same s2s configuration; all will be ignored',t),n.bids=H(n.bids,e).map((function(n){return n.bid_id=(0,a._d)(),n}))})),{adUnits:t=t.filter((function(n){return 0!==n.bids.length||null!=n.s2sBid})),hasModuleBids:r}}function F(n){var e=(0,a.I8)(n);return e.forEach((function(n){n.bids=H(n.bids,null)})),e=e.filter((function(n){return 0!==n.bids.length}))}var L=(0,l.z3)("sync",(function(n,e){return n}),"setupAdUnitMediaTypes");function z(n){(0,a.kJ)(n)||(n=[n]);var e=new Set([null]);return n.filter((function(n){return n&&n.enabled})).flatMap((function(n){return n.bidders})).forEach((function(n){return e.add(n)})),e}var W=(0,l.z3)("sync",(function(n,e){var t,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=r.getS2SBidders,u=void 0===i?z:i,c=u(e);return(0,a.pP)(n).reduce((function(n,e){return n[c.has(e)?j:S].push(e),n}),(t={},(0,o.Z)(t,S,[]),(0,o.Z)(t,j,[]),t))}),"partitionBidders");function K(n,e){var t=P[n],r=(null==t?void 0:t.getSpec)&&t.getSpec();if(r&&r[e]&&"function"==typeof r[e])return[r,r[e]]}function G(n,e,t,r){try{(0,a.PN)("Invoking ".concat(n,".").concat(e));for(var i=arguments.length,o=new Array(i>4?i-4:0),u=4;u5&&void 0!==arguments[5]?arguments[5]:{},u=arguments.length>6?arguments[6]:void 0;u=(0,b.Bf)(u),m.emit(y.FP.BEFORE_REQUEST_BIDS,n),(0,c.Fb)(n),n.forEach((function(n){(0,a.PO)(n.mediaTypes)||(n.mediaTypes={}),n.bids=n.bids.filter((function(n){return!n.bidder||U.isAllowed(T.UE,D(A.UL,n.bidder))}))})),n=L(n,i);var s=W(n,Z),d=s[S],l=s[j];f.vc.getConfig("bidderSequence")===f.FD&&(d=(0,a.TV)(d));var v=(0,p.nH)(),w=[],C=o.global||{},O=o.bidder||{};function E(n,e){var r=U.redact(null!=e?e:D(A.UL,n.bidderCode)),i=Object.freeze(r.ortb2((0,a.Ee)({source:{tid:t}},C,O[n.bidderCode])));return n.ortb2=i,n.bids=n.bids.map((function(n){return n.ortb2=i,r.bidRequest(n)})),n}Z.forEach((function(r){var i=N(r);if(r&&r.enabled&&U.isAllowed(T.UE,i)){var o=M(n,r),c=o.adUnits,s=o.hasModuleBids,d=(0,a.DO)();(0===l.length&&s?[null]:l).forEach((function(n){var o=(0,a._d)(),s=u.fork(),f=E({bidderCode:n,auctionId:t,bidderRequestId:o,uniquePbsTid:d,bids:_({bidderCode:n,auctionId:t,bidderRequestId:o,adUnits:(0,a.I8)(c),src:y.os.YZ,metrics:s}),auctionStart:e,timeout:r.timeout,src:y.os.YZ,refererInfo:v,metrics:s},i);0!==f.bids.length&&w.push(f)})),c.forEach((function(n){var e=n.bids.filter((function(n){return(0,g.sE)(w,(function(e){return(0,g.sE)(e.bids,(function(e){return e.bidId===n.bid_id}))}))}));n.bids=e})),w.forEach((function(n){void 0===n.adUnitsS2SCopy&&(n.adUnitsS2SCopy=c.filter((function(n){return n.bids.length>0||null!=n.s2sBid})))}))}}));var k=F(n);return d.forEach((function(n){var o=(0,a._d)(),c=u.fork(),s=E({bidderCode:n,auctionId:t,bidderRequestId:o,bids:_({bidderCode:n,auctionId:t,bidderRequestId:o,adUnits:(0,a.I8)(k),labels:i,src:"client",metrics:c}),auctionStart:e,timeout:r,refererInfo:v,metrics:c}),d=P[n];d||(0,a.H)("Trying to make a request for bidder that does not exist: ".concat(n)),d&&s.bids&&0!==s.bids.length&&w.push(s)})),w.forEach((function(n){h.rp.getConsentData()&&(n.gdprConsent=h.rp.getConsentData()),h.nX.getConsentData()&&(n.uspConsent=h.nX.getConsentData()),h.TJ.getConsentData()&&(n.gppConsent=h.TJ.getConsentData())})),w}),"makeBidRequests"),R.callBids=function(n,e,t,r,o,u,c){var s=arguments.length>7&&void 0!==arguments[7]?arguments[7]:{};if(e.length){var l=e.reduce((function(n,e){return n[Number(void 0!==e.src&&e.src===y.os.YZ)].push(e),n}),[[],[]]),g=(0,i.Z)(l,2),v=g[0],p=g[1],h=[];p.forEach((function(n){for(var e=-1,t=0;t0?C.join(", "):'No bidder specified, using "ortb2Imp" definition(s) only')),v.forEach((function(n){m.emit(y.FP.BID_REQUESTED,I(I({},n),{},{tid:n.auctionId}))})),f.callBids(w,p,t,(function(){return A.forEach((function(n){return n()}))}),e)}}else(0,a.H)("missing "+n.adapter);b++}})),v.forEach((function(n){n.start=(0,a.AB)();var e=P[n.bidderCode];f.vc.runWithBidder(n.bidderCode,(function(){(0,a.ji)("CALLING BIDDER"),m.emit(y.FP.BID_REQUESTED,n)}));var i=(0,d.OI)(u,o?{request:o.request.bind(null,n.bidderCode),done:o.done}:void 0),s=r.bind(n);try{f.vc.runWithBidder(n.bidderCode,e.callBids.bind(e,n,t,s,i,(function(){return c(n.bidderRequestId)}),f.vc.callbackWithBidder(n.bidderCode)))}catch(e){(0,a.H)("".concat(n.bidderCode," Bid Adapter emitted an uncaught error when parsing their bidRequest"),{e:e,bidRequest:n}),s()}}))}else(0,a.yN)("callBids executed with no bidRequests. Were they filtered by labels or sizing?")},R.videoAdapters=[],R.registerBidAdapter=function(n,e){var t,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=r.supportedMediaTypes,o=void 0===i?[]:i;n&&e?"function"==typeof n.callBids?(P[e]=n,h.qh.register(A.UL,e,null===(t=n.getSpec)||void 0===t?void 0:t.call(n).gvlid),(0,g.q9)(o,"video")&&R.videoAdapters.push(e),(0,g.q9)(o,"native")&&c.Sg.push(e)):(0,a.H)("Bidder adaptor error for bidder code: "+e+"bidder must implement a callBids() function"):(0,a.H)("bidAdapter or bidderCode not specified")},R.aliasBidAdapter=function(n,e,t){if(void 0===P[e]){var r=P[n];if(void 0===r){var i=[];Z.forEach((function(t){if(t.bidders&&t.bidders.length){var r=t&&t.bidders;t&&(0,g.q9)(r,e)?q[e]=n:i.push(n)}})),i.forEach((function(n){(0,a.H)('bidderCode "'+n+'" is not an existing bidder.',"adapterManager.aliasBidAdapter")}))}else try{var o,u=function(n){var e=[];return(0,g.q9)(R.videoAdapters,n)&&e.push("video"),(0,g.q9)(c.Sg,n)&&e.push("native"),e}(n);if(r.constructor.prototype!=Object.prototype)(o=new r.constructor).setBidderCode(e);else{var d=r.getSpec(),f=t&&t.gvlid;null!=d.gvlid&&null==f&&(0,a.yN)("Alias '".concat(e,"' will NOT re-use the GVL ID of the original adapter ('").concat(d.code,"', gvlid: ").concat(d.gvlid,"). Functionality that requires TCF consent may not work as expected."));var l=t&&t.skipPbsAliasing;o=(0,s.PZ)(Object.assign({},d,{code:e,gvlid:f,skipPbsAliasing:l})),q[e]=n}R.registerBidAdapter(o,e,{supportedMediaTypes:u})}catch(e){(0,a.H)(n+" bidder does not currently support aliasing.","adapterManager.aliasBidAdapter")}}else(0,a.ji)('alias name "'+e+'" has been already specified.')},R.resolveAlias=function(n){for(var e,t=n;q[t]&&(!e||!e.has(t));)t=q[t],(e=e||new Set).add(t);return t},R.registerAnalyticsAdapter=function(n){var e=n.adapter,t=n.code,r=n.gvlid;e&&t?"function"==typeof e.enableAnalytics?(e.code=t,x[t]={adapter:e,gvlid:r},h.qh.register(A._U,t,r)):(0,a.H)('Prebid Error: Analytics adaptor error for analytics "'.concat(t,'"\n analytics adapter must implement an enableAnalytics() function')):(0,a.H)("Prebid Error: analyticsAdapter or analyticsCode not specified")},R.enableAnalytics=function(n){(0,a.kJ)(n)||(n=[n]),n.forEach((function(n){var e=x[n.provider];e&&e.adapter?U.isAllowed(T.x$,D(A._U,n.provider,(0,o.Z)({},O.Hw,n)))&&e.adapter.enableAnalytics(n):(0,a.H)("Prebid Error: no analytics adapter found in registry for '".concat(n.provider,"'."))}))},R.getBidAdapter=function(n){return P[n]},R.getAnalyticsAdapter=function(n){return x[n]},R.callTimedOutBidders=function(n,e,t){e=e.map((function(e){return e.params=(0,a.S0)(n,e.adUnitCode,e.bidder),e.timeout=t,e})),e=(0,a.vM)(e,"bidder"),Object.keys(e).forEach((function(n){J(n,"onTimeout",e[n])}))},R.callBidWonBidder=function(n,e,t){e.params=(0,a.S0)(t,e.adUnitCode,e.bidder),v.f.incrementBidderWinsCounter(e.adUnitCode,e.bidder),J(n,"onBidWon",e)},R.callBidBillableBidder=function(n){J(n.bidder,"onBidBillable",n)},R.callSetTargetingBidder=function(n,e){J(n,"onSetTargeting",e)},R.callBidViewableBidder=function(n,e){J(n,"onBidViewable",e)},R.callBidderError=function(n,e,t){J(n,"onBidderError",{error:e,bidderRequest:t})},R.callDataDeletionRequest=(0,l.z3)("sync",(function(){for(var n=arguments.length,e=new Array(n),t=0;t2&&void 0!==arguments[2]?arguments[2]:{},r=t.index,o=void 0===r?m.K.index:r;if((e.width||0===parseInt(e.width,10))&&(e.height||0===parseInt(e.height,10)))return e.width=parseInt(e.width,10),e.height=parseInt(e.height,10),!0;var a=o.getBidRequest(e),u=o.getMediaTypes(e),c=a&&a.sizes||u&&u.banner&&u.banner.sizes,s=(0,p.sF)(c);if(1===s.length){var d=s[0].split("x"),f=(0,i.Z)(d,2),l=f[0],g=f[1];return e.width=parseInt(l,10),e.height=parseInt(g,10),!0}return!1}function R(n,e){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=t.index,i=void 0===r?m.K.index:r;function o(){var n=Object.keys(e);return O.every((function(t){return(0,v.q9)(n,t)&&!(0,v.q9)([void 0,null],e[t])}))}function a(n){return"Invalid bid from ".concat(e.bidderCode,". Ignoring bid: ").concat(n)}return n?e?o()?"native"!==e.mediaType||(0,d.r4)(e,{index:i})?"video"!==e.mediaType||(0,f.Dn)(e,{index:i})?!("banner"===e.mediaType&&!U(n,e,{index:i}))||((0,p.H)(a("Banner bids require a width and height")),!1):((0,p.H)(a("Video bid does not have required vastUrl or renderer property")),!1):((0,p.H)(a("Native bid missing some required properties.")),!1):((0,p.H)(a("Bidder ".concat(e.bidderCode," is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params."))),!1):((0,p.yN)("Some adapter tried to add an undefined bid for ".concat(n,".")),!1):((0,p.yN)("No adUnitCode was supplied to addBidResponse."),!1)}function P(n){return(0,b.Bf)(n.metrics).renameWith((function(e){return["adapter.client.".concat(e),"adapters.client.".concat(n.bidderCode,".").concat(e)]}))}},5730:function(n,e,t){t.d(e,{B:function(){return u}});var r=t(4614),i=t(4358),o=new WeakMap,a=["debugging","adloox","criteo","outstream","adagio","spotx","browsi","brandmetrics","justtag","tncId","akamaidap","ftrackId","inskin","hadron","medianet","improvedigital","aaxBlockmeter","confiant","arcspan","airgrid","clean.io","a1Media","geoedge","mediafilter","qortex","dynamicAdBoost"];function u(n,e,t,u,c){if(e&&n){if((0,r.q9)(a,e)){u||(u=document);var s=l(u,n);if(s)return t&&"function"==typeof t&&(s.loaded?t():s.callbacks.push(t)),s.tag;var d=o.get(u)||{},f={loaded:!1,tag:null,callbacks:[]};return d[n]=f,o.set(u,d),t&&"function"==typeof t&&f.callbacks.push(t),(0,i.yN)("module ".concat(e," is loading external JavaScript")),function(e,t,r,o){r||(r=document);var a=r.createElement("script");a.type="text/javascript",a.async=!0;var u=l(r,n);u&&(u.tag=a);a.readyState?a.onreadystatechange=function(){"loaded"!==a.readyState&&"complete"!==a.readyState||(a.onreadystatechange=null,t())}:a.onload=function(){t()};a.src=e,o&&(0,i.D9)(a,o);return(0,i.jC)(a,r),a}(n,(function(){f.loaded=!0;try{for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:{},r=t.method||(e?s:c);if(r===c&&e){var i=(0,a.en)(n,t);Object.assign(i.search,e),n=(0,a.Q2)(i)}var o=new Headers(t.customHeaders);o.set(d,t.contentType||"text/plain");var f={method:r,headers:o};return r!==c&&e&&(f.body=e),t.withCredentials&&(f.credentials="include"),t.browsingTopics&&isSecureContext&&(f.browsingTopics=!0),u.makeRequest(n,f)}function l(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:3e3,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=e.request,r=e.done,i=function(e,t){var r,i,a;null==n||null!=(null===(r=t)||void 0===r?void 0:r.signal)||o.vc.getConfig("disableAjaxTimeout")||(a=u.timeout(n,e),t=Object.assign({signal:a.signal},t));var c=u.fetch(e,t);return null!=(null===(i=a)||void 0===i?void 0:i.done)&&(c=c.finally(a.done)),c};return null==t&&null==r||(i=function(n){return function(e,i){var o=new URL(null==(null==e?void 0:e.url)?e:e.url,document.location).origin,a=n(e,i);return t&&t(o),r&&(a=a.finally((function(){return r(o)}))),a}}(i)),i}function g(n,e){var t=n.status,r=n.statusText,i=void 0===r?"":r,o=n.headers,u=n.url,c=0;function s(n){if(0===c)try{var t,r;c=(new DOMParser).parseFromString(e,null==o||null===(t=o.get(d))||void 0===t||null===(r=t.split(";"))||void 0===r?void 0:r[0])}catch(e){c=null,n&&n(e)}return c}return{readyState:XMLHttpRequest.DONE,status:t,statusText:i,responseText:e,response:e,responseType:"",responseURL:u,get responseXML(){return s(a.H)},getResponseHeader:function(n){return null!=o&&o.has(n)?o.get(n):null},toJSON:function(){return Object.assign({responseXML:s()},this)}}}function v(n,e){var t="object"===(0,i.Z)(e)&&null!=e?e:{success:"function"==typeof e?e:function(){return null},error:function(n,e){return(0,a.H)("Network error",n,e)}},o=t.success,u=t.error;n.then((function(n){return n.text().then((function(e){return[n,e]}))})).then((function(n){var e=(0,r.Z)(n,2),t=e[0],i=e[1],a=g(t,i);t.ok||304===t.status?o(i,a):u(t.statusText,a)}),(function(){return u("",g({status:0},""))}))}function p(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:3e3,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=e.request,r=e.done,i=l(n,{request:t,done:r});return function(n,e,t){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};v(i(f(n,t,r)),e)}}var h=p();l()},5686:function(n,e,t){t.d(e,{LX:function(){return $},RH:function(){return J},Yw:function(){return k},dg:function(){return V},lU:function(){return D},mv:function(){return I},vO:function(){return R}});var r=t(1002),i=t(4358),o=t(265),a=t(6463),u=t(59),c=t(9885),s=t(5706),d=t(3193),f=t(1974),l=t(2797),g=t(4614),v=t(154),p=t(4679),h=t(8653),m=t(5975),y=t(2021),b=t(6104),w=t(5644),A=t(8792),C=t(9128),T=t(6066),O=t(8640),E=f.k_.syncUsers,k="inProgress",I="completed";y.on(w.FP.BID_ADJUSTMENT,(function(n){!function(n){var e=(0,T.O)(n.cpm,n);e>=0&&(n.cpm=e)}(n)}));var B={},S={},j=[],U=(0,O.R)();function R(n){var e=n.adUnits,t=n.adUnitCodes,o=n.callback,a=n.cbTimeout,u=n.labels,c=n.auctionId,s=n.ortb2Fragments,f=n.metrics;f=(0,C.Bf)(f);var l,v,m,T,O=e,R=u,_=t,H=c||(0,i.DO)(),F=a,L=new Set,z=(0,A.P)(),G=[],J=o,V=[],Q=[],$=[],Y=[],nn=[];function en(){return{auctionId:H,timestamp:l,auctionEnd:v,auctionStatus:T,adUnits:O,adUnitCodes:_,labels:R,bidderRequests:V,noBids:$,bidsReceived:Q,bidsRejected:G,winningBids:Y,timeout:F,metrics:f,seatNonBids:nn}}function tn(n){if(n?y.emit(w.FP.AUCTION_TIMEOUT,en()):clearTimeout(m),void 0===v){var t=[];n&&((0,i.ji)("Auction ".concat(H," timedOut")),(t=V.filter((function(n){return!L.has(n.bidderRequestId)})).flatMap((function(n){return n.bids}))).length&&y.emit(w.FP.BID_TIMEOUT,t)),T=I,v=Date.now(),f.checkpoint("auctionEnd"),f.timeBetween("requestBids","auctionEnd","requestBids.total"),f.timeBetween("callBids","auctionEnd","requestBids.callBids"),z.resolve(),y.emit(w.FP.AUCTION_END,en()),x(O,(function(){try{if(null!=J){var r=Q.filter((function(n){return _.includes(n.adUnitCode)})).reduce(X,{});J.apply(U,[r,n,H]),J=null}}catch(n){(0,i.H)("Error executing bidsBackHandler",null,n)}finally{t.length&&b.ZP.callTimedOutBidders(e,t,F);var o=d.vc.getConfig("userSync")||{};o.enableOverride||E(o.syncDelay)}}))}}function rn(){d.vc.resetBidder(),(0,i.PN)("Bids Received for Auction with id: ".concat(H),Q),T=I,tn(!1)}function on(n){L.add(n)}function an(n){var e=this;n.forEach((function(n){var e;e=n,V=V.concat(e)}));var t={},o={bidRequests:n,run:function(){m=setTimeout((function(){return tn(!0)}),F),T=k,y.emit(w.FP.AUCTION_INIT,en());var o=function(n,e){var t=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).index,o=(void 0===t&&h.K.index,0),a=!1,u=new Set,c={};function s(){o--,a&&0===o&&n()}function f(n,e,t){return c[e.requestId]=!0,W(e,n),o++,t(s)}function l(n,t){f(n,t,(function(n){var i=K(t);y.emit(w.FP.BID_ACCEPTED,i),i.mediaType===p.pX?N(e,i,n):(null!=i.native&&"object"===(0,r.Z)(i.native)&&M(i),D(e,i),n())}))}function v(n,t,r){return f(n,t,(function(n){t.rejectionReason=r,(0,i.yN)("Bid from ".concat(t.bidder||"unknown bidder"," was rejected: ").concat(r),t),y.emit(w.FP.BID_REJECTED,t),e.addBidRejected(t),n()}))}function m(){var t=this,r=e.getBidRequests(),s=d.vc.getConfig("auctionOptions");if(u.add(t),s&&!(0,i.xb)(s)){var f=s.secondaryBidders;f&&!r.every((function(n){return(0,g.q9)(f,n.bidderCode)}))&&(r=r.filter((function(n){return!(0,g.q9)(f,n.bidderCode)})))}a=r.every((function(n){return u.has(n)})),t.bids.forEach((function(n){c[n.bidId]||(e.addNoBid(n),y.emit(w.FP.NO_BID,n))})),a&&0===o&&n()}return{addBidResponse:function(){function n(n,e){var t;P.call({dispatch:l},n,e,(t=!1,function(r){t||(v(n,e,r),t=!0)}))}return n.reject=v,n}(),adapterDone:function(){var n=this;q(A.Z.resolve()).finally((function(){return m.call(n)}))}}}(rn,e);b.ZP.callBids(O,n,o.addBidResponse,o.adapterDone,{request:function(n,e){u(B,e),u(t,n),S[n]||(S[n]={SRA:!0,origin:e}),t[n]>1&&(S[n].SRA=!1)},done:function(n){B[n]--,j[0]&&a(j[0])&&j.shift()}},F,on,s)}};function a(n){var e=!0,t=d.vc.getConfig("maxRequestsPerOrigin")||4;return n.bidRequests.some((function(n){var r=1,i=void 0!==n.src&&n.src===w.os.YZ?"s2s":n.bidderCode;return S[i]&&(!1===S[i].SRA&&(r=Math.min(n.bids.length,t)),B[S[i].origin]+r>t&&(e=!1)),!e})),e&&n.run(),e}function u(n,e){void 0===n[e]?n[e]=1:n[e]++}a(o)||((0,i.yN)("queueing auction due to limited endpoint capacity"),j.push(o))}return y.on(w.FP.SEAT_NON_BID,(function(n){var e;n.auctionId===H&&(e=n.seatnonbid,nn=nn.concat(e))})),{addBidReceived:function(n){Q=Q.concat(n)},addBidRejected:function(n){G=G.concat(n)},addNoBid:function(n){$=$.concat(n)},callBids:function(){T="started",l=Date.now();var n=f.measureTime("requestBids.makeRequests",(function(){return b.ZP.makeBidRequests(O,l,H,F,R,s,f)}));(0,i.PN)("Bids Requested for Auction with id: ".concat(H),n),f.checkpoint("callBids"),n.length<1?((0,i.yN)("No valid bid requests returned for auction"),rn()):Z.call({dispatch:an,context:this},n)},addWinningBid:function(n){var t=e.find((function(e){return e.transactionId===n.transactionId}));Y=Y.concat(n),(0,i.R_)(n),b.ZP.callBidWonBidder(n.adapterCode||n.bidder,n,e),t&&!t.deferBilling&&b.ZP.callBidBillableBidder(n)},setBidTargeting:function(n){b.ZP.callSetTargetingBidder(n.adapterCode||n.bidder,n)},getWinningBids:function(){return Y},getAuctionStart:function(){return l},getAuctionEnd:function(){return v},getTimeout:function(){return F},getAuctionId:function(){return H},getAuctionStatus:function(){return T},getAdUnits:function(){return O},getAdUnitCodes:function(){return _},getBidRequests:function(){return V},getBidsReceived:function(){return Q},getNoBids:function(){return $},getNonBids:function(){return nn},getFPD:function(){return s},getMetrics:function(){return f},end:z.promise}}var P=(0,l.z3)("sync",(function(n,e,t){this.dispatch.call(null,n,e)}),"addBidResponse"),q=(0,l.z3)("sync",(function(n){return n}),"responsesReady"),Z=(0,l.z3)("sync",(function(n){this.dispatch.call(this.context,n)}),"addBidderRequests"),x=(0,l.z3)("async",(function(n,e){e&&e()}),"bidsBackCallback");function D(n,e){!function(n){var e,t=!0===m.S.get(n.bidderCode,"allowZeroCpmBids")?n.cpm>=0:n.cpm>0;n.bidderCode&&(t||n.dealId)&&(e=function(n,e){var t=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).index,r=void 0===t?h.K.index:t;if(!e)return{};var i=r.getBidRequest(e),o={},a=$(e.mediaType,n);Y(o,a,e,i),n&&m.S.getOwn(n,w.k2.xn)&&(Y(o,m.S.ownSettingsFor(n),e,i),e.sendStandardTargeting=m.S.get(n,"sendStandardTargeting"));e.native&&(o=Object.assign({},o,(0,u.Ur)(e)));return o}(n.bidderCode,n));n.adserverTargeting=Object.assign(n.adserverTargeting||{},e)}(e),(0,C.Bf)(e.metrics).timeSince("addBidResponse","addBidResponse.total"),n.addBidReceived(e),y.emit(w.FP.BID_RESPONSE,e)}function N(n,e,t){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},a=r.index,u=void 0===a?h.K.index:a,c=!0,s=(0,o.Z)(u.getMediaTypes({requestId:e.originalRequestId||e.requestId,transactionId:e.transactionId}),"video"),f=s&&(0,o.Z)(s,"context"),l=s&&(0,o.Z)(s,"useCacheKey");d.vc.getConfig("cache.url")&&(l||f!==v.gZ)&&(!e.videoCacheKey||d.vc.getConfig("cache.ignoreBidderCacheKey")?(c=!1,z(n,e,t,s)):e.vastUrl||((0,i.H)("videoCacheKey specified but not required vastUrl for video bid"),c=!1)),c&&(D(n,e),t())}var _,H,M=function(n){var e,t,r=null===(e=h.K.index.getAdUnit(n))||void 0===e?void 0:e.nativeOrtbRequest,i=null===(t=n.native)||void 0===t?void 0:t.ortb;if(r&&i){var o=(0,u.zq)(i,r);Object.assign(n.native,o)}},F=function(n){(0,c.h)(n.map((function(n){return n.bidResponse})),(function(e,t){t.forEach((function(t,r){var o=n[r],a=o.auctionInstance,u=o.bidResponse,s=o.afterBidAdded;e?(0,i.yN)("Failed to save to the video cache: ".concat(e,". Video bid must be discarded.")):""===t.uuid?(0,i.yN)("Supplied video cache key was already in use by Prebid Cache; caching attempt was rejected. Video bid must be discarded."):(u.videoCacheKey=t.uuid,u.vastUrl||(u.vastUrl=(0,c.z)(u.videoCacheKey)),D(a,u),s())}))}))};d.vc.getConfig("cache",(function(n){_="number"==typeof n.cache.batchSize&&n.cache.batchSize>0?n.cache.batchSize:1,H="number"==typeof n.cache.batchTimeout&&n.cache.batchTimeout>0?n.cache.batchTimeout:0}));var L=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:setTimeout,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:F,t=[[]],r=!1,i=function(n){return n()};return function(o,a,u){var c=H>0?n:i;t[t.length-1].length>=_&&t.push([]),t[t.length-1].push({auctionInstance:o,bidResponse:a,afterBidAdded:u}),r||(r=!0,c((function(){t.forEach(e),t=[[]],r=!1}),H))}}(),z=(0,l.z3)("async",(function(n,e,t,r){L(n,e,t)}),"callPrebidCache");function W(n,e){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=t.index,o=void 0===r?h.K.index:r,a=o.getBidderRequest(n),u=o.getAdUnit(n),c=a&&a.start||n.requestTimestamp;Object.assign(n,{responseTimestamp:n.responseTimestamp||(0,i.AB)(),requestTimestamp:n.requestTimestamp||c,cpm:parseFloat(n.cpm)||0,bidder:n.bidder||n.bidderCode,adUnitCode:e}),null!=(null==u?void 0:u.ttlBuffer)&&(n.ttlBuffer=u.ttlBuffer),n.timeToRespond=n.responseTimestamp-n.requestTimestamp}function K(n){var e,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=t.index,o=void 0===i?h.K.index:i;y.emit(w.FP.BID_ADJUSTMENT,n);var u=(null===(e=o.getBidRequest(n))||void 0===e?void 0:e.renderer)||o.getAdUnit(n).renderer,c=n.mediaType,f=o.getMediaTypes(n),l=f&&f[c],g=l&&l.renderer,v=null;g&&g.url&&g.render&&(!0!==g.backupOnly||!n.renderer)?v=g:u&&u.url&&u.render&&(!0!==u.backupOnly||!n.renderer)&&(v=u),v&&(n.renderer=s.Th.install({url:v.url,config:v.options}),n.renderer.setRender(v.render));var p=G(n.mediaType,f,d.vc.getConfig("mediaTypePriceGranularity")),m=(0,a.D)(n.cpm,"object"===(0,r.Z)(p)?p:d.vc.getConfig("customPriceBucket"),d.vc.getConfig("currency.granularityMultiplier"));return n.pbLg=m.low,n.pbMg=m.med,n.pbHg=m.high,n.pbAg=m.auto,n.pbDg=m.dense,n.pbCg=m.custom,n}function G(n,e,t){if(n&&t){if(n===p.pX){var r=(0,o.Z)(e,"".concat(p.pX,".context"),"instream");if(t["".concat(p.pX,"-").concat(r)])return t["".concat(p.pX,"-").concat(r)]}return t[n]}}var J=function(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=e.index,r=void 0===t?h.K.index:t,i=G(n.mediaType,r.getMediaTypes(n),d.vc.getConfig("mediaTypePriceGranularity")),o="string"==typeof n.mediaType&&i?"string"==typeof i?i:"custom":d.vc.getConfig("priceGranularity");return o},V=function(n){return function(e){var t=n||J(e);return t===w.Ql.B7?e.pbAg:t===w.Ql.uN?e.pbDg:t===w.Ql.yE?e.pbLg:t===w.Ql.M2?e.pbMg:t===w.Ql.lj?e.pbHg:t===w.Ql.qN?e.pbCg:void 0}};function Q(n,e){return{key:n,val:"function"==typeof e?function(n,t){return e(n,t)}:function(n){return(0,i.NA)(n,e)}}}function $(n,e){var t=w.TD,r=Object.assign({},m.S.settingsFor(null));if(r[w.k2.xn]||(r[w.k2.xn]=function(){var n=w.TD;return[Q(n.BIDDER,"bidderCode"),Q(n.AD_ID,"adId"),Q(n.PRICE_BUCKET,V()),Q(n.SIZE,"size"),Q(n.DEAL,"dealId"),Q(n.SOURCE,"source"),Q(n.FORMAT,"mediaType"),Q(n.ADOMAIN,(function(n){return n.meta&&n.meta.advertiserDomains&&n.meta.advertiserDomains.length>0?[n.meta.advertiserDomains].flat()[0]:""})),Q(n.ACAT,(function(n){return n.meta&&n.meta.primaryCatId?n.meta.primaryCatId:""})),Q(n.DSP,(function(n){return n.meta&&(n.meta.networkId||n.meta.networkName)?(0,o.Z)(n,"meta.networkName")||(0,o.Z)(n,"meta.networkId"):""})),Q(n.CRID,(function(n){return n.creativeId?n.creativeId:""}))]}()),"video"===n){var a=r[w.k2.xn].slice();if(r[w.k2.xn]=a,[t.UUID,t.CACHE_ID].forEach((function(n){void 0===(0,g.sE)(a,(function(e){return e.key===n}))&&a.push(Q(n,"videoCacheKey"))})),d.vc.getConfig("cache.url")&&(!e||!1!==m.S.get(e,"sendStandardTargeting"))){var u=(0,i.en)(d.vc.getConfig("cache.url"));void 0===(0,g.sE)(a,(function(n){return n.key===t.CACHE_HOST}))&&a.push(Q(t.CACHE_HOST,(function(n){return(0,o.Z)(n,"adserverTargeting.".concat(t.CACHE_HOST))?n.adserverTargeting[t.CACHE_HOST]:u.hostname})))}}return r}function Y(n,e,t,r){var o=e[w.k2.xn];return t.size=t.getSize(),(o||[]).forEach((function(o){var a=o.key,u=o.val;if(n[a]&&(0,i.yN)("The key: "+a+" is being overwritten"),(0,i.LQ)(u))try{u=u(t,r)}catch(n){(0,i.H)("bidmanager","ERROR",n)}(void 0===e.suppressEmptyKeys||!0!==e.suppressEmptyKeys)&&a!==w.TD.DEAL&&a!==w.TD.ACAT&&a!==w.TD.DSP&&a!==w.TD.CRID||!(0,i.jH)(u)&&null!=u?n[a]=u:(0,i.PN)("suppressing empty key '"+a+"' from adserver targeting")})),n}function X(n,e){return n[e.adUnitCode]||(n[e.adUnitCode]={bids:[]}),n[e.adUnitCode].bids.push(e),n}},8653:function(n,e,t){t.d(e,{K:function(){return h}});var r=t(3324),i=t(9062),o=t(4358),a=t(5686);function u(n){Object.assign(this,{getAuction:function(e){var t=e.auctionId;if(null!=t)return n().find((function(n){return n.getAuctionId()===t}))},getAdUnit:function(e){var t=e.transactionId;if(null!=t)return n().flatMap((function(n){return n.getAdUnits()})).find((function(n){return n.transactionId===t}))},getMediaTypes:function(n){var e=n.transactionId,t=n.requestId;if(null!=t){var r=this.getBidRequest({requestId:t});if(null!=r&&(null==e||r.transactionId===e))return r.mediaTypes}else if(null!=e){var i=this.getAdUnit({transactionId:e});if(null!=i)return i.mediaTypes}},getBidderRequest:function(e){var t=e.requestId,r=e.bidderRequestId;if(null!=t||null!=r){var i=n().flatMap((function(n){return n.getBidRequests()}));return null!=r&&(i=i.filter((function(n){return n.bidderRequestId===r}))),null==t?i[0]:i.find((function(n){return n.bids&&null!=n.bids.find((function(n){return n.bidId===t}))}))}},getBidRequest:function(e){var t=e.requestId;if(null!=t)return n().flatMap((function(n){return n.getBidRequests()})).flatMap((function(n){return n.bids})).find((function(n){return n&&n.bidId===t}))}})}var c=t(5644),s=t(9128),d=t(613),f=t(8833),l=t(3193);function g(n,e){var t="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(!t){if(Array.isArray(n)||(t=function(n,e){if(!n)return;if("string"==typeof n)return v(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);"Object"===t&&n.constructor&&(t=n.constructor.name);if("Map"===t||"Set"===t)return Array.from(n);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return v(n,e)}(n))||e&&n&&"number"==typeof n.length){t&&(n=t);var r=0,i=function(){};return{s:i,n:function(){return r>=n.length?{done:!0}:{done:!1,value:n[r++]}},e:function(n){throw n},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){t=t.call(n)},n:function(){var n=t.next();return a=n.done,n},e:function(n){u=!0,o=n},f:function(){try{a||null==t.return||t.return()}finally{if(u)throw o}}}}function v(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t1&&void 0!==arguments[1]?arguments[1]:{},t=e.src,i=void 0===t?"client":t,o=e.bidder,a=void 0===o?"":o,u=e.bidId,c=e.transactionId,s=e.auctionId,d=i,f=n||0;function l(){switch(f){case 0:return"Pending";case 1:return"Bid available";case 2:return"Bid returned empty or error response";case 3:return"Bid timed out"}}this.bidderCode=a,this.width=0,this.height=0,this.statusMessage=l(),this.adId=(0,r._d)(),this.requestId=u,this.transactionId=c,this.auctionId=s,this.mediaType="banner",this.source=d,this.getStatusCode=function(){return f},this.getSize=function(){return this.width+"x"+this.height},this.getIdentifiers=function(){return{src:this.source,bidder:this.bidderCode,bidId:this.requestId,transactionId:this.transactionId,auctionId:this.auctionId}}}function o(n,e){return new i(n,e)}},3193:function(n,e,t){t.d(e,{FD:function(){return g},vc:function(){return y}});var r=t(4942),i=t(1002),o=t(3324),a=t(6463),u=t(4614),c=t(4358),s=t(265),d=t(5644);function f(n,e){var t=Object.keys(n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(n);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),t.push.apply(t,r)}return t}var l="TRUE"===(0,c.ak)(d.f).toUpperCase(),g="random",v={};v[g]=!0,v.fixed=!0;var p=g,h={LOW:"low",MEDIUM:"medium",HIGH:"high",AUTO:"auto",DENSE:"dense",CUSTOM:"custom"},m="*";var y=function(){var n,e,t,d=[],g=null;function y(){function r(n){return s[n].val}function i(n,e){s[n].val=e}n={};var s={publisherDomain:{set:function(n){null!=n&&(0,c.yN)("publisherDomain is deprecated and has no effect since v7 - use pageUrl instead"),i("publisherDomain",n)}},priceGranularity:{val:h.MEDIUM,set:function(n){g(n)&&("string"==typeof n?i("priceGranularity",f(n)?n:h.MEDIUM):(0,c.PO)(n)&&(i("customPriceBucket",n),i("priceGranularity",h.CUSTOM),(0,c.ji)("Using custom price granularity")))}},customPriceBucket:{val:{},set:function(){}},mediaTypePriceGranularity:{val:{},set:function(n){null!=n&&i("mediaTypePriceGranularity",Object.keys(n).reduce((function(e,t){return g(n[t])?"string"==typeof n?e[t]=f(n[t])?n[t]:r("priceGranularity"):(0,c.PO)(n)&&(e[t]=n[t],(0,c.ji)("Using custom price granularity for ".concat(t))):(0,c.yN)("Invalid price granularity for media type: ".concat(t)),e}),{}))}},bidderSequence:{val:p,set:function(n){v[n]?i("bidderSequence",n):(0,c.yN)("Invalid order: ".concat(n,". Bidder Sequence was not set."))}},auctionOptions:{val:{},set:function(n){(function(n){if(!(0,c.PO)(n))return(0,c.yN)("Auction Options must be an object"),!1;for(var e=0,t=Object.keys(n);e2&&void 0!==arguments[2]?arguments[2]:{},i=e;if("string"!=typeof n&&(i=n,n=m,t=e||{}),"function"==typeof i){var o={topic:n,callback:i};return d.push(o),t.init&&i(n===m?T():(0,r.Z)({},n,T(n))),function(){d.splice(d.indexOf(o),1)}}(0,c.H)("listener must be a function")}function j(n){var e=Object.keys(n);d.filter((function(n){return(0,u.q9)(e,n.topic)})).forEach((function(e){e.callback((0,r.Z)({},e.topic,n[e.topic]))})),d.filter((function(n){return n.topic===m})).forEach((function(e){return e.callback(n)}))}function U(n){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];try{r(n),n.bidders.forEach((function(r){t[r]||(t[r]={}),Object.keys(n.config).forEach((function(i){var o=n.config[i];if((0,c.PO)(o)){var a=e?c.Ee:Object.assign;t[r][i]=a({},t[r][i]||{},o)}else t[r][i]=o}))}))}catch(n){(0,c.H)(n)}function r(n){if(!(0,c.PO)(n))throw"setBidderConfig bidder options must be an object";if(!Array.isArray(n.bidders)||!n.bidders.length)throw"setBidderConfig bidder options must contain a bidders list with at least 1 bidder";if(!(0,c.PO)(n.config))throw"setBidderConfig bidder options must contain a config object"}}function R(n,e){g=n;try{return e()}finally{P()}}function P(){g=null}return y(),{getCurrentBidder:function(){return g},resetBidder:P,getConfig:T,getAnyConfig:C,readConfig:k,readAnyConfig:I,setConfig:B,mergeConfig:function(n){if((0,c.PO)(n)){var e=(0,c.Ee)(b(),n);return B(function(n){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:(0,p.AB)();this.generatedTime=e,(0,v.Z)(this,I,!0),A(this,S,U).call(this,n)}},{key:"getConsentData",value:function(){return(0,g.Z)(this,O)}},{key:"hash",get:function(){var n=this;return(0,g.Z)(this,I)&&((0,v.Z)(this,B,(0,p._R)(JSON.stringify((0,g.Z)(this,O)&&this.hashFields?this.hashFields.map((function(e){return(0,g.Z)(n,O)[e]})):(0,g.Z)(this,O)))),(0,v.Z)(this,I,!1)),(0,g.Z)(this,B)}}]),n}();function U(n){(0,v.Z)(this,k,!0),(0,v.Z)(this,O,n),(0,g.Z)(this,E).resolve(n)}var R=function(n){a(t,n);var e=y(t);function t(){return(0,d.Z)(this,t),e.apply(this,arguments)}return(0,f.Z)(t,[{key:"getConsentMeta",value:function(){var n=this.getConsentData();if(n&&this.generatedTime)return{usp:n,generatedAt:this.generatedTime}}}]),t}(j),P=function(n){a(t,n);var e=y(t);function t(){var n;(0,d.Z)(this,t);for(var r=arguments.length,o=new Array(r),a=0;a0&&void 0!==arguments[0]?arguments[0]:L;function e(e){return function(){return Object.fromEntries(n.map((function(n){var t=(0,r.Z)(n,2);return[t[0],t[1][e]()]})))}}return n=Object.entries(n),Object.assign({get promise(){return h.Z.all(n.map((function(n){var e=(0,r.Z)(n,2),t=e[0];return e[1].promise.then((function(n){return[t,n]}))}))).then((function(n){return Object.fromEntries(n)}))},get hash(){return(0,p._R)(n.map((function(n){var e=(0,r.Z)(n,2);e[0];return e[1].hash})).join(":"))}},Object.fromEntries(["getConsentData","getConsentMeta","reset"].map((function(n){return[n,e(n)]}))))}()},6463:function(n,e,t){t.d(e,{D:function(){return f},t:function(){return g}});var r=t(4614),i=t(4358),o=t(3193),a={buckets:[{max:5,increment:.5}]},u={buckets:[{max:20,increment:.1}]},c={buckets:[{max:20,increment:.01}]},s={buckets:[{max:3,increment:.01},{max:8,increment:.05},{max:20,increment:.5}]},d={buckets:[{max:5,increment:.05},{max:10,increment:.1},{max:20,increment:.5}]};function f(n,e){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,r=parseFloat(n);return isNaN(r)&&(r=""),{low:""===r?"":l(n,a,t),med:""===r?"":l(n,u,t),high:""===r?"":l(n,c,t),auto:""===r?"":l(n,d,t),dense:""===r?"":l(n,s,t),custom:""===r?"":l(n,e,t)}}function l(n,e,t){var a="";if(!g(e))return a;var u=e.buckets.reduce((function(n,e){return n.max>e.max?n:e}),{max:0}),c=0,s=(0,r.sE)(e.buckets,(function(e){if(n>u.max*t){var r=e.precision;void 0===r&&(r=2),a=(e.max*t).toFixed(r)}else{if(n<=e.max*t&&n>=c*t)return e.min=c,e;c=e.max}}));return s&&(a=function(n,e,t){var r=void 0!==e.precision?e.precision:2,a=e.increment*t,u=e.min*t,c=Math.floor,s=o.vc.getConfig("cpmRoundingFunction");"function"==typeof s&&(c=s);var d,f,l=Math.pow(10,r+2),g=(n*l-u*l)/(a*l);try{d=c(g)*a+u}catch(n){f=!0}(f||"number"!=typeof d)&&((0,i.yN)("Invalid rounding function passed in config"),d=Math.floor(g)*a+u);return(d=Number(d.toFixed(10))).toFixed(r)}(n,s,t)),a}function g(n){if((0,i.xb)(n)||!n.buckets||!Array.isArray(n.buckets))return!1;var e=!0;return n.buckets.forEach((function(n){n.max&&n.increment||(e=!1)})),e}},2021:function(n,e,t){t.r(e),t.d(e,{addEvents:function(){return w},clearEvents:function(){return C},emit:function(){return b},get:function(){return m},getEvents:function(){return y},has:function(){return A},off:function(){return h},on:function(){return p}});var r=t(4358),i=t(5644),o=t(613),a=t(3193),u="eventHistoryTTL",c=null,s=(0,o.Z)({monotonic:!0,ttl:function(){return c}});a.vc.getConfig(u,(function(n){var e,t=c;n=null===(e=n)||void 0===e?void 0:e[u],t!==(c="number"==typeof n?1e3*n:null)&&s.refresh()}));var d=Array.prototype.slice,f=Array.prototype.push,l=Object.values(i.FP),g=i.aI,v=function(){var n={},e={};function t(e,t){r.ji("Emitting event for: "+e);var i=t[0]||{},o=i[g[e]],a=n[e]||{que:[]},u=Object.keys(a),c=[];s.add({eventType:e,args:i,id:o,elapsedTime:r.bd()}),o&&u.includes(o)&&f.apply(c,a[o].que),f.apply(c,a.que),(c||[]).forEach((function(n){if(n)try{n.apply(null,t)}catch(n){r.H("Error executing handler:","events.js",n,e)}}))}function i(n){return l.includes(n)}return e.has=i,e.on=function(e,t,o){if(i(e)){var a=n[e]||{que:[]};o?(a[o]=a[o]||{que:[]},a[o].que.push(t)):a.que.push(t),n[e]=a}else r.H("Wrong event name : "+e+" Valid event names :"+l)},e.emit=function(n){var e=d.call(arguments,1);t(n,e)},e.off=function(e,t,i){var o=n[e];r.xb(o)||r.xb(o.que)&&r.xb(o[i])||i&&(r.xb(o[i])||r.xb(o[i].que))||(i?(o[i].que||[]).forEach((function(n){var e=o[i].que;n===t&&e.splice(e.indexOf(n),1)})):(o.que||[]).forEach((function(n){var e=o.que;n===t&&e.splice(e.indexOf(n),1)})),n[e]=o)},e.get=function(){return n},e.addEvents=function(n){l=l.concat(n)},e.getEvents=function(){return s.toArray().map((function(n){return Object.assign({},n)}))},e}();r.u2(v.emit.bind(v));var p=v.on,h=v.off,m=v.get,y=v.getEvents,b=v.emit,w=v.addEvents,A=v.has;function C(){s.clear()}},4078:function(n,e,t){t.d(e,{S:function(){return E}});var r=t(3324),i=t(2797),o=t(5102),a=t(8196),u=t(4358),c=t(6475),s=t(3193),d=t(8792),f=["architecture","bitness","model","platformVersion","fullVersionList"],l=["brands","mobile","platform"],g=function(){var n,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null===(n=window.navigator)||void 0===n?void 0:n.userAgentData,t=e&&l.some((function(n){return void 0!==e[n]}))?Object.freeze(p(1,e)):null;return function(){return t}}(),v=function(){var n,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null===(n=window.navigator)||void 0===n?void 0:n.userAgentData,t={},r=new WeakMap;return function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:f;if(!r.has(n)){var i=Array.from(n);i.sort(),r.set(n,i.join("|"))}var o=r.get(n);if(!t.hasOwnProperty(o))try{t[o]=e.getHighEntropyValues(n).then((function(n){return(0,u.xb)(n)?null:Object.freeze(p(2,n))})).catch((function(){return null}))}catch(n){t[o]=d.Z.resolve(null)}return t[o]}}();function p(n,e){function t(n,e){var t={brand:n};return(0,u.d8)(e)&&!(0,u.jH)(e)&&(t.version=e.split(".")),t}var r={source:n};return e.platform&&(r.platform=t(e.platform,e.platformVersion)),(e.fullVersionList||e.brands)&&(r.browsers=(e.fullVersionList||e.brands).map((function(n){return t(n.brand,n.version)}))),void 0!==e.mobile&&(r.mobile=e.mobile?1:0),["model","bitness","architecture"].forEach((function(n){var t=e[n];(0,u.d8)(t)&&(r[n]=t)})),r}var h=t(3790),m=t(571),y=t(286),b=t(4947),w=t(9633);function A(n,e){var t="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(!t){if(Array.isArray(n)||(t=function(n,e){if(!n)return;if("string"==typeof n)return C(n,e);var t=Object.prototype.toString.call(n).slice(8,-1);"Object"===t&&n.constructor&&(t=n.constructor.name);if("Map"===t||"Set"===t)return Array.from(n);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return C(n,e)}(n))||e&&n&&"number"==typeof n.length){t&&(n=t);var r=0,i=function(){};return{s:i,n:function(){return r>=n.length?{done:!0}:{done:!1,value:n[r++]}},e:function(n){throw n},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){t=t.call(n)},n:function(){var n=t.next();return a=n.done,n},e:function(n){u=!0,o=n},f:function(){try{a||null==t.return||t.return()}finally{if(u)throw o}}}}function C(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t0&&(t[i]=(0,u.Ee)({},o,t[i]))})),i&&(0,c.N)(t,"device.sua",Object.assign({},i,t.device.sua)),o){var d={cdep:o};(0,c.N)(t,"device.ext",Object.assign({},d,t.device.ext))}t=O(t);var f,l=A(h.Iq);try{for(l.s();!(f=l.n()).done;){var g=f.value;if((0,h.Qg)(t,g)){t[g]=(0,u.Ee)({},S(t,a),t[g]);break}}}catch(n){l.e(n)}finally{l.f()}return t}))}));function k(n){try{return n(T.getWindowTop())}catch(e){return n(T.getWindowSelf())}}function I(n){return(0,u.iG)(n,Object.keys(n))}var B={site:function(n,e){if(!h.Iq.filter((function(n){return"site"!==n})).some(h.Qg.bind(null,n)))return I({page:e.page,ref:e.ref})},device:function(){return k((function(n){return{w:n.innerWidth||n.document.documentElement.clientWidth||n.document.body.clientWidth,h:n.innerHeight||n.document.documentElement.clientHeight||n.document.body.clientHeight,dnt:(0,u.oV)()?1:0,ua:n.navigator.userAgent,language:n.navigator.language.split("-").shift()}}))},regs:function(){var n={};k((function(n){return n.navigator.globalPrivacyControl}))&&(0,c.N)(n,"ext.gpc",1);var e=s.vc.getConfig("coppa");return"boolean"==typeof e&&(n.coppa=e?1:0),n}};function S(n,e){var t,r,i,a=(0,o.hh)(e.page,{noLeadingWww:!0});return I({domain:a,keywords:null===(t=k((function(n){return n.document.querySelector("meta[name='keywords']")})))||void 0===t||null===(r=t.content)||void 0===r||null===(i=r.replace)||void 0===i?void 0:i.call(r,/\s/g,""),publisher:I({domain:T.findRootDomain(a)})})}},3790:function(n,e,t){t.d(e,{A_:function(){return o},Iq:function(){return i},Qg:function(){return a}});var r=t(4358),i=["dooh","app","site"];function o(n){return function(e){return i.reduce((function(t,i){return a(e,i)&&(null!=t?((0,r.yN)("".concat(n," specifies both '").concat(t,"' and '").concat(i,"'; dropping the latter.")),delete e[i]):t=i),t}),null),e}}function a(n,e){return null!=n[e]&&Object.keys(n[e]).length>0}},8196:function(n,e,t){t.d(e,{W:function(){return o}});var r=t(4358),i=(0,t(5164).eA)("fpdEnrichment"),o=(0,r.HP)((function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.location.host;if(!i.cookiesAreEnabled())return n;var e,t,o=n.split(".");if(2===o.length)return n;var a=-2,u="_rdc".concat(Date.now()),c="writeable";do{e=o.slice(a).join(".");var s=new Date((0,r.AB)()+1e4).toUTCString();i.setCookie(u,c,s,"Lax",e,void 0);var d=i.getCookie(u,void 0);d===c?(t=!1,i.setCookie(u,"","Thu, 01 Jan 1970 00:00:01 GMT",void 0,e,void 0)):(a+=-1,t=Math.abs(a)<=o.length)}while(t);return e}))},2797:function(n,e,t){t.d(e,{Bx:function(){return v},Cd:function(){return s},IF:function(){return p},bA:function(){return g},o0:function(){return f},v5:function(){return d},z3:function(){return u}});var r=t(9062),i=t(1432),o=t.n(i),a=t(8792),u=o()({ready:o().SYNC|o().ASYNC|o().QUEUE}),c=(0,a.P)();u.ready=function(){var n=u.ready;return function(){try{return n.apply(u,arguments)}finally{c.resolve()}}}();var s=c.promise,d=u.get;function f(n,e){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:15,r=n.getHooks({hook:e});0===r.length&&n.before(e,t)}var l={};function g(n,e){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=t.postInstallAllowed,o=void 0!==i&&i;u("async",(function(t){t.forEach((function(n){return e.apply(void 0,(0,r.Z)(n))})),o&&(l[n]=e)}),n)([])}function v(n){for(var e=arguments.length,t=new Array(e>1?e-1:0),r=1;r=n.length?{done:!0}:{done:!1,value:n[r++]}},e:function(n){throw n},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function(){t=t.call(n)},n:function(){var n=t.next();return a=n.done,n},e:function(n){u=!0,o=n},f:function(){try{a||null==t.return||t.return()}finally{if(u)throw o}}}}function g(n,e){(null==e||e>n.length)&&(e=n.length);for(var t=0,r=new Array(e);t0&&(o.img.ext={aspectratios:d})}else(0,u.H)("image.aspect_ratios was passed, but it's empty:",r.aspect_ratios);else(0,u.H)("image.aspect_ratios was passed, but it's not a an array:",r.aspect_ratios);r.sizes&&(2===r.sizes.length&&(0,u.U)(r.sizes[0])&&(0,u.U)(r.sizes[1])?(o.img.w=r.sizes[0],o.img.h=r.sizes[1],delete o.img.hmin,delete o.img.wmin):(0,u.H)("image.sizes was passed, but its value is not an array of integers:",r.sizes))}else"title"===t?o.title={len:r.len||140}:"ext"===t&&(o.ext=r,delete o.required);e.assets.push(o)}else e.privacy=1;else(0,u.H)("Unrecognized native asset code: ".concat(t,". Asset will be ignored."));return e}(n.nativeParams))}))}function j(n){var e=n.assets;if(!Array.isArray(e)||0===e.length)return(0,u.H)("assets in mediaTypes.native.ortb is not an array, or it's empty. Assets: ",e),!1;var t=e.map((function(n){return n.id}));return e.length!==new Set(t).size||t.some((function(n){return n!==parseInt(n,10)}))?((0,u.H)("each asset object must have 'id' property, it must be unique and it must be an integer"),!1):n.hasOwnProperty("eventtrackers")&&!Array.isArray(n.eventtrackers)?((0,u.H)("ortb.eventtrackers is not an array. Eventtrackers: ",n.eventtrackers),!1):e.every((function(n){return function(n){if(!(0,u.PO)(n))return(0,u.H)("asset must be an object. Provided asset: ",n),!1;if(n.img){if(!(0,u.hj)(n.img.w)&&!(0,u.hj)(n.img.wmin))return(0,u.H)("for img asset there must be 'w' or 'wmin' property"),!1;if(!(0,u.hj)(n.img.h)&&!(0,u.hj)(n.img.hmin))return(0,u.H)("for img asset there must be 'h' or 'hmin' property"),!1}else if(n.title){if(!(0,u.hj)(n.title.len))return(0,u.H)("for title asset there must be 'len' property defined"),!1}else if(n.data){if(!(0,u.hj)(n.data.type))return(0,u.H)("for data asset 'type' property must be a number"),!1}else if(n.video&&!(Array.isArray(n.video.mimes)&&Array.isArray(n.video.protocols)&&(0,u.hj)(n.video.minduration)&&(0,u.hj)(n.video.maxduration)))return(0,u.H)("video asset is not properly configured"),!1;return!0}(n)}))}function U(n){var e,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=t.index,i=void 0===r?s.K.index:r,o=i.getAdUnit(n);if(!o)return!1;var a=o.nativeOrtbRequest,u=(null===(e=n.native)||void 0===e?void 0:e.ortb)||z(n.native,a);return R(u,a)}function R(n,e){if(!(0,a.Z)(n,"link.url"))return(0,u.H)("native response doesn't have 'link' property. Ortb response: ",n),!1;var t=e.assets.filter((function(n){return 1===n.required})).map((function(n){return n.id})),r=n.assets.map((function(n){return n.id})),i=t.every((function(n){return(0,c.q9)(r,n)}));return i||(0,u.H)("didn't receive a bid with all required assets. Required ids: ".concat(t,", but received ids in response: ").concat(r)),i}function P(n,e){var t=e.native.ortb||L(e.native);return"click"===n.action?function(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,t=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).fetchURL,r=void 0===t?u.hq:t;if(e){var i,o=(n.assets||[]).filter((function(n){return n.link})).reduce((function(n,e){return n[e.id]=e.link,n}),{}),a=(null===(i=n.link)||void 0===i?void 0:i.clicktrackers)||[],c=o[e],s=a;c&&(s=c.clicktrackers||[]),s.forEach((function(n){return r(n)}))}else{var d;((null===(d=n.link)||void 0===d?void 0:d.clicktrackers)||[]).forEach((function(n){return r(n)}))}}(t,null==n?void 0:n.assetId):function(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=e.runMarkup,r=void 0===t?function(n){return(0,u.$8)(n)}:t,i=e.fetchURL,o=void 0===i?u.hq:i,a=(n.eventtrackers||[]).filter((function(n){return n.event===I})).reduce((function(n,e){return k.hasOwnProperty(e.method)&&n[k[e.method]].push(e.url),n}),{img:[],js:[]}),c=a.img,s=a.js;n.imptrackers&&(c=c.concat(n.imptrackers));c.forEach((function(n){return o(n)})),s=s.map((function(n){return'