diff --git a/.bowerrc b/.bowerrc deleted file mode 100755 index a3ee2c7e39..0000000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "/dist" -} \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..62842de840 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,21 @@ + + +## 🏷 Type of documentation + +- [ ] new bid adapter +- [ ] update bid adapter +- [ ] new feature +- [ ] text edit only (wording, typos) +- [ ] bugfix (code examples) +- [ ] new examples + +## 📋 Checklist + +- [ ] Related pull requests in prebid.js or server are linked -> Paste link in this list or reference it on the PR itself +- [ ] For new adapters check [submitting your adapter docs](https://docs.prebid.org/dev-docs/bidder-adaptor.html#submitting-your-adapter) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..f72c668240 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: Continuous Integration + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + # based on https://github.com/DavidAnson/markdownlint-cli2-action/blob/main/.github/workflows/changed.yml + # runs markdown lint only for changed files + markdownlint: + name: run markdownlint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: tj-actions/changed-files@v41 + id: changed-files + with: + files: '**/*.md' + separator: "," + - uses: DavidAnson/markdownlint-cli2-action@v15 + if: steps.changed-files.outputs.any_changed == 'true' + with: + globs: "${{ steps.changed-files.outputs.all_changed_files }},!_includes" + separator: "," + config: '.markdownlint.json' diff --git a/.gitignore b/.gitignore index 79e892f73a..3c50b583af 100755 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ Gemfile.lock /dist/bootstrap /dist/jquery /.idea +/.vscode .DS_Store /vendor /.bundle @@ -12,3 +13,7 @@ Gemfile.lock # Files generated by `npm install` node_modules/ +!_sass/node_modules +/.vs/prebid.github.io/v17/.suo +/.vs/slnx.sqlite +/.vs diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000000..ef360a2bf6 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "default": true, + "MD009": false, + "MD013": false, + "MD022": false, + "MD024": false, + "MD025": false, + "MD033": false, + "MD036": false +} diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000000..49cdd668e1 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.6 diff --git a/.sass-cache/a8ae1fbf8fe3cf0ae44282e4f927a25624204c54/main.scssc b/.sass-cache/a8ae1fbf8fe3cf0ae44282e4f927a25624204c54/main.scssc deleted file mode 100644 index 6db4f74c3a..0000000000 Binary files a/.sass-cache/a8ae1fbf8fe3cf0ae44282e4f927a25624204c54/main.scssc and /dev/null differ diff --git a/Gemfile b/Gemfile index cdaf1cdfe5..4d0186505c 100755 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,4 @@ source 'https://rubygems.org' -gem 'github-pages', '>= 30' +gem 'github-pages', '>= 228' + +gem "webrick", "~> 1.7" diff --git a/README.md b/README.md index 71c4ec7fda..3825aa02c9 100755 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ +# docs.prebid.org source + This repository contains the source files for the Prebid.js documentation site at [Prebid.org](https://prebid.org). Please see the sections below for more information: -+ [Contributing](#contributing) -+ [License](#license) -+ [Prerequisites](#prerequisites) -+ [Running Jekyll Locally](#running-jekyll-locally) -+ [Building Assets](#building-assets) -+ [The Downloads Page](#the-downloads-page) -+ [Thanks](#thanks) +* [Contributing](#contributing) +* [License](#license) +* [Prerequisites](#prerequisites) +* [Running Jekyll Locally](#running-jekyll-locally) +* [Building Assets](#building-assets) +* [The Downloads Page](#the-downloads-page) +* [Thanks](#thanks) - + ## Contributing @@ -20,32 +22,39 @@ For smaller changes, such as fixing a typo or adding a new section to an existin For larger changes such as reorganizing the site and moving/removing content, you may want to open an issue so we can discuss the work beforehand. This is a good idea because: -+ We want to value your time, so you don't do unnecessary work -+ We want to value our users' time; we don't want to break links and bookmarks for users +* We want to value your time, so you don't do unnecessary work +* We want to value our users' time; we don't want to break links and bookmarks for users - + ## License All docs are under the license shown in the `LICENSE` file in this directory. - + ## Prerequisites The site is hosted on GitHub pages, and uses [Jekyll](https://jekyllrb.com/) to generate the HTML. Jekyll is written in the [Ruby](https://www.ruby-lang.org/en/) language. -1. follow the instructions at https://jekyllrb.com/docs/installation/ for your OS +1. follow the instructions at [jekyllrb.com/docs/installation/](https://jekyllrb.com/docs/installation/) for your OS 1. gem install github-pages 1. start Jekyll as described below -For CSS, the site uses Laravel Mix to build CSS from Sass (scss-flavored) source files. Under the hood Laravel Mix uses Webpack. +For CSS, the site uses Jekyll board tools to compile SCSS down to CSS. + +1. Install `boostrap` via `npm install` to make the build work +1. [Jekyll assets management](https://jekyllrb.com/docs/assets/) +1. [Jekyll SASS plugin](https://jekyllrb.com/docs/configuration/sass/) -1. follow the instructions at https://nodejs.dev to install Node.js for your OS -1. `npm ci` to install packages for building assets -1. build assets as described below +The markdown files are linted via [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli). VSCode supports the [.markdownlintignore](.markdownlintignore) file. +You may need to configure the disabled rules specified in [.markdownlint.json](.markdownlint.json) directly in your project settings. You can invoke linting in CLI via + +```bash +markdownlint --config .markdownlint.json --ignore-path .markdownlintignore "**/*.md" +``` - + ## Running Jekyll Locally @@ -53,13 +62,13 @@ Before submitting a pull request, you should run the site locally to make sure y To get started editing the site and seeing your changes, clone this repo and enter the following commands in your terminal: -- `cd path/to/prebid.github.io` -- `export JEKYLL_ENV=production` -- `bundle exec jekyll serve` +```bash +JEKYLL_ENV=production bundle exec jekyll serve --watch --incremental +``` You should see output that looks something like this: -``` +```bash Configuration file: /Users/me/git/prebid.github.io/_config.yml Source: /Users/me/git/prebid.github.io Destination: /Users/me/git/prebid.github.io/_site @@ -76,13 +85,13 @@ Configuration file: /Users/me/git/prebid.github.io/_config.yml Open the `Server address` URL in your browser, and you should see a locally running copy of the site. - + ## Building Assets -- `npm run dev` to build unminified CSS for development -- `npm run prod` to build minified CSS for production -- `npm run watch` to use [Browsersync](https://browsersync.io) to rebuild CSS on demand and reload the browser +* `npm run dev` to build unminified CSS for development +* `npm run prod` to build minified CSS for production +* `npm run watch` to use [Browsersync](https://browsersync.io) to rebuild CSS on demand and reload the browser ## The Downloads Page @@ -97,7 +106,11 @@ The Downloads page is generated from [the Markdown bidder adapter docs](https:// This means an adaptor is not available to download from Prebid.org as soon as the code gets merged into Prebid.js - it will be available after the next release (usually in a couple of weeks). - + + +## Liquid Templating + +* [jekyll - check for non empty](https://michaelcurrin.github.io/dev-cheatsheets/cheatsheets/jekyll/liquid/conditionals/non-empty.html) ## Thanks diff --git a/_assets/sass/abstracts/_breakpoints.scss b/_assets/sass/abstracts/_breakpoints.scss deleted file mode 100644 index dea3f2d4a2..0000000000 --- a/_assets/sass/abstracts/_breakpoints.scss +++ /dev/null @@ -1,50 +0,0 @@ -// Breakpoint Declarations -// -// Responsive breakpoint declarations -// Breakpoints are matched in Responsive VC Design Options Plugin -// http://actian/wp-admin/admin.php?page=bb_edo_all_devices -// -// Markup: -// 'phone-xs': 320px, -// 'phone-sm': 480px, -// 'phone': 767px, // Page Builder Default -// 'tablet': 960px, // Page Builder Default -// 'desktop-sm': 1200px, -// 'desktop': 1980px, -// -// Styleguide Layout.Breakpoints - -// Site width -$t-site-width-pixels: 1180; -$t-site-width: 1180px; -$t-site-width--padded: 1210px; - -$t-phone-xs: 320px; -$t-phone-sm: 480px; -$t-phone-md: 640px; -$t-phone: 767px; // Page Builder Default -$t-tablet: 992px; // Page Builder Default -$t-ipad-landscape: 1024px; -$t-desktop-aio: 1257px; // Site width + scrollbar (17px) + margins (60px). *** This is where the content starts to shrink. *** -$t-desktop: 1200px; // Page Builder Default -$t-fullscreen: 1903px; // 1920 - 17px scrollbar - -$t-screen-sm-min: $t-phone; -$t-screen-md-min: $t-tablet; -$t-screen-lg-min: $t-desktop; - -$t-screen-xs-max: $t-screen-sm-min - 1; -$t-screen-sm-max: $t-screen-md-min - 1; -$t-screen-md-max: $t-screen-lg-min - 1; - -$breakpoints: ( - 'phone-xs': $t-phone-xs, - 'phone-sm': $t-phone-sm, - 'phone-md': $t-phone-md, - 'phone': $t-phone, - 'tablet': $t-tablet, - 'ipad-landscape': $t-ipad-landscape, - 'site-width': $t-site-width, - 'desktop': $t-desktop, - 'fullscreen': $t-fullscreen, -) !default; diff --git a/_assets/sass/abstracts/_mixins.scss b/_assets/sass/abstracts/_mixins.scss deleted file mode 100644 index 6ba4b12a23..0000000000 --- a/_assets/sass/abstracts/_mixins.scss +++ /dev/null @@ -1,241 +0,0 @@ -// Sass Mixins -// -// Styleguide Sass.Mixins - -// Font Mixins -// -// Styleguide Sass.Mixins.Fonts - -// primary-font-loaded -// -// Selector wrapper to apply styles only when the primary font is loaded. -// -// Compatible in all browsers -// -// Weight: 10 -// -// Styleguide Sass.Mixins.Fonts.PrimaryFontLoaded -@mixin primary-font-loaded { - @at-root .html__font-loaded--primary #{&} { - @content; - } -} - -// font-weight-light -// -// Light font weight with !important option -// -// Compatible in all browsers -// -// $important - boolean - whether to output !important or not -// -// Weight: 100 -// -// Styleguide Sass.Mixins.Fonts.Font Weight Light -@mixin font-weight-light($important: false) { - @if ($important) { - font-weight: 300 !important; - } @else { - font-weight: 300; - } -} - -// font-weight-normal -// -// Normal font weight with !important option -// -// Compatible in all browsers -// -// $important - boolean - whether to output !important or not -// -// Weight: 110 -// -// Styleguide Sass.Mixins.Fonts.Font Weight Normal -@mixin font-weight-normal($important: false) { - @if ($important) { - font-weight: 400 !important; - } @else { - font-weight: 400; - } -} - -// font-weight-semibold -// -// Semibold font weight with !important option -// -// Compatible in all browsers -// -// $important - boolean - whether to output !important or not -// -// Weight: 130 -// -// Styleguide Sass.Mixins.Fonts.Font Weight Semibold -@mixin font-weight-semibold($important: false) { - @if ($important) { - font-weight: 600 !important; - } @else { - font-weight: 600; - } -} - -// font-weight-medium -// -// Semibold font weight with !important option -// -// Compatible in all browsers -// -// $important - boolean - whether to output !important or not -// -// Weight: 130 -// -// Styleguide Sass.Mixins.Fonts.Font Weight Semibold -@mixin font-weight-medium($important: false) { - @if ($important) { - font-weight: 500 !important; - } @else { - font-weight: 500; - } -} - -@mixin font-weight-bold($important: false) { - @if ($important) { - font-weight: 700 !important; - } @else { - font-weight: 700; - } -} -// Detect Mixins -// -// Mixins that can be used to wrap styles and apply them conditionally on -// browser or feature detection. -// -// Styleguide Sass.Mixins.Detect - -// js-enabled -// -// Selector wrapper to apply styles only when JS is available. -// -// Styleguide Sass.Mixins.Detect.JSEnabled -@mixin js--enabled() { - @at-root .html--js #{&} { - @content; - } -} - -// js-disabled -// -// Selector wrapper to apply styles only when JS is not available. -// -// Styleguide Sass.Mixins.Detect.JSEnabled -@mixin js--disabled() { - @at-root .html--no-js #{&} { - @content; - } -} - -// ie10-and-up -// -// Selector wrapper to apply styles only when the browser is IE10 or IE11. -// Using this mixin in Sass lets us make the intent clear and separate the -// mechanics of browser detection. -// -// Needs to be tested on Edge. -// -// Styleguide Sass.Mixins.Detect.JSEnabled -@mixin ie10-and-up { - @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { - @content - } -} - -// linear-gradient -// -// Linear Gradient Mixin supporting color, stops & angle with legacy support -// based on https://www.sitepoint.com/building-linear-gradient-mixin-sass/ -// -// Styleguide Sass.Mixins.Linear Gradient - -/// Mixin printing a linear-gradient -/// as well as a plain color fallback -/// and the `-webkit-` prefixed declaration -/// @access public -/// @param {String | List | Angle} $direction - Linear gradient direction -/// @param {Arglist} $color-stops - List of color-stops composing the gradient -@mixin linear-gradient-bg($direction, $color-stops...) { - @if is-direction($direction) == false { - $color-stops: ($direction, $color-stops); - $direction: 180deg; - } - - background: nth(nth($color-stops, 1), 1); - background: -webkit-linear-gradient(legacy-direction($direction), $color-stops); - background: linear-gradient($direction, $color-stops); -} - - -@mixin flex-center-all { - display: flex !important; - align-content: center !important; - align-items: center !important; - justify-content: center !important; -} - -@mixin debug { - border: 1px solid red !important; -} - -@mixin minimized-pillar { - @at-root .c-ecosystem-pillar.is-minimized & { - @content; - } -} - -@mixin active-pillar($sel: '') { - @at-root .c-ecosystem-pillar.is-active#{$sel} & { - @content; - } -} - -@mixin blog-meta { - @extend %u-padding-bottom--xs; - font-size: 16px; - - a { - $lt-color: #f7822a; - @include font-weight-bold; - color: $lt-color; - } - - .entry-date { - display: inline-block; - - @include media('>phone') { - &::before { - $lt-color: #ced4dd; - display: inline-block; - margin-right: 4px; - color: $lt-color; - content: '|'; - } - } - } -} - -@mixin checkmark-list { - margin-left: 0; - list-style: none; - - li { - position: relative; - margin: 0 0 10px 12px; - padding-left: 45px; - - &::before { - @include position(absolute, 4px null null 0); - @include size(23px, 17px); - display: block; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='23px' height='17px' viewBox='0 0 23 17'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='checkmark' fill='%23FF6F00' fill-rule='nonzero'%3E%3Cpolygon points='8.086 17 0 8.718 2.033 6.777 8.086 12.764 20.321 0.442 22.333 2.752'%3E%3C/polygon%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); - content: ''; - } - } -} diff --git a/_assets/sass/base/_base.scss b/_assets/sass/base/_base.scss deleted file mode 100644 index e2718bac06..0000000000 --- a/_assets/sass/base/_base.scss +++ /dev/null @@ -1,3 +0,0 @@ -img { - max-width: 100%; -} diff --git a/_assets/sass/components/_search.scss b/_assets/sass/components/_search.scss deleted file mode 100644 index 0909593a1b..0000000000 --- a/_assets/sass/components/_search.scss +++ /dev/null @@ -1,44 +0,0 @@ -.algolia-autocomplete { - .algolia-docsearch-suggestion--category-header { - display: none !important; - } -} - -.c-search { - position: relative; - - @include media('<=990px') { - float: left; - } - - &::after { - @include position(absolute, 50% 10px null null); - @include size(20px); - transform: translateY(-50%); - background: url(/assets/images/icons/search-icon2.svg); - background-size: cover; - content: ''; - } - - input[type="search"] { - @include padding(null 8px); - border: 1px solid rgba(0, 0, 0, 0.125); - max-width: 120px; - transition: max-width 200ms ease-in-out; - - &:hover, &:focus { - max-width: 200px; - outline: none; - } - - /* clears the ‘X’ from Internet Explorer */ - &::-ms-clear { display: none; width : 0; height: 0; } - &::-ms-reveal { display: none; width : 0; height: 0; } - - /* clears the ‘X’ from Chrome */ - &::-webkit-search-decoration, - &::-webkit-search-cancel-button, - &::-webkit-search-results-button, - &::-webkit-search-results-decoration { display: none; } - } -} diff --git a/_assets/sass/main.scss b/_assets/sass/main.scss deleted file mode 100644 index ad4090dbd6..0000000000 --- a/_assets/sass/main.scss +++ /dev/null @@ -1,43 +0,0 @@ -// General layout is according to https://sass-guidelin.es/#the-7-1-pattern - -// Abstracts should not output any CSS, they just help setup -// the environment - -// Abstracts -@import 'abstracts/colors'; -@import 'abstracts/tokens'; -@import 'abstracts/bootstrap-variables'; -@import 'abstracts/functions'; -@import 'abstracts/mixins'; -@import 'abstracts/breakpoints'; - -// Vendor Includes -@import 'vendor/bootstrap'; -@import 'vendor/bourbon'; -@import 'vendor/include-media'; -@import 'vendor/awesomplete'; - -// Base Styles -@import 'base/base'; -@import 'base/typography'; - -// Core Layout -@import 'layout/header'; -@import 'layout/sidebar'; -@import 'layout/footer'; - -// Components -@import 'components/card'; -@import 'components/banner'; -@import 'components/buttons'; -@import 'components/pb'; -@import 'components/social-media'; -@import 'components/table'; -@import 'components/download-form'; -@import 'components/autocomplete-filter'; -@import 'components/bidder-list'; -@import 'components/search'; - -// Pages -@import 'pages/home'; -@import 'pages/404'; diff --git a/_assets/sass/pages/_404.scss b/_assets/sass/pages/_404.scss deleted file mode 100644 index 50e7b273e0..0000000000 --- a/_assets/sass/pages/_404.scss +++ /dev/null @@ -1,13 +0,0 @@ -.error404 { - width:100%; - height: 100%; - text-align: center; -} - -.error404 h1 { - color: #FF0000; - font-size: 60px; - font-weight: bold; -} - - diff --git a/_assets/sass/vendor/_bootstrap.scss b/_assets/sass/vendor/_bootstrap.scss deleted file mode 100644 index 0d44b0260c..0000000000 --- a/_assets/sass/vendor/_bootstrap.scss +++ /dev/null @@ -1,17 +0,0 @@ -@import "../../../node_modules/bootstrap/scss/functions"; -@import "../../../node_modules/bootstrap/scss/variables"; -@import "../../../node_modules/bootstrap/scss/mixins"; - -@import "../../../node_modules/bootstrap/scss/reboot"; -@import "../../../node_modules/bootstrap/scss/grid"; -@import "../../../node_modules/bootstrap/scss/buttons"; -@import "../../../node_modules/bootstrap/scss/transitions"; -@import "../../../node_modules/bootstrap/scss/dropdown"; -@import "../../../node_modules/bootstrap/scss/navbar"; -@import "../../../node_modules/bootstrap/scss/nav"; -@import "../../../node_modules/bootstrap/scss/tables"; -@import "../../../node_modules/bootstrap/scss/card"; -@import "../../../node_modules/bootstrap/scss/code"; -@import "../../../node_modules/bootstrap/scss/alert"; -@import "../../../node_modules/bootstrap/scss/modal"; -@import "../../../node_modules/bootstrap/scss/utilities"; diff --git a/_assets/sass/vendor/_bourbon.scss b/_assets/sass/vendor/_bourbon.scss deleted file mode 100644 index 7b679df018..0000000000 --- a/_assets/sass/vendor/_bourbon.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import '../../node_modules/bourbon/core/bourbon'; - diff --git a/_assets/sass/vendor/_include-media.scss b/_assets/sass/vendor/_include-media.scss deleted file mode 100644 index 51a8d7f31f..0000000000 --- a/_assets/sass/vendor/_include-media.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import '../../node_modules/include-media/dist/include-media'; - diff --git a/_config.yml b/_config.yml index 8f03e0bebe..28619e1870 100755 --- a/_config.yml +++ b/_config.yml @@ -1,5 +1,7 @@ # name of the software name: Prebid +# GitHub Metadata: site.name is set in _config.yml, but many plugins and themes expect site.title to be used instead +title: Prebid # current version of the software version: 1.0.0 # licence of the software @@ -85,7 +87,8 @@ collections: port: 8080 -exclude: ['README.md', 'LICENSE', 'bower.json', 'Gemfile.lock', 'Gemfile', 'vendor', 'node_modules', '_assets', 'mix-manifest.json', 'webpack.mix.js', 'find-ungrouped-bidders.sh' ] +exclude: ['README.md', 'LICENSE', 'Gemfile.lock', 'Gemfile', 'vendor', 'find-ungrouped-bidders.sh' ] +include: ['node_modules'] keep_files: - assets/css/main-bundle.css diff --git a/_data/dropdown_v2.yml b/_data/dropdown_v2.yml index 268f618bad..9e8f7102dc 100644 --- a/_data/dropdown_v2.yml +++ b/_data/dropdown_v2.yml @@ -244,15 +244,6 @@ isHeader: 0 isSubSectionStart: 0 - - subsectionId: 2 - sectionId: 2 - sectionName: Support - title: Training Videos - link: /videos/index.html - needsDivider: 0 - isHeader: 0 - isSubSectionStart: 0 - - subsectionId: 2 sectionId: 2 sectionName: Support @@ -312,7 +303,7 @@ sectionId: 3 sectionName: Download title: Prebid Mobile - link: /prebid-mobile/download.html + link: /prebid-mobile/prebid-mobile-download.html needsDivider: 0 isHeader: 0 isSubSectionStart: 1 diff --git a/_data/partners.yml b/_data/partners.yml index 8a606fc372..f7cbc7c227 100644 --- a/_data/partners.yml +++ b/_data/partners.yml @@ -2,33 +2,33 @@ link: https://www.indexexchange.com/ imgURL: /assets/images/partners/leader/IX-logo.png type: leader - + - company: Magnite link: https://www.magnite.com/ imgURL: /assets/images/partners/leader/Magnite_logo.png type: leader - -- company: MediaMath + +- company: MediaMath link: https://www.mediamath.com/ imgURL: /assets/images/partners/leader/MediaMath-wordmark.png type: leader - -- company: OpenX + +- company: OpenX link: https://www.openx.com/ imgURL: /assets/images/partners/leader/openx.png type: leader - -- company: Pubmatic + +- company: Pubmatic link: https://pubmatic.com/products/header-bidding/ imgURL: /assets/images/partners/leader/pubmatic.png type: leader -- company: SpotX +- company: SpotX link: https://spotx.tv imgURL: /assets/images/partners/leader/spotx_logo.png type: leader -- company: theTradeDesk +- company: theTradeDesk link: https://www.thetradedesk.com/ imgURL: /assets/images/partners/leader/TTD_logo.png type: leader @@ -37,38 +37,38 @@ link: https://www.xandr.com/platform/ imgURL: /assets/images/partners/founders/xandr.png type: leader - + - company: Beachfront Media link: https://www.beachfront.com/ imgURL: /assets/images/partners/tech/beachfront_logo.png type: technology - -- company: Conversant - link: https://www.conversantmedia.com/ - imgURL: /assets/images/partners/tech/conversant_logo.png - type: technology - -- company: Criteo + +- company: Criteo link: https://www.criteo.com/for-publishers/products/criteo-direct-bidder/ imgURL: /assets/images/partners/tech/criteo.png type: technology - -- company: Datablocks + +- company: Datablocks link: https://datablocks.net/ imgURL: /assets/images/partners/tech/datablocks_logo.png type: technology - -- company: LiveRamp + +- company: Epsilon + link: https://www.epsilon.com/ + imgURL: /assets/images/partners/tech/epsilon_logo.png + type: technology + +- company: LiveRamp link: https://liveramp.com/ imgURL: /assets/images/partners/tech/LiveRamp-Logo.png type: technology - -- company: Marfeel + +- company: Marfeel link: https://www.marfeel.com/ imgURL: /assets/images/partners/tech/marfeel.png type: technology - -- company: PubNative + +- company: PubNative link: https://pubnative.net/ imgURL: /assets/images/partners/tech/Pubnative-RGB-Logo.png type: technology @@ -78,27 +78,27 @@ imgURL: /assets/images/partners/tech/rakuten_logo.png type: technology -- company: StreamAMP +- company: StreamAMP link: https://streamamp.com/ imgURL: /assets/images/partners/tech/StreamAMP_logo.png type: technology -- company: Tapad +- company: Tapad link: https://tapad.com/ imgURL: /assets/images/partners/tech/tapad_logo.png type: technology -- company: Verizon Media +- company: Verizon Media link: https://www.verizonmedia.com/advertising imgURL: /assets/images/partners/tech/verizon_logo.png type: technology - -- company: Advance Local Media + +- company: Advance Local Media link: https://advancelocal.com imgURL: /assets/images/partners/publisher/advancelocal_logo.png type: publisher -- company: CafeMedia +- company: CafeMedia link: https://www.cafemedia.com/ imgURL: /assets/images/partners/publisher/cafemedia.png type: publisher @@ -107,28 +107,28 @@ link: https://www.chegg.com/ imgURL: /assets/images/partners/publisher/chegg.png type: publisher - + - company: diDNA link: https://didna.io/ imgURL: /assets/images/partners/publisher/didna-logo.png type: publisher - + - company: Freestar link: https://freestar.com/ imgURL: /assets/images/partners/publisher/freestar-logo.png type: publisher - + - company: Glewed TV link: https://www.glewed.tv/ imgURL: /assets/images/partners/publisher/glewed_logo.png type: publisher - + - company: Hive Media link: https://www.hivemedia.com imgURL: /assets/images/partners/publisher/Hive-Media-Group-Stacked-Color-web.png type: publisher - -- company: Insider, Inc. + +- company: Insider, Inc. link: https://www.insider-inc.com/ imgURL: /assets/images/partners/publisher/Insider_Inc_logo.png type: publisher @@ -163,12 +163,7 @@ imgURL: /assets/images/partners/publisher/SHE_Media_Logo.png type: publisher -- company: Sortable - link: https://www.sortable.com/ - imgURL: /assets/images/partners/publisher/sortable.png - type: publisher - -- company: Havas +- company: Havas link: https://havasmedia.com/ imgURL: /assets/images/partners/buyer/Havas_Media_Logo.png type: buyer @@ -178,11 +173,6 @@ imgURL: /assets/images/partners/community/Adform-Logo.png type: community -- company: Adomik - link: https://adomik.com/ - imgURL: /assets/images/partners/community/Adomik-logo.png - type: community - - company: Adtelligent link: https://adtelligent.com/ type: community diff --git a/_data/sidebar.yml b/_data/sidebar.yml index 4d7f4bb534..8dd030909a 100644 --- a/_data/sidebar.yml +++ b/_data/sidebar.yml @@ -20,7 +20,15 @@ subgroup: 0 - sbSecId: 0 - title: What is Prebid? + title: Intro to Header Bidding + link: /overview/intro-to-header-bidding.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Intro to Prebid link: /overview/intro.html isHeader: 0 isSectionHeader: 0 @@ -42,6 +50,14 @@ isSectionHeader: 0 subgroup: 0 +- sbSecId: 0 + title: Glossary + link: /overview/glossary.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + - sbSecId: 0 title: Codes of Conduct link: @@ -77,7 +93,7 @@ - sbSecId: 0 title: Contributing - link: /contributing/contribute.html + link: /policies/contribute.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -85,7 +101,7 @@ - sbSecId: 0 title: Prebid.org IP Policy - link: /overview/ip-policy.html + link: /policies/ip-policy.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -93,19 +109,26 @@ - sbSecId: 0 title: Privacy Policy - link: /privacy.html + link: /policies/privacy.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - sbSecId: 0 - title: Cookies - link: /cookies.html + title: Antitrust Policy + link: /policies/antitrust.html isHeader: 0 isSectionHeader: 0 + sectionTitle: subgroup: 2 +- sbSecId: 0 + title: Cookies + link: /policies/cookies.html + isHeader: 0 + isSectionHeader: 0 + subgroup: 2 #--------------Prebid.js--------------| @@ -120,7 +143,7 @@ sbCollapseId: prebidjs - sbSecId: 1 - title: Developer Quick Start + title: General link: isHeader: 1 headerId: devquickstart @@ -138,13 +161,29 @@ subgroup: 0 - sbSecId: 1 - title: Getting Started + title: Getting Started for Developers link: /dev-docs/getting-started.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 0 +- sbSecId: 1 + title: Basic Impression Flow + link: /prebid/prebidjs-flow-video.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 1 + title: Prebid.js Components + link: /prebid/prebidjs-components-video.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + - sbSecId: 1 title: Consent Management Best Practices link: /dev-docs/cmp-best-practices.html @@ -202,6 +241,14 @@ sectionTitle: subgroup: 1 +- sbSecId: 1 + title: Running without an ad server + link: /dev-docs/examples/no-adserver.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + - sbSecId: 1 title: Legacy Browser Example link: /dev-docs/examples/legacy-browser-example.html @@ -211,7 +258,7 @@ subgroup: 1 - sbSecId: 1 - title: Using Prebid.js with AppNexus Publisher Ad Server + title: Using Prebid.js with Microsoft Monetize Ad Server link: /dev-docs/examples/use-prebid-with-appnexus-ad-server.html isHeader: 0 isSectionHeader: 0 @@ -242,7 +289,7 @@ isSectionHeader: 0 sectionTitle: subgroup: 1 - + - sbSecId: 1 title: Meta Bid Filtering link: /dev-docs/examples/meta-bid-filtering.html @@ -252,6 +299,15 @@ sectionTitle: subgroup: 1 +- sbSecId: 1 + title: Synchronize Transaction Ids With Another Library + link: /dev-docs/examples/sync-tid.html + Item: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + - sbSecId: 1 title: Troubleshooting link: @@ -311,32 +367,32 @@ subgroup: 3 - sbSecId: 1 - title: Ad Unit Reference - link: /dev-docs/adunit-reference.html + title: Internal API Reference + link: /dev-docs/internal-api-reference.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 1 - title: Bidder Params - link: /dev-docs/bidders.html + title: Ad Unit Reference + link: /dev-docs/adunit-reference.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 1 - title: Prebid.js Releases - link: /prebid/prebidjsReleases.html + title: Bidder Params + link: /dev-docs/bidders.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 1 - title: Prebid 1.0 Publisher API Changes - link: /dev-docs/prebid-1.0-API.html + title: Prebid.js Release Notes + link: /dev-docs/release-notes.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -359,6 +415,8 @@ sectionTitle: subgroup: 4 + + - sbSecId: 1 title: How to Add an Analytics Adapter link: /dev-docs/integrate-with-the-prebid-analytics-api.html @@ -375,6 +433,22 @@ sectionTitle: subgroup: 4 +- sbSecId: 1 + title: How to Add a Prebid.js Video submodule + link: /dev-docs/add-video-submodule.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 1 + title: Vendor Billing in Prebid.js + link: /dev-docs/vendor-billing.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + - sbSecId: 1 title: Prebid.js Modules link: @@ -523,9 +597,17 @@ sectionTitle: subgroup: 8 +- sbSecId: 1 + title: Activity Controls + link: /dev-docs/activity-controls.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + - sbSecId: 1 title: Interstitial Ads - link: /features/interstitialAds.html + link: /features/InterstitialAds.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -571,7 +653,7 @@ - sbSecId: 2 title: Getting Started With Prebid Mobile - link: /prebid-mobile/prebid-mobile-pbs.html + link: /prebid-mobile/prebid-mobile-getting-started.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -587,7 +669,7 @@ - sbSecId: 2 title: Privacy Regulation - link: /prebid-mobile/privacy-regulation.html + link: /prebid-mobile/prebid-mobile-privacy-regulation.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -595,151 +677,27 @@ - sbSecId: 2 title: Download - link: /prebid-mobile/download.html + link: /prebid-mobile/prebid-mobile-download.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 0 - -- sbSecId: 2 - title: Rendering API (Open Beta) - link: - isHeader: 1 - headerId: rendering - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Rendering Overview - link: /prebid-mobile/modules/rendering/modules-rendering.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: "iOS" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: SDK Integration - link: /prebid-mobile/modules/rendering/ios-sdk-Integration.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Pure In-App Bidding - link: /prebid-mobile/modules/rendering/ios-sdk-integration-pb.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Integration with GAM - link: /prebid-mobile/modules/rendering/ios-sdk-integration-gam.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Integration with MoPub - link: /prebid-mobile/modules/rendering/ios-sdk-integration-mopub.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Targeting - link: /prebid-mobile/modules/rendering/ios-sdk-parameters.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - sbSecId: 2 - title: "Android" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: SDK Integration - link: /prebid-mobile/modules/rendering/android-sdk-integration.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Pure In-app Bidding - link: /prebid-mobile/modules/rendering/android-sdk-integration-pb.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Integration with GAM - link: /prebid-mobile/modules/rendering/android-sdk-integration-gam.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Integration with MoPub - link: /prebid-mobile/modules/rendering/android-sdk-integration-mopub.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Targeting - link: /prebid-mobile/modules/rendering/android-sdk-parameters.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: "Ad Server" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 2 - title: Rendering Order - GAM - link: /prebid-mobile/modules/rendering/rendering-gam-line-item-setup.html + title: For Contributors + link: /prebid-mobile/prebid-mobile-for-contributors.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 1 + subgroup: 0 - sbSecId: 2 - title: Rendering Order - MoPub - link: /prebid-mobile/modules/rendering/rendering-mopub-line-item-setup.html + title: Prebid Mobile FAQ + link: /faq/prebid-mobile-faq.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 1 + subgroup: 0 # - sbSecId: 2 # title: Modules @@ -767,7 +725,7 @@ # hasSubMenus: 1 # sectionTitle: # subgroup: 1 - + - sbSecId: 2 title: For iOS link: @@ -778,7 +736,7 @@ subgroup: 2 - sbSecId: 2 - title: Code Integration + title: SDK Integration link: /prebid-mobile/pbm-api/ios/code-integration-ios.html isHeader: 0 isSectionHeader: 0 @@ -786,80 +744,40 @@ subgroup: 2 - sbSecId: 2 - title: iOS Mobile API - link: /prebid-mobile/pbm-api/ios/pbm-api-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 2 - title: Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-adunit-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 2 - title: Banner Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 2 - title: Banner Interstitial Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 2 - title: Native Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 2 - title: In App Native Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-native-inapp-ios.html + title: GAM Original Integration + link: /prebid-mobile/pbm-api/ios/ios-sdk-integration-gam-original-api.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - + - sbSecId: 2 - title: Video Outstream Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.html + title: Custom or No mediation + link: /prebid-mobile/modules/rendering/ios-sdk-integration-pb.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - sbSecId: 2 - title: Video Instream Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-video-instream-ios.html + title: AdMob + link: /prebid-mobile/modules/rendering/ios-sdk-integration-admob.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - sbSecId: 2 - title: Video interstitial Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.html + title: AppLovin MAX + link: /prebid-mobile/modules/rendering/ios-sdk-integration-max.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - + - sbSecId: 2 - title: Video Rewarded Ad Unit - link: /prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.html + title: GAM Rendering Integration + link: /prebid-mobile/modules/rendering/ios-sdk-integration-gam.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -872,25 +790,17 @@ isSectionHeader: 0 sectionTitle: subgroup: 2 - -- sbSecId: 2 - title: Result Codes - link: /prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - + - sbSecId: 2 - title: Prebid Mobile Object - link: /prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html + title: Ad Experience Controls + link: /prebid-mobile/modules/rendering/combined-ad-experience-controls.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 2 - sbSecId: 2 - title: Prebid Utilities + title: Prebid Utility Functions link: /prebid-mobile/pbm-api/ios/pbm-util-ios.html isHeader: 0 isSectionHeader: 0 @@ -898,7 +808,7 @@ subgroup: 2 - sbSecId: 2 - title: For Android + title: "For Android" link: isHeader: 1 headerId: android @@ -907,7 +817,7 @@ subgroup: 3 - sbSecId: 2 - title: Code Integration + title: SDK Integration link: /prebid-mobile/pbm-api/android/code-integration-android.html isHeader: 0 isSectionHeader: 0 @@ -915,230 +825,188 @@ subgroup: 3 - sbSecId: 2 - title: Android Mobile API - link: /prebid-mobile/pbm-api/android/pbm-api-android.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 3 - -- sbSecId: 2 - title: Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-adunit-android.html + title: GAM Original Integration + link: /prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - + - sbSecId: 2 - title: Banner Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-banneradunit-android.html + title: Custom or No mediation + link: /prebid-mobile/modules/rendering/android-sdk-integration-pb.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 2 - title: Native Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-nativeadunit-android.html + title: AdMob + link: /prebid-mobile/modules/rendering/android-sdk-integration-admob.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 2 - title: In App Native Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-native-inapp-android.html + title: AppLovin MAX + link: /prebid-mobile/modules/rendering/android-sdk-integration-max.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - + - sbSecId: 2 - title: Banner Interstitial Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-bannerinterstitialadunit-android.html + title: GAM Rendering Integration + link: /prebid-mobile/modules/rendering/android-sdk-integration-gam.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 2 - title: Video Outstream Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-videooutstreamadunit-android.html + title: Targeting Parameters + link: /prebid-mobile/pbm-api/android/pbm-targeting-params-android.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - + - sbSecId: 2 - title: Video Intream Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-video-instream-android.html + title: Ad Experience Controls + link: /prebid-mobile/modules/rendering/combined-ad-experience-controls.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 2 - title: Video Interstitial Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-videointerstitialadunit-android.html + title: Prebid Utility Functions + link: /prebid-mobile/pbm-api/android/pbm-util-android.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 - sbSecId: 2 - title: Video Rewarded Ad Unit - link: /prebid-mobile/pbm-api/android/pbm-video-rewarded-adunit-android.html + title: Prebid Plugin Renderer + link: /prebid-mobile/pbm-api/android/pbm-plugin-renderer.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 3 +#--------------Ad Ops--------------| -- sbSecId: 2 - title: Targeting Parameters - link: /prebid-mobile/pbm-api/android/pbm-targeting-params-android.html +- sbSecId: 3 + title: + link: isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 3 - -- sbSecId: 2 - title: Result Codes - link: /prebid-mobile/pbm-api/android/pbm-api-result-codes-android.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 3 - -- sbSecId: 2 - title: Prebid Mobile Object - link: /prebid-mobile/pbm-api/android/prebidmobile-object-android.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 3 - -- sbSecId: 2 - title: Prebid Utility Functions - link: /prebid-mobile/pbm-api/android/pbm-util-android.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 3 + isSectionHeader: 1 + sectionTitle: Ad Ops + sectionId: ad-ops + subgroup: 1000 + sbCollapseId: ad-ops -- sbSecId: 2 - title: For Contributors +- sbSecId: 3 + title: General link: isHeader: 1 - headerId: forcontributors - isSectionHeader: 0 + headerId: adopsoverview + isSectionHeader: sectionTitle: - subgroup: 4 + subgroup: 0 -- sbSecId: 2 - title: Add an Ad Server Adapter - link: /prebid-mobile/add-an-ad-server-adapter.html +- sbSecId: 3 + title: 'Ad Ops Overview' + link: /adops/before-you-start.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 4 + subgroup: 0 -- sbSecId: 2 - title: Legacy API +- sbSecId: 3 + title: Ad Ops Essentials link: isHeader: 1 - headerId: legacyapi + headerId: adopsess isSectionHeader: 0 - sectionTitle: - subgroup: 5 - -- sbSecId: 2 - title: Code Integration - iOS - link: /prebid-mobile/legacy/ios/code-integration-ios.html + sectionTitle: Ad Ops Essentials + subgroup: 1 +- sbSecId: 3 + title: "Planning" + link: isHeader: 0 isSectionHeader: 0 + isCatHeader: 1 sectionTitle: - subgroup: 5 + subgroup: 1 -- sbSecId: 2 - title: Targeting Parameters - iOS - link: /prebid-mobile/legacy/ios/targeting-params-ios.html +- sbSecId: 3 + title: 'Planning Guide' + link: /adops/adops-planning-guide.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 5 + subgroup: 1 -- sbSecId: 2 - title: Logging and Troubleshooting - iOS - link: /prebid-mobile/legacy/ios/logging-troubleshooting-ios.html +- sbSecId: 3 + title: 'Ad Server Integration' + link: /adops/ad-server-integration.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 5 + subgroup: 1 -- sbSecId: 2 - title: Code Integration - Android - link: /prebid-mobile/legacy/android/code-integration-android.html +- sbSecId: 3 + title: 'Send All Bids vs Top Price' + link: /adops/send-all-vs-top-price.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 5 + subgroup: 1 -- sbSecId: 2 - title: Targeting Parameters - Android - link: /prebid-mobile/legacy/android/targeting-params-android.html +- sbSecId: 3 + title: 'Line Item Creation' + link: /adops/line-item-creation.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 5 + subgroup: 1 -- sbSecId: 2 - title: Logging and Troubleshooting - Android - link: /prebid-mobile/legacy/android/logging-troubleshooting-android.html +- sbSecId: 3 + title: 'Price Granularity' + link: /adops/price-granularity.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 5 - -#--------------Ad Ops--------------| + subgroup: 1 - sbSecId: 3 - title: - link: + title: 'Creative Considerations' + link: /adops/creative-considerations.html isHeader: 0 - isSectionHeader: 1 - sectionTitle: Ad Ops - sectionId: ad-ops - subgroup: 1000 - sbCollapseId: ad-ops - -- sbSecId: 3 - title: Ad Ops Tutorials - link: - isHeader: 1 - headerId: adopstuts isSectionHeader: 0 - sectionTitle: Ad Ops - subgroup: 0 + sectionTitle: + subgroup: 1 - sbSecId: 3 - title: "Prebid" + title: "Ad Ops Information" link: isHeader: 0 isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 1 - sbSecId: 3 - title: 'AdOps View of Prebid' - link: /adops/before-you-start.html + title: 'Key Values' + link: /adops/key-values.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 1 - sbSecId: 3 title: 'Prebid Universal Creative' @@ -1146,24 +1014,24 @@ isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 1 - sbSecId: 3 - title: 'Send All Bids' - link: /adops/send-all-bids-adops.html + title: 'Deals in Prebid' + link: /adops/deals.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 1 - sbSecId: 3 - title: 'Enable Deals' - link: /adops/deals.html - Item: 1 - isHeader: 0 - isSectionHeader: 0 + title: Ad Server Setup + link: + isHeader: 1 + headerId: adopssetup + isSectionHeader: sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 title: "Google Ad Manager" @@ -1172,205 +1040,182 @@ isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Guide to Prebid in Ad Manager' - link: /adops/step-by-step.html + title: 'Header Bidding Trafficking Setup' + link: /adops/gam-hbt-step-by-step.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up for AMP in GAM' - link: /adops/setting-up-prebid-for-amp-in-dfp.html + title: 'Line Item Setup' + link: /adops/step-by-step.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Multi-Format in GAM' - link: /adops/setting-up-prebid-multi-format-in-dfp.html + title: 'Creative Setup: Banner/Outstream/AMP' + link: /adops/gam-creative-banner-sbs.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Native in GAM' + title: 'Creative Setup: Native' link: /adops/gam-native.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Video in GAM' + title: 'Creative Setup: Video' link: /adops/setting-up-prebid-video-in-dfp.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Long-Form Video in GAM' - link: /adops/setting-up-prebid-ott-video-in-gam.html + title: "Setting up Order for Mobile Rendering API" + link: /adops/mobile-rendering-gam-line-item-setup.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: "Mobile" + title: "Freewheel" link: isHeader: 0 isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 - -- sbSecId: 3 - title: Setup Line Items For MoPub - link: /prebid-mobile/adops-line-item-setup-mopub.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Setup Rewarded Video Line Items For MoPub - link: /prebid-mobile/adops-setup-rewarded-video-mopub.html + title: 'Setting up Long-Form Video' + link: /adops/setting-up-prebid-video-in-freewheel.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Setup Full Screen Video Line Items For MoPub - link: /prebid-mobile/adops-setup-full-screen-video-mopub.html + title: "Microsoft Monetize Publisher" + link: isHeader: 0 isSectionHeader: 0 + isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Setup Native Ads - link: /prebid-mobile/adops-native-setup.html + title: 'Setting up Prebid' + link: /adops/setting-up-prebid-with-the-appnexus-ad-server.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Price Granularity - link: /prebid-mobile/adops-price-granularity.html + title: "Smart Ad Server" + link: isHeader: 0 isSectionHeader: 0 + isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Dr. Prebid Validation App - link: /prebid-mobile/dr-prebid.html + title: 'Setting up Prebid' + link: /adops/setting-up-prebidjs-with-Smart-Ad-Server.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 - + subgroup: 2 + - sbSecId: 3 - title: "Freewheel" + title: "AdMob" link: isHeader: 0 isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 - + subgroup: 2 + - sbSecId: 3 - title: 'Setting up Long-Form Video' - link: /adops/setting-up-prebid-video-in-freewheel.html + title: "Mediation Group - AdMob" + link: /adops/mobile-rendering-admob-line-item-setup.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 - + subgroup: 2 + - sbSecId: 3 - title: "AppNexus Publisher" + title: "AppLovin MAX" link: isHeader: 0 isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Prebid' - link: /adops/setting-up-prebid-with-the-appnexus-ad-server.html + title: "Custom Network - MAX" + link: /adops/mobile-rendering-max-line-item-setup.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: "Smart Ad Server" + title: "Other Ad Servers" link: - isHeader: 0 isSectionHeader: 0 isCatHeader: 1 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: 'Setting up Prebid' - link: /adops/setting-up-prebidjs-with-Smart-Ad-Server.html + title: 'General Ad Server Setup' + link: /adops/adops-general-sbs.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 2 - sbSecId: 3 - title: Studies + title: Optimization link: isHeader: 1 - headerId: studies - isSectionHeader: 0 - sectionTitle: - subgroup: 2 - -- sbSecId: 3 - title: Optimize Header Bidding Setup - link: /overview/how-many-bidders-for-header-bidding.html - isHeader: 0 + headerId: optimization isSectionHeader: 0 sectionTitle: - subgroup: 2 + subgroup: 3 - sbSecId: 3 - title: An Optimal Setup for Header Bidding + title: Analyze Header Bidding Setup link: /overview/optimal-header-bidding-setup.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 2 - -- sbSecId: 3 - title: Reduce Header Bidding Latency With Prebid.js - link: /overview/how-to-reduce-latency-of-header-bidding.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 2 + subgroup: 3 - sbSecId: 3 - title: How to Simplify Line Item Setup - link: /overview/how-to-simplify-line-item-setup.html + title: Optimize Header Bidding Setup + link: /overview/how-many-bidders-for-header-bidding.html isHeader: 0 isSectionHeader: 0 sectionTitle: - subgroup: 2 + subgroup: 3 #--------------Prebid Video--------------| @@ -1385,7 +1230,7 @@ sbCollapseId: prebid-video - sbSecId: 4 - title: Overview + title: General link: isHeader: 1 headerId: vidoverview @@ -1409,319 +1254,32 @@ sectionTitle: subgroup: 0 -- sbSecId: 4 - title: Getting Started with Long Form Video for Prebid.js - link: /prebid-video/video-long-form.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 - - -- sbSecId: 4 - title: Show Video Ads with Google Ad Manager - link: /dev-docs/show-video-with-a-dfp-video-tag.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 - sbSecId: 4 - title: Show OTT Video Ads with Prebid - link: /dev-docs/show-long-form-video-with-gam.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 - -- sbSecId: 4 - title: Outstream Video Ads - link: /dev-docs/show-outstream-video-ads.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 - -- sbSecId: 4 - title: Training Videos - link: /videos/prebid-video.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 0 - -- sbSecId: 4 - title: Examples + title: Prebid.js Video Module link: isHeader: 1 - headerId: videxamples - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: "Instream" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Akamai AMP' - link: /examples/video/instream/akamai/pb-ve-amp.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'AdPlayer.Pro' - link: /examples/video/instream/adplayerpro/pb-ve-adplayerpro.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Brid' - link: /examples/video/instream/brid/pb-ve-brid.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Brightcove' - link: /examples/video/instream/brightcove/pb-ve-brightcove.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Flowplayer' - link: /examples/video/instream/flowplayer/pb-ve-flowplayer.html - Item: 1 - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'JW Player (Platform)' - link: /examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'JW Player (Self-Hosted)' - link: /examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Kaltura' - link: /examples/video/instream/kaltura/pb-ve-kaltura.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Ooyala' - link: /examples/video/instream/ooyala/pb-ve-ooyala.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Radiant' - link: /examples/video/instream/radiant/pb-ve-radiant.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'VideoJS' - link: /examples/video/instream/videojs/pb-ve-videojs.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: "Prebid Server" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Brid' - link: /examples/video/server/brid/pbs-ve-brid.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'JW Player (Platform)' - link: /examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'JW Player (Self-Hosted)' - link: /examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Kaltura' - link: /examples/video/server/kaltura/pbs-ve-kaltura.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Ooyala' - link: /examples/video/server/ooyala/pbs-ve-ooyala.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Radiant' - link: /examples/video/server/radiant/pbs-ve-radiant.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'VideoJS' - link: /examples/video/server/videojs/pbs-ve-videojs.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: "Cross Player" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Flowplayer' - link: /examples/video/crossplayer/flowplayer/pb-cp-flowplayer.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'JW Player' - link: /examples/video/crossplayer/jwplayer/pb-cp-jwplayer.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Kaltura' - link: /examples/video/crossplayer/kaltura/pb-cp-kaltura.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'VideoJS' - link: /examples/video/crossplayer/videojs/pb-cp-videojs.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: "Outstream" - link: - isHeader: 0 - isSectionHeader: 0 - isCatHeader: 1 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Google Ad Manager' - link: /examples/video/outstream/pb-ve-outstream-dfp.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'Radiant' - link: /examples/video/outstream/pb-ve-outstream-radiant.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'AdPlayer.Pro' - link: /examples/video/outstream/pb-ve-outstream-app.html - isHeader: 0 - isSectionHeader: 0 - sectionTitle: - subgroup: 1 - -- sbSecId: 4 - title: 'No Server' - link: /examples/video/outstream/pb-ve-outstream-no-server.html - isHeader: 0 + headerId: pbjsVideoModule isSectionHeader: 0 sectionTitle: subgroup: 1 - sbSecId: 4 - title: "Long-Form (Ad Pods)" - link: + title: Prebid Video Module + link: /prebid-video/video-module.html isHeader: 0 isSectionHeader: 0 - isCatHeader: 1 sectionTitle: subgroup: 1 - sbSecId: 4 - title: 'Freewheel' - link: /examples/video/long-form/pb-ve-lf-freewheel.html + title: Integrating Prebid.js with video on your own + link: /prebid-video/video-integrating-solo.html isHeader: 0 isSectionHeader: 0 sectionTitle: subgroup: 1 - #--------------Prebid Server--------------| - sbSecId: 5 @@ -1735,7 +1293,7 @@ sbCollapseId: prebid-server - sbSecId: 5 - title: Overview + title: General link: isHeader: 1 headerId: serveroverview @@ -1783,6 +1341,14 @@ sectionTitle: subgroup: 0 +- sbSecId: 5 + title: 'PBS+Digital Out Of Home' + link: /prebid-server/use-cases/pbs-dooh.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + - sbSecId: 5 title: 'Hosting Your Own PBS' link: /prebid-server/hosting/pbs-hosting.html @@ -1799,6 +1365,14 @@ sectionTitle: subgroup: 0 +- sbSecId: 5 + title: Prebid Server FAQ + link: /faq/prebid-server-faq.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + - sbSecId: 5 title: Versions link: @@ -1849,6 +1423,22 @@ sectionTitle: subgroup: 3 +- sbSecId: 5 + title: Native + link: /prebid-server/features/pbs-native.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 5 + title: Audio + link: /prebid-server/features/pbs-audio.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + - sbSecId: 5 title: Caching link: /prebid-server/features/pbs-caching.html @@ -1866,8 +1456,8 @@ subgroup: 3 - sbSecId: 5 - title: Interstitials - link: /prebid-server/features/pbs-interstitials.html + title: Floors + link: /prebid-server/features/pbs-floors.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -1881,6 +1471,14 @@ sectionTitle: subgroup: 3 +- sbSecId: 5 + title: Interstitials + link: /prebid-server/features/pbs-interstitials.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + - sbSecId: 5 title: Stored Requests link: /prebid-server/features/pbs-storedreqs.html @@ -1913,7 +1511,6 @@ sectionTitle: subgroup: 3 - - sbSecId: 5 title: Modules link: /prebid-server/pbs-modules/ @@ -1963,6 +1560,14 @@ sectionTitle: subgroup: 5 +- sbSecId: 5 + title: Building a Privacy Module + link: /prebid-server/developers/add-a-privacy-module.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + - sbSecId: 5 title: Code Reviews link: /prebid-server/developers/code-reviews.html @@ -2053,6 +1658,15 @@ sectionTitle: subgroup: 6 +- sbSecId: 5 + title: '/version' + link: /prebid-server/endpoints/pbs-endpoint-version.html + Item: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 6 + - sbSecId: 5 title: 'Event Endpoints' link: /prebid-server/endpoints/pbs-endpoint-event.html @@ -2119,7 +1733,7 @@ - sbSecId: 6 title: Video - link: /prebid-video/video-overview.html + link: /formats/video.html isHeader: 0 isSectionHeader: 0 sectionTitle: @@ -2188,12 +1802,34 @@ subgroup: 0 - sbSecId: 7 - title: Training Videos - link: /videos/ - isHeader: 0 + title: Privacy Resources + link: + isHeader: 1 + headerId: privacy isSectionHeader: 0 sectionTitle: - subgroup: 0 + subgroup: 1 + +- sbSecId: 7 + title: Prebid Privacy Overview + link: /support/privacy-resources.html + isHeader: 0 + isSectionHeader: 0 + subgroup: 1 + +- sbSecId: 7 + title: Prebid and MSPA + link: /features/mspa-usnat.html + isHeader: 0 + isSectionHeader: 0 + subgroup: 1 + +- sbSecId: 7 + title: Prebid and Quebec Privacy Support + link: /features/ac-quebec.html + isHeader: 0 + isSectionHeader: 0 + subgroup: 1 - sbSecId: 7 title: FAQs @@ -2240,7 +1876,15 @@ sectionTitle: subgroup: 0 -#-------------- Prebid Identity --------------| +- sbSecId: 8 + title: Professor Prebid + link: /tools/professor-prebid.html + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + + #-------------- Prebid Identity --------------| - sbSecId: 9 title: @@ -2276,4 +1920,3 @@ isSectionHeader: 0 sectionTitle: subgroup: 0 - diff --git a/_includes/adops/adops-creative-declaration.html b/_includes/adops/adops-creative-declaration.html index e7fcc0d2a8..f4bd582cc2 100644 --- a/_includes/adops/adops-creative-declaration.html +++ b/_includes/adops/adops-creative-declaration.html @@ -1,10 +1,9 @@ As of August 2020, privacy regulations have changed such that new creatives entered in GAM may require a declaration of the ad technology provider. The first step is to note the domain you serve the creative from. The examples above offer the -use of the jsdelvr.com CDN. However, you may obtain the creative from a managed +use of the jsdelvr CDN. However, you may obtain the creative from a managed service or you may host it yourself. If you receive a warning from ad manager about "declaring self-created ad technology", you should be able to work around -this by editing the creative and filling out the "Associated Ad Technology Provid -ers" section as shown in this screen capture: +this by editing the creative and filling out the "Associated ad technology providers" section as shown in this screen capture:

Creative Declaration

diff --git a/_includes/adops/adops-gam-setup.html b/_includes/adops/adops-gam-setup.html deleted file mode 100644 index 35db7cdf1c..0000000000 --- a/_includes/adops/adops-gam-setup.html +++ /dev/null @@ -1,190 +0,0 @@ -
- -

Step By Step Guide to Google Ad Manager Setup

- -
-

(Sorry, YouTube videos aren't available with your cookie privacy settings.)

-

Cookie Settings


-
- - - - - - - - - -

Step 1. Add a line item

- -

In Google Ad Manager, create a new order with a $0.50 line item.

- -

Enter all of the inventory sizes that your website has.

- -

Inventory Sizes

- -

Because header bidding partners return prices, set the Line Item Type to Price priority to enable them to compete on price.

- -

Price Priority

- -


- -

Set the Rate to $0.50 so that this line item will compete with your other demand sources at $0.50 ECPM.

- -

Rate

- -


- -

Set Display Creatives to One or More since we’ll have one or more creatives attached to this line item.

- -

Set Rotate Creatives to Evenly.

- -

Display and Rotation

- -

Choose the inventory that you want to run header bidding on.

- -

By default, prebid.js will send the highest bid price to Google Ad Manager using the keyword hb_pb.

- -

This line item will capture the bids in the range from $0.50 to $1 by targeting the keyword hb_pb set to 0.50 in the Key-values section.

- -

You must enter the value to two decimal places, e.g., 1.50. If you don’t use two decimal places, header bidding will not work.

- -

Key-values

- -


- -

Step 2. Add a Creative

- -

Next, add a creative to this $0.50 line item; we will duplicate the creative later.

- -

Choose the same advertiser we’ve assigned the line item to.

- -

Note that this has to be a Third party creative. The “Serve into a Safeframe” box can be UNCHECKED or CHECKED (Prebid universal creatve is SafeFrame compatible).

- -

Copy this creative code snippet and paste it into the Code snippet box.

- - - -
<script src = "https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js"></script>
-<script>
-  var ucTagData = {};
-  ucTagData.adServerDomain = "";
-  ucTagData.pubUrl = "%%PATTERN:url%%";
-  ucTagData.targetingMap = %%PATTERN:TARGETINGMAP%%;
-  ucTagData.hbPb = "%%PATTERN:hb_pb%%";
-
-  try {
-    ucTag.renderAd(document, ucTagData);
-  } catch (e) {
-    console.log(e);
-  }
-</script>
-
- -

New creative

- -

Make sure the creative size is set to 1x1. This allows us to set up size override, which allows this creative to serve on all inventory sizes.

- -

Note that safeframes don’t work with older versions of Prebid.js (v1.23 and before) in combination with recent versions of Prebid Universal Creative.

- -As of August 2020, privacy regulations have changed such that new creatives entered -in GAM may require a [declaration of the ad technology provider](https://support.google.com/admanager/answer/9972771?hl=en). The first step -is to note the domain you serve the creative from. The examples above offer the -use of the jsdelvr.com CDN. However, you may obtain the creative from a managed -service or you may host it yourself. If you receive a warning from ad manager -about "declaring self-created ad technology", you should be able to work around -this by editing the creative and filling out the "Associated Ad Technology Providers" section as shown in this screen capture: - -

Creative Declaration

- -

Step 3. Attach the Creative to the Line Item

- -

Next, let’s attach the creative to the $0.50 line item you just created. Click into the Line Item, then the Creatives tab.

- -

There will be yellow box showing each ad spot that you haven’t uploaded creatives for yet. Since you’ve already made the creatives, click use existing creatives next to each size.

- -

Use existing creatives list

- -

In the pop-up dialog that appears, click Show All to remove the default size filters and see the 1x1 creatives. Include the prebid creative and click Save.

- -

Use existing creatives dialog

- -

Back in the line item, go into the Creatives tab again, and click into the creative you just added.

- -

Then, in the creative’s Settings tab, enable the Size overrides field and set all your line item’s potential sizes.

- -

Save the creative and go back to the line item.

- -


- -

Step 4. Duplicate Creatives

- -

Google Ad Manager has a constraint that one creative can be served to at most one ad unit in a page under GPT’s single request mode.

- -

Let’s say your page has 4 ad slots. We need to have at least 4 creatives attached to the line item in case more than 2 bids are within the $0.50 range.

- -

Therefore, we need to duplicate our Prebid creative 4 times.

- -

Once that’s done, we have a fully functioning line item with 4 creatives attached that can potentially fill 4 ad slots of varying sizes during a single pageview.

- -


- -

Step 5. Duplicate Line Items

- -

Now let’s duplicate our line item for bids above $0.50.

- -

In the Prebid order page, copy the line item with shared creatives.

- -

This way you only have 4 creatives to maintain, and any updates to those creatives are applied to all pre-bid line items.

- -

For example, we can duplicate 3 more line items:

- - - -

Let’s go into each of them to update some settings. For each duplicated line item:

- -
    -
  1. -

    Change the name to reflect the price, e.g., “Prebid_1.00”, “Prebid_1.50”

    -
  2. -
  3. -

    Change the Rate to match the new price of the line item.

    -
  4. -
  5. -

    In Key-values, make sure to target hb_pb at the new price, e.g., $1.00. Again, be sure to use 2 decimal places.

    -
  6. -
  7. -

    (Optional) Set the start time to Immediate so you don’t have to wait.

    -
  8. -
- -

Repeat for your other line items until you have the pricing granularity level you want.

- -
diff --git a/_includes/adops/adops-gam-video-setup.html b/_includes/adops/adops-gam-video-setup.html deleted file mode 100644 index 1825186ccd..0000000000 --- a/_includes/adops/adops-gam-video-setup.html +++ /dev/null @@ -1,133 +0,0 @@ -
- -

Setting up Prebid Video in Google Ad Manager

- -

This page describes how to set up video creatives in Google Ad Manager for use with Prebid.js.

- -

For general Google Ad Manager line item setup instructions, see the other pages in this section.

- -

For engineering setup instructions, see -Show Video Ads with a Google Ad Manager Video Tag.

- - - - - -

Line Item Setup

- -
    -
  1. In the New line item dialog, choose "Video".
  2. -
  3. Select the appropriate Line Item Type, etc.
  4. -
  5. In the Expected creatives section, choose your video size, e.g., 640x480v.
  6. -
  7. Set the dates, rate, limit, and targeting as desired. For example, for SendAllBids include targeting for "hb_bidder_rubicon=rubicon" as well as the hb_pb_rubicon targeting. This isn't needed if only creating one set of orders for all bidders.
  8. -
  9. Remember to set the hb_pb=BUCKET targeting for each line item, or hb_pb_BIDDER=BUCKET if using separate line items for each bidder.
  10. -
  11. Save the line item.
  12. -
-

Be sure to duplicate your line item and video creative for each Prebid price bucket you intend to create.

-

By default, Prebid.js caps all CPMs at $20. As a video seller, you may expect to see CPMs higher than $20. In order to receive those bids, you’ll need to make sure your dev team implements custom price buckets as described in the engineering setup instructions. Once those changes are made on the engineering side, there should be no changes required from the ad ops side to support CPMs over $20.

- -

Creative Setup

- -When setting up video creatives, it's important to understand where the VAST XML is stored for each of your bidders. The most common place to store VAST XML is AppNexus' cache, but some bidders (such as RubiconProject and SpotX) use their own cache services. To support such -bidders, see the Multiple Cache Locations instructions below. - -

Single Cache Location

- -If you only use bidders that provide full VAST responses, do the following: - -

1. For each line item you create, click on the Creatives tab, click the ADD CREATIVE button, and choose the size you're entering.

- -

2. In the dialog that appears, choose Redirect.

- -

3. Set the VAST tag URL to the cache location. - -

If you’re using a single order for all bidders, then the VAST URL will be the same for each bidder:

- -
   https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:hb_uuid%%
-or
-   [other bidder cache location]
- -

If you’re using different orders for each bidder, the VAST URL for each will include the bidder-specific targeting variable:

- -
   https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:hb_uuid_BIDDERCODE%%
-or
-   [other bidder cache location]
- -

This VAST tag URL is required in order to show video ads. It points to a server-side cache hosted by your Prebid Server provider.

- -

Prebid Cache and the VAST creative URL warning
- Google Ad Manager will show you a warning stating that fetching VAST from the creative - URL failed. This is expected, since the creative URL above points - to a server-side asset cache hosted by Prebid Server.

- -

4. Set the Duration to the max length of video ads you serve. If you don't know what the max length is, set it to 30.

- -

In the past Prebid used to recommend setting duration to 0 or 1, but GAM now requires that this field reflect the actual video ad length. Since ads flowing through header bidding are going to differ in length, choose a value that matches a common ad length like 15 or 30.

- -

The resulting creative should look something like the following:

- -

Google Ad Manager Video Creative Setup

- - -

Multiple Cache Locations

- -If you're utilizing any bidders that cache their own VAST, you have two options: - -
- -To set up multiple video creatives in the same line item (i.e., to run AppNexus, Rubicon, and SpotX all together in the same video line item), you can utilize creative targeting. -
-
-

-1. In the line item's Expected creatives box, choose Creative Targeting and "Add New Targeting". - -

-2. Give the targeting set a name like "Prebid Default Video Cache URL" and set Custom Targeting as appropriate, e.g., "hb_bidder is none of rubicon, spotx". Save the targeting. - -

-3. For each bidder that uses their own cache, click ADD SIZE in the "Expected creatives" section. Again, choose Creative Targeting and "Add New Targeting". - -

-4. Give the targeting a name like "Prebid Rubicon Video Cache URL". Set Custom Targeting appropriately, e.g., "hb_bidder is any of rubicon". Save the targeting. - -

-5. Save the line item. - -

Now that the targeting is defined, we're going to add the creatives.

- -

-6. Go to the line item's Creatives tab. - -

-7. Make one creative for each of the targets. There are a couple of ways to do this on the GAM UI, but each approach will result in a creative entry screen similar to the screenshot above for the "Single Cache Location" process. Enter a name (e.g. "AppNexus VAST tag") and the VAST URL as described above. - -

-8. The end result should look something like this: - -

Google Ad Manager Video Creative Setup

- -

That’s it as far as Prebid setup is concerned. At this point you can add any other options you would normally use, such as labels or tracking URLs.

- -

Further Reading

- - diff --git a/_includes/body-end.html b/_includes/body-end.html index 023416be3f..e8bcc5edb4 100644 --- a/_includes/body-end.html +++ b/_includes/body-end.html @@ -1,8 +1,9 @@ - + + + diff --git a/_includes/gptjs.html b/_includes/gptjs.html new file mode 100644 index 0000000000..658fc5e8f7 --- /dev/null +++ b/_includes/gptjs.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/_includes/head--common.html b/_includes/head--common.html index c5cdec7209..c0a82eb02d 100644 --- a/_includes/head--common.html +++ b/_includes/head--common.html @@ -1,12 +1,12 @@ - - + + {% if page.head_title %} @@ -15,29 +15,23 @@ {{page.title}} for Header Bidding {% endif %} - {% if jekyll.environment == "production" %} - - - - - {% endif %} + + + - + - - - + + diff --git a/_includes/left_nav.html b/_includes/left_nav.html index edaa1e4548..5101e4ca63 100644 --- a/_includes/left_nav.html +++ b/_includes/left_nav.html @@ -72,6 +72,10 @@ {% for thisSubItem in arrSubItems %} {% if thisSubItem.link == page.url %} {% assign isOpen = 1 %} + {% elsif page.layout == "api_prebidjs" and thisSubItem.link == "/dev-docs/publisher-api-reference.html" %} + {% assign isOpen = 1 %} + {% elsif page.layout == "bidder" and thisSubItem.link == "/dev-docs/bidders.html" %} + {% assign isOpen = 1 %} {% endif %} {% endfor %} @@ -98,6 +102,10 @@ {% assign isPage = 0 %} {% if thisSubItem.link == page.url %} {% assign isPage = 1 %} + {% elsif page.layout == "api_prebidjs" and thisSubItem.link == "/dev-docs/publisher-api-reference.html" %} + {% assign isPage = 1 %} + {% elsif page.layout == "bidder" and thisSubItem.link == "/dev-docs/bidders.html" %} + {% assign isPage = 1 %} {% endif %} {% assign item_classes = base_item_classes | push: 'list-group-item--level-2' %} @@ -107,6 +115,7 @@ {% if subsectionIdx == 0 % || thisSubItem.isCatHeader == 1 %} + {% if thisSubItem.isCatHeader == 1 %} diff --git a/_includes/legal-warning.html b/_includes/legal-warning.html new file mode 100644 index 0000000000..bb31e735b6 --- /dev/null +++ b/_includes/legal-warning.html @@ -0,0 +1,7 @@ + diff --git a/_includes/prebidjs-non-prod.html b/_includes/prebidjs-non-prod.html new file mode 100644 index 0000000000..6a90ae991b --- /dev/null +++ b/_includes/prebidjs-non-prod.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/_includes/video/head.html b/_includes/video/head.html index 135969ba37..069581a519 100644 --- a/_includes/video/head.html +++ b/_includes/video/head.html @@ -3,11 +3,9 @@ {% include head--common.html %} +{% include prebidjs-non-prod.html %} - - - - + - - - - - - - - - - diff --git a/_includes/video/pb-cp-jw.html b/_includes/video/pb-cp-jw.html deleted file mode 100644 index 566fefd3e3..0000000000 --- a/_includes/video/pb-cp-jw.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-cp-kl.html b/_includes/video/pb-cp-kl.html deleted file mode 100644 index 424012f23b..0000000000 --- a/_includes/video/pb-cp-kl.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - diff --git a/_includes/video/pb-cp-vjs.html b/_includes/video/pb-cp-vjs.html deleted file mode 100644 index 3e7689ac10..0000000000 --- a/_includes/video/pb-cp-vjs.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - diff --git a/_includes/video/pb-cp.html b/_includes/video/pb-cp.html deleted file mode 100644 index 3033a22d12..0000000000 --- a/_includes/video/pb-cp.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-is-amp.html b/_includes/video/pb-is-amp.html deleted file mode 100644 index b3cc436870..0000000000 --- a/_includes/video/pb-is-amp.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-is-app.html b/_includes/video/pb-is-app.html deleted file mode 100644 index 710fedf75f..0000000000 --- a/_includes/video/pb-is-app.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - diff --git a/_includes/video/pb-is-bc.html b/_includes/video/pb-is-bc.html deleted file mode 100644 index 0c53878f4a..0000000000 --- a/_includes/video/pb-is-bc.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-is-br.html b/_includes/video/pb-is-br.html deleted file mode 100644 index 57f9c2ca54..0000000000 --- a/_includes/video/pb-is-br.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - diff --git a/_includes/video/pb-is-fp.html b/_includes/video/pb-is-fp.html deleted file mode 100644 index 8f79f4f4f8..0000000000 --- a/_includes/video/pb-is-fp.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - - diff --git a/_includes/video/pb-is-jw01.html b/_includes/video/pb-is-jw01.html index ce30dd1c7e..f5c3c3bf94 100644 --- a/_includes/video/pb-is-jw01.html +++ b/_includes/video/pb-is-jw01.html @@ -1,74 +1,72 @@ + + {% include head--common.html %} + {% include prebidjs-non-prod.html %} - -{% include head--common.html %} - - - - - - - - - + - + + + + + diff --git a/_includes/video/pb-is-jw02.html b/_includes/video/pb-is-jw02.html index 09c498ba4a..0db58fb5a5 100644 --- a/_includes/video/pb-is-jw02.html +++ b/_includes/video/pb-is-jw02.html @@ -1,77 +1,76 @@ + + {% include head--common.html %} {% include prebidjs-non-prod.html %} - -{% include head--common.html %} - - - - - - + + - - - - + - + + + + + diff --git a/_includes/video/pb-is-kl.html b/_includes/video/pb-is-kl.html deleted file mode 100644 index 3aa790f73c..0000000000 --- a/_includes/video/pb-is-kl.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - diff --git a/_includes/video/pb-is-ol.html b/_includes/video/pb-is-ol.html deleted file mode 100644 index 8508fc3d19..0000000000 --- a/_includes/video/pb-is-ol.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_includes/video/pb-is-rd.html b/_includes/video/pb-is-rd.html deleted file mode 100644 index e8127ec577..0000000000 --- a/_includes/video/pb-is-rd.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-is-vjs.html b/_includes/video/pb-is-vjs.html index 1d928f4bc4..fe351b8694 100644 --- a/_includes/video/pb-is-vjs.html +++ b/_includes/video/pb-is-vjs.html @@ -1,77 +1,93 @@ + + {% include head--common.html %} {% include prebidjs-non-prod.html %} - -{% include head--common.html %} - - - - - - - - - - - + - + + + + - - - - - + + diff --git a/_includes/video/pb-lf-fw.html b/_includes/video/pb-lf-fw.html index c47ec1c709..8b51be86bc 100644 --- a/_includes/video/pb-lf-fw.html +++ b/_includes/video/pb-lf-fw.html @@ -1,65 +1,70 @@ + + {% include head--common.html %} {% include prebidjs-non-prod.html %} - -{% include head--common.html %} - - - - - - - - - - - + + + + + - + + + + + - - - - + - + + - + + diff --git a/_includes/video/pb-os-app.html b/_includes/video/pb-os-app.html deleted file mode 100644 index 554cdf1a6e..0000000000 --- a/_includes/video/pb-os-app.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-os-basic-ima.html b/_includes/video/pb-os-basic-ima.html new file mode 100644 index 0000000000..6f3d311902 --- /dev/null +++ b/_includes/video/pb-os-basic-ima.html @@ -0,0 +1,8 @@ + + + + {% include head--common.html %} + + + + diff --git a/_includes/video/pb-os-dfp.html b/_includes/video/pb-os-dfp.html index fd22f18c4e..4496ea51a0 100644 --- a/_includes/video/pb-os-dfp.html +++ b/_includes/video/pb-os-dfp.html @@ -1,76 +1,74 @@ + + {% include head--common.html %} {% include prebidjs-non-prod.html %} {% include gptjs.html %} - -{% include head--common.html %} - - - - - - - + - googletag.cmd.push(function() { - var slot1 = googletag.defineSlot('/19968336/prebid_outstream_adunit_1', [[1, 1]], 'video1').addService(googletag.pubads()); - googletag.pubads().disableInitialLoad(); - googletag.pubads().enableSingleRequest(); - googletag.enableServices(); - }); - - - - - + + diff --git a/_includes/video/pb-os-nas-renderer.html b/_includes/video/pb-os-nas-renderer.html new file mode 100644 index 0000000000..a73741d997 --- /dev/null +++ b/_includes/video/pb-os-nas-renderer.html @@ -0,0 +1,90 @@ + + + + {% include head--common.html %} + {% include prebidjs-non-prod.html %} + + + + + + diff --git a/_includes/video/pb-os-nas.html b/_includes/video/pb-os-nas.html index e995efd511..533197b79b 100644 --- a/_includes/video/pb-os-nas.html +++ b/_includes/video/pb-os-nas.html @@ -1,51 +1,55 @@ + + {% include head--common.html %} + {% include prebidjs-non-prod.html %} - -{% include head--common.html %} - - - - - - - - - + - + + diff --git a/_includes/video/pb-os-rd.html b/_includes/video/pb-os-rd.html deleted file mode 100644 index a68d4d5627..0000000000 --- a/_includes/video/pb-os-rd.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pb-ve-lf-fw.html b/_includes/video/pb-ve-lf-fw.html deleted file mode 100644 index 751f45dbb2..0000000000 --- a/_includes/video/pb-ve-lf-fw.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_includes/video/pb-vm-vjs.html b/_includes/video/pb-vm-vjs.html new file mode 100644 index 0000000000..8fa417ddd5 --- /dev/null +++ b/_includes/video/pb-vm-vjs.html @@ -0,0 +1,37 @@ + + + + + {% include head--common.html %} + + + + + + + + + + {% include prebidjs-non-prod.html %} + + + diff --git a/_includes/video/pbs-br.html b/_includes/video/pbs-br.html deleted file mode 100644 index f1f2294f55..0000000000 --- a/_includes/video/pbs-br.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - diff --git a/_includes/video/pbs-jw01.html b/_includes/video/pbs-jw01.html deleted file mode 100644 index bd40af8000..0000000000 --- a/_includes/video/pbs-jw01.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - diff --git a/_includes/video/pbs-jw02.html b/_includes/video/pbs-jw02.html deleted file mode 100644 index da4a45d0f5..0000000000 --- a/_includes/video/pbs-jw02.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - diff --git a/_includes/video/pbs-kl.html b/_includes/video/pbs-kl.html deleted file mode 100644 index 19d842bc59..0000000000 --- a/_includes/video/pbs-kl.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pbs-oy.html b/_includes/video/pbs-oy.html deleted file mode 100644 index 73a73206aa..0000000000 --- a/_includes/video/pbs-oy.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_includes/video/pbs-rd.html b/_includes/video/pbs-rd.html deleted file mode 100644 index 6ef91f8f58..0000000000 --- a/_includes/video/pbs-rd.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - diff --git a/_includes/video/pbs-vjs.html b/_includes/video/pbs-vjs.html deleted file mode 100644 index 4619df3be2..0000000000 --- a/_includes/video/pbs-vjs.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - -{% include head--common.html %} - - - - - - - - - - - - - - - - - diff --git a/_includes/vimeo-iframe.html b/_includes/vimeo-iframe.html new file mode 100644 index 0000000000..84494b2e5e --- /dev/null +++ b/_includes/vimeo-iframe.html @@ -0,0 +1,14 @@ +
+ + +
\ No newline at end of file diff --git a/_layouts/analytics.html b/_layouts/analytics.html index 45e91208b1..b56424190e 100644 --- a/_layouts/analytics.html +++ b/_layouts/analytics.html @@ -7,18 +7,18 @@
-
diff --git a/_layouts/bidder.html b/_layouts/bidder.html index 93fcabc0ba..54c7c37499 100644 --- a/_layouts/bidder.html +++ b/_layouts/bidder.html @@ -7,18 +7,18 @@
-
@@ -49,56 +49,9 @@

Note:

This is a Prebid Server adapter only.

Features

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bidder Code{{ page.biddercode }}Prebid.org Member{% if page.prebid_member == true %}yes{% else %}no{% endif %}
Media Types{% unless page.media_types contains 'no-display' %}display{% if page.media_types contains 'video' %},{% endif %}{% endunless %}{% if page.media_types contains 'video' %} video{% endif %}{% if page.media_types != "no-display, native" and page.media_types contains 'native' %}, native{% endif %}{% if page.media_types == "no-display, native" %}native{% endif %}GDPR TCF Support{% if page.gdpr_supported == true %}yes{% else %}no{% endif %}
User IDs{% if page.userIds and page.userIds != '' %}{{page.userIds}}{% else %}none{% endif %}USP/CCPA Support{% if page.usp_supported == true %}yes{% else %}no{% endif %}
Supply Chain Support{% if page.schain_supported == true %}yes{% else %}no{% endif %}COPPA Support{% if page.coppa_supported == true %}yes{% else %}no{% endif %}
Demand Chain Support{% if page.dchain_supported == true %}yes{% else %}no{% endif %}Safeframes OK{% if page.safeframes_ok == false %}no{% elsif page.safeframes_ok == true %}yes{% else %}check with bidder{% endif %}
Supports Deals{% if page.deals_supported == false %}no{% elsif page.deals_supported == true %}yes{% else %}check with bidder{% endif %}Prebid.js Adapteryes
IAB GVL ID{% if page.gvl_id %}{{page.gvl_id}}{% else %}check with bidder{% endif %}Prebid Server Adapter{% if page.pbs == true %}yes{% else %}no{% endif %}
Floors Module Support{% if page.floors_supported == true %}yes{% else %}no{% endif %}First Party Data Support{% if page.fpd_supported == true %}yes{% elsif page.fpd_supported == false %}no{% else %}check with bidder{% endif %}
+ {% include dev-docs/bidder-meta-data.html page=page %} + + {{content}}

"Send All Bids" Ad Server Keys

@@ -131,9 +84,6 @@

"Send All Bids" Ad Server Keys

This bidder previously had a bidder code of `{{ page.prevBiddercode }}`, but prefers new configurations to use `{{ page.biddercode }}`. {% endif %} - - {{content}} -

Back to Bidders

diff --git a/_layouts/example.html b/_layouts/example.html index c917458838..f88e6fcfd1 100644 --- a/_layouts/example.html +++ b/_layouts/example.html @@ -7,18 +7,18 @@
-
@@ -33,7 +33,7 @@

Who should use this example:

{% endif %} -

This page contains:

+

About this example:

    @@ -43,52 +43,68 @@

    This page contains:

-

- For tips and troubleshooting info, see: -

-

-
- {% include dev-docs/build-from-source-warning.md %} + {% include dev-docs/not-for-production-warning.md %}
-

+

- On the JSFiddle example below: -

  • click 'Result' to see the output of the page.
  • -
  • Click 'Edit in JSFiddle' to open the example in a new tab.
+ In the JSFiddle example below: +
  • Click Result to see the example output.
  • +
  • Click Edit in JSFiddle to open the example in the JSFiddle editor in a new tab.

-
-

(Sorry, jsfiddle code examples aren't available with your cookie privacy settings.)

-

Cookie Settings


+ +
+ +
+ +
+ {% include dev-docs/build-from-source-warning.md %}
+ +

Further Reading

+

+

+

-
+
+ +
- {% include footer.html %} diff --git a/_layouts/home.html b/_layouts/home.html index 71f7092e2f..19af7069e8 100644 --- a/_layouts/home.html +++ b/_layouts/home.html @@ -9,7 +9,8 @@

Prebid Documentation

-

Welcome to the Prebid.org technical documentation portal. Here you will find the help you need to work with the Prebid.org family of products. Visit Prebid.org for general product overviews, blog updates, and additional information on membership and events. If you're wondering what Prebid and Header Bidding are all about, check out Why Prebid?

+

Welcome to the Prebid.org technical documentation portal. Here you will find the help you need to work with the Prebid.org family of Header Bidding products. You could start with the video introduction to Prebid or visit Prebid.org for general product overviews, blog updates, and additional information on membership and events. If you're wondering what Header Bidding is all about, check out our Introduction to Header Bidding

. +
@@ -39,7 +40,7 @@

Prebid Documentation

Prebid Mobile SDK

Lightweight SDK enabling app publishers to move beyond the waterfall

View Docs -

Download Mobile SDK

+

Download Mobile SDK

@@ -138,7 +139,7 @@

Prebid is Completely Open Source! Join our Community

Subscribe for Updates

-

Please review our privacy policy

+

Please review our privacy policy

+ +``` + +{: .alert.alert-warning :} + +* Replace `%%MACRO%%` with the appropriate macro for your ad server. (Refer to your ad server’s documentation or consult with a representative for specific details regarding the proper macros and how to use them.) +* Replace BIDDERCODE with the appropriate code for the bidder your line item is targeting. For example, if you’re targeting BidderA, the macro variable for adId might look like `ucTagData.adId = "%%PATTERN:hb_adid_BidderA%%";`. +* If you're hosting your own Prebid Universal Creative, make sure it's version 1.15 or later, or replace `%%PATTERN:hb_format%%.js` with `creative.js`. + +The example above uses the jsdelvr CDN as the domain from which the creative will serve. However, you may obtain the creative from a managed service or host it yourself. You might need to edit the creative and make adjustments to your creative settings depending on the CDN you're using. + +## Additional Steps + +The final steps in configuring Prebid on your ad server are to do the following: + +1. Duplicate your creatives as needed. If you’re using the Prebid Universal Creative, the body of your creatives for each format will be the same. Duplicate and rename the creative to create as many as you’ll need to attach to the line item. +2. Associate the creatives with the line item. +3. Duplicate the line item. You’ll need one line item per price bucket. If you’re sending all bids, you’ll need one line item per price bucket and per bidder. For each line item you duplicate, edit the line item to have the correct name, price bucket, and bidder code. + +## Further Reading + +* [Ad Ops Planning Guide](/adops/adops-planning-guide.html) +* [Ad Ops and Prebid Overview](/adops/before-you-start.html) + \ No newline at end of file diff --git a/adops/adops-overview-video.md b/adops/adops-overview-video.md new file mode 100644 index 0000000000..2fa112ddd7 --- /dev/null +++ b/adops/adops-overview-video.md @@ -0,0 +1,157 @@ +--- +layout: page_v2 +title: Video Intro to Prebid AdOps +description: A video overview of Prebid AdOps +sidebarType: 3 +--- + +# Video Overview of Prebid and Ad Operations + +An overview of the process of planning a Prebid integration for ad operations. + +{% include vimeo-iframe.html id="891677441" title="Prebid Ad Operations Planning" %} + +

+Further Content: + +- [Intro to Header Bidding](/overview/intro-to-header-bidding.html) +- [Header Bidding with Prebid](/overview/intro.html#header-bidding-with-prebid) +- [AdOps Planning Guide](/adops/adops-planning-guide.html) +- [Creative Considerations](/adops/creative-considerations.html) +- [Deals in Prebid](/adops/deals.html) +- [Prebid Managed Services](https://prebid.org/managed-services/) + +Related Videos: + +- [Introduction to Prebid.js](/prebid/prebidjs-video.html) +- [Prebid.js Impression Flow](/prebid/prebidjs-flow-video.html) +- [Components of Prebid.js](/prebid/prebidjs-components-video.html) +- [All Videos](/overview/all-videos.html) + +## Transcript + +### Introduction + +This video is a guide for Ad Ops professionals on planning an integration of Prebid.js with their primary ad server. + +A Prebid ad server setup can be complex, and every publisher’s approach is different. Setting up an ad server to use Prebid can be a large project, so it’s a good idea to make a plan before setting things up. + +This video will give an overview of 8 subjects to consider during your planning phase. The topics are: + +- Ad Server Integration Type +- Bid Transparency +- Price Granularity +- Line Item Settings +- Creatives +- Key-Value Pairs +- Deals + +This video and the help documents at docs.prebid.org will guide you through each of the topics. Check the video description for a link to the help documentation. + +### Objectives + +Before we get into the topics, let’s take a step back and talk about what we’re trying to achieve. + +An ideal Prebid integration maximizes yield and transparency while keeping complexity in check. + +Maximizing yield means generating the most advertising revenue possible by creating a competitive auction for every impression and maximizing the delivery of high-value demand sources such as private marketplace deals. To maximize transparency is to reveal as much about the auction as possible in reporting. Rich reporting allows you to maximize yield and troubleshoot issues more effectively. + +The ad stack should also be easy and inexpensive to set up, operate, and maintain. A complex setup is more prone to errors, requires more resources to run, and is more likely to bump up against ad server limits such as the maximum ad request character length or the maximum number of line items. + +### Topic 1: Ad Server Integration Type +Next, we’ll give an overview of each topic. For more information on each subject, check out the help documentation at docs.prebid.org. + +The first topic is Ad Server Integration Type. This stage is about evaluating the capabilities of your ad server to support header bidding. + +Header bidding’s power lies in its ability to value each impression individually. This means that for each available impression, Prebid needs to tell the ad server the price that header bidding buyers are willing to pay. + +Despite header bidding’s wide adoption online, ad servers have been slow to develop mechanisms for header bidding to submit dynamic prices at the impression level. The Prebid community has worked around the lack of options by making creative use of the ad server’s line item key-value targeting features. + +These techniques are tried and true: they power header bidding on the world’s biggest websites. But they also require ad ops teams to create large numbers of line items. Ideally, all ad servers would provide powerful dedicated support for header bidding, because this would deliver the best results for publishers. Some ad servers such as Google Ad Manager are beginning to test dedicated header bidding integration in a limited fashion. These experiments are promising, but are generally still too limited for most publishers. As a result, most Prebid publishers still use a traditional line-item-based integration method. As you start the planning process, check to see what your ad servers latest header bidding integration features are + +The rest of this video will assume that you’re using a traditional line item setup. Techniques designed to improve the yield and transparency of your header bidding often require you to create more line items. + +A typical Prebid.js integration can include thousands of ad server line items, and once the line items are set up, they’ll run for as long as they meet your header bidding needs. + +One goal of this planning process is determining how to satisfy your yield and reporting needs while keeping your line item count in check + +### Topic 2: Bid Transparency + +The next topic, Bid Transparency, illustrates the trade off between transparency and line item count. + +Most Prebid auctions will collect bids from multiple bidders, but it doesn’t have to send all of the bids to the ad server. Instead, it can send only the highest-priced bid. + +The Send All Bids option allows you to use ad server reporting to analyze Prebid auctions in more detail, but this extra power comes at the cost of larger ad server requests, more ad server line items, and more complexity inside the ad server. + +Note that using send top bid does not limit your ability to give special priority to bids with deal IDs. We’ll touch upon this special case later on. + +### Topic 3: Price Granularity + +Next comes Price Granularity. + +This is the setting in Prebid.js that defines the rounding of header bidding bids to match the line items set up in the ad server. For example, using a price granularity of $0.10 means that a bid price of $1.26 will be considered by the ad server’s decisioning algorithm to have a price of $1.20. + +Price Granularity does not affect the price that buyers pay for the ads they serve through header bidding, but does affect how header bidding bids compete with other demand sources. + +Using high price granularity with many tiers helps to drive yield by valuing header bidding bids accurately. When price granularity is low, the ad server will more often misjudge the value of header bidding bids, which degrades yield. + +However, higher price granularity also means more line items, which may be limited by operations resources or by limits imposed by your ad server provider. + +To give you a sense for how your Prebid choices affect line item counts, let’s run through some examples. Using Prebid’s high price granularity setting, which sets a $0.01 price tier increment from $0 to $20, will result in about 2,000 line items with a Send Top Bid setting. Using Send All Bids means multiplying 2,000 by the number of bidders. In this example, we’ll assume there are 10 bidders. Using Prebid’s low setting, which is $0.50 tier increment between $0 and $5, results in just 10 line items with Send Top Price and 100 line items with Send All Bids. + +Eliminating trade off between yield and line item count is one key way in which direct ad server integrations for header bidding could improve performance for publishers. Consider talking about this with your ad server provider. + +### Topic 4: Line Item Settings + +Bid Transparency and Price Granularity are the two factors that have the most impact on your line item count. Once you’ve made these decisions, you’ll need to decide next how to name and group your line items. + +Each organization will have their own practices around order naming, line item naming, advertisers, and other ad server settings. Publishers that use the Send All Bids option in Prebid.js will sometimes create separate Orders for each bidder, and many publishers use a separate set of line items to be able to give a special price granularity to high-CPM formats like video. + +For practical tips on Prebid.js line item setup, check out the Line Item Creation document at docs.prebid.org. + +### Topic 5: Creatives + +Next, let’s talk creatives. + +Creatives are Javascript tags that are linked to ad server line items. When the ad server selects a Prebid line item, it triggers the creative to render the winning Prebid ad. + +Many Prebid integrations use the Prebid Universal Creative or “PUC”, which is a one-size-fits all solution for rendering every ad format other than VAST video. The PUC is the easiest way to get set up with an ad server creative. + +Most publishers use the PUC, but you could develop a custom solution too. Some advanced publishers choose to use custom rendering solutions to gain small improvements in ad rendering performance. + +The Creative Considerations page at docs.prebid.org includes more information about the PUC, along with many more tips and best practices on creative setup for Prebid. + +### Topic 6: Key-Value Pairs + +The next subject is Key-Value Pairs. + +With a line item-based header bidding setup, Prebid.js communicates bid prices and other information to the ad server using key-value pairs that are appended to the ad server request URL. + +Key-value pairs are used to signify the bid prices of Prebid bidders, but that’s not all. Deal IDs, ad size, ad format information, and much more can be transmitted to the ad server. + +It’s important to know which key values will be used to pass Prebid data into your ad server, because key values supply the data that you need to target header bidding line items and report on header bidding activity with ad server reports. Sometimes, key value pairs are also necessary for the proper rendering of ads, particularly with the native and video ad formats. Because of this, it’s critically important that the engineering team in charge of Prebid integration are in close communication with the ad operations team. + +Here’s a list of some of the key-value pairs that Prebid.js is able to append to ad server requests. + +You may want to augment or restrict the information that Prebid.js sends to your ad server. For example, if your site already uses key-value pairs to deliver large amounts of contextual page information to the ad server, then you may need to restrict Prebid.js key-value pairs to control the size of your ad server requests. The Prebid.js configuration allows you to add, remove, or modify key-value pairs to meet your needs. + +### Topic 7: Deals + +In our final topic, we’ll explain how to think about working with Private Marketplace Deals in your ad server setup for Prebid. + +Deals help publishers drive revenue by developing strategic relationships with buyers. + +You can control deal delivery by creating line items targeted to specific deal IDs. This allows you to fine-tune the priority of deal bids relative to other bids and can improve deal reporting. There are options in both Prebid.js and Prebid Server to include or prioritize deal bids. Check the links below this video for more information. + +### Line Item Implementation + +Once you’ve made a decision about how you will organize your line item setup, you’ll need to think about how you’ll implement it. + +Ad ops teams can create header bidding line items manually in the ad server’s UI, but most teams use automated solutions. +Prebid’s Line Item Manager is an open-source command line tool that automates the creation and configuration of Prebid line items in Google Ad Manager. + +Some publishers also choose to develop their own line item managers. + +Prebid Managed Service providers also offer robust line item managers along with Prebid hosting, configuration, and optimization services. + +For information about the Prebid Line Item Manager and Prebid Managed Services, visit the links in the description below. diff --git a/adops/adops-planning-guide.md b/adops/adops-planning-guide.md new file mode 100644 index 0000000000..3213832502 --- /dev/null +++ b/adops/adops-planning-guide.md @@ -0,0 +1,80 @@ +--- +layout: page_v2 +title: Ad Operations Planning +head_title: Ad Operations Planning +sidebarType: 3 +sbUUID: 3.2 +--- + +# Ad Ops Planning Guide +{: .no_toc } + +- TOC +{: toc } + +There are several decisions you need to make as you’re planning out your Prebid implementation. The following diagram guides you through these decisions. Click on the boxes to navigate to detailed information about each one. (See below for an overview of these options.) + +Ad Ops Decisions + + + Ad Server Integration + Send All Bids vs Top Price + Line Item Creation + Price Granularity + Creative Considerations + + + + +{: .alert.alert-success :} +As you go through the steps, we recommend that you document all your decisions. Many of the decisions will need to be made only once when you first set up Prebid, so good documentation will help you and future users understand the decisions and why they were made. + +## AdOps Video Overview + +An overview of the process of planning a Prebid integration for ad operations. + +{% include vimeo-iframe.html id="891677441" title="Prebid Ad Operations Planning" %} + +Notes: + +- [Creative Considerations](/adops/creative-considerations.html) +- [Deals in Prebid](/adops/deals.html) +- [Transcript of this video overview](/adops/adops-overview-video.html) + +## Planning Process + +We’ve presented the decision steps in what we believe is a logical order, but you can go in any order that makes sense to you and your implementation. Here is a brief overview of each step so you can decide where to start. + +[Ad Server Integration](/adops/ad-server-integration.html): Determine what type of support your ad server has for header bidding and whether you want to add that into your configuration. + +[Send All Bids vs Top Price](/adops/send-all-vs-top-price.html): You can choose to send all bids that are received from header bidding demand partners, or send only the top bid. Learn the advantages and disadvantages of each. + +[Line Item Creation](/adops/line-item-creation.html): Here we provide you with some general recommendations and requirements for setting up your line items. + +[Price Granularity](/adops/price-granularity.html): The granularity you want in your line item pricing is dependent on your goals, your workload, and more. Learn how to balance everything to get the outcomes you want. + +[Creative Considerations](/adops/creative-considerations.html): Do you want to work with one universal creative, or have many different creatives? Should you use SafeFrames? These and other questions related to working with creatives are addressed here. + +Some additional resources that might be helpful as you work through your setup include: + +[Key Values for Ad Ops](/adops/key-values.html): Your line item setup is dependent on the key-value pairs the ad server receives in the ad request. Learn what key-value pairs are and how they’re used by Prebid, and the coordination required between ads op and engineering to ensure information gets to and from the ad server correctly. + +[Prebid Universal Creative](/overview/prebid-universal-creative.html): Simplify your line item setup with the Prebid Universal Creative. + +[Deals in Prebid](/adops/deals.html): You can negotiate deals with header bidding demand partners and have them compete with ad server inventory. You’ll need to create additional line items to support these deals. This document explains how to set up Prebid to make that happen. + +## Terminology + +Throughout this planning guide, we use the following terms to describe elements within the ad server. These terms may vary among different ad servers. + +**Order**: A container used to group line items that share similar properties. Orders contain information that applies to all line items attached to that order. Prebid integrations are typically set up with at least one order per bidder. + +**Line Item**: Line items contain the details of each bid, such as price, priority, and media format. Each line item has at least one creative attached. + +**Creative**: A creative is the ad that will be displayed in the ad slot if the associated line item wins the auction. In Prebid, creatives are entered in the ad server as an ad tag (or script) with directions to the actual media that will be displayed. + +**Key Value Pair (KVP)**: Additional parameters sent to the ad server to provide additional targeting or reporting information. Prebid sends keys with associated values that enable the ad server to match a line item to the bid and display the winning creative. A key value pair for a Prebid parameter can include things like the bid price or the name of the bidder. See [Key Values](/adops/key-values.html) for more information. + +## Next Step + +- [Ad Server Integration](/adops/ad-server-integration.html) diff --git a/adops/before-you-start.md b/adops/before-you-start.md index c00642c581..23b075abe2 100644 --- a/adops/before-you-start.md +++ b/adops/before-you-start.md @@ -6,126 +6,27 @@ sidebarType: 3 sbUUID: 3.2 --- - - # Ad Ops and Prebid -{: .no_toc } - -Prebid products are designed to integrate with the ad ops line item configuration on the publisher's selected ad server. Whether using Prebid.js, Prebid Server or Prebid Mobile, bid targeting parameters are passed to the ad server. The ad server then attempts to match the targeting parameters to a preset line item. If successful, that line item is compared to other line items and if the Prebid bid wins the auction, the creative is returned to the web page or app for display. - -{% capture importantNote %} -This page assumes you have read [Getting Started with Prebid.js](/overview/getting-started.html), though it applies to Prebid SDK and Server as well. -{% endcapture %} - -{% include alerts/alert_important.html content=importantNote %} - -* TOC -{: toc } - -## Supported ad servers - -The table below lists ad servers supported by Prebid and provides links to step by step documentation for the configurations those ad servers support. - -{: .table .table-bordered .table-striped } -| Server | Page | -|--------------+-----------------------------------------------------------------------------------------------------------------------------------------| -| **Google Ad Manager** | [Step by step guide to Google Ad Manager setup](/adops/step-by-step.html) | -| | [Send all bids to the ad server](/adops/send-all-bids-adops.html) | -| | [Setting up Prebid for AMP in Google Ad Manager](/adops/setting-up-prebid-for-amp-in-dfp.html) | -| | [Setting up Prebid Video in Google Ad Manager](/adops/setting-up-prebid-video-in-dfp.html) | -| | [Setting up Prebid Native in Google Ad Manager](/adops/gam-native.html) | -| **AppNexus** | [Setting up Prebid with the AppNexus Publisher Ad Server](/adops/setting-up-prebid-with-the-appnexus-ad-server.html) | -| **Smart Ad Server** | [Setting up Prebid.js with Smart Ad Server](/adops/setting-up-prebidjs-with-Smart-Ad-Server.html) | -| **FreeWheel** | [FreeWheel Guide for Premium Long-Form Video](/adops/setting-up-prebid-video-in-freewheel.html) | - -## Decide on price bucket granularity - -On a publisher's selected server the ad ops team will need to setup line items. These line items provide targeting information for the ad server, to include the CPM per impression. Prebid will pass in a bid's targeting parameters via key-values. The ad server will read these incoming targeting parameters and search through the line items for a match. - -Example: - -* Prebid.js is going to call your bidders for their price, then pass it into your ad server on the query-string. You want to target this bid price with a line item that earns you the same amount if it serves. - -* If you had 1-line item for every bid at a penny granularity of $0.01, $0.02, $0.03, ..., 1.23, ..., $4.56 you'd need 1,000 line items just to represent bids from $0-$10. We call this the “Exact” granularity option. - -* Creating 1,000 line items can be a hassle, so publishers typically use price buckets to represent price ranges that matter. For example, you could group bids into 10 cent increments, so bids of $1.06 or $1.02 would be rounded down into a single price bucket of $1.00. - -Our recommendation is to start with $1 or 10 cent granularity until you're more comfortable with Prebid.js. At $1, you only need to setup 10-20 line items – easy. When you're ready, get more granular with the price buckets to improve yield. - -{% capture dfpNote %} - -[Google Ad Manager has a limit](https://support.google.com/admanager/answer/1628457?hl=en#Trafficking) of 450 line items per order, which includes archived line items. If you are designing your own granularity setup, make sure you do not exceed that amount. Refer to our recommended pre-configured granularities in Prebid's API reference under the [Set Config Price Granularity instructions](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity). -{% endcapture %} - -{% include alerts/alert_note.html content= dfpNote %} +{: .no_toc } -## One set of line items for all bidders vs. a set of line items for each bidder - -### One set of line items for all bidders - -One set of line items for all bidders is the recommended way of setting up your line items. Choose this option if you prefer an easier, low-maintenance setup: - -- It's quicker and easier to setup, because you only have to create one set of line items. -- It's easier to maintain because adding more bidders requires no change to your line item setup. -- It's less error-prone because you only need to maintain 3 keywords: - -{% include default-keyword-targeting.md %} - - -{% capture successNote %} -For instructions on setting up pre-bid with one set of line items for all bidders, see [Send Top Bid to Ad Server - Step by Step guide to Google Ad Manager setup](/adops/step-by-step.html). -{% endcapture %} - -{% include alerts/alert_tip.html content=successNote %} - - -### One set of line items for each bidder - -Choose one set of line items for each bidder if you: - -- Have to rely on line item reporting (not query string reporting) to get winning bid by bidder analytics - - With one set of line items for all bidders, Prebid.js only sends the highest bid to the ad server (the decision logic of choosing the highest bid can be customized by you). This is sufficient if the winning bids matter the most to you. For example, a bidder bidding 100% of time but losing in every auction still has a fill rate of 0%. However, if having access to all bid information is important to you, use one set of line items for each bidder. - -- Require bid landscape data for header bidding partners - - With one set of line items for all bidders, Prebid.js sends the bidder information (Which bidder has the highest price) via a keyword `bidder=bidder_name`. To run a report to attribute winning bids to bidders, you will need to rely on your ad server's keyword reports. Google Ad Manager supports this, but some ad servers do not. Google Ad Manager does not support running reports for more than 2 keywords. Therefore, if you have existing reports that already rely on keywords, and you want to add a winning bid by bidder dimension, use one set of line items for each bidder. - -- Requires setting more keyword targeting within your ad server. The table below lists the required and optional keys for targeting with each of your header bidder partners. - -{% include send-all-bids-keyword-targeting.md %} - -{% capture successNote %} -For instructions on setting up pre-bid with one set of line items for each bidder, see [Send all bids to the ad server - Ad Ops setup](/adops/send-all-bids-adops.html). -{% endcapture %} - -{% include alerts/alert_tip.html content=successNote %} - -## Safeframes - -[SafeFrames are defined by the IAB](https://www.iab.com/guidelines/safeframe/) as a "managed API-enabled iframe that opens a line of communication between the publisher page and the iframe-contained ad creative." - -When setting up line items in your ad server, you'll need to consider whether to make the creatives safeframes or not. In general, for standard banner and native, safeframes are a good idea. Certain special mediatypes cannot use safeframes. +Ad Operations (Ad Ops) are the people who work directly with the ad server software to create, analyze, and update ad campaigns. In companies that use automated processes rather than working directly in the ad server UI, people in Ad Ops define the inputs to the automation that ensure campaigns run as expected. Whatever your actual job title or exact job description, when we refer to “Ad Ops” we’re talking about the non-engineering tasks involved in running and managing ad campaigns. -### Bidders known to be incompatible with safeframes +## Ad Ops Role in Prebid -{% assign bidder_pages = site.pages | where: "layout", "bidder" | where: "safeframes_ok", false %} -

    -{% for page in bidder_pages %} -
  • {{ page.title }}
  • -{% endfor %} -
+To understand your role in implementing Prebid, you need to understand how header bidding works. You can get a general overview in our [Introduction to Header Bidding](/overview/intro-to-header-bidding.html) and [Introduction to Prebid](/overview/intro.html). But we’re going to provide a few more details here. -There may be others, please check with bidders directly if you have questions about their support. +Header bidding is a process for collecting bids for an ad slot before the ad server is called. Those bids and their related targeting information are consolidated and sent along with the ad request to the ad server. -## Work together with your dev team +When the ad request arrives at the ad server, the ad server reads the targeting information and looks for matching line items. This is where ad ops comes in. You need to ensure that those line items exist and are configured correctly. In order to do that, there are a number of decisions you need to make before you begin your ad server setup. Our [Ad Ops Planning](/adops/adops-planning-guide.html) guide will lead you through these decisions. -Implementing header bidding requires much more collaboration with your dev team than normal Ad Ops setup. For example: +After you’ve completed your planning, move on to the appropriate setup documentation for your ad server. -> Setting up price granularity requires you and the dev team working together to ensure the price buckets match. We have seen cases when the code on page sends $0.10 increments, while the line item setup expects $0.50 increments. This results in the ad server not catching 80% of the bids. +- [Google Ad Manager](/adops/step-by-step.html) +- [Xandr Monetize Ad Server](/adops/setting-up-prebid-with-the-appnexus-ad-server.html) +- [Smart Ad Server](/adops/setting-up-prebidjs-with-Smart-Ad-Server.html) +- [FreeWheel](/adops/setting-up-prebid-video-in-freewheel.html) -## Related Topics +## Next Step -- [Getting Started with Prebid.js](/overview/getting-started.html): How Prebid.js works at a high level. -- [Prebid.js and Ad Server Key Values](/features/adServerKvps.html) -- [What is Prebid?](/overview/intro.html): Overview and history of header bidding and Prebid.js. -+ [Docs by Format](/dev-docs/docs-by-format.html): Engineering and ad ops docs arranged by ad format (video, native, etc.). +Read the [Ad Ops Planning](/adops/adops-planning-guide.html) guide. diff --git a/adops/creative-considerations.md b/adops/creative-considerations.md new file mode 100644 index 0000000000..396f19feaa --- /dev/null +++ b/adops/creative-considerations.md @@ -0,0 +1,139 @@ +--- +layout: page_v2 +title: Creative Considerations +head_title: Creative Considerations +sidebarType: 3 +sbUUID: 3.2 +--- + +# Creative Considerations + +{: .no_toc } + +- TOC +{: toc } + +Some of the major decisions you need to make as you’re setting up your campaigns have to do with creatives. This document will provide information to help you make those decisions. + +{: .alert.alert-info :} +Throughout this discussion we’re assuming you’ve chosen to use the Prebid Universal Creative (PUC). See [Prebid Universal Creative](#prebid-universal-creative) below for advantages and disadvantages of this approach. For more information on the PUC as well as alternatives, see the [Prebid Universal Creative Overview](/overview/prebid-universal-creative.html). + +## Creatives Overview + +When you set up a line item for a campaign in your ad server, you have to add images or ad tags that will be displayed for that campaign. Header bidding line items have a particular kind of ad tag. + +The Prebid ad tag is entered into creatives on the ad server in the form of a script that will enable Prebid to find the bid that goes with a winning line item. Depending on your ad server, you’ll have to declare your creative as a Third Party creative (Google Ad Manager), or set it to use HTML, or some other means of entering an ad tag (the Prebid script) rather than an image. + +## Prebid Universal Creative + +The first decision you’ll need to make when it comes to creatives (with the exception of VAST video) is whether you want to use the Prebid Universal Creative (PUC). The PUC is a collection of rendering routines that can pull a particular ad ID from the Prebid cache and do the right thing to display it. You can find full details about the PUC in the [Prebid Universal Creative Overview](/overview/prebid-universal-creative.html). For now we’ll focus on the advantages and disadvantages to using the PUC. + +The big advantage to using the PUC is that it’s the simplest approach to configuring Prebid in your ad server. It provides a robust mechanism that can be used across several formats, platforms, devices, and ad servers. + +The primary disadvantage to using the PUC is that it takes an extra fetch to load the PUC file vs doing everything inline to the creative. Also, loading a “universal” creative means that more bytes are loaded than are actually necessary for the display of a single creative. This all leads to a slight performance penalty. + +You’ll need to determine whether the ease of implementation is worth the small performance penalty. + +## Prebid.js dynamic creatives + +If you have line items that target only browsers running Prebid.js, you can use [dynamic creatives](/adops/js-dynamic-creative.html) to avoid the PUC performance penalty but keep the same ease of setup and maintenance. The disadvantage of this approach is that it does not support platforms that do not run Prebid.js, such as AMP or mobile apps. + +## Where to Host the PUC + +If you choose to use the Prebid Universal Creative, you'll need to decide where to load it from: + +1. Prebid hosts an always-up-to-date copy of the PUC at `https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/*`. The upside of this location is that it's automatically updated so it contains new features automatically. +1. You can host the PUC at your own location. The upside of this option is that you can control when upgrades happen. +1. You can copy the body of the PUC into your ad server creative directly. This eliminates a browser fetch, but could make upgrades more difficult. + +## Creative Naming + +You can name your creatives whatever makes sense to your organization. We recommend names in the following format: Prebid - Type - Size - N. For example, a banner creative using the PUC would be `Prebid - banner - 1x1 - 1`. + +## Creative Modes + +No matter what type of media you’re working with, you need to decide how you’re going to represent the size options in the ad server. There are three creative size modes: + +- Creatives are all sized 1x1 +- Creatives are sized their actual size +- Line items are targeted per size + +### All Creatives 1x1 + +If you select this mode, in the ad server you’ll set the size of all your Prebid creatives to 1x1. The creatives will then be resized based on the value supplied by the demand partner in the hb_size key. This is the simplest option to implement and requires the fewest number of creatives to be created. + +If you’re working with Google Ad Manager (GAM) we recommend you create one general 1x1 creative, then duplicate it to attach 3 - 5 identical creatives to each line item. The reason for this is that GAM doesn’t make a distinction between creatives with images attached and creatives with a script that could be used to retrieve one of many different images. It treats every creative as an individual image, and allows each one to be served to only one ad unit per page. + +For Prebid line items, this means that if your page has multiple ad slots that fit the same line item targeting, GAM would allow only one of them to display the creative, not realizing that one creative could point to different images. Attaching multiple identical creatives to each line item ensures that creatives from a line item matching the targeting on multiple ad slots can serve on the same page. + +For example, say you're using "low" granularity, which means that one line item covers bids from $1.00 to $1.49. If you have three creatives associated with that line item, the page could not display anymore than three Prebid bids in that price range. If you have infinite scroll pages, you'll have to consider the tradeoff for how many copies of creatives you want to have. + +### Creative Actual Size + +With this mode, you set specific sizes on the creatives. This mode allows for more precise reporting if you’re interested in knowing the exact sizes of creatives being served from Prebid. As with the 1x1 option, we recommend you create 3 - 5 duplicate creatives of each size. The downside is that this requires a lot of creatives per line item. If you specify 20 sizes, you would need as many as 100 duplicate creatives. + +### One Line Item Per Size + +We recommend against using this mode, but are aware some publishers use it for reporting purposes. With this mode, you would target your line item based on the value of the hb_size key. This would require you to create one line item for every size, for every bidder, for every price. The number of line items required could get extremely large. Here’s an example (see [Price Granularity](/adops/price-granularity.html) for more details): + +- Bidders: 10 +- Price Increment: 0.10 +- Price Cap: 20 +- Sizes: 5 +- Send all bids + +This scenario would require you to create 10,000 line items (10 x 200 x 5). If you were to use either 1x1 mode or creative-level sizing you would need only 2,000 line items. + +## Banner and Outstream Creatives + +As we mentioned, each creative requires an ad tag script that will call the [Prebid Universal Creative](/overview/prebid-universal-creative.html) to display the correct image. + +One decision you'll want to make is which version of the PUC you want to use. Prebid hosts a copy, which you're free to use. But some publishers might want to use their own copy of the PUC so as to have greater control over the upgrade windows. + +{: .alert.alert-info :} +Engineers can find the PUC code in the [Prebid Github repository](https://github.com/prebid/prebid-universal-creative). + +## Native + +Native ads require close collaboration between web designers, engineering, and ad ops. The primary decision to be made that affects ad ops is where to store the rendering template. Your options are: + +- The ad server +- The page's Prebid.js adunit +- An external script + +If you already have templates stored in your ad server for some native ads, it might make sense to also store the templates for Prebid there and keep everything together and consistent. This also gives ad ops control over when templates change. + +The second two options require engineering to make any changes when template updates are required. Because native ad formatting is tied to the look of the site, these options could fit in with normal site maintenance. + +Each option requires a different PUC ad tag to be used in the associated creatives, so be sure to get the correct script (and CSS file) from the engineers. + +{: .alert.alert-info :} +Engineering details outlining each template storage option can be found in the [Prebid.js Native Implementation Guide](/prebid/native-implementation.html). + +## VAST Video + +VAST video (instream and long-form video) does not use the PUC. Instead, video bids provide VAST that Prebid caches to obtain a cache ID that can be retrieved with a URL. The cache ID is passed as a key value to the ad server. (See [Video Overview](/prebid-video/video-overview.html) for details.) + +When you’re running campaigns with video creatives, the primary decision you need to make is where to cache your video bids. You’ll enter this location in the creative you add to the line item. The cache location is typically independent of the bidders. The most common cache location is . See [Setting Up Video In GAM](/adops/setting-up-prebid-video-in-dfp.html) for detailed instructions on configuring a video creative in GAM. + +## SafeFrames + +Another decision you need to make with regards to banner and native creatives is whether to run them in SafeFrames. A SafeFrame is defined by the IAB as “a managed API-enabled iframe that opens a line of communication between the publisher page and the iframe-contained ad creative.” SafeFrames provide an added layer of security by separating the ad from your web page. + +We recommend using SafeFrames for banner and native creatives, but there are some things to keep in mind if you do this. For example: + +- Some creatives, such as richmedia formats, can’t render in SafeFrames. +- Some bidders do not support the use of SafeFrames. + +If you don't trust all your bidders to provide creatives that can safely run inside of SafeFrames, then you'll want to consider using [Send All Bids](/adops/send-all-vs-top-price.html) (the default), which will enable you to allow some bidders to use SafeFrames and some not. + +[Prebid documentation for each bidder](/dev-docs/bidders.html) provides information on whether the bidder supports SafeFrames. + +Be sure to check with bidders directly if you have questions about their SafeFrame support. + +## Related Reading + +- [Planning Guide](/adops/adops-planning-guide.html) +- [Key Values for Ad Ops](/adops/key-values.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Deals in Prebid](/adops/deals.html) diff --git a/adops/deals.md b/adops/deals.md index f2c838e137..b38c9034a8 100644 --- a/adops/deals.md +++ b/adops/deals.md @@ -1,135 +1,61 @@ --- layout: page_v2 -title: Enable Deals -head_title: Enable Deals in Prebid for Header Bidding -description: Enable Deals in Prebid for Header Bidding Analysis. -pid: 4 - +title: Deals in Prebid +head_title: Deals in Prebid sidebarType: 3 +sbUUID: 3.2 --- -# Enable Deals in Prebid -{:.no_toc} - -In order to enable deals for prebid, the ad ops setup is slightly different from the standard header bidding setup. Specifically: - -+ From the ad ops side, you'll create separate orders and line items that target the deal ID key-values. These line items will be at different (probably higher) priorities than your standard header bidding line items. +# Deals in Prebid -+ From the dev side, if your page is using the standard prebid.js key-values, no change or work is required. - -{: .bg-info :} -In this example we will use the Google Ad Manager setup to illustrate, but the steps are basically the same for any ad server. +{: .no_toc } * TOC -{:toc} - -### Step 1: Understand Key-values - -Whenever a bidder responds with a bid containing a deal ID, Prebid.js will generate and attach deal-related key-values to the ad server call in the format: `hb_deal_BIDDERCODE = DEAL_ID`. - -For example, given the submitted bids, prices, and deals shown here: - -``` -bid 1: Bidder = Rubicon, CPM = 1.50, Deal ID = RBC_123 -bid 2: Bidder = AppNexus, CPM = 1.20, Deal ID = APN_456 -``` - -The key-values attached to the ad server call (that the line items will target) will be: - -``` -hb_pb_rubicon = 1.50 -hb_deal_rubicon = RBC_123 -hb_pb_appnexus = 1.20 -hb_deal_appnexus = APN_456 -// hb_adid, hb_size, and hb_adid omitted -``` - -{% capture noteAlert %} -We recommend confirming with your development team that the page is set up to send all deal targeting to the ad server. There are two ways to do this: -- Set the `enableSendAllBids` to **true**. -- Set `enableSendAllBids` to **false** and `alwaysIncludeDeals` to **true**. This option will minimize the number of targeting variables sent to the ad server. -See the [enableSendAllBids](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) documentation for details. -{% endcapture %} - -{% include alerts/alert_note.html content=noteAlert %} - -
- -### Step 2: Create Key-values - -For each header bidding partner you work with, create a keyword in the format of `hb_deal_BIDDERCODE`, e.g., `hb_deal_pubmatic`. For more examples of the keyword format, see the [API Reference for `pbjs.getAdserverTargeting`](/dev-docs/publisher-api-reference/getAdserverTargeting.html). - -
- -![Inventory Sizes]({{ site.github.url }}/assets/images/demo-setup/deals/key-val.png){: .pb-lg-img :} - -
- -### Step 3: Create Line Items for Deals - -In Google Ad Manager, create a new line item. - -Enter all the **Inventory sizes** for your deal (or deals): - -![Inventory Sizes]({{ site.github.url }}/assets/images/demo-setup/inventory-sizes.png){: .pb-md-img :} +{: toc } -
+In the same way that you can negotiate deals with advertisers in your ad server, you can also set up deals with your header bidding partners. When you do that, there are just a few things to keep in mind to ensure those deals get sent to the ad server and your line items are prepared to receive them. -Set the **priority** to the level you prefer. +## Send Deal to Ad Server -![Inventory Sizes]({{ site.github.url }}/assets/images/demo-setup/deals/deal-priority.png){: .pb-lg-img :} +In [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) we described those two options for sending bids to the ad server. There is also a third option created specifically for deals: Send top price and deals. -
+### Deals with Send All Bids -Set **Display Creatives** to *One or More* since we'll have one or more creatives attached to this line item. +If you send all bids to the ad server, deals will be sent along with the rest of the bids. If you want your deals to be prioritized over the rest of the bids, be sure to inform the software engineers so they can configure Prebid for this scenario. -Set **Rotate Creatives** to *Evenly*. +{: .alert.alert-info :} +See [Configure Send Bids Control](/dev-docs/publisher-api-reference/setConfig.html#configure-send-bids-control) for engineering instructions on this configuration. -![Display and Rotation]({{ site.github.url }}/assets/images/demo-setup/display-and-rotation.png){: .pb-md-img :} +### Deals with Send Top Price -
+If you decide to send only the top price bid, the deal might not be the top price, in which case it would not be sent and the ad server would never see it. To ensure deals make it to the ad server, the software engineers need to know that deal bids should be included along with the top priced bid. They can then configure Prebid to send both the top price and any deals that come through. -Then you'll need to target the **inventory** that you want to this deal to run on. +{: .alert.alert-info :} +See the [Send All Bids engineering reference](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) for engineering instructions on sending deals along with the top bid. -
+## Deal Line Item Details -**Use Key-values targeting to target deal ID(s)** +In [Line Item Creation](/adops/line-item-creation.html) we talked about some requirements and recommendations for setting up line items for Prebid. You can follow most of those settings for deals, with the modifications outlined here. -There are two ways to target deal IDs using *Key-values* targeting: +### Deal Key Value Pairs -1. If you would like the deals to have the same priority and target the same inventory, you can include multiple deal IDs (as shown below). -2. Otherwise, you must create a separate line item for each deal ID you want to target. +From the ad server side, you need to create special line items for each deal. This is done through a key-value pair. (See [Key Values](/adops/key-values.html) for details on how key value pairs work.) -![Inventory Sizes]({{ site.github.url }}/assets/images/demo-setup/deals/targeting.png){: .pb-lg-img :} +For each header bidding partner you negotiate deals with, create a keyword in the format hb_deal_BIDDERCODE, e.g., hb_deal_BidderA. Then when you create the line item for the deal, add in that code with the associated deal ID. For example, hb_deal_BidderA=BDA_123. -
+{: .alert.alert-info :} +The actual value of the deal ID (BDA_123 in this example) will be obtained from the demand partner. -### Step 4: Attach Creatives to Line Items +### Start and End Dates -Like all line items, those that represent deals need to be associated with creatives that pass the correct adid back to Prebid.js for display. +Prebid line items normally start immediately with no end date; the line item exists to receive a bid at any time, whenever it gets sent to the ad server. Because deals are negotiated with the demand partner, deals will have date ranges in accordance with the agreement. -e.g. if the line item is targeted to `hb_deal_pubmatic`, then the creative needs to send `hb_adid_pubmatic` in the creative. Like this: +### Priority - - +## Further Reader -If however, the line item is targeted to `hb_deal` (without a bidder code), -then the simplified creative setup in the [step-by-step instructions](/adops/step-by-step.html#step-2-add-a-creative) will be fine. +* [Planning Guide](/adops/adops-planning-guide.html) +* [Key Values for Ad Ops](/adops/key-values.html) +* [Prebid Universal Creative](/overview/prebid-universal-creative.html) diff --git a/adops/gam-creative-banner-sbs.md b/adops/gam-creative-banner-sbs.md new file mode 100644 index 0000000000..3fc6d0b04e --- /dev/null +++ b/adops/gam-creative-banner-sbs.md @@ -0,0 +1,122 @@ +--- +layout: page_v2 +title: GAM Step by Step - Banner/Outstream/AMP Creatives +head_title: GAM Step by Step - Banner/Outstream/AMP Creatives +description: Set up banner and outstream creatives for Prebid in Google Ad Manager. +pid: 2 +sidebarType: 3 +--- + + +# GAM Step by Step - Banner/Outstream/AMP Creatives + +This page walks you through the steps required to create banner and outstream creatives to attach to your Prebid line items in Google Ad Manager (GAM). + +{: .alert.alert-success :} +For complete instructions on setting up Prebid line items in Google Ad Manager, see [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html). + +1. In GAM, select **Delivery** > **Creatives**. +2. Under the **Display creatives** tab, click **New Creative**. +3. Select your advertiser, then click **Third party**. +4. Enter a **Name** for your creative. For example, `Prebid – banner – 1x1 - 1`. +5. Enter a **Target ad unit size** of `1x1`. This allows the creative to serve on all inventory sizes. + +{: .alert.alert-warning :} +These instructions assume you're using the Prebid Universal Creative (PUC) after v1.15 that supports the separate `banner.js` file. See the [Prebid Universal Creative](/overview/prebid-universal-creative.html) documentation for alternate approaches. + +{: .alert.alert-danger :} +**AMP**: If you choose to bypass the PUC for AMP, Prebid Server analytics will not work. + +{:start="6"} +6. Select **Standard** as the **Code type**. + +{: .alert.alert-info :} +**AMP**: If you are using AMP, you should still select **Standard** as the code type. The “AMP” option is for AMPHTML hosted by a 3rd party. + +{:start="7"} +7. Enter one of the scripts shown below, depending on whether Prebid is configured to send all bids or only the top price bid. + +**Send All Bids Configuration** + +{: .alert.alert-warning :} +Be sure to replace BIDDERCODE with the appropriate bidder. For example, if the bidder code is `PBbidder`, the `adid` would be `%%PATTERN:hb_adid_PBbidder%%`. + +```html + + +``` + +{: .alert.alert-info :} +Note: the `mobileResize` parameter is a workaround to a bug in the Google Mobile Ads SDK. The Prebid SDK uses the existence of the "hb_size" string that's provided in %%PATTERN:TARGETINGMAP%%, but this bidder-specific version of the creative doesn't utilize the TARGETINGMAP, so the value is added here. The important part is the value that contains `hb_size:`. + +{: .alert.alert-danger :} +Warning: Be sure none of the attribute names are longer than 20 characters. See [Send All Bids Key Value Pairs](/adops/send-all-vs-top-price.html#key-value-pairs) for more information. + +**Send Top Price Bid Configuration** + +In top-price mode, you can make use of the GAM `TARGETINGMAP` feature instead of listing out each attribute. + +```html + + +``` + +{:start="8"} +8. Select whether to **Serve into a SafeFrame**. See [Creative Considerations](/adops/creative-considerations.html) for more on using SafeFrames. + +{: .alert.alert-info :} +**AMP**: For AMP, you must select **Serve into a SafeFrame**. + +Your creative settings will look something like this. In this example we're assuming a Send All Bids configuration, and we’ve replaced BIDDERCODE with the code for our bidder, PBbidder. (Notice that some of the key names have been truncated to adhere to the GAM 20-character key length limit.) + +![Banner creative settings](/assets/images/ad-ops/gam-sbs/banner-creative-settings.png) + +{: .alert.alert-info :} +Note: You can ignore the “Sorry, we don’t recognize this tag” warning. GAM doesn’t have built-in macros for Prebid and so doesn’t recognize them. The ad tag will still work correctly. + +{:start="9"} +9. If you're using jsdelivr, set your **Associated ad technology provider**: + +{% include /adops/adops-creative-declaration.html %} + +{:start="10"} +10. Click **Save and preview**. + +## Further Reading + +* [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) +* [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) +* [Prebid Universal Creatives](/overview/prebid-universal-creative.html) +* [Creative Considerations](/adops/creative-considerations.html) +* [Ad Ops Planning Guide](/adops/adops-planning-guide.html) diff --git a/adops/gam-hbt-step-by-step.md b/adops/gam-hbt-step-by-step.md new file mode 100644 index 0000000000..0ab5fbdaa7 --- /dev/null +++ b/adops/gam-hbt-step-by-step.md @@ -0,0 +1,84 @@ +--- +layout: page_v2 +title: Header Bidding Trafficking with Prebid Step by Step +head_title: Header Bidding Trafficking with Prebid Step by Step +description: Step-by-step instructions for setting up Header Bidding Trafficking in GAM for Prebid. +#note the sidebar type needs to reflect the section this file is displayed in. See _data/sidenav.yml for the side nav categories. +sidebarType: 3 +--- + +# Header Bidding Trafficking with Prebid Step by Step +{: .no_toc } + +- TOC +{: toc } + +Publishers new to header bidding can use this guide to set up header bidding trafficking for Prebid in Google Ad Manager. Unlike a line item setup, header bidding trafficking provides publishers with precise bid prices to compete in the auction and no need for header bidding creatives. It also provides unified reporting, and a straightforward workflow. These instructions describe only the specific settings required for header bidding trafficking; they are not intended to be comprehensive instructions that replace or duplicate the GAM documentation. + +- If you prefer to use line items to manage your header bidding setup, visit [Line item setup](/adops/step-by-step.html). +- For how to migrate from line items to header bidding trafficking, visit [Header bidding trafficking](https://support.google.com/admanager/answer/12273163) and the corresponding [FAQ](https://support.google.com/admanager/answer/12270263). These instructions also describe how to run an experiment to show potential revenue uplift from migrating to header bidding trafficking from a line item setup. + +## Prerequisites + +Before you begin, we recommend you read through our [Planning Guide](/adops/adops-planning-guide.html) to make sure you know what your configuration is going to look like and you’ve thoroughly documented your decisions. + +## Requirements + +To use header bidding trafficking, you must: + +- Be on Google Ad Manager 360. +- Use a "[standard implementation](https://support.google.com/admanager/answer/12270263?sjid=14160336224257855972-NA#standard&zippy=%2Cwhats-a-standard-implementation-of-the-prebid-wrapper)" of Prebid.js. +- Use Google Publisher Tag (GPT) on your website. + +Note: You don't have to set up any line items, including price priority line items, to use header bidding trafficking. + +### Tagging +First, configure Prebid.js to collect bids from your selected bidders and pass those bids onto Ad Manager. For details on tagging changes, visit [Getting Started for Developers](/dev-docs/getting-started.html). + +## Enable Header Bidding for you Ad Manager Network + +1. Sign in to Google Ad Manager. +2. Click *Delivery*, then *Bidders*. +3. Click the *Header bidding* tab. +4. Click *Get started* to enable Prebid trafficking for the network, if it’s not already enabled. + +![Get Started with Prebid](/assets/images/ad-ops/gam-hbt-sbs/hbt-start.png) + +{:start="5"} +5. Review each detected bidder. + +![Review Bidders](/assets/images/ad-ops/gam-hbt-sbs/hbt-bidders.png) + +For each bidder, there are three configuration options: + +- *Enable SafeFrame*: When enabled, ads returned by the bidder will render inside of a SafeFrame. Bidders may vary in their compatibility with SafeFrame. +- *Enable optimized Private Auction deals*: When enabled, bids that include a deal ID will enter the auction at the optimized Private Auction [priority](https://support.google.com/admanager/answer/10863708). If disabled, such bids will continue to work with any relevant line items in your network. +- *Allow ads on child-directed requests*: When enabled, the associated bidder’s ads may show on inventory that is classified in Ad Manager as child-directed. + +{:start="6"} +6. Click *Continue*. +7. Select *Run Prebid on entire network* + +![Run Prebid](/assets/images/ad-ops/gam-hbt-sbs/hbt-run-prebid.png) + +{:start="8"} +8. Click *Finish*. Your Ad Manager UI should look like this, with your own bidders and specified configuration settings listed. + +![Finished](/assets/images/ad-ops/gam-hbt-sbs/hbt-setup-finished.png) + +## Header bidding reporting + +Historical reporting in Ad Manager helps you understand how header bidding is performing. + +- Use the Bidder dimension to see performance by exchange. In Data Transfer files, this is called Buyer Network. +- Add the Demand Channel dimension to see whether buyers accessed your inventory through header bidding (the Demand Channel dimension has a value of “Header bidding”). This is called Product in Data Transfer files. + +## Using protections with header bidding + +To exclude the header bidders from the auction: + +- Create an [inventory exclusion protection](https://support.google.com/admanager/answer/9376326). +- Select the header bidding demand source and appropriate targeting. +- To exclude certain formats from Header Bidding Trafficking, you can create an + inventory exclusion that targets the relevant hb_format key-value. Header + Bidding Trafficking supports display and outstream video, but not native ads. diff --git a/adops/gam-native.md b/adops/gam-native.md index f8e81e65cd..c3ab7c68f5 100644 --- a/adops/gam-native.md +++ b/adops/gam-native.md @@ -1,90 +1,93 @@ --- layout: page_v2 -title: Setting up Prebid Native in Google Ad Manager -head_title: Setting up Prebid Native in Google Ad Manager -description: Setting up Prebid Native in Google Ad Manager +title: GAM Step by Step - Native Creatives +head_title: GAM Step by Step - Native Creatives +description: Set up native creatives for Prebid in Google Ad Manager. sidebarType: 3 --- -# Setting up Prebid Native in Google Ad Manager -{: .no_toc} - -This page describes how to set up native creatives in Google Ad Manager for use with Prebid.js. +# GAM Step by Step - Native Creatives -For more information about Google Ad Manager native ad setup, see the [Google Ad Manager native ads documentation](https://support.google.com/admanager/answer/6366845). - -{% capture version2 %} -This document replaces the [original documentation](/adops/setting-up-prebid-native-in-dfp.html) that described how to set up Prebid.js native for GAM. That documentation is still valid, but the approach described here is better in every way, so we recommend that all new and revised implementations follow this approach. Here are the key differences between the original approach and the preferred approach described in this document: -{::nomarkdown} -
    -
  • The macro format is different: instead of using AdServer-defined macros, Prebid.js now has its own macro format. -
  • Targeting variables aren't sent from Prebid.js to the AdServer. Rather, they're queried at display time. -
  • A different rendering library is used. - -{:/} -{% endcapture %} -{% include alerts/alert_important.html content=version2 %} +{: .no_toc} * TOC {:toc} -{: .alert.alert-info :} -Manually configuring GAM for Prebid can be a fair amount of work. -Consider using our official command line tool, [Prebid Line Item Manager](/tools/line-item-manager.html), to create the setup. Using this tool may save you time and help you avoid mistakes. +This page walks you through the steps required to create a native ad template and a native creative to attach to your Prebid line items in Google Ad Manager (GAM). +{: .alert.alert-success :} +For complete instructions on setting up Prebid line items in Google Ad Manager, see [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html). -## 1. Create a native ad +For more information about Google Ad Manager native ad setup, see the [Google Ad Manager native ads](https://support.google.com/admanager/answer/6366845) documentation. -From Google Ad Manager, select **Delivery > Native**. Click **Create Native Ad**. +## Create a Native Ad -![native delivery](/assets/images/ad-ops/dfp-native/create_prebid_native.png){: .pb-md-img :} +1. In GAM, select **Delivery** > **Native**. +2. Click **New native ad** and select **Single ad**. -Select the **HTML & CSS editor** option. +{: .alert.alert-info :} +For information on the Multiplex ad option, see the [Traffic Multiplex ads](https://support.google.com/admanager/answer/9428537) GAM documentation. -![HTML editor option](/assets/images/ad-ops/dfp-native/prebid_native_html_option.png){: .pb-md-img :} +{:start="3"} +3. Under **HTML & CSS editor**, click **Select**. This will slide out the **New native style** window. -## 2. Define settings for native format +### Define Settings for Native Format -For **Ad size** you can select a specific size for the ad unit or specify the "fluid" size. In this case we'll go with **Fluid**. +1. Under **Ad size** you can select a specific size for the ad unit or specify the "fluid" size. In this case we'll go with **Fluid**. +2. Under **Custom format**, select **New format**. (If you’ve already created an ad unit with the format you want, you can select **Existing format** and select the format to apply to this ad unit.) +3. Enter a **Format name**, such as `pb-native-fluid`. +4. Click **Add variable**. This will slide out the **New variable** window. -Under **Custom format**, select **New format**. (If you’ve already created an ad unit with the format you want, you can select Existing format and select the format to apply to this ad unit.) +Every format needs at least one variable. Don't worry, you can add more later. GAM requires at least one variable in order to move on to the next step. -Every format needs at least one "variable". In this example we've added **title** as a variable. Don't worry, you can add more later. Or not. Either way, GAM requires at least one variable in order to move on to the next step. +{:start="5"} +5. Type in a **Variable name**. In this example, we've used the name `title`. +6. Click **OK**. -![native adunit settings](/assets/images/ad-ops/dfp-native/gam-native-format.png){: .pb-md-img :} +![Native adunit settings](/assets/images/ad-ops/gam-sbs/gam-native-format.png){: .pb-md-img :} -When done, click **Continue**. +{:start="7"} +7.Click **Continue**. -## 3. Style your native ad +### Style Your Native Ad -Next, add the HTML and CSS to define your native ad template. To allow for trackers, titles, images, and other assets within a Prebid native creative template, you’ll need to include a CDN-hosted script in the HTML. +1. The first step in styling your native ad is to add the HTML and CSS to define your native ad template. To allow for trackers, titles, images, and other assets within a Prebid native creative template, you’ll need to include a CDN-hosted script in the HTML. -![native ad styling](/assets/images/ad-ops/dfp-native/gam-native-template.png){: .pb-xlg-img :} +![native ad styling](/assets/images/ad-ops/gam-sbs/gam-native-template.png){: .pb-xlg-img :} {: .alert.alert-warning :} Any link that needs to fire a click tracker must include `class='pb-click'`. If this creative is served, it will fire impression trackers on load. Clicking the link will fire the click tracker and the link will work as normal, in this case going to the `hb_native_linkurl` destination. -The creative template HTML will depend on which of the three scenarios you're implementing, as described in the [Native Implementation Guide](/prebid/native-implementation.html). You can choose to manage the native template: +The creative template HTML will depend on which of the three scenarios you're implementing. You can choose to manage the native template: + +* in GAM ([Managing the Native Template in GAM](#managing-the-native-template-in-gam) below) +* in the Prebid.js AdUnit ([Managing the Native Template Outside of GAM](#managing-the-native-template-outside-of-gam) below) +* in a separate JavaScript file ([Managing the Native Template Outside of GAM](#managing-the-native-template-outside-of-gam) below) -- in GAM ([section 3.1](/adops/gam-native.html#31-managing-the-native-template-in-gam) below) -- in the Prebid.js AdUnit ([section 3.2](/adops/gam-native.html#32-managing-the-native-template-outside-of-gam) below) -- in a separate JavaScript file ([section 3.2](/adops/gam-native.html#32-managing-the-native-template-outside-of-gam) below) +{: .alert.alert-info :} +For engineering instructions, see [Native Implementation Guide](/prebid/native-implementation.html). + +{:start="2"} +2. After entering your HTML and CSS per the approriate instructions below, click **Continue**. +3. Add any targeting you want to apply and click **Save and activate** (or **Save** if you're not yet ready to activate your template.) +4. Provide a **Name** for your native style and click **Save**. -### 3.1. Managing the native template in GAM +#### Managing the Native Template in GAM There are three key aspects of the native template: -1. Build the creative with special Prebid.js macros, e.g. `##hb_native_assetname##`. See the appendix for an exhaustive list of assets and macros. Note that macros can be placed in the body (HTML) and/or head (CSS) of the native creative. -2. Load the Prebid.js native rendering code. You may utilize the jsdelivr version of native-render.js or host your own copy. If you use the version hosted on jsdelivr, make sure to declare jsdelivr as an ad technology provider in GAM. Admin → EU User Consent → Declare ad technology providers +1. Build the creative with special Prebid.js macros, e.g. `##hb_native_assetname##`. Note that macros can be placed in the body (HTML) and/or head (CSS) of the native creative. +2. Load the Prebid.js native rendering code. You can utilize the jsdelivr version of native.js or host your own copy. If you use the version hosted on jsdelivr, make sure to declare jsdelivr as an ad technology provider in GAM. (Go to **Privacy & messaging** and click the Settings icon under **GDPR**. Under **Review your ad partners** click into **Commonly used ad partners**.) See Step 6 under [Create a New Native Creative](#create-a-new-native-creative) below. 3. Invoke the Prebid.js native rendering function with an object containing the following attributes: - - adid - used to identify which Prebid.js creative holds the appropriate native assets - - pubUrl - the URL of the page, which is needed for the HTML postmessage call - - requestAllAssets - tells the renderer to get all the native assets from Prebid.js. + * adid - Used to identify which Prebid.js creative holds the appropriate native assets. + * pubUrl - The URL of the page, which is needed for the HTML postmessage call. + * requestAllAssets - Tells the renderer to get all the native assets from Prebid.js. Example creative HTML: -``` + +```html - + ``` {: .alert.alert-warning :} -When using `Send All Bids` you should update `pbNativeTagData.adId = "%%PATTERN:hb_adid_biddercode%%";` for each bidder’s creative +When using Send All Bids, use `pbNativeTagData.adId = "%%PATTERN:hb_adid_BIDDERCODE%%";` rather than `pbNativeTagData.adId = "%%PATTERN:hb_adid%%";` for each bidder’s creative, replacing `BIDDERCODE` with the actual bidder code, such as `%%PATTERN:hb_adid_BidderA%%`. Example CSS: -``` + +```css .sponsored-post { background-color: #fffdeb; font-family: sans-serif; @@ -156,71 +160,104 @@ p { } ``` -### 3.2. Managing the native template outside of GAM +#### Managing the Native Template Outside of GAM The GAM creative is identical whether the template is defined in the AdUnit or the external render JavaScript. There are two key aspects of the native creative in this scenario: -1. Load the Prebid.js native rendering code. You may utilize the jsdelivr version of native-render.js or host your own copy. If you use the version hosted on jsdelivr, make sure to declare jsdelivr as an ad technology provider in GAM. Admin → EU User Consent → Declare ad technology providers +1. Load the Prebid.js native rendering code. You may utilize the jsdelivr version of native.js or host your own copy. If you use the version hosted on jsdelivr, make sure to declare jsdelivr as an ad technology provider in GAM. Admin → EU User Consent → Declare ad technology providers. 2. Invoke the Prebid.js native rendering function with an object containing the following attributes: - - adid - used to identify which Prebid.js creative holds the appropriate native assets - - pubUrl - the URL of the page, which is needed for the HTML postmessage call - - requestAllAssets - tells the renderer to get all the native assets from Prebid.js. + * adid - Used to identify which Prebid.js creative holds the appropriate native assets. + * pubUrl - The URL of the page, which is needed for the HTML postmessage call. + * requestAllAssets - Tells the renderer to get all the native assets from Prebid.js. Example creative HTML: -``` - + +```html + ``` {: .alert.alert-warning :} -When using `Send All Bids` you should update `pbNativeTagData.adId = "%%PATTERN:hb_adid_biddercode%%";` for each bidder’s creative +When using Send All Bids, use `ucTagData.adId = "%%PATTERN:hb_adid_BIDDERCODE%%";` rather than `ucTagData.adId = "%%PATTERN:hb_adid%%";` for each bidder’s creative, replacing `BIDDERCODE` with the actual bidder code, such as `%%PATTERN:hb_adid_BidderA%%`. -The example CSS in section 3.1 applies here as well. +The example CSS in the previous section applies here as well. +## Create a New Native Creative -## 4. Create new native order and line items +Now that you've defined your native template you can create your native creatives. -1. Create a new order as usual. -2. Create a new line item as usual, selecting Ad type "Display". -3. Add your native format in the "Expected creatives" section. +1. Select **Display** > **Creatives** and click **New creative**. +2. Select your advertiser. +3. Under **Native Format** select the native template you just created and click **Continue**. - -![create a native order and line item](/assets/images/ad-ops/dfp-native/gam-line-item.png){: .pb-md-img :} +![Native Format](/assets/images/ad-ops/gam-sbs/native-format.png){: .pb-md-img :} {:start="4"} -4. For targeting, set inventory targeting and key-value targeting on `hb_pb` or `hb_pb_BIDDER` corresponding to the line item’s CPM. -5. Save the line item +4. Under **Settings**, enter a **Name** for your creative. +5. Enter any value into the **Click-through URL** field; this value will be overwritten by the native asset values. Also, if you operate in Europe and are using the jsdelivr-hosted native.js, make sure you set jsdelivr as your ad technology provider. (See Step 6 below.) +![Native Creative](/assets/images/ad-ops/gam-sbs/gam-new-creative-part2.png){: .pb-md-img :} -## 5. Create a new native creative +{:start="6"} +6. If you're using jsdelivr, set your **Associated ad technology provider**: -1. After saving the line item, click on **Creatives** and then **New creative**. +{% include /adops/adops-creative-declaration.html %} -![create a new native creative](/assets/images/ad-ops/dfp-native/gam-new-creative.png){: .pb-md-img :} +{:start="7"} +7. Click **Save and preview**. -{:start="2"} -2. On the creative type screen choose **Native Format** and select the format you created above. +### Create Mobile In-App Creative -![Native Format](/assets/images/ad-ops/dfp-native/gam-creative-type.png){: .pb-md-img :} +Use these instructions if you integrate In-App native ads on [iOS](/prebid-mobile/pbm-api/ios/ios-sdk-integration-gam-original-api.html#in-app-native) or [Android](/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html#in-app-native). The difference is in choosing the GAM option for supporting Android & iOS app code. -{:start="3"} -3. Under **Settings**, enter a Name for your creative. Enter any value into the **Click-through URL** field; this value will be overwritten by the native asset values. Also, if you operate in Europe and are using the jsdelivr-hosted native-render.js, make sure you set jsdelivr as your ad technology provider. +1. Sign in to Google Ad Manager. +2. Create an ad unit with fluid ad size. +3. Click `Delivery` and then `Native` +4. Click `New native style`. +5. Click `Android & iOS app code`. +6. Name your new format. +7. Choose `Add variable` and add the following variable names and placeholders as type `text`. -![Native Creative](/assets/images/ad-ops/dfp-native/gam-new-creative-part2.png){: .pb-md-img :} +{: .table .table-bordered .table-striped } +| Variable Name | Placeholder | Type | +|---------------------+-------------------------+------| +| isPrebid | [%isPrebid%] | Text | +| hb_cache_id_local | [%hb_cache_id_local%] | Text | -{:start="4"} -4. Click **Save**. -5. Review the order, line item, and creative. -6. Approve the order as needed. +Make sure to indicate that the variables are required. + +{:start="8"} +8. Hit "Save". +9. Return to the home screen, click `Delivery > Creatives`, and create a creative with `Native Format`, choosing the format you created. +10. Choose a creative name and other desired settings. In the user-defined variables you just created, set the following values: + +{: .table .table-bordered .table-striped } +| Variable Name | Value | +|---------------------+----------------------------------| +| isPrebid | 1 | +| hb_cache_id_local | %%PATTERN:hb_cache_id_local%% | + +{:start="11"} +11. Create Prebid line items with price priority and a display ad type that is targeting `hb_pb key-values`. Associate the creative you added in steps 4 thru 8 (making sure to choose your native format as expected creatives on the line item) to the ad unit you created in the second step. + +## Attach the Creative to Your Line Item + +Follow the instructions in [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html#duplicate-creative) to duplicate your creative and attach it to your line item. ## Further Reading -- [Prebid Native Format](/formats/native.html) -- [Prebid Native Implementation Guide](/prebid/native-implementation.html) +* [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) +* [Prebid Native Implementation Guide](/prebid/native-implementation.html) +* [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) +* [Prebid Universal Creatives](/overview/prebid-universal-creative.html) +* [Creative Considerations](/adops/creative-considerations.html) +* [Ad Ops Planning Guide](/adops/adops-planning-guide.html) diff --git a/adops/js-dynamic-creative.md b/adops/js-dynamic-creative.md new file mode 100644 index 0000000000..3eb5fc493a --- /dev/null +++ b/adops/js-dynamic-creative.md @@ -0,0 +1,45 @@ +--- +layout: page_v2 +title: Prebid.js dynamic creatives +head_title: Prebid.js dynamic creatives +sidebarType: 3 +--- + +# Prebid.js dynamic creatives +{:.no_toc} + +- TOC +{: toc} + +## Overview + +For line items that target browsers only, you may use Prebid.js dynamic creatives as an alternative to [Prebid Universal Creative](/overview/prebid-universal-creative.html). The former provides slightly better performance and ease of use, but relies on Prebid.js, meaning that it does not support non-JS use cases (such as mobile apps or AMP). + +## Comparison vs PUC for Prebid.js + +A creative set up to use Prebid Universal Creative: + +- loads a separate script, typically from a CDN; the script contains various rendering routines, including some specific to Prebid.js; +- if the script determines that the ad render was initiated by Prebid.js, it retrieves from it information about the winning bid and renders it; +- requires different setups for different use cases (such as banner vs native). + +A Prebid.js dynamic creative: + +- does not load any additional script - it's instead set up with a small block of inline Javascript; +- it expects to always find Prebid.js, retrieving from it information about the winning bid _and_ the rendering logic to use for it; +- uses the same setup for all cases - but does not work when the render is not initiated by Prebid.js. + +## How to use + +{: .alert.alert-warning :} +Dynamic creatives require Prebid.js version 8.36 or higher. + +Set up the creative following [this example](https://github.com/prebid/Prebid.js/blob/master/integrationExamples/gpt/x-domain/creative.html). If you are not using GAM, replace the macros in the second `script` tag with appropriate equivalents. + +To render native ads, you also need to include the [nativeRendering](/dev-docs/modules/nativeRendering.html) module in your Prebid.js bundle. + +## Further reading + +- [Creative Considerations](/adops/creative-considerations.md) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Native rendering module](/dev-docs/modules/nativeRendering.html) diff --git a/adops/key-values.md b/adops/key-values.md new file mode 100644 index 0000000000..6c2f77d784 --- /dev/null +++ b/adops/key-values.md @@ -0,0 +1,108 @@ +--- +layout: page_v2 +title: Key Values +head_title: Key Values +sidebarType: 3 +sbUUID: 3.2 +--- + +# Key Values + +{: .no_toc } + +- TOC +{: toc } + +Prebid uses key-value pairs to pass bid information to the ad server. This puts key values at the core of how Prebid works. Without key values, Prebid would have no way of communicating with ad servers, and therefore no way to make header bidding part of the auction. This document explains how bid information is sent to the ad server, what information is sent, and options for modifying the amount and types of information that is sent. + +## Sending Bids to the Ad Server + +Prebid sends information to the ad server about the bids it receives by creating a query string of key-value pairs (KVPs) and attaching it to the ad request that is sent to the ad server. A portion of that query string might look something like this: + +`?hb_pb=1.50&hb_adid=234234&hb_bidder=bidderA` + +In this example, hb_pb is the bid price bucket (1.50), hb_adid is an identifier for the specific bid (234234), and hb_bidder is the name of the bidding SSP or exchange (bidderA). In order for a bid that comes from the header bidding process to compete with bids on the ad server, you must have line items set up with key values that match the KVPs in the query string. + +## Prebid Keys + +This table lists the keys that can be sent from Prebid to the ad server. Depending on the media type, most of these keys are sent by default. + +{: .alert.alert-info :} +You can work with your engineers to modify the default list. See [Restricting Data Sent to the Ad Server](#restricting-data-sent-to-the-ad-server) below for more information. + +{: .table .table-bordered .table-striped } +| Key | Usage | Scenario | Description | Example Value | +| --- | ----- | -------- | ----------- | ------------- | +| hb_pb | targeting | All | The bid price bucket (adjusted for price granularity). | 2.10 | +| hb_adid | rendering | All | The ad ID. Used by the Prebid Universal Creative (PUC) ad server creative to render the winning Prebid ad. | 123456 | +| hb_bidder | targeting and reporting | Could be used for creative-level targeting in video scenarios; reporting for all scenarios | The bidder code. Used for logging and reporting to learn which bidder has higher fill rate/CPM. | BidderA | +| hb_size | rendering | Banner, native, outstream. Not used for video. | The size used for resizing the iframe for the winning creative. | 300x250 | +| hb_format | targeting and reporting | Needed only if there's a different set of line items for different media types | Used when creating a separate set of line items for banner vs video | video | +| hb_deal | targeting | All | Target private marketplace deals | 7777777 | +| hb_uuid | rendering | Video only | Carries the cache retrieval ID for VAST video creatives | 1111-2222-3333-4444 | +| hb_cache_id | rendering | Banner, native, outstream; mobile app only | Carries the cache retrieval ID for mobile bids | 2222-3333-4444-5555 | +| hb_cache_host | rendering | Banner, native, outstream; mobile app only | The host where the cached creative lives | `"https://mycachehost.example.com"` | +| hb_cache_path | rendering | Banner, native, outstream; mobile app only | The web path where the cached creative lives | /cache | +| hb_source | reporting | Server-to-server testing | Used to report the A/B test results for client- vs server-side performance. | s2s | +| hb_adomain | reporting and special | All | Used to report on VAST errors, set floors on certain buyers, monitor volume from a buyer, or track down bad creatives | example.com | + +When you’re sending the [Top Price Bid](/adops/send-all-vs-top-price.html) to the ad server, the preceding keys are the only keys that will be sent. If you’re [Sending All Bids](/adops/send-all-vs-top-price.html), the preceding keys will be sent, plus the same set of keys specific to each bidder, with the bidder name appended. For example, if you receive bids from BidderA and BidderB, the keys hb_pb, hb_pb_BidderA, and hb_pb_BidderB will all be sent to the ad server with the values provided by the associated bidders. (Even in that scenario, the "winning" keys [hb_pb, etc.] will still have the values for the top bid.) + +## Key Value Pair Usage + +KVPs sent from Prebid are used in the ad server for a variety of purposes: targeting, reporting, creative rendering, and to supply additional information. + +### Targeting + +Targeting KVPs are used to pick out which line items match the request, or possibly which creative within a line item should be used. They will need to be entered in the line items you create to capture the bids coming in from Prebid. These key values can also be used in reports. + +{: .alert.alert-success :} +It's also possible to use regular ad server targeting values on header bidding line items. For example, if you want to have different price granularities in one country, you could create multiple sets of line items differentiated by country. + +### Reporting + +Some publishers rely on ad server KVPs for important business reporting. Reporting on the Prebid keys can help you determine the performance of your header bidding partners and your overall Prebid configuration. Key values that are for reporting only are not entered in line items. Depending on your ad server, reporting keys might need to be created in the ad server in order to be used in reporting. + +### Rendering + +These values are needed for rendering the creative properly when the Prebid line item is chosen. + +### Special Usage + +The hb_adomain key was created to provide additional information about a bid or to help with troubleshooting. See [setConfig](/dev-docs/publisher-api-reference/setConfig.html#details-on-the-allowtargetingkeys-setting) for engineering information on using the hb_adomain key. + +## Restricting Data Sent to the Ad Server + +When Prebid creates the query string that is sent to the ad server, it includes a default set of keys (along with the associated values provided by the demand partners). However, you might not need or want all the default values, or maybe you need additional values. Because of this, Prebid provides tools that allow for modifications to the amount of data sent to the ad server. + +You’ll need to determine which keys you want sent and then work with your engineers to ensure the keys that are sent match those you’re expecting. Some things to consider: + +How much information do you need and want? +Does your ad server have restrictions on the amount of data it can receive? + +### Key Values in Your Configuration + +The information you need and want are entirely dependent on your configuration and usage requirements. Maybe not all the reporting keys are useful to you, in which case you can omit some or all of those keys. Making sure the keys you need match the keys that are sent to the ad server will help ensure the targeting and reporting you’ve set up on your ad server work correctly. + +### Query String Restrictions + +Some ad servers restrict the number of characters they’ll accept on the query string. When you use [Send All Bids](/adops/send-all-vs-top-price.html), the number of key value pairs sent to the ad server can be very large, depending on the number of bidders and ad slots.This large number of key value pairs can make for a very long query string. + +If the query string has too many characters, an ad server with restrictions could simply truncate the string to the length it will accept. This could prevent bids from being received, or could truncate a bidder’s key values to the point where they won’t match any line items. Fortunately, Prebid can be configured to deal with this issue. + +In addition to being able to specify which keys to send, Prebid can also be configured to limit the length of the query string that will be appended to the ad request. Prebid will prioritize the bids to ensure top bids and deals are included, along with all of their associated key value pairs. + +{: .alert.alert-info :} +For details on how Prebid prioritizes bids based on query string length, see “Details on the auctionKeyMaxChars setting“ under [Configure Targeting Controls](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls). + +Reducing the number of default keys sent and limiting the number of bidders will reduce the length of the query string. Work with your engineers to evaluate the typical length of your query strings and make modifications as necessary to achieve the best results for your organization. + +{: .alert.alert-info :} +For engineering information on configuration options, see [Prebid.js Controls](/features/adServerKvps.html#controls). In particular, note the following: + [Configure Targeting Controls](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls). + +## Further Reader + +- [Planning Guide](/adops/adops-planning-guide.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Deals in Prebid](/adops/deals.html) diff --git a/adops/line-item-creation.md b/adops/line-item-creation.md new file mode 100644 index 0000000000..51abec0d1e --- /dev/null +++ b/adops/line-item-creation.md @@ -0,0 +1,176 @@ +--- +layout: page_v2 +title: Line Item Creation +head_title: Line Item Creation +sidebarType: 3 +sbUUID: 3.2 +--- + +# Line Item Creation + +{: .no_toc } + +- TOC +{: toc } + +The settings you apply when creating line items to capture bids coming in from the header bidding process are typically different from those you apply when creating line items for house ads. This document will walk you through some of the differences, and outline requirements and recommendations for creating line items to work with Prebid. + +{: .alert.alert-success :} +Manually configuring ad server elements for Prebid can be a fair amount of work. If you’re using Google Ad Manager (GAM), consider using our official command line tool, [Prebid Line Item Manager](/tools/line-item-manager.html#prebid-line-item-manager.html), to create the setup. Using this tool may save you time and help you avoid mistakes. + +## Advertisers and Orders + +Line items (and creatives) must, at some level, be associated with advertisers. When you create line items to capture Prebid bids, you won’t know who the actual advertisers are. Instead you need to create generic advertisers in your ad server that are used for Prebid. For example, you can create an advertiser named “Prebid Advertiser.” Or if you’re using Send All Bids, you can create one advertiser per bidder, such as “Prebid BidderA,” “Prebid BidderB,” etc. You then associate your line items and creatives with those advertisers. + +Depending on your ad server, line items are typically grouped within orders under each advertiser. + +## Line Item Details + +You have many options for the way in which you set up your line items. The following are Prebid requirements, and also some recommendations, to ensure bids are captured correctly and to make keeping track of your header bidding line items easier. + +### At a Glance + +These tables show the Prebid line item recommendations and requirements. The following sections provide more details on each. + +**Required** + +{: .table .table-bordered .table-striped } +| Detail | Requirement | +| ------ | ----------- | +| Line Item Type | Price Priority (depending on your ad server) | +| Key Value Pricing | Include the number of decimal places that are defined in the price granularity precision. Normally this is two decimal places, e.g. hb_pb=0.50 or hb_pb=1.00 | + +**Recommended** + +{: .table .table-bordered .table-striped } +| Detail | Recommendation | +| ------ | -------------- | +| Line Item Groups | Determine the number of containers you'll need to store the line items based on price granularity, number of bidders, and ad server restrictions. Name your group in the format Prebid, format, bidder name (for [Send All Bids](/adops/send-all-vs-top-price.html)), and unique number; for example, `Prebid - banner - BidderA - 1`. | +| Line Item Name | Name each line item for the header bidding price bucket. Use the naming pattern Prebid, mediatype, bidder (for Send All Bids), and price bucket; for example, `Prebid - banner - BidderA - 1.50`. | +| Creative Name | In the creative name, include Prebid, the media type and the size (if applicable), and a unique identifying number (if more than one creative of a given size is attached to the line item). If using Send All Bids, also include the bidder name; for example, `Prebid - banner - BidderA - 1x1 - 1`. | +| Start and End Dates | Start immediately, no end date | +| Priority | Above house ads but below directly sold ads | +| Impression Goal | None | +| Media Types | Group media types by price granularity. This typically means you can group banner, outstream video, and native together but video will be a separate set of line items. | + +### Line Item Type + +If your ad server supports it, you should set your line item type to Price Priority, which will let it compete with bids from other sources. + +### Key Value Pricing + +When you enter your key values for price, you must include the number of digits following the decimal point that are specified with your [price granularity](/adops/price-granularity.html). This is known as the precision value. For example, if Prebid is configured with a precision of two decimal places, then when you enter a value for the key hb_pb you must include two decimal places in your value: 0.50 or 1.00 rather than 0.5 or 1. If you don’t include the correct number of decimal places, your line item will not match any header bidding values. + +For predefined Prebid price granularities the precision is 2; for custom price granularities this value can be defined in your Prebid configuration. + +{: .alert.alert-info :} +Engineering instructions for setting the precision value can be found in [setConfig Price Granularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity). + +See [Key Values](/adops/key-values.html) for general information about key value pairs. + +### Line Item Groups + +If you are [sending all bids](/adops/send-all-vs-top-price.html) to the ad server, you’ll most likely want to group your line items by bidder. (In Google Ad Manager this means creating at least one set of orders per bidder, with that bidder’s line items attached to the order.) This allows each group to have a set of line items that use the same targeting keywords, all of which include the bidder’s name. For example, if you are working with BidderA, all line items within a group would use the key hb_pb_BidderA in the line item’s key-value targeting, and hb_adid_BidderA in the attached creative. + +Depending on your ad server and the number of line items you’re creating, you might need more than one group per bidder. For example, suppose you need to create 2000 line items for one bidder. If GAM is your ad server, you’re allowed only 450 line items per order, so you will need five orders per bidder to store the 2000 line items, for a total of 25 orders. + +We recommend naming the group to include “Prebid”, media type, the bidder name, and also a number or other identifier if you need more than one group per bidder. For example, `Prebid - banner - BidderA - 1`. For [Send Top Price Bid](/adops/send-all-vs-top-price.html) you can omit the bidder name: `Prebid - banner - 1`. + +### Line Item Name + +Because you’ll be creating one line item per price within each [price bucket](/adops/price-granularity.html), it’s helpful to name your line items based on the price. It can also be helpful to include the mediatype, since different types of media could be priced the same. Some examples include `Prebid - banner - 1.00`, `Prebid - video - 1.50`, etc. If you’re [sending all bids](/adops/send-all-vs-top-price.html), include the bidder code: `Prebid - banner - BidderA - 1.00`, `Prebid - banner - BidderA - 1.50`. + +### Creative Name + +We recommend naming creatives to include the media type, size (where applicable), and a number if there is more than one. For example, `Prebid - banner - BidderA - 1x1 - 1`; `Prebid - video - BidderA - 1`. + +### Start and End Dates + +With header bidding, start and end dates of the actual ad campaigns are controlled by the header bidding demand partners. The demand partners check their inventory and bid for an ad slot based on campaigns running on their systems. The line items you’re creating are generic and immortal line items created to capture a bid from a campaign your demand partner will be running at some point in the future. + +What this means is that you typically don’t want to include an end date in your line items. Your line item will always be active to read in bids coming from your demand partner. + +Set your start date to begin immediately. + +### Priority + +Unless you’re working with [deals](/adops/deals.html), bids received from header bidding will typically have a priority lower than directly sold ads but higher than any competing house ads. + +### Impression Goal + +We recommend you do not set an impression goal. Because these are general line items with (typically) no end date, there’s no need to set a goal. + +### Media Types + +Prebid supports many media types, and you can set up a single line item with multiple types. The media types you choose can impact the way in which you decide to organize your line items. + +Grouping media types within line items is typically dictated by the pricing structure: + +- Banner, outstream video, and native generally run together because they have similar pricing expectations and therefore can share [price granularities](/adops/price-granularity.html). +- Instream video is normally created as a separate set of line items because they are usually priced higher than other formats, often requiring custom price granularity. + +You must set a key value for each format used by an ad unit using the hb_format (or hb_format_BIDDER) key and setting its value to the appropriate format. For example, if the ad unit is set up as a banner ad, you would target hb_format=banner (along with the price, such as hb_pb=1.00). If your ad unit supports multiple types, set the key value to include all types: `hb_format` in `banner`,`native`. + +## Example Line Item Setup + +Here's an example that encapsulates a number of the key decisions outlined in this document. In this scenario, we’ve made the following decisions: + +- Send Top Bid +- Banner granularity: high +- Video granularity: custom +- Order naming pattern: Prebid - banner - N, Prebid - video - N +- Line Item naming pattern: Prebid - banner - PRICE, Prebid - video - PRICE +- Creative naming pattern: Prebid - banner - 1x1 - N, Prebid - video - N +- Choosing to make three copies of each creative + +The granularity we’ve chosen means we’ll be creating 2000 line items for banner and 1000 line items for video. Those line items will be named as shown here: + +- Order: Prebid - banner - 1 + - LI: Prebid - banner - 0.00 (If the bid is less than 1 penny, it rounds down to 0, but is still worth something) + - Creative: Prebid - banner - 1x1 - 1 + - Creative: Prebid - banner - 1x1 - 2 + - Creative: Prebid - banner - 1x1 - 3 + - LI: Prebid - banner - 0.01 + - ... creatives ... + - LI: Prebid - banner - 0.02 + - LI: Prebid - banner - 0.03 + - ... + - LI: Prebid - banner - 4.49 +- Order: Prebid - banner - 2 + - LI: Prebid - banner - 4.50 + - LI: Prebid - banner - 4.51 + - LI: Prebid - banner - 4.52 + - LI: Prebid - banner - 4.53 + - ... + - LI: Prebid - banner - 09.49 +- ... other banner orders up to 20.00 ... + +- Order: Prebid - video - 1 + - LI: Prebid - video - 0.00 + - Creative: Prebid - video - 1 + - Creative: Prebid - video - 2 + - Creative: Prebid - video - 3 + - LI: Prebid - video - 0.05 + - LI: Prebid - video - 0.10 + - ... +- ... + +If we had chosen Send All Bids (the Prebid default), every element shown above would be recreated for each bidder, and each name would include the bidder name. For example: + +- Order: Prebid - banner - BidderA - 1 + - LI: Prebid - banner - BidderA - 0.00 + - Creative: Prebid - banner - BidderA - 1x1 - 1 + - Creative: Prebid - banner - BidderA - 1x1 - 2 + - Creative: Prebid - banner - BidderA - 1x1 - 3 +- ... + +## Next Step + +[Price Granularity](/adops/price-granularity.html) + +## Further Reader + +- [Planning Guide](/adops/adops-planning-guide.html) +- [Key Values for Ad Ops](/adops/key-values.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Deals in Prebid](/adops/deals.html) diff --git a/adops/mobile-rendering-admob-line-item-setup.md b/adops/mobile-rendering-admob-line-item-setup.md new file mode 100644 index 0000000000..39db9166ad --- /dev/null +++ b/adops/mobile-rendering-admob-line-item-setup.md @@ -0,0 +1,86 @@ +--- + +layout: page_v2 +title: Prebid Mobile Rendering Modules +description: Prebid Mobile Rendering Modules architecture +sidebarType: 3 + +--- + +# AdMob Setup + +## Mediation Group Setup + +### Step 1: Create Mediation Group + +In your AdMob account go to `Mediation` and click on `Create Mediation Group`: + + Pipeline Screenshot + +Choose one of the ad formats: + +- Banner +- Interstitial +- Native Advanced +- Rewarded interstitial + +Choose a platform - iOS or Android. + +Press `CONTINUE`. Then set the name for the mediation group and other properties: + +Pipeline Screenshot + +Press `ADD AD UNITS` and select the target items in the modal dialog: + +Pipeline Screenshot + +Press `DONE`. And move to the next step. + +### Step 2: Add Custom Events + +Pipeline Screenshot + +Now you have to add custom events for possible bid prices. Follow the [price granularity](/adops/price-granularity.html) guide to determine how many entries you need. + +Press `ADD CUSTOM EVENT`: + +Pipeline Screenshot + +Set the `Label` and `eCPM` for the custom event. Press `CONTINUE`. + +Pipeline Screenshot + +The fields in this dialog are critical for the proper integration: + +- `Class Name` is a name of respective adapter. + - Banner: + - iOS: `PrebidAdMobBannerAdapter` + - Android: `org.prebid.mobile.admob.PrebidBannerAdapter` + - Interstitial Display: + - iOS: `PrebidAdMobInterstitialAdapter` + - Android: `org.prebid.mobile.admob.PrebidInterstitialAdapter` + - Interstitial Video: + - iOS: `PrebidAdMobVideoInterstitialAdapter` + - Android: `org.prebid.mobile.admob.PrebidInterstitialAdapter` + - Rewarded: + - iOS: `PrebidAdMobRewardedVideoAdapter` + - Android: `org.prebid.mobile.admob.PrebidRewardedAdapter` + - Native: + - iOS: `PrebidAdMobNativeAdapter` + - Android: `org.prebid.mobile.admob.PrebidNativeAdapter` +- `Parameter` is a keywords for the current ad source. **Important**: make sure that the price of the ad source is the same as the price in this keyword. For example: + +```json +{"hb_pb":"0.10"} +``` + +Prebid SDK will compare the keywords in the winning bids with keywords provided in the `Parameter` fields. + +{: .alert.alert-warning :} +The adapter will render the winning bid only if the bid's targeting keywords contain `all` keywords from the Parameter field. + +Press `DONE` and repeat the adding of the custom events for all needed prices. + +Pipeline Screenshot + +Once you add all needed custom events - press `DONE`. The Mediation Group is ready to serve the prebid demand to your app. diff --git a/adops/mobile-rendering-gam-line-item-setup.md b/adops/mobile-rendering-gam-line-item-setup.md new file mode 100644 index 0000000000..f9d35b6da5 --- /dev/null +++ b/adops/mobile-rendering-gam-line-item-setup.md @@ -0,0 +1,204 @@ +--- + +layout: page_v2 +title: Prebid Mobile Rendering GAM Line Item Setup +description: Prebid Mobile Rendering Modules GAM line item setup +sidebarType: 3 + +--- + +# Google Ad Manager Setup + +## Step 1: Create New Order + + Pipeline Screenshot + +## Step 2: Create Line Item + +To integrate the Prebid demand you have to create a Line Items with a specific price and targeting keywords. + +> Even though a Line Item can be named in any way, we strongly recommend to use the price or targeting keyword in the name. It will help to navigate through hundreds of them. + +### Select Type + +Create a Line Item depending on the type of expected creative kind: + +* **Display** - for the Banner, HTML Interstitial +* **Video and Audio** - for the Video Interstitial, Rewarded Video, and Outstream Video ads. + +Pipeline Screenshot + +Set sizes respectively to expected creatives. + +### Select Price + +The Line Item price should be chosen according to the price granularity policy. + +Pipeline Screenshot + +### Set Targeting Keywords + +The **Custom targeting** property should contain a special keyword with the price of winning bid. The same as a Rate of the Line Item. + +Pipeline Screenshot + +## Step 3: Prepare Prebid Creative + +### Display Banner, Video Banner, Display Interstitial, Video Interstitial + +The Prebid SDK integrates with GAM basing on [App Events](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner#app_events) feature, almost for all ad formats. That means that creative should contain a special tag that will be processed by Prebid's GAM Event Handlers. + +If GAM Event Handler receives the `PrebidAppEvent` event it will render the winning bid. Otherwise the control will be passed to the GAM Ad View and it will render the received creative. + +``` html + + +``` + +Pipeline Screenshot + +### Rewarded Video + +Prebid rendering for Rewarded video ads is based on the [OnAdMetadataChangedListener](https://developers.google.com/android/reference/com/google/android/gms/ads/rewarded/OnAdMetadataChangedListener). So you need to set up a special VAST tag in the creative. + +``` js +https://cdn.jsdelivr.net/npm/prebid-universal-creative/dist/prebid-mobile-rewarded-vast.xml +``` + +Pipeline Screenshot + +If GAM Event Handler receives the tag's info it will render the winning bid. Otherwise the control will be passed to the GAM Ad View and it will render the received creative. + + diff --git a/adops/mobile-rendering-max-line-item-setup.md b/adops/mobile-rendering-max-line-item-setup.md new file mode 100644 index 0000000000..4c7786b848 --- /dev/null +++ b/adops/mobile-rendering-max-line-item-setup.md @@ -0,0 +1,45 @@ +--- + +layout: page_v2 +title: Prebid Mobile Rendering Modules +description: Prebid Mobile Rendering Modules architecture +sidebarType: 3 + +--- + +# AppLovin MAX Setup + +## Custom Network Setup + +In your MAX account go to `Mediation` -> `Manage` -> `Networks` and click `Click here to add a Custom Network`. Then create an **SDK** custom network with the following adapter names: + +Pipeline Screenshot + +iOS adapter: + +```noformat +PrebidMAXMediationAdapter +``` + +Android Adapter: + +```noformat +com.applovin.mediation.adapters.PrebidMaxMediationAdapter +``` + +## Add Placements + +Now you have to add placements for Prebid Custom Network into the respective ad unit's waterfall. + +Create or choose an existing Ad Unit. Go the the `Custom Networks & Deals` section. Chose the Prebid's custom network that you created at the previous step. Change the status to active and add placements following the [price granularity](/adops/price-granularity.html) guide to determine how many entries you need. + +Pipeline Screenshot + +Make sure that the `Custom Parameters` field contain expecting targetting keywords of the winning bid: + +```json +{"hb_pb":"0.10"} +``` + +{: .alert.alert-warning :} +The adapter will render the winning bid only if the bid's targeting keywords contain `all` keywords from the `Custom Parameters` field. diff --git a/adops/overview b/adops/overview deleted file mode 100644 index f782148079..0000000000 --- a/adops/overview +++ /dev/null @@ -1,5 +0,0 @@ ---- -layout: page_v2 -title: Ad Operations | Overview -sidebarType: 3 ---- \ No newline at end of file diff --git a/adops/price-granularity.md b/adops/price-granularity.md new file mode 100644 index 0000000000..c0c3c9a681 --- /dev/null +++ b/adops/price-granularity.md @@ -0,0 +1,173 @@ +--- +layout: page_v2 +title: Price Granularity +head_title: Price Granularity +sidebarType: 3 +sbUUID: 3.2 +--- + +# Price Granularity + +{: .no_toc } + +- TOC +{: toc } + +Price granularity is a way to quantize bids so that you don't need to make an infinite number of line items. It allows you to balance the work of creating line items with the desire to optimize revenue from your header bidding partners. This document will explain price granularity in detail and why it’s necessary, and provide you with the information you need to make the best decisions for your Prebid implementation. + +## Price Granularity Explained + +When your ad server looks to fill an ad request, it takes many things into consideration. Broken down to its simplest form, we can say that the highest price that matches the targeting will win the auction for the ad slot. In a non-header bidding scenario, when you set up line items for your advertisers in your ad server, you specify the amount of money the advertiser is willing to spend for a particular ad unit based on whether it matches the targeting. For example, an advertiser might be willing to pay 1.52 CPM for an ad unit that targets people aged 18 - 25 who live in the U.S. So you set up your line item for that advertiser with a rate of 1.52 CPM. + +With header bidding, you have bids coming in from outside the ad server, so you don’t have any price information until the actual bid is passed into the ad server. Instead, it works like this: + +- Prebid contacts your demand partners, who find advertisers running campaigns that match the available contextual and user information. +- The demand partners send in their top bid or bids for the ad slot. +- Those bids are then sent to your ad server. + +With this process, you don’t know in advance what price your demand partner’s advertisers were willing to pay. So how do you know what price to target in your line items? Do you have to create a line item for every possible price that could come in? Given the fact that open market bids can be fractions of units (so a bid of 0.255 is acceptable), the number of line items you would have to create to cover every possibility is almost infinite. + +This is where price granularities come in. Price granularities allow you to group bids into “price buckets.” These buckets give you a definitive set of bid prices to target, and therefore a definitive set of line items to create. + +## Components of Price Granularity + +In Prebid, there are four components to price granularity. + +**Price increments**: The increments between prices you’ll be targeting in your line items. For example, if you choose .10 increments, you will create line items with prices of 0.00, 0.10, 0.20, 0.30, etc. Prebid comes with built-in options for .10 and .50 increments, and also allows you to define your own. + +**Price cap**: The maximum price allowed within a set of price increments. For example, if you choose an increment of .50 and a cap of 5.00, your line item pricing will range from 0.00 through 5.00 at .50 increments: 0.00, 0.50, 1.00, 1.50…5.00. + +**Price range**: An increment/price cap within a price granularity. You can have multiple price ranges within one price granularity, which allows you to specify different increments at different CPM values. For example, you might want a smaller increment (such as .10) for CPMs under 10, and larger increments (such as .50) for any CPM over 10. + +**Price bucket**: The actual price targeted in the line item. (Note the name of the key that is passed in with the bid price, hb_pb, stands for header bidding price bucket.) For example, if you’re using 0.50 increments and you have one bidder who bids 1.45 and another who bids 1.20, both will be rounded down and placed into the 1.00 price bucket. (See the next section for a description of Rounding.) + +## Rounding + +Bids received from your Prebid demand partners are rounded down according to your price granularity. If your granularity is .50, a bid of 2.95 will be rounded down to 2.50. Consider the following scenario: + +- Price granularity is set to .50 +- BidderA submits a bid for 2.75. +- BidderB submits a bid for 2.55. + +In this case, BidderA is the top bid at 2.75. If only the top bid is sent to the ad server, BidderA will be rounded down to 2.50 and sent. If all bids are sent, BidderA would still be the top bid, but both BidderA and BidderB bids will be rounded down to 2.50 and sent to the ad server. After reaching the ad server, both bids could lose to an ad server bidder that bid 2.51, even though both BidderA and BidderB initially bid higher than that. + +{: .alert.alert-warning :} +**Important**: Rounding does not impact the price paid, only the auction on the ad server. For example, if your bid for 2.75 is rounded down to 2.50 and wins on the ad server at 2.50, you will be paid 2.75. + +Bids also round down to reflect the top price in your granularity definition. If your price cap is 5.00 and you receive a bid of 20.00, that bid will be rounded down to 5.00. This is important to keep in mind for [video inventory](#video-price-granularity), which often sells for higher prices than other media types. + +{: .alert.alert-success :} +You might have noticed earlier that we gave examples of price buckets of 0.00. This is necessary because it captures bids that are less than the increment value, but are still valid bids. For example, if you have 0.10 granularity and a bid price of 0.02, that gets rounded down to 0.00. Even with a 0.01 granularity, there can be fractional bids, so a bid price of 0.005 would still have value but get rounded down to 0.00. It's not going to compete very well, but if the hb_pb=0.00 line item is chosen, the bidder will still pay their bid price of 0.005. + +This rounding might initially sound like a bad idea. You’re obviously losing revenue when a lower bid price wins over a higher price, right? But there are advantages to using price granularities and price caps, which we’ll discuss below in “Pros and Cons.” + +## Prebid Default Price Granularities + +Prebid provides several default price granularity options. Work with your software engineers to ensure the Prebid implementation is configured to match your line item setup. + +### Currency Considerations + +Before we get into the details of Prebid’s price granularity options we need to talk about different currencies. Prebid’s built-in granularity options were designed to represent typical bid prices in 2016 if your currency was USD, EUR, GBP, CAD, AUD, or other currency of similar value. So when you read the values below, think about whether your normal bid prices fall into these ranges. + +If you’re working with currencies, such as JPY, INR, and CZK, that don’t fit into the predefined price granularities, you may need to define custom price buckets (explained below). See [Currency Module](/dev-docs/modules/currency.html) for more information and additional options for working with these currencies. Specifically note the granularity multiplier option, which lets you "scale up" the standard buckets to make sense for your currency. + +### Built-In Price Granularity Options + +{: .table .table-bordered .table-striped } +| Granularity | Increment | Cap | Number of Line Items Required per Bidder | +| ----------- | --------- | --- | ---------------------------------------- | +| low | 0.50 | 5.00 | 11 | +| medium | 0.10 | 20.00 | 201 | +| high | 0.01 | 20.00 | 2001 | +| auto | Sliding scale | Sliding scale | See [Auto](#auto) | +| dense | Sliding scale | Sliding scale | See [Dense](#dense) | +| custom | Custom sliding scale | Custom sliding scale | Dependent on scale | + +#### Auto + +The auto option contains a series of predefined buckets. Any bid over the cap falls into the next highest bucket. + +{: .table .table-bordered .table-striped } +| Increment | Cap | Number of Line Items Required per Bidder | +| --------- | --- | ---------------------------------------- | +| 0.05 | 5.00 | 101 | +| 0.10 | 10.00 | 50 | +| 0.50 | 20.00 | 20 | +| Any bid > 20.00 | 20.00 | n/a | +| | | Total: 171 | + +#### Dense + +Dense provides a sliding scale similar to auto, but with smaller granularity. Any bid over the cap falls into the next highest bucket. + +{: .table .table-bordered .table-striped } +| Increment | Cap | Number of Line Items Required per Bidder | +| --------- | --- | ---------------------------------------- | +| 0.01 | 3.00 | 301 | +| 0.05 | 8.00 | 100 | +| 0.50 | 20.00 | 24 | +| Any bid over 20.00 | 20.00 | n/a | +| | | Total: 425 | + +#### Custom + +Custom buckets allow you to set your own price granularity. In determining what that granularity should be, we recommend analyzing your average bid prices from SSPs and placing them into a histogram. The price cap should be around your 95th-percentile bid, and there should be finer-grained buckets where more popular bid values are clustered. Note that if you use a [price floor](/dev-docs/modules/floors.html#price-floors-module), you shouldn't need fine-grained buckets below that floor. + +After you’ve determined what you’d like your granularity and caps to be, work with your software engineers to ensure the Prebid configuration matches your line item setup. + +## Pros and Cons + +As we mentioned earlier, you need to create a line item for every price that could come in from your header bidding demand partners. Without price buckets this could result in an almost infinite number of line items. Instead, you’ll need to weigh the pros and cons of high vs low granularity, and possibly adjust your granularities as you analyze the results of your Prebid implementation. + +The following examples give a general idea of the pros and cons of high and low granularity. + +### Example: High Price Granularity + +- 10 bidders +- Cap 20.00 +- Increment .01 +- Send top price: Minimum 2,000 line items +- Send all bids: Minimum 20,000 line items + +**Pro**: At .01 increments, there will be minimal price rounding (up to the price cap). All bids will compete at (or very near) the price the demand partner is willing to pay, maximizing revenue. + +**Con**: You have to create a lot of line items. The numbers shown above increase dramatically as you increase your price cap and your number of bidders. If you send all bids and add five more bidders, suddenly you need 10,000 more line items. + +### Example: Low Price Granularity + +- 10 bidders +- Cap 5.00 +- Increment 1.00 +- Send top price: Minimum 5 line items +- Send all bids: Minimum 50 line items + +**Pro**: Setting up your line items is a relatively quick process because you won’t need very many. You’re also less likely to run into volume limits your ad server might impose on numbers of line items. + +**Con**: Prices received from demand partners will be rounded down, so you could be losing money. A bid of 2.95 would be rounded down to 2.00, and lose to an ad server bid of 2.05. You’d be losing almost a dollar CPM. + +The following diagram, based on the high and low granularity scenarios with ten bidders we described above, illustrates just how quickly your line item count can grow. + +![Line Items Required per Price Granularity](/assets/images/ad-ops/planning/pg-line-items-required.png){: .center-image :} + +### Balanced Price Granularity + +Taking the pros and cons into consideration, you’ll want to balance your price granularity in a way that makes sense for your configuration. We recommend starting with the predefined Prebid price bucket that makes the most sense based on bids you expect, then adjusting as needed as you evaluate the results. The exceptions to this would be in the case of video (see below), and when you’re working with currencies that don’t fit well into the predefined values. In both these cases we recommend custom price granularities. + +## Video Price Granularity + +The predefined price granularities in Prebid max out with price caps of 20.00. However, video inventory is often valued much higher. You don’t want to have a 20.00 price cap in place for inventory for which you’re expecting to receive 50.00 or more. For video inventory, we recommend you create custom price granularities. Determine the granularity and caps for your video inventory, and work with your software engineers to ensure they configure Prebid with custom price buckets to match your line items. + +## Mobile Price Granularity + +We’ve mentioned that you need to work with your software engineers to ensure the price buckets in the Prebid configuration match the line items you’re setting up in the ad server. However, if you’re setting up line items for advertising in a mobile app, your software engineers will be working with the Prebid Mobile SDK, which does not have price granularity controls; price buckets for mobile are set in Prebid Server. In this case you’ll need to work with your managed service provider to ensure price buckets are set up to match your line items. Note that from the ad server side, line item setup for price buckets is the same whether you’re working with mobile or web. + +## Next Step + +[Creative Considerations](/adops/creative-considerations) + +## Further Reader + +- [Planning Guide](/adops/adops-planning-guide.html) +- [Key Values for Ad Ops](/adops/key-values.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Deals in Prebid](/adops/deals.html) diff --git a/adops/send-all-bids-adops.md b/adops/send-all-bids-adops.md deleted file mode 100644 index 19129ea43a..0000000000 --- a/adops/send-all-bids-adops.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -layout: page_v2 -title: Send All Bids to the Ad Server -head_title: Send All Bids to the Ad Server -description: Send all bids to the ad server for reporting and data analysis. -pid: 2 -sidebarType: 3 ---- - - -# Send all bids to the ad server - Ad Ops setup -{: .no_toc } - -This page shows how to set up your ad server so that you can send all bids and report on them. - -* TOC -{: toc } - -## Overview - -As a publisher, you may want to have your ad server see **all** header bidding bids (instead of seeing only the winning bids in each auction). Reasons you might want this behavior include: - -+ You want your ad server to see all header bidding bids so that your ad server can report on bid prices instead of only winning prices. - -+ You have a contractual agreement with your header bidding partner. - -{: .alert.alert-success :} -See the [Publisher API Reference](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) for more details. - - -If you decide to send all bids to the ad sever, your developers have the option of explicitly adding `enableSendAllBids: true` to `pbjs.setConfig()`. However, since the default value is `true` this addition is not strictly necessary. For details, see the [Publisher API Reference](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids). - -From the ad ops side, you can choose to set up one order per bidder, which allows for each order to have a set of line items using targeting keywords that include the bidder's name. For example, if you are working with [Rubicon](/dev-docs/bidders.html#rubicon), you would use `hb_pb_rubicon` in your line item's key-value targeting, and `hb_adid_rubicon` in the creative. - -{% include send-all-bids-keyword-targeting.md %} - -{: .alert.alert-info :} -Manually configuring GAM for Prebid can be a fair amount of work. -Consider using our official command line tool, [Prebid Line Item Manager](/tools/line-item-manager.html), to create the setup. Using this tool may save you time and help you avoid mistakes. - -## Step 1. Add an order - -In Google Ad Manager, create a new order for one of the header bidding partners. Each header bidding partner should have its own Google Ad Manager order. Repeat this step and the following when you are adding a new header bidding partner. - - -## Step 2. Add a line item - -In Google Ad Manager, create a new order with a $0.50 line item. - -Enter all of the inventory sizes that your website has. - -![Inventory Sizes]({{ site.github.url }}/assets/images/demo-setup/inventory-sizes.png){: .pb-md-img :} - -Because header bidding partners return prices, set the Line Item **Type** to **Price priority** to enable them to compete on price. - -![Price Priority]({{ site.github.url }}/assets/images/demo-setup/price-priority.png){: .pb-sm-img :} - -
    - -Set the **Rate** to $0.50 so that this line item will compete with your other demand sources at $0.50 ECPM. - -![Rate]({{ site.github.url }}/assets/images/demo-setup/rate.png){: .pb-sm-img :} - -
    - -Set **Display Creatives** to *One or More* since we'll have one or more creatives attached to this line item. - -Set **Rotate Creatives** to *Evenly*. - -![Display and Rotation]({{ site.github.url }}/assets/images/demo-setup/display-and-rotation.png){: .pb-md-img :} - -Choose the inventory that you want to run header bidding on. - -This line item will target the bids in the range from $0.50 to $1.00 from the bidder you specify by targeting the keyword `hb_pb_BIDDERCODE` set to `0.50` in the **Key-values** section. For example, if this order and line item is for the bidder AppNexus, the keyword would be `hb_pb_appnexus`. The `BIDDERCODE` for other bidders can be found [here]({{site.baseurl}}/dev-docs/bidders.html). - -**You must enter the value to two decimal places, e.g., `1.50`. If you don't use two decimal places, header bidding will not work.** - -![Key-values]({{ site.github.url }}/assets/images/demo-setup/send-all-bids/key-values.png){: .pb-md-img :} - -## Step 3. Add a Creative - -Next, add a creative to this $0.50 line item; we will duplicate the creative later. - -- Choose the same advertiser we've assigned the line item to. -- Set it to be a **Third party** creative. -- Make sure the creative size is set to 1x1. This allows the creative to serve on all inventory sizes. When associating with the line item, just change the creative filter setting to show all creatives instead of 'Inventory filtered based on size'. -- The **"Serve into a Safeframe"** box can be **UNCHECKED** or **CHECKED** (Prebid universal creative is SafeFrame compatible). -- Copy this creative code snippet for each bidder and paste it into the **Code snippet** box, replacing BIDDERCODE with the current bidder name. - -``` - - -``` - -{% capture noteAlert %} -Replace the *BIDDERCODE* placeholders in the above template with the appropriate bidder your line item is targeting. For example, if you're targeting the bidder *appnexus*, the macro variable for `adId` would look like `ucTagData.adId = "%%PATTERN:hb_adid_appnexus%%";`. IMPORTANT: Make sure that none of the values are -longer than 20 characters. e.g. you'll need to truncate hb_cache_host_triplelift to hb_cache_host_triple. GAM doesn't support attributes longer than 20 chars, so all Prebid software truncates attributes to that length. -{% endcapture %} - -{% include alerts/alert_note.html content=noteAlert %} - -![New creative]({{ site.github.url }}/assets/images/demo-setup/new-creative.png){: .pb-lg-img :} - -**Prebid universal creative code for other ad servers** - -If you're using an ad server other than Google Ad Manager, your code snippet will look similar to one of the following: - -For Mopub: - - - - -{% capture noteAlert %} -See note above in regards to replacing *BIDDERCODE* placeholders. -{% endcapture %} - -{% include alerts/alert_note.html content=noteAlert %} - -{% include adops/adops-creative-declaration.html %} - -For other ad servers: - - - - -Replace `MACRO` with the appropriate macro for the ad server. (Refer to your ad server's documentation or consult with a representative for specific details regarding the proper macros and how to use them.) - -{% capture noteAlert %} -See note above in regards to replacing *BIDDERCODE* placeholders. -{% endcapture %} - -{% include alerts/alert_note.html content=noteAlert %} - -## Step 4. Attach the Creative to the Line Item - -Next, let's attach the creative to the $0.50 line item you just created. Click into the Line Item, then the **Creatives** tab. - -There will be yellow box showing each ad spot that you haven't uploaded creatives for yet. Since you've already made the creatives, click the **use existing creatives** next to each size. - -![Use existing creatives list]({{ site.github.url }}/assets/images/demo-setup/use-existing-creatives-01.png) - -In the pop-up dialog that appears, click **Show All** to remove the default size filters and see the 1x1 creatives. Include the prebid creative and click **Save**. - -![Use existing creatives dialog]({{ site.github.url }}/assets/images/demo-setup/use-existing-creatives-02.png) - -Back in the line item, go into the **Creatives** tab again, and click into the creative you just added. - -Then, in the creative's **Settings** tab, enable the **Size overrides** field and set all your line item's potential sizes. - -Save the creative and go back to the line item. - -## Step 5. Duplicate Creatives - -Google Ad Manager has a constraint that one creative can be served to at most one ad unit in a page under GPT's single request mode. - -Let's say your page has 4 ad slots. We need to have at least 4 creatives attached to the line item in case more than 2 bids are within the $0.50 range. - -Therefore, we need to duplicate our Prebid creative 4 times. - -Once that's done, we have a fully functioning line item with 4 creatives attached that can potentially fill 4 ad slots of varying sizes during a single pageview. - -## Step 6. Duplicate Line Items - -Now let's duplicate our line item for bids above $0.50. - -In the Prebid order page, copy the line item with shared creatives. - -This way you only have 4 creatives to maintain, and any updates to those creatives are applied to all pre-bid line items. - -For example, we can duplicate 3 more line items: - -- $1.00 -- $1.50 -- $2.00 - -Let's go into each of them to update some settings. For each duplicated line item: - -1. Change the name to reflect the price, e.g., "Prebid\_BIDDERCODE\_1.00", "Prebid\_BIDDERCODE\_1.50" - -2. Change the **Rate** to match the new price of the line item. - -3. In **Key-values**, make sure to target `hb_pb_BIDDERCODE` at the new price, e.g., $1.00. Again, be sure to use 2 decimal places. - -4. (Optional) Set the start time to *Immediate* so you don't have to wait. - -Repeat for your other line items until you have the pricing granularity level you want. - -## Step 7. Create Orders for your other bidder partners - -Once you've created line items for `BIDDERCODE` targeting all the price buckets you want, start creating orders for each of your remaining bidder partners using the steps above. diff --git a/adops/send-all-vs-top-price.md b/adops/send-all-vs-top-price.md new file mode 100644 index 0000000000..b8ef60ef08 --- /dev/null +++ b/adops/send-all-vs-top-price.md @@ -0,0 +1,147 @@ +--- +layout: page_v2 +title: Send All Bids vs Top Price +head_title: Send All Bids vs Top Price +sidebarType: 3 +sbUUID: 3.2 +--- + +# Send All Bids vs Top Price + +{: .no_toc } + +- TOC +{: toc } + +Prebid provides two options for the number of bids that will be sent to the ad server: + +- Send all bids to the ad server that are received from the header bidding demand partners. This is the default behavior in Prebid. +- Send only the top bid from among all the demand partner responses. + +{: .alert.alert-info :} +There is also a third option if you’re using deals. See [Deals in Prebid](/adops/deals.html) for more information. + +Here’s a brief comparison chart showing the primary differences between these approaches. + +{: .table .table-bordered .table-striped } +| | Send All Bids (Default) | Send Top Price Bid | +| | ----------------------- | ------------------ | +| Number of bids sent to the ad server | Sends all bids that are received before the timeout period has expired. | Sends one bid per ad request. Only the bid with the top price for each request is sent. | +| Reporting | Gives your ad server the information to generate detailed reports on bids received from individual demand partners whether they are top bidders or not. | Your ad server can report only on bids it receives, so you won’t have visibility from within your ad server into bids from demand partners that were not top bidders. | +| Line Items | Typically requires a large number of line items to capture individual bidder information. | You can set up line items that are independent of the bidder, resulting in far fewer line items. | +| Key Value Pairs | Separate keys need to be defined for every bidder. | Only one set of keys needs to be defined. | +| Data considerations | The amount of information that is being sent to the ad server can become very large. You may need to place limits on the number of bids or key values that are sent. | You’re unlikely to run into any data issues when you’re sending information from only one bid. | + +## Send All Bids + +“Send all bids to the ad server” does exactly what it sounds like: every bid that comes in from demand partners before the specified timeout period will be sent to the ad server. (There are some limits, which we’ll talk about in a moment.) **This is the default behavior in Prebid.** + +### Reporting + +You might be wondering why you’d want to send more than the top bid. After all, if a bid wasn’t the top bid from the header bidding process, how could it possibly be the top bid after reaching the ad server? + +Realistically, it can’t. The main reason for sending all bids to the ad server is for reporting and optimization. With all bids, your ad server has the information it needs to provide you with reports that can tell you who bid on your inventory and what the bid price was. This helps you to: + +- Evaluate the bid rate of your demand partners +- Ensure contractual obligations with your demand partners are being met +- Adjust your Prebid settings based on who is bidding and for how much +- Evaluate the effectiveness of your current Prebid setup + +### Line Items + +When you send all bids, you’ll want to create a set of line items for each of your bidders. Each line item within a set (or a Google Ad Manager order) will be targeted towards a different price bucket. (See [Price Granularity](/adops/price-granularity.html) for more information.) While this is an ideal scenario for reporting, it can create difficulties in setting up line items. + +For example, suppose you have the following line item setup: + +- 200 prices +- 10 bidders + +This would require you to create 2000 line items (200 x 10). If, on the other hand, you didn’t need to separate out your line items by bidder, you would reduce this number dramatically to 200 line items (200 x 1). + +{: .alert.alert-info :} +The Send All Bids option also sends the top bid, so a hybrid scenario is possible where you need to create only one set of line items, but you’ll use all other variables passed in for reporting. + +In addition, some ad servers limit the number of line items you can create. Check with your ad server to ensure you won’t be exceeding this number. + +### Key Value Pairs + +{: .alert.alert-info :} +For an overview of key value targeting, see [Key Values](/adops/key-values.html). + +When you send all bids, you’ll need to have a set of keys defined for each bidder. This requires the creation of a lot of keys. For example, one bid could include five or more key value pairs. If you have ten bidders, this would require creation of at least 50 unique keys. + +{: .alert.alert-info :} +Because the number of key value pairs sent to the ad server can be very large, Prebid provides a number of ways to control this. See [Prebid.js Controls](/features/adServerKvps.html#controls) for engineering information on how to modify the amount of data being sent to the ad server. + +One thing to keep in mind is the length of your key values. When you create separate line items for each bidder, the keys you target will include the bidder name. For example, if you’re creating line items for BidderA, your key-value pairs will look something like this: + +hb_adid_BidderA=123456 +hb_pb_BidderA=2.10 +hb_size_BidderA=300x250 + +Some ad servers have limits on key name length. In Google Ad Manager (GAM) the maximum length is 20 characters. GAM will truncate any key name longer than 20 characters. For example: + +- One of your bidders is named BidderWithLongNameABC +- Prebid passes the creative size for this bidder in the key hb_size_BidderWithLongNameABC +- GAM truncates this name to hb_size_BidderWithLo + +When you enter the key values into the line item, you must use the truncated name: + +hb_size_BidderWithLo=300x250 + +If you forget about or are unaware of your ad server’s truncation and include the full name, the line item targeting will not match. + +{: .alert.alert-success :} +**Tip**: Prebid documentation lists the GAM truncated versions of ad server keys on each bidder parameter page. See [AndBeyondMedia](https://docs.prebid.org/dev-docs/bidders/andBeyondMedia.html) for an example. + +### Data Considerations + +Imagine you’re sending all bids to the ad server and you have the following scenario: + +- 15 bidders +- 7 key value pairs (KVPs) per bidder +- 25 characters per KVP + +You now have an ad request query string that is 2,625 characters long. There are many options for limiting the amount of data that’s sent on the query string. See [Configure Targeting Controls](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) for engineering options on reducing the amount of data being sent to the ad server. + +## Send Top Price Bid + +“Send top price bid” is the simpler of the two options. With this approach, the only bid sent to the ad server with each ad request is the bid with the highest price. If multiple bidders respond with the same price, the bid from among those bidders that was received first is sent to the ad server. Here are some things to consider when deciding whether to go with this option. + +### Reporting + +The ad server can report only on the information it receives. So if you send only one bid from the header bidding process, the ad server can include only that one bid in your reports. Send top bid is a good option if: + +- you’re interested in reporting only on overall Prebid fill rates and top bid prices. +- you want to prioritize simplicity over detailed analysis of your header bidding results +- you don’t have any contractual obligations with demand partners that require more detailed reporting + +### Line Items + +If you’re sending only one bid with each ad request, there’s no need to create separate line items for each bidder. You can create one line for each price and creative size. For example: + +- 200 prices +- 1 bidder + +In this example you need to create only 200 line items (200 x 1). + +### Key Value Pairs + +When you send only the top price bid to the ad server, you need to create only one generic set of keys. This means you’ll typically need to create five to ten keys to include in your line item targeting. + +Because the key names are the same no matter which bidder’s bid is sent to the ad server, key names will not include the name of the bidder. For example, the bid price will be sent in hb_pb rather than hb_pb_BidderName. This means you’re unlikely to have to worry about ad server limits on name lengths. See [Key Values](/adops/key-values.html) for details on setting key values in the ad server. + +### Data Considerations + +Send top bid sends the least amount of data possible to the ad server, and therefore has the least impact on client latency. + +## Next Step + +[Line Item Creation](/adops/line-item-creation.html) + +## Further Reader + +- [Planning Guide](/adops/adops-planning-guide.html) +- [Key Values for Ad Ops](/adops/key-values.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) +- [Deals in Prebid](/adops/deals.html) diff --git a/adops/setting-up-prebid-for-amp-in-dfp.md b/adops/setting-up-prebid-for-amp-in-dfp.md deleted file mode 100644 index f3552c8658..0000000000 --- a/adops/setting-up-prebid-for-amp-in-dfp.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -layout: page_v2 -title: Setting up Prebid for AMP in Google Ad Manager -head_title: Setting up Prebid for AMP in Google Ad Manager -description: Setting up Prebid for AMP in Google Ad Manager -sidebarType: 3 ---- - - - -# Setting up Prebid for AMP in Google Ad Manager -{: .no_toc} - -This page describes how to set up a line item and creative to serve on AMP pages with Prebid.js. - -* TOC -{:toc} - -{: .alert.alert-info :} -Manually configuring GAM for Prebid can be a fair amount of work. -Consider using our official command line tool, [Prebid Line Item Manager](/tools/line-item-manager.html), to create the setup. Using this tool may save you time and help you avoid mistakes. - -{: .alert.alert-success :} -For engineering setup instructions, see [Show Prebid Ads on AMP Pages]({{site.github.url}}/dev-docs/show-prebid-ads-on-amp-pages.html). - -## Line Item Setup - -In addition to your other line item settings, you'll need the following: - -+ Enter the **Inventory Sizes** of the creatives you want the line item to use, e.g., *300x250*, *300x50*, etc. - -+ Set the **Type** to *Price Priority* - -+ Set **Display creatives** to *One or More*. - -+ Set **Rotate creatives** to *Evenly*. - -+ In the targeting section, select **Key-values** targeting. You'll need to coordinate with your development team on what key-values you want to target. - -Save your line item and add a creative. - -## Creative Setup - -On the new creative screen, select the **Third party** creative type. - -Ensure that the **Serve into a SafeFrame** box is checked. - -Enter the below code snippet in the **Code snippet** text area. - -{% capture sendAllBidsAlert %} -If you're using the `Send All Bids` scenario (where every bidder has a separate -order), the creative and targeting will be different from the example shown here. See [Send All Bids](/adops/send-all-bids-adops.html) for details. -{% endcapture %} - -{% include alerts/alert_important.html content=sendAllBidsAlert %} - -{% highlight html %} - - - -{% endhighlight %} - -{: .alert.alert-success :} -You can always get the latest version of the creative code from [the AMP example creative file in our GitHub repo](https://github.com/prebid/prebid-universal-creative/blob/master/template/amp/dfp-creative.html). - -{% include adops/adops-creative-declaration.html %} - -## Further Reading - -+ [Show Prebid Ads on AMP Pages]({{site.github.url}}/dev-docs/show-prebid-ads-on-amp-pages.html) -+ [How Prebid on AMP Works]({{site.github.url}}/dev-docs/how-prebid-on-amp-works.html) - - - - - -[PBS]: {{site.baseurl}}/dev-docs/get-started-with-prebid-server.html -[RTC-Overview]: https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md diff --git a/adops/setting-up-prebid-multi-format-in-dfp.md b/adops/setting-up-prebid-multi-format-in-dfp.md deleted file mode 100644 index bff3323bb0..0000000000 --- a/adops/setting-up-prebid-multi-format-in-dfp.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -layout: page_v2 -title: Setting up Prebid Multi-Format in Google Ad Manager -head_title: Setting up Prebid Multi-Format in Google Ad Manager -description: Setting up Prebid Multi-Format in Google Ad Manager -pid: 3 - -top_nav_section: adops -nav_section: tutorials -sidebarType: 3 ---- - - - -# Setting up Prebid Multi-Format in Google Ad Manager -{: .no_toc} - -This page shows how to set up your ad server so that you can serve multi-format ads. - -Multi-Format ads allow you to declare multiple media types on a single ad unit. For example, you can set up one ad on the page that could show a banner, native, or outstream video ad, depending on which had the highest bid. - -{: .alert.alert-info :} -For instructions on how to set up multi-format ads from the engineering side, see [Show Multi-Format Ads with Prebid.js]({{site.baseurl}}/dev-docs/show-multi-format-ads.html). - -* TOC -{: toc } - -{: .alert.alert-info :} -Manually configuring GAM for Prebid can be a fair amount of work. -Consider using our official command line tool, [Prebid Line Item Manager](/tools/line-item-manager.html), to create the setup. Using this tool may save you time and help you avoid mistakes. - -## Step 1. Add an Ad Unit - -In Google Ad Manager, [create an ad unit](https://support.google.com/admanager/answer/177203). - -Decide what combination of formats will be permitted on the ad unit. This will determine what sizes you allow to serve. The ad unit's sizes must be configured properly to support the combination of formats that will be permitted. - -If your ad unit will support native ads, you may want to create a custom **Prebid Native Format** and at least one **Prebid Native Style**. Examples of each are given in [Setting up Prebid Native in Google Ad Manager][nativeAdSetup]. - -## Step 2. Add an Order - -In Google Ad Manager, create a new order. This order will be associated with the multiple line items needed to run multi-format auctions. - -## Step 3. Add Line Items and Creatives for each Media Type - -Multi-format ad units which support native require at least two distinct sets of line items and creatives: - -+ One for [banners and/or outstream video][bannerAdSetup]. Banners and outstream videos will serve into a Google Ad Manager banner creative. - -+ One for [native][nativeAdSetup]. Native ads will serve into a native creative with native format and styles. - -### Banner/Outstream - -Follow the instructions for creating line items and creatives in [Send all bids to the ad server][bannerAdSetup], with the following changes: - -+ Add key-value targeting for **'hb_format' is ('banner' OR 'video')** - + This will ensure that the appropriate ad server line item is activated for banner / outstream bids - + For bidder-specific line items, specify `hb_format_{BIDDER_CODE}`, e.g., `hb_format_appnexus` - - ![Set hb_format to 'banner,video']({{site.baseurl}}/assets/images/ad-ops/multi-format/hb_format_video_banner.png) - -+ Make sure that you're targeting the right sizes for both banner ads and any outstream ads you want to serve in this slot, e.g., - + 1x1 for outstream (or whatever size you pass into Google Ad Manager as your outstream impression) - + whatever banner sizes are valid for your site / use case - -### Native - -Follow the instructions for creating line items, creatives, custom native formats, and native styles in [Show Native Ads][nativeAdSetup], with the following changes: - -+ Add key-value targeting for **'hb_format' is 'native'** - - ![Set 'hb_format' to 'native']({{site.baseurl}}/assets/images/ad-ops/multi-format/hb_format_native.png) - -+ Make sure you're targeting the right sizes for the native ads you want to serve: - + Fixed-size native, where you specify one or more absolute sizes - + Fluid, which expands to fit whatever space it's put in - + For more information on fluid vs. fixed, see [the Google Ad Manager docs](https://support.google.com/admanager/answer/6366914) - -## Related Topics - -+ [Show Multi-Format Ads with Prebid.js]({{site.baseurl}}/dev-docs/show-multi-format-ads.html) (Engineering setup) -+ [Multi-Format Example]({{site.baseurl}}/dev-docs/examples/multi-format-example.html) (Example code) - - - - - -[bannerAdSetup]: /adops/send-all-bids-adops.html -[nativeAdSetup]: /adops/gam-native.html diff --git a/adops/setting-up-prebid-native-in-dfp.md b/adops/setting-up-prebid-native-in-dfp.md deleted file mode 100644 index 6a04ee6dff..0000000000 --- a/adops/setting-up-prebid-native-in-dfp.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -layout: page_v2 -title: Setting up Prebid Native in Google Ad Manager (Alpha) -head_title: Setting up Prebid Native in Google Ad Manager -description: Setting up Prebid Native in Google Ad Manager -pid: 3 - -top_nav_section: adops -nav_section: tutorials -sidebarType: 3 ---- - - - -# Setting up Prebid Native in Google Ad Manager (Alpha) -{: .no_toc} - -{% capture version1 %} -The procedures in this document still work, but we strongly recommend -using the improved [Guide for Setting up Prebid Native in GAM](/adops/gam-native.html). -{% endcapture %} -{% include alerts/alert_warning.html content=version1 %} - -This page describes how to set up native creatives in Google Ad Manager for use with Prebid.js. - -For more information about Google Ad Manager native ad setup, see the [Google Ad Manager native ads documentation](https://support.google.com/admanager/answer/6366845). - -* TOC -{:toc} - -## 1. Create a native ad - -From Google Ad Manager, select **Delivery > Native**. Click **Create Native Ad**. - -![native delivery]({{site.github.url}}/assets/images/ad-ops/dfp-native/create_prebid_native.png){: .pb-md-img :} - -Select the **HTML & CSS editor** option. - -![HTML editor option]({{site.github.url}}/assets/images/ad-ops/dfp-native/prebid_native_html_option.png){: .pb-md-img :} - -## 2. Define ad settings - -For **Ad size** you can specify a specific size for the ad unit or specify the "fluid" size. In this case we'll go with **Fluid**. - -Select **New format** under **Custom format**. (If you've already created an ad unit with the format you want, you can select **Existing format** and select the format to apply to this ad unit.) - -![native adunit settings]({{site.github.url}}/assets/images/ad-ops/dfp-native/prebid_native_settings.png){: .pb-md-img :} - -## 3. Style your native ad - -You can add HTML and CSS to define your native ad template. To allow for native impression trackers, click trackers, and [automatic placeholder value replacement]({{site.github.url}}/dev-docs/show-native-ads.html#sending-asset-placeholders) within a Prebid native creative template, you'll need to include a CDN-hosted script in the HTML, as shown here (see Example HTML below for the full script): - -![native ad styling]({{site.github.url}}/assets/images/ad-ops/dfp-native/prebid_native_styling.png){: .pb-md-img :} - -{: .alert.alert-danger :} -**Native impression and click tracking requirements** -Any link that should fire a click tracker needs to include a `pbAdId` attribute set to `hb_adid`. This attribute is required because the script needs the bidId/adId, which can be filled in only by the targeting key on the ad server, not from within the script. - -If this creative is served, it will fire impression trackers on load. Clicking the link will fire the click tracker and the link will work as normal, in this case going to the `hb_native_linkurl` destination. - -Example HTML and CSS: - -{% highlight html %} - - - - - -{% endhighlight %} - -{% highlight css %} - -.sponsored-post { - background-color: #fffdeb; - font-family: sans-serif; - padding: 10px 20px 10px 20px; -} - -.content { - overflow: hidden; -} - -.thumbnail { - width: 120px; - height: 100px; - float: left; - margin: 0 20px 10px 0; - background-image: url(%%PATTERN:hb_native_image%%); - background-size: cover; -} - -h1 { - font-size: 18px; - margin: 0; -} - -a { - color: #0086b3; - text-decoration: none; -} - -p { - font-size: 16px; - color: #444; - margin: 10px 0 10px 0; -} - -.attribution { - color: #fff; - font-size: 9px; - font-weight: bold; - display: inline-block; - letter-spacing: 2px; - background-color: #ffd724; - border-radius: 2px; - padding: 4px; -} - -{% endhighlight %} - -## 4. Create new native order and line items - -1. Add the native format created in **Step 1** under **Inventory Sizes** (in this case, "Prebid Native Format") -2. Be sure to set inventory targeting and key-value targeting on `hb_pb` corresponding to the line item's CPM. - -![create a native order and line item]({{site.github.url}}/assets/images/ad-ops/dfp-native/new-order-and-line-item.png){: .pb-md-img :} - -![add targeting]({{site.github.url}}/assets/images/ad-ops/dfp-native/add-targeting.png){: .pb-md-img :} - -## 5. Create a new native creative - -1. Be sure to select the format you created in **Step 1** (in this case, "Prebid Native Format") -2. Under **Click-through URL**, add any value. This will be overwritten by Prebid. - -![create a new native creative]({{site.github.url}}/assets/images/ad-ops/dfp-native/new-creative.png){: .pb-md-img :} - -![creative click-through URL]({{site.github.url}}/assets/images/ad-ops/dfp-native/creative-click-through-url.png){: .pb-md-img :} - -## Related Topics - -+ [Show Native Ads with Prebid.js]({{site.github.url}}/dev-docs/show-native-ads.html) (Engineering setup instructions) -+ [Step by Step Guide to Google Ad Manager Setup]({{site.github.url}}/adops/step-by-step.html) (Send top bid to ad server) -+ [Send all bids to the ad server]({{site.github.url}}/adops/send-all-bids-adops.html) diff --git a/adops/setting-up-prebid-ott-video-in-gam.md b/adops/setting-up-prebid-ott-video-in-gam.md deleted file mode 100644 index 679aff9b1a..0000000000 --- a/adops/setting-up-prebid-ott-video-in-gam.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -layout: page_v2 -title: Setting up OTT Video in Google Ad Manager for Prebid -head_title: Setting up OTT Video in Google Ad Manager for Prebid -description: Setting up OTT Video in Google Ad Manager for Prebid -sidebarType: 3 ---- - -# Setting up OTT Video in Google Ad Manager for Prebid - -POP delivers programmatic advertising to video publisher’s OTT inventory. Utilizing the open source Prebid header bidding technology, `POP` provides fill optimization and enables competitive separation within ad pods. - -{% include alerts/alert_note.html content="Competitive separation is the process of preventing ads from the same industry group from appearing either in the same ad pod or adjacent to each other in the same ad pod." %} - -## Configuring Google Ad Manager - -Configuring Google Ad Manager (GAM) for `POP` delivery follows the same Prebid configuration process for video with the additional requirements of adding a custom keyword for targeting and including the VAST URL for the video redirect. - -The process for bidding on long-form video with `POP` requires a GAM account with a `Network` that contains at least one `Advertiser`. If you do not have a GAM account, visit [Google](https://ads.google.com/home/tools/manager-accounts/). If a GAM account exists or has been created, log in. -1. Log into your GAM account. -2. Ensure a `Network` is set up. (For information on setting up a `Network` review this [Google support document.](https://support.google.com/admanager/answer/6013048?hl=en)) -3. Within the `Network`, select or add an `Advertiser`. The Ad Manager 360 screen will load. - -## Orders -From the left navigation, under `Delivery`, select `Orders`. -The `Orders` summary page will load. - -![Google Ad Manager Orders Summary]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_orders.png){: .pb-lg-img :} - - -This page will display any existing `Orders`. An `Order` is required to start an advertising campaign. - -To create a new `Order`, click the `New Order` button. The `New Order` screen will load. - -![Google Ad Manager New Orders]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_new_orders.png){: .pb-lg-img :} - -Enter the following information: - -**Name**: An identifier for this ad campaign. -**Advertiser**: The `Advertiser` of the campaign. -**Trafficker**: The person responsible for uploading `Creatives` and for tracking the performance of the campaign. -**Labels** (optional): Industry identifiers that enable `POP` to prevent ads in the same industry group from appearing either within or adjacent to each other in the ad pod. `Labels` entered in the `Order` section are available to all of its related `Line Items`. - -{% include alerts/alert_warning.html content="At this time POP only recognizes `Labels` entered in the `Line Item` section of GAM but not the `Order` section. POP will only read one label per `Line Item`, even though GAM accepts multiple entries. To target multiple `Labels` create additional `Line Items`, each targeting a specific label." %} -**Teams** (optional): Groups of users that share access to the same advertisers, agencies, orders and line items. - -You can view additional optional entries by clicking on the `Optional` order fields toggle. Additional `Advertiser` and agency contact information can be entered in these fields. Refer to the GAM documentation for details on these entries. - -## Line items - -Once the `Order` information has been added scroll down to the `Line Item` entry form. The `Line Item` data controls when an ad will display and for how long, at the CPM or other pricing model, the size of the `Creative`, etc. The `Line Item` is separated into five sections; `Initial information`, `Creative forecasting defaults`, `Settings`, `Adjust delivery`, and `Add targeting`. - -### Initial information - -This section provides initial settings for a `Line Item`. Enter the following information: - -**Name**: An identifier for the `Line Item`. - -**Inventory sizes**: For `POP`, select `Video VAST`. Selecting this option will display the `Master` input section. This section is where the size of the `Creative`, accompanying creatives and additional targeting can be added.
To enter the size of the `Creative`, click in the first text field (with the movie clip icon), a drop down menu will display with options for standard video sizes along with the option to enter a custom video size. - -Information on the `Creative` targeting option can be found reviewed at [Google support:](https://support.google.com/admanager/answer/6222493?hl=en). - -![Google Ad Manager Video Size]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_lineitem_video_size.png){: .pb-lg-img :} - -**Labels** (optional): Industry identifiers that enable `POP` to prevent ads in the same industry group from appearing either within or adjacent to each other in the ad pod. `Labels` entered in a Line Item are only applied to that `Line Item`.  - -**Comments & Custom fields** (optional): These entries are provided to assist in reporting on the campaign. They have no affect on ad serving or delivery. - -### Creative forecasting defaults - -This section is only available when the `Video Vast` option of the `Inventory sizes` setting is selected. It allows you to enter the `Max duration` of the video creative. This value is used for forecasting purposes and will not affect delivery. - -![Google Ad Manager Creative Forecasting]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_lineorder_creatingforecast.png){: .pb-lg-img :} - -### Settings - -In the `Settings` section you can enter information regarding the campaign, including start and end times, the desired rate, currency and revenue type. Please refer to [Google Ad Manager documentation](https://support.google.com/admanager/answer/82236?hl=en&ref_topic=7506394) for specific information regarding the settings for these fields. - -**Quantity**: The number of impressions, clicks or viewable impressions. - -**Rate**: The amount for either CPM or CPA (currency can be changed to dollars, euros, GBP, or Australian dollars). - -**Discount**: The amount the `Line Item` cost will be reduced. This value is only for reference and is not reflected in revenue reporting nor does it affect a `Line Item’s` priority. - -![Google Ad Manager Line Item Settings]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_lineitem_settings.png){: .pb-lg-img :} - -### Adjust delivery - -This section provides delivery and display options for the Creatives. Review the [Google Ad Manager documentation](https://support.google.com/admanager/answer/82236?hl=en&ref_topic=7506394) for specific details on these settings. - -**Deliver impressions**: Determines how the impressions will be delivered. Options are *Evenly*, *Frontloaded*, and *As fast as possible*. - -**Display companions**: Determines whether the creative will be delivered based on the delivery of companion creatives. Available options are *Optional*, *At least one*, and *All*. - -**Rotate creative sets**: How the creative sets will rotate the display of individual `Creatives`. Available options are: *Evenly*, *Optimized*, *Weighted* and *Sequential*. - -**Day and time**: The days of the week and times of the day the `Line Item` can be delivered. - -**Frequency**: Limits how often the `Line Item` can be delivered to one viewer. - -![Google Ad Manager Line Item Adjust Delivery]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_lineitem_adjust.png){: .pb-lg-img :} - -### Add targeting - -The targeting sections enable you to set values to focus the targeting of your ad space to certain types of ads or audiences. This document outlines targeting of long-form video, for targeting of other `Creatives` review the [Google Ad Manager documentation](https://support.google.com/admanager/answer/82236?hl=en&ref_topic=7506394). - -**Video position**: This setting enables the placement of the `Creative` within the video. For example: pre-roll for the beginning of a video or post-roll for the end. - -**Inventory**: Select which inventory to include. - -**Key-values and Audience**: Enables the selection of an audience segment and age to target for the ad unit. Also allows for the inclusion of custom keywords. - -> For `POP` the custom `keyword hb_pb_cat_dur` is required. The value of this key can be visualized as `hb_pb_cat_dur = RATE_LABEL_DURATION` where:
 - **RATE**: The currency amount entered in the `Rate` field of the
 `Settings` section. - **LABEL**: The value of the label field in the `Line Item`. - **DURATION**: The length of the video in seconds. - -{% include alerts/alert_tip.html content="For a `Line Item` with a $10.00 CPM entered in the `Rate` field, News entered in the `Label` field and 30s entered in the `Duration` field, you would enter the following in the `Custom key-value` field: `hb_pb_cat_dur = 10.00_news_30s`" %} - -**Geography**: The geographic location where the `Creative` will display. - -**Devices**: Settings for targeting browser, browser language, device, and operating system. - -**Connection**: Settings for targeting bandwidth, mobile carriers and domains. - -![Google Ad Manager Line Item Targeting]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_lineitem_addtargeting.png){: .pb-lg-img :} - -## Creatives - -`Line Items` that have an `Inventory sizes` selection of `Standard` or `Master/Roadblock` have `Creatives` attached directly to them, those with `Video VAST` selections do not have `Creatives`. Instead they have `Creative Sets` associated with them. Each `Creative Set` contains a URL that points to the cached `VAST XML`. (This is because most video players can only work with a URL that returns `VAST XML`.) - -{% include alerts/alert_important.html content="Some bidders cache the `VAST XML` on the server side while others rely on Prebid.js to perform the caching" %} - -### Making a Creative Set - -To make a `Creative Set` click on the `Creative link` in the left navigation. This will display the `Creatives` section of Google Ad Manager with a default view of `All creatives`. Click the `Creative sets` link along the top navigation. - -This will display the `Creative Sets` listing. If there were previously created `Creative Sets` they can be viewed and opened from here. - -![Google Ad Manager Creatives]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_creatives_top_nav.png){: .pb-lg-img :} - -Click the `New Creative Set` button. A popover will display. In the `Advertiser` field enter the name of the `Advertiser` this set is being created for. Select `Video VAST` and enter or select a video size in the input field with the movie clip icon. Click the `
Continue` button. - -A `Creative set` entry form will display. Enter a name for the set in the `Creative set` name field. Click the `Redirect` link in the `Select a creative set` type section.
 - -![Google Ad Manager Creative Sets]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_creatives_new_set.png){: .pb-lg-img :} - -The page will now display the `Redirect` form. Enter a name for the `Redirect` in the `Name` field. In the `VAST tag URL` field enter the cache location. For example: - -`https://prebid.adnxs.com/pbc/v1/cache?uuid=50.00_news_30s_%%PATTERN:hb_cache_id%%` - -![Google Ad Manager Creative Sets Redirect]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_creatives_set_redirect.png){: .pb-lg-img :} - -Enter a time in seconds in the `Duration` field. This should match the duration entered in the value for the custom keyword `hb_pb_cat_dur` created earlier. There is no need to enter `Label` information, the label entered in the `Line Item` will be used. For the remainder of the entries refer to the [Google Ad Manager documentation](https://support.google.com/admanager/answer/1171783). - -Save the settings by clicking the `Save` button. - -## Attaching a Creative to a Line Item - -Once the `Creative Set` is saved the `Creative Set Preview` will display. - -![Google Ad Manager Creative Sets Redirect]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_creative_set_addlineitem_select.png){: .pb-lg-img :} - -Click the `Attach Line Item` button. This will display the `Add line items` popover. -Click on the `Line Items` option. `Line Items` that match the `Creative Set` size and type will be listed. Select the `Line Items` to attach to this `Creative Set`. When finished, click the `Include` button. The selected `Line Items` will now appear in the `Selected Items` list. Click the `Save` button to complete the process. - -The `Line Item` is now prepared for bidding on publisher’s inventory. - -![Google Ad Manager Creative Sets Redirect]({{site.baseurl}}/assets/images/ad-ops/gam_pop/gam_creative_set_lineitem.png){: .pb-lg-img :} - - -## Further Reading -[GAM Video Solutions advertising overview](https://support.google.com/admanager/answer/1711021?hl=en) -[Traffic in-stream video redirects]( -https://support.google.com/dcm/answer/6286181?hl=en) -[Media Planner for in-stream video creatives. A best practice guide:](https://support.google.com/dcm/answer/4348108) -Setting up Prebid video in GAM diff --git a/adops/setting-up-prebid-video-in-dfp.md b/adops/setting-up-prebid-video-in-dfp.md index beb82e163e..13b3327fcf 100644 --- a/adops/setting-up-prebid-video-in-dfp.md +++ b/adops/setting-up-prebid-video-in-dfp.md @@ -1,10 +1,106 @@ --- layout: page_v2 -title: Setting up Prebid Video in Google Ad Manager -head_title: Setting up Prebid Video in Google Ad Manager -description: Setting up Prebid Video in Google Ad Manager +title: GAM Step by Step - Video Creatives +head_title: GAM Step by Step - Video Creatives +description: Setting up in-player and long-form video for Prebid in Google Ad Manager top_nav_section: adops sidebarType: 3 --- -{% include adops/adops-gam-video-setup.html %} +# GAM Step by Step - Video Creatives + +{: .no_toc } + +- TOC +{:toc} + +This page walks you through the steps required to create in-player and long-form video creatives to attach to your Prebid line items in Google Ad Manager (GAM). + +{: .alert.alert-success :} +For complete instructions on setting up Prebid line items in Google Ad Manager, see [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html). + +{: .alert.alert-info :} +For engineering setup instructions, see [Show Video Ads with a Google Ad Manager Video Tag](/dev-docs/show-video-with-a-dfp-video-tag.html). + +Each VAST creative contains a URL that points to the cached VAST XML. (This is because most video players can only work with a URL that returns VAST XML.) When setting up video creatives, it's important to understand where the VAST XML is stored for each of your bidders. The most common place to store VAST XML is the AppNexus cache, but some bidders (such as RubiconProject and SpotX) use their own cache services. To support such bidders, see [Multiple Cache Locations](#multiple-cache-locations) below. + +## Single Cache Location + +All of your bidders may use the same VAST cache server in these scenarios: + +- Mobile SDK video interacts with Prebid Server which will be set up to cache VAST. +- All of your Prebid.js bidders return VAST XML. +- You utilize the Prebid.js [ignoreBidderCacheKey](/dev-docs/publisher-api-reference/setConfig.html#setConfig-vast-cache) option. + +In any of these cases, you only need to set up creatives pointing to the VAST cache: + +1. Select **Delivery** > **Creatives** and click the **VAST creatives** tab. +2. Click **New creative**. +3. In the **New VAST creative** screen, select your **Advertiser**, then select **Redirect**. +4. Enter a **Name** for your creative. +5. Set the **VAST tag URL** to the cache location. + +{: .alert.alert-info :} +**Prebid Cache and the VAST creative URL warning**: +Google Ad Manager will show you a warning stating that fetching VAST from the creative URL failed. This is expected, since the creative URL points to a server-side asset cache hosted by Prebid Server. + +**In Player Video Cache Location** + +If you’re using a Send Top Price Bid configuration, then the VAST URL will be the same for each bidder: + +`https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:hb_uuid%%` + +or + +`[other bidder cache location]` + +If you’re using Send All Bids, the VAST URL will include the bidder-specific targeting variable. Be sure to replace `BIDDERCODE` with the actual bidder code for your bidders: + +`https://prebid.adnxs.com/pbc/v1/cache?uuid=%%PATTERN:hb_uuid_BIDDERCODE%%` + +or + +`[other bidder cache location]` + +**Long-Form Video Cache Location** + +If your creative is for long-form (OTT) video, you must include a prefix in your VAST URL. For example (Send Top Price Bid): + +`https://prebid.adnxs.com/pbc/v1/cache?uuid=50.00_news_30s_%%PATTERN:hb_cache_id%%` + +or (Send All Bids): + +`https://prebid.adnxs.com/pbc/v1/cache?uuid=50.00_news_30s_%%PATTERN:hb_cache_id_BIDDERCODE%%` + +In these examples, the `uuid` is set to the value of the `hb_pb_cat_dur` key you target in your line item. This value consists of the price bucket, label (for competitive exculsions), and video duration. In this example we've specified a price bucket of `50.00`, a label of `news`, and a duration of `30s`. See [GAM with Prebid Step by Step](/adops/step-by-step.html#targeting) for more information. + +{:start="6"} +6. Set the **Duration** to the max length of video ads you serve. Ads flowing through header bidding are going to differ in length, so if you don't know what the max length is, set it to `30`. If you're using long-form video, this value should match the duration you specified in your uuid targeting. + +The resulting creative should look something like the following: + +![GAM Video Creative Setup](/assets/images/ad-ops/gam-sbs/appnexus_vast_tag.png) + +{:start="7"} +7. If you're using jsdelivr, set your **Associated ad technology provider**: + +{% include /adops/adops-creative-declaration.html %} + +{:start="8"} +8. Click **Save and preview**. + +## Multiple Cache Locations + +If you're utilizing any bidders that cache their own VAST, you have two options: + +- If you're using Prebid.js 4.28 or later, your engineers can specify the [ignoreBidderCacheKey](/dev-docs/publisher-api-reference/setConfig.html#setConfig-vast-cache) option on `setConfig({cache})`. This will cause the browser to generate a VAST wrapper and cache it in your standard location. Then you can use the instructions above for "Single Cache Location". The tradeoff is that this approach requires the video player to unwrap one extra level of VAST. +- Utilize creative-level targeting in the ad server. See [GAM with Prebid Step by Step](/adops/step-by-step.html#creative-level-targeting) for details. In this case, you'll target on the `hb_bidder` or `hb_bidder_BIDDERCODE` (replacing BIDDERCODE with the code for your bidder) key with a value of the bidder whose VAST is associated with that creative. + +## Further Reading + +- [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) +- [Show Video Ads with Google Ad Manager](/dev-docs/show-video-with-a-dfp-video-tag.html) +- [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) +- [Prebid Universal Creatives](/overview/prebid-universal-creative.html) +- [Creative Considerations](/adops/creative-considerations.html) +- [Ad Ops Planning Guide](/adops/adops-planning-guide.html) diff --git a/adops/setting-up-prebid-video-in-freewheel.md b/adops/setting-up-prebid-video-in-freewheel.md index 10218d9022..ad1a7ac7f4 100644 --- a/adops/setting-up-prebid-video-in-freewheel.md +++ b/adops/setting-up-prebid-video-in-freewheel.md @@ -3,15 +3,14 @@ layout: page_v2 title: Setting up Prebid Video in FreeWheel head_title: Setting up Prebid Video in FreeWheel description: Setting up Prebid Video in FreeWheel -pid: 3 - -top_nav_section: adops -nav_section: tutorials sidebarType: 3 --- # FreeWheel Guide for Premium Long-Form Video +{: .alert.alert-warning :} +This guide is not written, maintained, or endorsed by Freewheel. Freewheel recommends speaking to your account team before implementing any header-bidding setup to ensure full implications for direct-sold ad delivery, forecasting, and reporting is understood. + This page describes how to set up Campaigns for long form video using FreeWheel's ad server. As with Google Ad Manager for digital ads, ad ops will need to configure their FreeWheel server account so that the server can provide the correct creatives for the video player. If you do not have an account visit [FreeWheel](https://www.freewheel.com/) to create one. @@ -19,20 +18,22 @@ As with Google Ad Manager for digital ads, ad ops will need to configure their F Once your account is set up log in to the FreeWheel site. You will be presented with a dashboard area. Click on either the Advertising button in the top navigation bar or the Campaign link in the main body. ## Campaigns + This will display the Campaign & IO screen. If you have not established any campaigns yet click the Add New Campaign link. This will present the Add New Campaign screen. - - Enter a name for the campaign - - Add an external identifier (optional) - - Select an Advertiser and Agency from the drop down menus. - - Click the Create and Continue Editing button when finished. +- Enter a name for the campaign +- Add an external identifier (optional) +- Select an Advertiser and Agency from the drop down menus. +- Click the Create and Continue Editing button when finished. You will be returned to the Campaign & IO screen and your new campaign should appear in the Campaign & IOs table. To begin your campaign you will need to create some insertion orders. Click on the campaign name, which appears in the Campaign column. This will present the Insertion Orders screen. ## Insertion Orders + Click on the Add New IO link. This will present a pop over for adding a new Insertion Order. Return to the Campaign & IOs screen and check the box in the first column of the row containing your I&O. Click the Load Placements button. This will reload the screen with the details of the Insertion Order you selected and the Placements for that Insertion Order. @@ -43,14 +44,15 @@ If there are no Placements or you want to add a new one click on the Add New Pla The FreeWheel module within Prebid sends key-value targeting pairs to the FreeWheel SDK, which then forwards them to the FreeWheel server. The FreeWheel server uses those targeting key-value pairs to select the correct creatives to return to Prebid. The key-value pairs are written as: - +```text 'hb_pb_cat_dur': ’12.00_399_30s' - +``` The value is a concatenation of the CPM (12.00), the FreeWheel industry code (399) and the ad length in seconds (30s). The name of the Placement must be written in the same format: - +```text 12.00_399_30s +``` Once you have created a Placement it will appear in the first row of the Placement table. @@ -58,7 +60,7 @@ In the last column of each row is a magnifying glass icon. Clicking on that will ### Schedule and Budget -The Schedule and Budget section enables an ad ops to schedule when the Placement will run, the price bucket and the budget type. +The Schedule and Budget section enables an ad ops to schedule when the Placement will run, the price bucket and the budget type. Following the naming convention for Placements, 12.00_399_30s, the first item in the name represents the CPM (12.00). Ensure that the Placement Price matches the CPM. From our example, this should be $12.00. To edit, click on the Price link. @@ -73,22 +75,23 @@ The Delivery and Forecast section determines how frequently a Placement will app - Do Not Allow to Repeat ### Exclusivity -Exclusivity is the process of preventing ads from the same industry group from appearing either in the same ad pod or adjacent to each other in the same ad pod. -Scroll to the Exclusivity section. Ensure that the Level of Exclusivity and Scope of Exclusivity is at the desired setting for this Placement. Also ensure that the industry displayed matches the industry identifier for this Placement. (399 portion of the 12:00_399_30s value). If not, click on the Exclusivity title. A pop over will display enabling you to change the Exclusivity parameters. +Exclusivity is the process of preventing ads from the same industry group from appearing either in the same ad pod or adjacent to each other in the same ad pod. + +Scroll to the Exclusivity section. Ensure that the Level of Exclusivity and Scope of Exclusivity is at the desired setting for this Placement. Also ensure that the industry displayed matches the industry identifier for this Placement. (399 portion of the 12:00_399_30s value). If not, click on the Exclusivity title. A pop over will display enabling you to change the Exclusivity parameters. -The Level of Exclusivity determines the range of ads that fall within the competitive separation rules. There are three options, available from the pop up at the top of the pop over. They are: +The Level of Exclusivity determines the range of ads that fall within the competitive separation rules. There are three options, available from the pop up at the top of the pop over. They are: - None: As it implies, none means there is no exclusivity. - Full: No other industry ads will appear within the ad pod. -- Custom: There is a custom exclusivity set up. +- Custom: There is a custom exclusivity set up. -Checking the box next to the industry name and clicking the Exclude button will add that industry to the list of industries excluded from appearing with this Placement. It is recommended that you exclude an industry if the Placement intends on delivering ads from that industry. -The Scope of Exclusivity determines on what ad types the competitive separation will occur. There are three choices: +Checking the box next to the industry name and clicking the Exclude button will add that industry to the list of industries excluded from appearing with this Placement. It is recommended that you exclude an industry if the Placement intends on delivering ads from that industry. +The Scope of Exclusivity determines on what ad types the competitive separation will occur. There are three choices: - All Ad Units: Exclusivity is applied to any ad. -- Targeted Ads: Exclusivity is only applied to targeted ads. - - Adjacent Ads: Exclusivity is only applied to ads appearing adjacent to this creative. . +- Targeted Ads: Exclusivity is only applied to targeted ads. +- Adjacent Ads: Exclusivity is only applied to ads appearing adjacent to this creative. . ### Custom Targeting @@ -96,50 +99,61 @@ The Custom Targeting section is where a custom target will be set to match the k ### Industry -The Industry section enables publishers to set the Industry Group associated with the Placement. Ensure that the Industry Group matches the FreeWheel industry identifier. If not, click on the Industry title, a pop over will display that will enable you to change the Industry Group. For each Placement there can only be one Industry Group. +The Industry section enables publishers to set the Industry Group associated with the Placement. Ensure that the Industry Group matches the FreeWheel industry identifier. If not, click on the Industry title, a pop over will display that will enable you to change the Industry Group. For each Placement there can only be one Industry Group. The Industry Group must match the Industry Group Identifier that is contained in the passed in key-value targeting pair. In our example case, that Industry Group Identifier is 399 (12.00_399_30s). ## Creatives -Return to the Campaign & IO screen by clicking the Campaign button. Click the Creative button to the right of the Campaign button. This will display the Creative Library. -Publishers must create one Creative for each ad duration they wish to support. For example, if a publisher will support 15s, 30s, and 60s durations, they will need three Creatives, regardless of how many Placements they have at that duration. If there are one hundred Placements with 30s durations, only one Creative targeting 30s duration is needed. +Return to the Campaign & IO screen by clicking the Campaign button. Click the Creative button to the right of the Campaign button. This will display the Creative Library. + +Publishers must create one Creative for each ad duration they wish to support. For example, if a publisher will support 15s, 30s, and 60s durations, they will need three Creatives, regardless of how many Placements they have at that duration. If there are one hundred Placements with 30s durations, only one Creative targeting 30s duration is needed. If there are no creatives in the library click the Add New Creative button. A pop over will display enabling you to add a new creative. The new Creative will appear in the Creative Library. Click on the Creative name, a new screen will be displayed with information about that Creative. ### Duration -Duration determines the length of the Creative. This value must match the duration portion of the key-value target passed into FreeWheel server. The 30s portion of our example (12:00_399_30s). If not, click on the Duration link. A pop over will display enabling you to enter the correct duration for this Creative. + +Duration determines the length of the Creative. This value must match the duration portion of the key-value target passed into FreeWheel server. The 30s portion of our example (12:00_399_30s). If not, click on the Duration link. A pop over will display enabling you to enter the correct duration for this Creative. For each Placement duration you should have one Creative that matches. For example, if you had Placements with targeting values of 12:00_399_15s, 12:00_399_30s, and 12:00_399_45s, you should have three Creatives, one with a 15 second duration, another with a 30 second duration and a third one with a 45 second duration. -Only one Creative is needed for each Placement duration. For example, if you had Placements with targeting values of 12:00_398_30s, 12:00_399_30s and 12:00_400_30s you would only need one Creative with a duration of 30 seconds. +Only one Creative is needed for each Placement duration. For example, if you had Placements with targeting values of 12:00_398_30s, 12:00_399_30s and 12:00_400_30s you would only need one Creative with a duration of 30 seconds. -### Creative URL +### Creative URL In order for FreeWheel SDK to send the correct Creative to the video player it needs to request the VAST XML stored in Prebid cache. The Creative URL has to point to the correct cache location. To ensure the cache URL is correct there are two macros that dynamically populate the URL query. To confirm the dynamic URL is formatted correctly click on the URL link in the Detail field. A pop over will display with the dynamic URL. -The scheme, host, and path should read as follows: -https://prebid.adnxs.com/pbc/v1/cache +The scheme, host, and path should point to your Prebid Server cache. For instance, if you +utilize Xandr's AppNexus cache: + +```text +https://prebid.adnxs.com/pbc/v1/cache +``` -The query should have one key-value items: +The query should have one key-value items: +```text uuid=#{ad.placement.name}_#{request.keyValue(“hb_cache_id")} +``` -The first macro, #{ad.placement.name}, will format the Placement name. It will be the CPM_IndustryIdentfier_Duration format passed in from Prebid for targeting and the name used for the Placement. (12.00_399_30s) +The first macro, `#{ad.placement.name}`, will format the Placement name. It will be the CPM_IndustryIdentfier_Duration format passed in from Prebid for targeting and the name used for the Placement. (12.00_399_30s) -The second macro, #{request.keyValue(“hb_cache_id”), formats the unique Prebid cached id. +The second macro, `#{request.keyValue(“hb_cache_id”)`, formats the unique Prebid cached id. -In real-time, when the dynamic URL is formatted it will appear like: +In real-time, when the dynamic URL is formatted it will appear like: -https://prebid.adnxs.com/pbc/v1/cache?uuid=12.00_391_30s_6c422e51-46cf-4b0a-ae41-64c61c1ca125 +```text +https://prebid.adnxs.com/pbc/v1/cache?uuid=12.00_391_30s_6c422e51-46cf-4b0a-ae41-64c61c1ca125 +``` In order for the above URL to format correctly ensure that the URL in the text box appears as: -https://prebid.adnxs.com/pbc/v1/cache?uuid=#{ad.placement.name}_#{request.keyValue("hb_cache_id")} - -Your ad ops should now be completed and set up for premium long-form video. +```text +https://prebid.adnxs.com/pbc/v1/cache?uuid=#{ad.placement.name}_#{request.keyValue("hb_cache_id")} +``` +Your ad ops should now be completed and set up for premium long-form video. diff --git a/adops/setting-up-prebid-with-the-appnexus-ad-server.md b/adops/setting-up-prebid-with-the-appnexus-ad-server.md index d6a92142bd..43aa5ca4c1 100644 --- a/adops/setting-up-prebid-with-the-appnexus-ad-server.md +++ b/adops/setting-up-prebid-with-the-appnexus-ad-server.md @@ -1,8 +1,8 @@ --- layout: page_v2 -title: Setting up Prebid with the Xandr Publisher Ad Server -head_title: Setting up Prebid with the Xandr Publisher Ad Server -description: Setting up Prebid with the Xandr Publisher Ad Server +title: Setting up Prebid with the Microsoft Monetize Ad Server +head_title: Setting up Prebid with the Microsoft Monetize Ad Server +description: Setting up Prebid with the Microsoft Monetize Ad Server pid: 3 top_nav_section: adops @@ -10,32 +10,31 @@ nav_section: tutorials sidebarType: 3 --- +# Setting up Prebid with the Microsoft Monetize Ad Server - -# Setting up Prebid with the Xandr Publisher Ad Server {: .no_toc} -This page describes how to set up the Xandr Publisher Ad Server to work with Prebid.js from an Ad Ops perspective. +This page describes how to set up the Microsoft Monetize Ad Server to work with Prebid.js from an Ad Ops perspective. -In some cases there are links to the [Xandr Help Center](https://monetize.xandr.com/docs/home) which require a customer login. +In some cases there are links to the [Microsoft Help Center](https://docs.xandr.com/). -Once the Ad Ops setup is complete, developers will need to add code to the page as shown in the example [Using Prebid.js with Xandr as your Ad Server]({{site.github.url}}/dev-docs/examples/use-prebid-with-appnexus-ad-server.html). +Once the Ad Ops setup is complete, developers will need to add code to the page as shown in the example [Using Prebid.js with Microsoft Monetize as your Ad Server]({{site.github.url}}/dev-docs/examples/use-prebid-with-appnexus-ad-server.html). {: .alert.alert-success :} -**Xandr Publisher Ad Server Features** -Note that the functionality described on this page uses some features that are only available in the Xandr Publisher Ad Server product, such as [key-value targeting](https://monetize.xandr.com/docs/key-value-targeting). For more information, contact your Xandr representative. +**Microsoft Monetize Ad Server Features** +Note that the functionality described on this page uses some features that are only available in the Microsoft Monetize Ad Server product. For more information, contact your Microsoft Monetize representative. {: .alert.alert-info :} -**Object Limits** -Note that using Prebid with Xandr as your ad server may cause you to -hit your Xandr [Object Limits](https://monetize.xandr.com/docs/viewing-your-object-limits). +**Object Limits** +Note that using Prebid with Microsoft Monetize as your Ad Server may cause you to +hit your [Object Limits](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/viewing-your-object-limits.html). * TOC {:toc} ## Step 1. Add Key-Values -In the [key-value targeting](https://monetize.xandr.com/docs/key-value-targeting) in Console, set up the keys and values shown below. Keep in mind that all of the keys described below should use string values (**not** numeric). +In the [key-value targeting](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/key-value-targeting.html) in Monetize, set up the keys and values shown below. Keep in mind that all of the keys described below should use string values (**not** numeric). If you are only sending the winning bid to the ad server, set up your keys like so: @@ -54,31 +53,34 @@ Otherwise, if you are [sending all bids to the ad server](/dev-docs/publisher-ap Depending on the price granularity you want, you may find one of the following CSV files helpful. Each file has the buckets for that granularity level predefined. You can avoid manually setting up key-value targeting by uploading the appropriate CSV file on the [key-values screen](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/key-value-targeting.html): -+ [10cent-prebid-buckets.csv]({{site.github.url}}/assets/csv/10cent-prebid-buckets.csv) -+ [25cent-prebid-buckets.csv]({{site.github.url}}/assets/csv/25cent-prebid-buckets.csv) -+ [dense-prebid-buckets.csv]({{site.github.url}}/assets/csv/dense-prebid-buckets.csv) +* [10cent-prebid-buckets.csv]({{site.github.url}}/assets/csv/10cent-prebid-buckets.csv) +* [25cent-prebid-buckets.csv]({{site.github.url}}/assets/csv/25cent-prebid-buckets.csv) +* [dense-prebid-buckets.csv]({{site.github.url}}/assets/csv/dense-prebid-buckets.csv) For more information about how to set up price bucket granularity in Prebid.js code, see the API documentation for [`pbjs.setPriceGranularity`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity). {: .alert.alert-success :} You can only report on price bucket values if you provide them in the Key-Value Targeting UI. -## Step 2. Add Creatives +## Step 2. Add Advertiser -You'll need one creative per ad size you'd like to serve. You can re-use a creative across any number of line items and campaigns. +Depending on whether you are sending all bids or sending top bid you will need to create an Advertiser per bidder e.g. *Rubicon - Prebid Advertiser* vs *Prebid Advertiser* -Follow the creative setup instructions in [Add Creatives](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/add-a-creative.html) with the following setting: +Follow the advertiser setup instructions in [Create an Advertiser](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-an-advertiser.html) -- Select **Show Template Selector**. +## Step 3. Add Creatives -- Select a template with an HTML format. +You'll need one creative per ad size you'd like to serve. You can re-use a creative across any number of line items, as long as the creative belongs to the same advertiser as the line item. -- Paste the code snippet shown below into the code box. +Follow the banner creative setup instructions in [Add Creatives](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/add-a-creative.html), navigating the the Creative Manager and selecting the appropriate advertiser from the previous step, with the following setting: -![New creative]({{ site.github.url }}/assets/images/ad-ops/appnexus-setup/prebid-creative-appnexus.png) {: .pb-lg-img :} +* Paste the below universal creative code as the creative asset tag code. +* Name the creative e.g. *Rubicon - Prebid Creative 300x250*. +* Select the creative size e.g. *300x250*. +* Self-Audit the creative and confirm compliance. -{% highlight html %} - +```html + -{% endhighlight %} +``` {: .alert.alert-warning :} -**Creative Expiration** -Note that creatives are automatically marked as inactive by the Xandr systems after 45 days of inactivity. This may happen to Prebid creatives since they are loaded relatively infrequently compared to other use cases. For help with mitigating this issue, please contact your Xandr representative. +**Creative Expiration** +Note that creatives are automatically marked as inactive by the Microsoft Monetize systems after 45 days of inactivity. This may happen to Prebid creatives since they are loaded relatively infrequently compared to other use cases. For help with mitigating this issue, please contact your Microsoft Monetize representative. {: .alert.alert-warning :} **SafeFrame** -If you want your creative to serve into a SafeFrame, this will need to be enabled on the site-side of the Prebid.js implementation rather than as a setting in the ad server. A developer can learn how to enable this setting for the publisher by referencing [Using Prebid.js with Xandr Publisher Ad Server]({{site.github.url}}/dev-docs/examples/use-prebid-with-appnexus-ad-server.html). Additionally if the Xandr ad server tags are configured to use SafeFrames, you **will** need to use the above creative template to properly render the creative. Earlier versions of the Prebid.js creative template may not be fully SafeFrame compliant (if they are still in-use from older setups), so it is recommended to switch to the above template in this scenario. +If you want your creative to serve into a SafeFrame, this will need to be enabled on the site-side of the Prebid.js implementation rather than as a setting in the ad server. A developer can learn how to enable this setting for the publisher by referencing [Using Prebid.js with Microsoft Monetize Ad Server]({{site.github.url}}/dev-docs/examples/use-prebid-with-appnexus-ad-server.html). Additionally if the Microsoft Monetize Ad Server tags are configured to use SafeFrames, you **will** need to use the above creative template to properly render the creative. Earlier versions of the Prebid.js creative template may not be fully SafeFrame compliant (if they are still in-use from older setups), so it is recommended to switch to the above template in this scenario. + +## Step 4. Set up Insertion Order + +You'll need to create an insertion order, belonging to your advertiser, for your line items. +Follow the insertion order setup setup instructions in [Create a Seamless Insertion Order (IO)](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-an-insertion-order.html), with the following settings: -## Step 3. Set up Line Items +* Choose a flexible budget type. +* Set no end date. -You'll need to create one line item for every price bucket you intend to serve. +## Step 5. Set up Line Items + +You'll need to create one line item for every price bucket you intend to serve. These line items will need to be under the advertiser and insertion order in step 2 and 4. For example, if you want to have $0.10 price granularity, you'll need 201 line items, one for each of your key-value targeting settings from Step 1. -For each line item, follow the line item setup instructions in [Create a Line Item](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-a-standard-line-item.html), with the following settings: +For each line item, follow the line item setup setup instructions in [Create an Augmented Line Item (ALI)](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-an-augmented-line-item-ali.html), with the following settings: + +* Set the **Name** e.g., *€00.01 - Rubicon - Prebid Banner*. -- Set the **Revenue Type** to *CPM*. +* Set **Ad Type** Banner. -- Set the **Revenue Value** to one of the price bucket key-values from Step 1, e.g., \$0.2. +* Set the **Revenue Type** to *CPM*. -- Under **Associated Creatives**, choose to manage creatives at the line item level. +* Set the **Revenue Value** to one of the price bucket key-values from Step 1, e.g., *0.01*. -- Associate as many creative sizes with the line item as you need. Set the **Creative Rotation** to *Even*. +* Set the **Budget Setup** to *Unlimited Budget*. -- In your line item's targeting settings, use the key-value that matches the line item's price bucket, e.g. (you set these up in Step 1). +* Set the **End Date** sometime in the future e.g. *6/26/2033*. -- Still in the targeting settings, target the custom category `prebid_enabled`. This will allow you to turn targeting on and off for a placement (or an entire placement group) by adding it to the custom category, which you'll do in one of the later steps. This is useful for troubleshooting. +* Within **Inventory & Brand Safety Targeting** and for **Supply Source** select *Managed Inventory*. -For more information about targeting custom content categories, see [Content Category Targeting](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/content-category-targeting.html). +* Set the **Line Item Priority** for more information on line item priority see [Bidding Priority](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/bidding-priority.html) -## Step 4. Set up Campaigns +* Optional: Still in the targeting settings, target the custom category `prebid_enabled`. This will allow you to turn targeting on and off for a placement (or an entire placement group) by adding it to the custom category, which you'll do in one of the later steps. This is useful for troubleshooting. For more information about targeting custom content categories, see [Content Category Targeting](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/content-category-targeting.html). -For each line item, create one campaign to associate with it. The campaign should have an unlimited budget, start running right away, and run indefinitely. +* In your line item's targeting settings, set the **Key/Value Targeting** to match the line item's price bucket/revenue value. -You shouldn't have to do anything else. All other settings (such as budget and targeting) are inherited from the line item. +* Under **Creatives**, associate as many creative sizes with the line item as you need. Set the **Creative Rotation** to *Evenly weight creatives*. -For more information, see the full campaign setup instructions at [Create a Campaign](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-a-campaign.html). +* Scroll back up to **Budgeting & Scheduling** and select *No daily budget* within **Pacing** (this can only be selected when managed invenotry is targeted). -## Step 5. Add the `prebid_enabled` Custom Category to Placements +## Step 6. Add the `prebid_enabled` Custom Category to Placements (Optional) -Make sure the placements you're using for Prebid are added to the following custom category: `prebid_enabled`. +If while setting up line items, you set custom category targety to `prebid_enabled`, make sure the placements you're using for Prebid are added to the custom category `prebid_enabled`. This will make sure these placements are targeted by the line items you just set up. -It will also make it easy to turn the targeting on and off for a given placement (or placement group) by adding or removing it from the custom category. This can be very useful when troubleshooting. +It will also make it easy to turn the targeting on and off for a given placement (or placement group) by adding or removing it from the custom category. This can be useful when troubleshooting. ## Related Topics -+ [Getting Started with Prebid.js for Header Bidding]({{site.github.url}}/overview/getting-started.html) - -+ [Using Prebid.js with Xandr as your Ad Server]({{site.github.url}}/dev-docs/examples/use-prebid-with-appnexus-ad-server.html) (Developer example) +* [Ad Ops and Prebid](/adops/before-you-start.html) +* [Ad Ops Planning Guide](/adops/adops-planning-guide.html) +* [Getting Started with Prebid.js for Developers](/dev-docs/getting-started.html) +* [Using Prebid.js with Microsoft Monetize Ad Server](/dev-docs/examples/use-prebid-with-appnexus-ad-server.html)(Developer example) diff --git a/adops/setting-up-prebidjs-with-Smart-Ad-Server.md b/adops/setting-up-prebidjs-with-Smart-Ad-Server.md index 969d3af0f3..2dfc95c07a 100644 --- a/adops/setting-up-prebidjs-with-Smart-Ad-Server.md +++ b/adops/setting-up-prebidjs-with-Smart-Ad-Server.md @@ -9,24 +9,29 @@ sidebarType: 3 # Setting up Prebid.js with Smart Ad Server + ## Introduction + This article describes the basic steps to set up Prebid.js with Smart Ad Server. Comprehensive documentation is available in the article [Holistic+ Setup](https://support.smartadserver.com/s/article/Holistic-Setup) in Smart AdServer’s Help Center. This documentation may be more up to date than the explanations below. -For some of the setup steps described below, you need to have a login to [Smart AdServer’s UI](https://manage.smartadserver.com/). +For some of the setup steps described below, you need to have a login to [Smart AdServer’s UI](https://manage.smartadserver.com/). ## How it works - - You implement the Prebid.js header bidding wrapper as well as Smart AdServer’s ad tags on your website. - - The header auction winner’s data (bidder name, CPM, currency) is passed with the ad call executed by Smart AdServer’s ad tag. - - In Smart AdServer’s UI, you simply set up an RTB+ insertion in order to establish the competition between the header auction winner and Smart AdServer’s connected monetization partners (DSPs); there is no need to set up multiple line items, price buckets, keyword targeting etc. - - At the same time, Smart AdServer’s holistic yield algorithm will make sure your direct (guaranteed) campaigns meet their targets. - - Finally, the impression is given to the highest bid: (1) Smart AdServer’s own RTB+ (2) a direct campaign or (3) the header auction winner. +- You implement the Prebid.js header bidding wrapper as well as Smart AdServer’s ad tags on your website. +- The header auction winner’s data (bidder name, CPM, currency) is passed with the ad call executed by Smart AdServer’s ad tag. +- In Smart AdServer’s UI, you simply set up an RTB+ insertion in order to establish the competition between the header auction winner and Smart AdServer’s connected monetization partners (DSPs); there is no need to set up ultiple line items, price buckets, keyword targeting etc. +- At the same time, Smart AdServer’s holistic yield algorithm will make sure your direct (guaranteed) campaigns meet their targets. +- Finally, the impression is given to the highest bid: (1) Smart AdServer’s own RTB+ (2) a direct campaign or (3) the header auction winner. ## Setup + ### Step 1 - Implement the wrapper + Proceed as follows: + - Go to the [Prebid.js download page](/download.html). - Select the relevant **Bidder Adapter(s)**, an **Analytics Adapter** (optional) and **Module(s)** (optional). - Download the code. @@ -37,25 +42,31 @@ Proceed as follows: This step is also documented [here](https://support.smartadserver.com/s/article/Holistic-Setup#implement-wrapper). ### Step 2 - Implement Smart AdServer’s tag + Smart AdServer’s OneCall tagging is strongly recommended. With OneCall, you can set header bidding data per `tagId`. The `tagId` is the Id of the container (`
    `), where the ad will be displayed. The `tagId` format is `sas_`. e.g. `sas_1234`. Make sure you use Smart AdServer’s **new OneCall tagging**, which uses POST requests with all the necessary information in the request body; simply check if you see the `formats` array in your tag. If you see `formatId`, you are still dealing with an old tag - in this case, get back to your service contact at Smart AdServer. -For samples of both the new and legacy OneCall as well as a full implementation example, read [here](https://support.smartadserver.com/s/article/Holistic-Setup#onecall). +For samples of both the new and legacy OneCall as well as a full implementation example, read [here](https://support.smartadserver.com/s/article/Holistic-Setup#onecall). **Additional resources**: + - [Implementation with Smart AdServer’s Standard Call tagging](https://support.smartadserver.com/s/article/Holistic-Setup#implement-smart-tag) -- [Full tagging guide](https://support.smartadserver.com/s/article/Tagging-guide) +- [Full tagging guide](https://support.smartadserver.com/s/article/Tagging-guide) ### Step 3 - Setup in Smart AdServer’s UI + Things to keep in mind for the Setup in [Smart AdServer’s UI](https://manage.smartadserver.com/): + - In the RTB+ insertion, you must enable the checkbox "Activate Holistic yield mode" in the "General settings" section of the insertion. - RTB+ must be enabled and configured in the network global settings. - The Holistic+ feature must be enabled on the network. - You must use the official and Holistic RTB+ script templates in the insertions. For more details, read [here](https://support.smartadserver.com/s/article/Holistic-Setup#setup-ui). + ### Step 4 - Get reporting + Read these articles to learn more about the available header bidding reporting: -- [Holistic Dashboard](https://support.smartadserver.com/s/article/Holistic-dashboard) - provides a fast and easy overview of basic metrics by delivery channel and RTB product. + - [Big Data Reports](https://support.smartadserver.com/s/article/Holistic-Setup#bdr) - provides full, in-depth reporting with header bidding related dimensions and metrics. diff --git a/adops/step-by-step.md b/adops/step-by-step.md index 9b1f650c73..0e85b68a8c 100644 --- a/adops/step-by-step.md +++ b/adops/step-by-step.md @@ -1,9 +1,219 @@ --- layout: page_v2 -title: Setup Line items For Google Ad Manager -head_title: Step by step guide to Google Ad Manager Setup -description: Setting up GAM for Prebid.js +title: Google Ad Manager with Prebid Step by Step +head_title: Google Ad Manager with Prebid Step by Step +description: Step-by-step instructions for setting up line items in GAM for Prebid. #note the sidebar type needs to reflect the section this file is displayed in. See _data/sidenav.yml for the side nav categories. sidebarType: 3 --- -{% include /adops/adops-gam-setup.html %} + +# Google Ad Manager with Prebid Step by Step + +{: .no_toc } + +- TOC +{: toc } + +This guide contains step-by-step instructions for manually setting up line items in Google Ad Manager (GAM) to work with Prebid. These instructions describe only the specific settings required for Prebid, they are not intended to be comprehensive instructions that replace or duplicate the [GAM documentation](https://support.google.com/admanager#topic=7505988). + +Because integrating with Prebid could mean having to create thousands of line items, most companies will automate these steps. We’re showing them here so you can manually create the line items if you need or want to, and also to provide context for the automation. + +{: .alert.alert-success :} +Prebid provides a script you can use to automate these steps: [Prebid Line Item Manager](/tools/line-item-manager.html). + +## Prerequisites + +Before you begin, we recommend you read through our [Planning Guide](/adops/adops-planning-guide.html) to make sure you know what your configuration is going to look like and you’ve thoroughly documented your decisions. + +### Create Advertisers and Orders + +GAM works as a hierarchical structure, where line items are children of orders, and orders are children of advertisers. You must have your advertisers and orders set up before you can start creating line items and creatives. The advertisers you create for Prebid will typically depend on whether you’re sending all bids or only the top price bid to the ad server. + +- Send Top Bid: Create one general Prebid advertiser +- Send All Bids: Create one Prebid advertiser per bidder where Orders are organized by bidder, with one or more orders containing line items targeted towards a single bidder. + +![Google Ad Manager hierarchy](/assets/images/ad-ops/gam-sbs/gam-hierarchy.png) + +### Create Native Template + +If you’re working with native inventory, you must have your native template created and stored before you begin creating your line item. See [GAM Step by Step - Native Creatives](/adops/gam-native.html). + +### Create Keys + +When you create your line item, you’ll be targeting key-value pairs that are being sent with the ad request to the ad server. Any keys you target need to be defined in GAM before you can use them in your line items. + +To define new keys, in GAM go to **Inventory** > **Key-Values** and enter your Prebid-specific keys, e.g. `hb_pb`, `hb_adid`, `hb_size`, `hb_format`, etc. + +You can also define accepted values for the keys, but you don’t need to. If you create Dynamic keys, values can be added when you set up your line item. + +{: .alert.alert-danger :} +Keys in GAM have a maximum length of 20 characters; any keys passed to GAM longer than that will be truncated. This means that if Prebid passes in the key `hb_format_BidderWithALongName`, GAM will truncate it to `hb_format_BidderWith`. When you create your keys, you must use the truncated name. + +See [Key Values](/adops/key-values.html) for information on the keys you'll need. + +## Create a Line Item + +Open the order you want to associate the line item with and click **New line item**. + +### General Settings + +From the **Settings** tab, do the following: + +1. Select your **Ad type**: + - Banner/Outstream/Native/AMP: Click **Select display ad**. + - Video/Audio: Click **Select video or audio ad**. + +2. Enter the **Name** of your line item. Suggested format: Prebid – format - bidder – price bucket. For example, `Prebid – banner - BidderA - 1.50`. + +3. Set the **Line Item Type** to **Price priority (12)**. (This will most likely be higher for deals. See [Deals in Prebid](/adops/deals.html) for more information.) + +4. Enter your **Expected Creatives**: + - Banner/Outstream/AMP/Video: Select the sizes of all ad slots included in the Prebid process. + - Native: Select a native template. (See [GAM Step by Step - Native Creatives](/adops/gam-native.html) for instructions on creating native templates.) + +![New line item settings](/assets/images/ad-ops/gam-sbs/line-item-settings.png) + +{:start="5"} +5. For Long-Form (OTT) Video: If you're using competitive exclusions, under **Additional settings** enter the value for competitive exclusions in the **Label** field. This value will be included in your targeting within the value for the `hb_pb_cat_dur` key. See [Targeting](#targeting) below for more information. +6. Under **Delivery settings**: + - Set **Start time** to **Immediately**. + - Set **End time** to **Unlimited**. + - Set **Rate** to your [price bucket]. + - Set **Goal** type to **None**. + +![Line item delivery settings](/assets/images/ad-ops/gam-sbs/delivery-settings.png) + +{:start="7"} +7. Under **Adjust delivery**, set **Display creatives** to **One or more** and **Rotate creatives** to **Evenly**. You can leave the defaults for everything else. + +### Targeting + +Under **Add targeting**, expand **Custom targeting**. + +{: .alert.alert-info :} +These instructions assume you’re sending all bids to the ad server (the default). If you’re sending only the top price bid, your targeting keys will not include the bidder code. For example, rather than targeting price buckets with `hb_pb_BidderA`, you’ll target `hb_pb`. See [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) for more information. + +Select the price bucket key: **hb_pb_BIDDERCODE** (where BIDDERCODE is the actual code for your bidder, such as `hb_pb_BidderA`). + +Leave **is any of** and enter (or select) your price bucket. + +![Custom targeting on price bucket](/assets/images/ad-ops/gam-sbs/custom-targeting-pb.png) + +The following additional keys must be added for the corresponding formats: + +**Banner/Outstream/Native**: + +You can use the same line item for banner, outstream, and/or native creatives. If your ad slot could be filled by two or more of these formats, you must include the hb_format key with values specifying all expected formats. Select **hb_format_BIDDERCODE > is any of > video, banner, native**. + +![Custom targeting on format](/assets/images/ad-ops/gam-sbs/custom-targeting-format.png) + +{: .alert.alert-warning :} +If you combine native with another format in a single line item, you’ll need to add creative-level targeting to designate which creatives target which format. See [Creative-level Targeting](#creative-level-targeting) below. + +**In-Player and Outstream Video**: + +Both in-player (instream) and outstream video ads supply the `hb_format_BIDDERCODE=video` key-value pair, so targeting on that key alone is not enough to choose the correct line items. If you're running both instream and outstream video ads, they will most likely be separate line items, so you will need to target outstream line items to either "Inventory Type=display" or "Inventory in (list of GAM AdUnits)". + +**Long-Form (OTT) Video**: + +For long-form video the custom key **hb_pb_cat_dur_BIDDERCODE** is required. The value of this key breaks down like this: + +- *_pb* represents the price bucket. This is the currency amount entered in the **Rate** field of the **Settings** section. +- *_cat* indicates the competitive exclusion industry code. (For engineering information, refer to the [Category Translation module](/dev-docs/modules/categoryTranslation.html)). This is the value entered in the **Label** field for the purpose of competitive exclusion. Having this value in the target helps GAM choose the line items that declare the competitive exclusion label. If you are not using competitive exclusion, you can omit this portion of the value. +- *_dur* is the length of the video in seconds. This is the value listed in the **Max duration** field in the **Creative forecasting defaults** section. Having this value in the target helps GAM choose the line items whose creatives are set up with the right duration. + +For example, for a line item with a $10.00 CPM entered in the Rate field, a Label of “news”, and 30s entered in the Duration field, you would enter the following in the Custom key-value field: `hb_pb_cat_dur_BIDDERCODE = 10.00_news_30s`. If you’re not using competitive exclusion, you can have a value such as this: `hb_pb_cat_dur_BIDDERCODE = 10.00_30s`. + +{: .alert.alert-info :} +For deals, the Rate portion of this value will contain the dealID if deals are prioritized. See [Getting Started with Long Form Video](/prebid-video/video-long-form.html#configuration) for engineering information. + +{: .alert.alert-info :} +Engineers will need to include the [Adpod module](/dev-docs/modules/adpod.html) and the [Category Translation module](/dev-docs/modules/categoryTranslation.html) in Prebid.js to implement long-form video bidding. + +### Creative-level Targeting + +In the **Expected Creatives** section, you can add targeting that applies to creatives rather than to the entire line item. For Prebid you might want to do this if you’re going to use a single line item for multiple formats, or if you have multiple video cache locations. + +To set creative-level targeting, do the following: + +1. In the line item's **Expected creatives** box, enter the creative size or sizes. +2. Click **Show creative details** (for display) or **Expand all** (for video). +3. In the first creative size box, under **Creative targeting** click **Add targeting** and select **Add new targeting**. This slides out the **Creative targeting** window. +4. Expand **Custom targeting** and enter the appropriate key values. + +Repeat the preceding steps for each creative in the line item. + +### Save the Line Item + +You’ve now added all fields necessary for targeting Prebid line items. You can add any other line item options you would normally use, such as additional targeting for geography. When you’ve filled in all the above fields, click **Save** to save your line item. + +## Create Creatives + +The process you use to create your creatives differs based on the media type. Follow the instructions for the appropriate media type: + +- [Banner/Outstream/AMP](/adops/gam-creative-banner-sbs.html) +- [Native](/adops/gam-native.html) +- [Video](/adops/setting-up-prebid-video-in-dfp.html) + +## Duplicate Creative + +After you've created your creatives, you’ll need to associate a creative with each size in your line item. Even if you’ve specified only one or two sizes, you might actually want more creatives than you have sizes. Because the creative body itself is identical no matter which size you’re associating it with, you can duplicate the creative so you have as many as you need. + +{: .alert.alert-info :} +You need extra copies of the creative because GAM will display only one creative per line item per page. See [Creative Considerations](/adops/creative-considerations.html) for more information. + +1. Select **Delivery** > **Creatives**. +2. Find the creative you want to duplicate and click the check mark to the left. +3. At the top of the creatives list, click **Copy**. This will create a copy of your creative in the same location, with "(Copy)" appended to the name. +4. Continue to click **Copy** to create as many creatives as you’ll need for your line item. +5. After you’ve created the copies, click into each one and change the **Name**. If you’ve followed our suggestions, you can name each one the same but append a subsequent number. For example, `Prebid – banner – 1x1 – 1`, `Prebid – banner – 1x1 – 2`, etc. + +![List of duplicated creatives](/assets/images/ad-ops/gam-sbs/duplicate-creatives.png) + +## Attach Creatives to Line Item + +Now we need to attach the creatives to your line item. Navigate to **Delivery** > **Line items** and select the line item you created earlier. + +Under the **Creatives** tab, you’ll see a yellow box showing each size you entered for your line item that doesn’t yet have a creative attached. For each size in the list, do the following: + +1. Click **Existing creative**. A message at the top of the screen will tell you that creatives have been filtered based on size. Click **Undo**. + +![Creative filter based on size](/assets/images/ad-ops/gam-sbs/creative-filter.png) + +{:start="2"} +2. Click **Creatives**. +3. Select one of the creatives you just created and click **Save**. (If you have more creatives than you do sizes, you can select multiple creatives before clicking Save.) + +![Select creatives to attach to line item](/assets/images/ad-ops/gam-sbs/select-creative.png) + +Repeat the preceding steps until all the sizes in your line item have creatives associated with them. When you’re done, the **Creatives** tab under your line item will show a list of all the associated creatives. + +## Duplicate Line Item + +You’ve now created a line item for one price bucket for a single bidder. Next you need to create line items for the rest of the price buckets for that bidder. The simplest way to do that (outside of automation) is to duplicate the line item you just created. + +1. From **Display** > **Line Items**, click the check box next to your line item. +2. Select **Copy to** from the action bar that appears. +3. In the **Copy line item** window, select **Copy and share creatives**, and copy to **Same order**. +4. Input the number of copies you need to make to cover all price buckets for the bidder. +5. Click **OK**. + +You now need to click into each line item to change the following values to reflect the new price bucket: + +- Rate +- Name +- hb_pb_BIDDERCODE key value +- Long-form video only: hb_pb_cat_dur key value + +## Additional Bidders + +If you’re using a Send Top Price cofiguration, at this point you’re done. Congratulations! + +If you’re using a Send All Bids configuration, you need to repeat all the above steps for each of your bidders. You can copy one of the existing creatives and change the BIDDERCODE, and you can copy the existing line items and change the names, so you don’t have to completely start from scratch. + +## Further Reading + +- [Prebid Ad Ops Planning Guide](/adops/adops-planning-guide.html) +- [GAM Step by Step Creatives: Banner/Outstream/AMP](/adops/gam-creative-banner-sbs.html) +- [GAM Step by Step Creatives: Native](/adops/gam-native.html) +- [GAM Step by Step Creatives: Video](/adops/setting-up-prebid-video-in-dfp.html) diff --git a/assets/css/main-bundle.css b/assets/css/main-bundle.css deleted file mode 100644 index 390273a89b..0000000000 --- a/assets/css/main-bundle.css +++ /dev/null @@ -1 +0,0 @@ -.awesomplete [hidden]{display:none}.awesomplete .visually-hidden{position:absolute;clip:rect(0,0,0,0)}.awesomplete{display:inline-block;position:relative}.awesomplete>input{display:block}.awesomplete>ul{position:absolute;left:0;z-index:1;min-width:100%;box-sizing:border-box;list-style:none;padding:0;margin:0;background:#fff}.awesomplete>ul:empty{display:none}*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-size:1rem;font-weight:400;color:#212529;text-align:left;background-color:#eceeef}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{font-style:normal;line-height:inherit}address,dl,ol,ul{margin-bottom:1rem}dl,ol,ul{margin-top:0}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{border-style:none}img,svg{vertical-align:middle}svg{overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:10px;padding-left:10px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1200px}}.row{display:flex;flex-wrap:wrap;margin-right:-10px;margin-left:-10px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-auto,.col-lg,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-auto,.col-md,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md-auto,.col-sm,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-auto{position:relative;width:100%;padding-right:10px;padding-left:10px}.col{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width:576px){.col-sm{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width:768px){.col-md{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width:992px){.col-lg{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width:1200px){.col-xl{flex-basis:0;flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary.focus,.btn-primary:focus,.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary.focus,.btn-secondary:focus,.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success.focus,.btn-success:focus,.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info.focus,.btn-info:focus,.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning.focus,.btn-warning:focus,.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger.focus,.btn-danger:focus,.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light.focus,.btn-light:focus,.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark.focus,.btn-dark:focus,.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3}.btn-link.focus,.btn-link:focus,.btn-link:hover{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty:after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:24px 0;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:0 solid rgba(0,0,0,.15);border-radius:0}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:0}.dropup .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:0}.dropright .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty:after{margin-left:0}.dropright .dropdown-toggle:after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:0}.dropleft .dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";display:none}.dropleft .dropdown-toggle:before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty:after{margin-left:0}.dropleft .dropdown-toggle:before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#797f90;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#ff6f00;text-decoration:none;background-color:transparent}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:24px 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#797f90}.navbar{position:relative;padding:0 1rem}.navbar,.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:-.1875rem;padding-bottom:-.1875rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:0;padding-bottom:0}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat 50%;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand,.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a,.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand,.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:hsla(0,0%,100%,.7)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:hsla(0,0%,100%,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:hsla(0,0%,100%,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:hsla(0,0%,100%,.7);border-color:hsla(0,0%,100%,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.7)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:hsla(0,0%,100%,.7)}.navbar-dark .navbar-text a,.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:0 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#eceeef;border-color:#dee2e6 #dee2e6 #eceeef}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.pbTable,.table{width:100%;margin-bottom:1rem;color:#797f90}.pbTable td,.pbTable th,.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dddfe3}.pbTable thead th,.table thead th{vertical-align:bottom;border-bottom:2px solid #dddfe3}.pbTable tbody+tbody,.table tbody+tbody{border-top:2px solid #dddfe3}.table-sm td,.table-sm th{padding:.3rem}.pbTable,.pbTable td,.pbTable th,.table-bordered,.table-bordered td,.table-bordered th{border:1px solid #dddfe3}.pbTable thead td,.pbTable thead th,.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.pbTable tbody tr:nth-of-type(odd),.table-striped tbody tr:nth-of-type(odd){background-color:#f8f9f9}.table-hover tbody tr:hover{color:#797f90;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover,.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover,.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover,.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover,.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover,.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover,.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover,.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover,.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th,.table-hover .table-active:hover,.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.pbTable .thead-dark th,.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.pbTable .thead-light th,.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dddfe3}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.pbTable,.table-dark.table-bordered{border:0}.table-dark.pbTable tbody tr:nth-of-type(odd),.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:hsla(0,0%,100%,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:hsla(0,0%,100%,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.pbTable,.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.pbTable,.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.pbTable,.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.pbTable,.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.pbTable,.table-responsive>.table-bordered{border:0}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:0}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:0;border-top-right-radius:0}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;min-height:1px;padding:30px}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem}.card-subtitle,.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:30px}.card-header{padding:.75rem 30px;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:0 0 0 0}.card-footer{padding:.75rem 30px;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 0 0}.card-header-tabs{margin-bottom:-.75rem;border-bottom:0}.card-header-pills,.card-header-tabs{margin-right:-15px;margin-left:-15px}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:0}.card-img,.card-img-bottom,.card-img-top{flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:0;border-top-right-radius:0}.card-img,.card-img-bottom{border-bottom-right-radius:0;border-bottom-left-radius:0}.card-deck .card{margin-bottom:10px}@media (min-width:576px){.card-deck{display:flex;flex-flow:row wrap;margin-right:-10px;margin-left:-10px}.card-deck .card{flex:1 0 0%;margin-right:10px;margin-bottom:0;margin-left:10px}}.card-group>.card{margin-bottom:10px}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-moz-column-count:3;column-count:3;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.alert,.pb-alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info,.pb-alert-tip{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr,.pb-alert-tip hr{border-top-color:#abdde5}.alert-info .alert-link,.pb-alert-tip .alert-link{color:#062c33}.alert-warning,.pb-alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr,.pb-alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link,.pb-alert-warning .alert-link{color:#533f03}.alert-danger,.pb-alert-important{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr,.pb-alert-important hr{border-top-color:#f1b0b7}.alert-danger .alert-link,.pb-alert-important .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translateY(-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered:before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable:before{content:none}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;padding:1rem}.modal-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered:before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important}.rounded-right,.rounded-top{border-top-right-radius:.25rem!important}.rounded-bottom,.rounded-right{border-bottom-right-radius:.25rem!important}.rounded-bottom,.rounded-left{border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix:after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive:before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9:before{padding-top:42.8571428571%}.embed-responsive-16by9:before{padding-top:56.25%}.embed-responsive-4by3:before{padding-top:75%}.embed-responsive-1by1:before{padding-top:100%}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-fill{flex:1 1 auto!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}@media (min-width:576px){.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}}@media (min-width:768px){.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;-ms-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{top:0}.fixed-bottom,.fixed-top{position:fixed;right:0;left:0;z-index:1030}.fixed-bottom{bottom:0}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.m-6{margin:3.75rem!important}.mt-6,.my-6{margin-top:3.75rem!important}.mr-6,.mx-6{margin-right:3.75rem!important}.mb-6,.my-6{margin-bottom:3.75rem!important}.ml-6,.mx-6{margin-left:3.75rem!important}.m-7{margin:4.5rem!important}.mt-7,.my-7{margin-top:4.5rem!important}.mr-7,.mx-7{margin-right:4.5rem!important}.mb-7,.my-7{margin-bottom:4.5rem!important}.ml-7,.mx-7{margin-left:4.5rem!important}.m-8{margin:5rem!important}.mt-8,.my-8{margin-top:5rem!important}.mr-8,.mx-8{margin-right:5rem!important}.mb-8,.my-8{margin-bottom:5rem!important}.ml-8,.mx-8{margin-left:5rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.p-6{padding:3.75rem!important}.pt-6,.py-6{padding-top:3.75rem!important}.pr-6,.px-6{padding-right:3.75rem!important}.pb-6,.py-6{padding-bottom:3.75rem!important}.pl-6,.px-6{padding-left:3.75rem!important}.p-7{padding:4.5rem!important}.pt-7,.py-7{padding-top:4.5rem!important}.pr-7,.px-7{padding-right:4.5rem!important}.pb-7,.py-7{padding-bottom:4.5rem!important}.pl-7,.px-7{padding-left:4.5rem!important}.p-8{padding:5rem!important}.pt-8,.py-8{padding-top:5rem!important}.pr-8,.px-8{padding-right:5rem!important}.pb-8,.py-8{padding-bottom:5rem!important}.pl-8,.px-8{padding-left:5rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-n6{margin:-3.75rem!important}.mt-n6,.my-n6{margin-top:-3.75rem!important}.mr-n6,.mx-n6{margin-right:-3.75rem!important}.mb-n6,.my-n6{margin-bottom:-3.75rem!important}.ml-n6,.mx-n6{margin-left:-3.75rem!important}.m-n7{margin:-4.5rem!important}.mt-n7,.my-n7{margin-top:-4.5rem!important}.mr-n7,.mx-n7{margin-right:-4.5rem!important}.mb-n7,.my-n7{margin-bottom:-4.5rem!important}.ml-n7,.mx-n7{margin-left:-4.5rem!important}.m-n8{margin:-5rem!important}.mt-n8,.my-n8{margin-top:-5rem!important}.mr-n8,.mx-n8{margin-right:-5rem!important}.mb-n8,.my-n8{margin-bottom:-5rem!important}.ml-n8,.mx-n8{margin-left:-5rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.m-sm-6{margin:3.75rem!important}.mt-sm-6,.my-sm-6{margin-top:3.75rem!important}.mr-sm-6,.mx-sm-6{margin-right:3.75rem!important}.mb-sm-6,.my-sm-6{margin-bottom:3.75rem!important}.ml-sm-6,.mx-sm-6{margin-left:3.75rem!important}.m-sm-7{margin:4.5rem!important}.mt-sm-7,.my-sm-7{margin-top:4.5rem!important}.mr-sm-7,.mx-sm-7{margin-right:4.5rem!important}.mb-sm-7,.my-sm-7{margin-bottom:4.5rem!important}.ml-sm-7,.mx-sm-7{margin-left:4.5rem!important}.m-sm-8{margin:5rem!important}.mt-sm-8,.my-sm-8{margin-top:5rem!important}.mr-sm-8,.mx-sm-8{margin-right:5rem!important}.mb-sm-8,.my-sm-8{margin-bottom:5rem!important}.ml-sm-8,.mx-sm-8{margin-left:5rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.p-sm-6{padding:3.75rem!important}.pt-sm-6,.py-sm-6{padding-top:3.75rem!important}.pr-sm-6,.px-sm-6{padding-right:3.75rem!important}.pb-sm-6,.py-sm-6{padding-bottom:3.75rem!important}.pl-sm-6,.px-sm-6{padding-left:3.75rem!important}.p-sm-7{padding:4.5rem!important}.pt-sm-7,.py-sm-7{padding-top:4.5rem!important}.pr-sm-7,.px-sm-7{padding-right:4.5rem!important}.pb-sm-7,.py-sm-7{padding-bottom:4.5rem!important}.pl-sm-7,.px-sm-7{padding-left:4.5rem!important}.p-sm-8{padding:5rem!important}.pt-sm-8,.py-sm-8{padding-top:5rem!important}.pr-sm-8,.px-sm-8{padding-right:5rem!important}.pb-sm-8,.py-sm-8{padding-bottom:5rem!important}.pl-sm-8,.px-sm-8{padding-left:5rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-n6{margin:-3.75rem!important}.mt-sm-n6,.my-sm-n6{margin-top:-3.75rem!important}.mr-sm-n6,.mx-sm-n6{margin-right:-3.75rem!important}.mb-sm-n6,.my-sm-n6{margin-bottom:-3.75rem!important}.ml-sm-n6,.mx-sm-n6{margin-left:-3.75rem!important}.m-sm-n7{margin:-4.5rem!important}.mt-sm-n7,.my-sm-n7{margin-top:-4.5rem!important}.mr-sm-n7,.mx-sm-n7{margin-right:-4.5rem!important}.mb-sm-n7,.my-sm-n7{margin-bottom:-4.5rem!important}.ml-sm-n7,.mx-sm-n7{margin-left:-4.5rem!important}.m-sm-n8{margin:-5rem!important}.mt-sm-n8,.my-sm-n8{margin-top:-5rem!important}.mr-sm-n8,.mx-sm-n8{margin-right:-5rem!important}.mb-sm-n8,.my-sm-n8{margin-bottom:-5rem!important}.ml-sm-n8,.mx-sm-n8{margin-left:-5rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.m-md-6{margin:3.75rem!important}.mt-md-6,.my-md-6{margin-top:3.75rem!important}.mr-md-6,.mx-md-6{margin-right:3.75rem!important}.mb-md-6,.my-md-6{margin-bottom:3.75rem!important}.ml-md-6,.mx-md-6{margin-left:3.75rem!important}.m-md-7{margin:4.5rem!important}.mt-md-7,.my-md-7{margin-top:4.5rem!important}.mr-md-7,.mx-md-7{margin-right:4.5rem!important}.mb-md-7,.my-md-7{margin-bottom:4.5rem!important}.ml-md-7,.mx-md-7{margin-left:4.5rem!important}.m-md-8{margin:5rem!important}.mt-md-8,.my-md-8{margin-top:5rem!important}.mr-md-8,.mx-md-8{margin-right:5rem!important}.mb-md-8,.my-md-8{margin-bottom:5rem!important}.ml-md-8,.mx-md-8{margin-left:5rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.p-md-6{padding:3.75rem!important}.pt-md-6,.py-md-6{padding-top:3.75rem!important}.pr-md-6,.px-md-6{padding-right:3.75rem!important}.pb-md-6,.py-md-6{padding-bottom:3.75rem!important}.pl-md-6,.px-md-6{padding-left:3.75rem!important}.p-md-7{padding:4.5rem!important}.pt-md-7,.py-md-7{padding-top:4.5rem!important}.pr-md-7,.px-md-7{padding-right:4.5rem!important}.pb-md-7,.py-md-7{padding-bottom:4.5rem!important}.pl-md-7,.px-md-7{padding-left:4.5rem!important}.p-md-8{padding:5rem!important}.pt-md-8,.py-md-8{padding-top:5rem!important}.pr-md-8,.px-md-8{padding-right:5rem!important}.pb-md-8,.py-md-8{padding-bottom:5rem!important}.pl-md-8,.px-md-8{padding-left:5rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-n6{margin:-3.75rem!important}.mt-md-n6,.my-md-n6{margin-top:-3.75rem!important}.mr-md-n6,.mx-md-n6{margin-right:-3.75rem!important}.mb-md-n6,.my-md-n6{margin-bottom:-3.75rem!important}.ml-md-n6,.mx-md-n6{margin-left:-3.75rem!important}.m-md-n7{margin:-4.5rem!important}.mt-md-n7,.my-md-n7{margin-top:-4.5rem!important}.mr-md-n7,.mx-md-n7{margin-right:-4.5rem!important}.mb-md-n7,.my-md-n7{margin-bottom:-4.5rem!important}.ml-md-n7,.mx-md-n7{margin-left:-4.5rem!important}.m-md-n8{margin:-5rem!important}.mt-md-n8,.my-md-n8{margin-top:-5rem!important}.mr-md-n8,.mx-md-n8{margin-right:-5rem!important}.mb-md-n8,.my-md-n8{margin-bottom:-5rem!important}.ml-md-n8,.mx-md-n8{margin-left:-5rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.m-lg-6{margin:3.75rem!important}.mt-lg-6,.my-lg-6{margin-top:3.75rem!important}.mr-lg-6,.mx-lg-6{margin-right:3.75rem!important}.mb-lg-6,.my-lg-6{margin-bottom:3.75rem!important}.ml-lg-6,.mx-lg-6{margin-left:3.75rem!important}.m-lg-7{margin:4.5rem!important}.mt-lg-7,.my-lg-7{margin-top:4.5rem!important}.mr-lg-7,.mx-lg-7{margin-right:4.5rem!important}.mb-lg-7,.my-lg-7{margin-bottom:4.5rem!important}.ml-lg-7,.mx-lg-7{margin-left:4.5rem!important}.m-lg-8{margin:5rem!important}.mt-lg-8,.my-lg-8{margin-top:5rem!important}.mr-lg-8,.mx-lg-8{margin-right:5rem!important}.mb-lg-8,.my-lg-8{margin-bottom:5rem!important}.ml-lg-8,.mx-lg-8{margin-left:5rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.p-lg-6{padding:3.75rem!important}.pt-lg-6,.py-lg-6{padding-top:3.75rem!important}.pr-lg-6,.px-lg-6{padding-right:3.75rem!important}.pb-lg-6,.py-lg-6{padding-bottom:3.75rem!important}.pl-lg-6,.px-lg-6{padding-left:3.75rem!important}.p-lg-7{padding:4.5rem!important}.pt-lg-7,.py-lg-7{padding-top:4.5rem!important}.pr-lg-7,.px-lg-7{padding-right:4.5rem!important}.pb-lg-7,.py-lg-7{padding-bottom:4.5rem!important}.pl-lg-7,.px-lg-7{padding-left:4.5rem!important}.p-lg-8{padding:5rem!important}.pt-lg-8,.py-lg-8{padding-top:5rem!important}.pr-lg-8,.px-lg-8{padding-right:5rem!important}.pb-lg-8,.py-lg-8{padding-bottom:5rem!important}.pl-lg-8,.px-lg-8{padding-left:5rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-n6{margin:-3.75rem!important}.mt-lg-n6,.my-lg-n6{margin-top:-3.75rem!important}.mr-lg-n6,.mx-lg-n6{margin-right:-3.75rem!important}.mb-lg-n6,.my-lg-n6{margin-bottom:-3.75rem!important}.ml-lg-n6,.mx-lg-n6{margin-left:-3.75rem!important}.m-lg-n7{margin:-4.5rem!important}.mt-lg-n7,.my-lg-n7{margin-top:-4.5rem!important}.mr-lg-n7,.mx-lg-n7{margin-right:-4.5rem!important}.mb-lg-n7,.my-lg-n7{margin-bottom:-4.5rem!important}.ml-lg-n7,.mx-lg-n7{margin-left:-4.5rem!important}.m-lg-n8{margin:-5rem!important}.mt-lg-n8,.my-lg-n8{margin-top:-5rem!important}.mr-lg-n8,.mx-lg-n8{margin-right:-5rem!important}.mb-lg-n8,.my-lg-n8{margin-bottom:-5rem!important}.ml-lg-n8,.mx-lg-n8{margin-left:-5rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.m-xl-6{margin:3.75rem!important}.mt-xl-6,.my-xl-6{margin-top:3.75rem!important}.mr-xl-6,.mx-xl-6{margin-right:3.75rem!important}.mb-xl-6,.my-xl-6{margin-bottom:3.75rem!important}.ml-xl-6,.mx-xl-6{margin-left:3.75rem!important}.m-xl-7{margin:4.5rem!important}.mt-xl-7,.my-xl-7{margin-top:4.5rem!important}.mr-xl-7,.mx-xl-7{margin-right:4.5rem!important}.mb-xl-7,.my-xl-7{margin-bottom:4.5rem!important}.ml-xl-7,.mx-xl-7{margin-left:4.5rem!important}.m-xl-8{margin:5rem!important}.mt-xl-8,.my-xl-8{margin-top:5rem!important}.mr-xl-8,.mx-xl-8{margin-right:5rem!important}.mb-xl-8,.my-xl-8{margin-bottom:5rem!important}.ml-xl-8,.mx-xl-8{margin-left:5rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.p-xl-6{padding:3.75rem!important}.pt-xl-6,.py-xl-6{padding-top:3.75rem!important}.pr-xl-6,.px-xl-6{padding-right:3.75rem!important}.pb-xl-6,.py-xl-6{padding-bottom:3.75rem!important}.pl-xl-6,.px-xl-6{padding-left:3.75rem!important}.p-xl-7{padding:4.5rem!important}.pt-xl-7,.py-xl-7{padding-top:4.5rem!important}.pr-xl-7,.px-xl-7{padding-right:4.5rem!important}.pb-xl-7,.py-xl-7{padding-bottom:4.5rem!important}.pl-xl-7,.px-xl-7{padding-left:4.5rem!important}.p-xl-8{padding:5rem!important}.pt-xl-8,.py-xl-8{padding-top:5rem!important}.pr-xl-8,.px-xl-8{padding-right:5rem!important}.pb-xl-8,.py-xl-8{padding-bottom:5rem!important}.pl-xl-8,.px-xl-8{padding-left:5rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-n6{margin:-3.75rem!important}.mt-xl-n6,.my-xl-n6{margin-top:-3.75rem!important}.mr-xl-n6,.mx-xl-n6{margin-right:-3.75rem!important}.mb-xl-n6,.my-xl-n6{margin-bottom:-3.75rem!important}.ml-xl-n6,.mx-xl-n6{margin-left:-3.75rem!important}.m-xl-n7{margin:-4.5rem!important}.mt-xl-n7,.my-xl-n7{margin-top:-4.5rem!important}.mr-xl-n7,.mx-xl-n7{margin-right:-4.5rem!important}.mb-xl-n7,.my-xl-n7{margin-bottom:-4.5rem!important}.ml-xl-n7,.mx-xl-n7{margin-left:-4.5rem!important}.m-xl-n8{margin:-5rem!important}.mt-xl-n8,.my-xl-n8{margin-top:-5rem!important}.mr-xl-n8,.mx-xl-n8{margin-right:-5rem!important}.mb-xl-n8,.my-xl-n8{margin-bottom:-5rem!important}.ml-xl-n8,.mx-xl-n8{margin-left:-5rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:transparent}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:hsla(0,0%,100%,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.awesomplete>ul{background:#333;padding:0!important}.awesomplete>ul>li{padding:10px 15px;border-bottom:1px solid #707070;color:#efefef;font-size:17px}.awesomplete>ul>li:last-child{border-bottom:0}.awesomplete>ul>li[aria-selected=true]{background-color:#ff6f00}.awesomplete>ul>li:before{content:none!important}img{max-width:100%}body{color:#797f90;font-family:Arial,sans-serif;font-size:18px;line-height:1.5}@media (min-width:768px){body{font-size:18px}}.html__font-loaded--primary body{font-family:Open Sans,Arial,sans-serif}a{color:#ff6f00;text-decoration:underline}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:600;color:#333}.typography-white .h1,.typography-white .h2,.typography-white .h3,.typography-white .h4,.typography-white .h5,.typography-white .h6,.typography-white h1,.typography-white h2,.typography-white h3,.typography-white h4,.typography-white h5,.typography-white h6{color:#fff}.h1.no-margin-top,.h2.no-margin-top,.h3.no-margin-top,.h4.no-margin-top,.h5.no-margin-top,.h6.no-margin-top,.no-margin-top .h1,.no-margin-top .h2,.no-margin-top .h3,.no-margin-top .h4,.no-margin-top .h5,.no-margin-top .h6,.no-margin-top h1,.no-margin-top h2,.no-margin-top h3,.no-margin-top h4,.no-margin-top h5,.no-margin-top h6,h1.no-margin-top,h2.no-margin-top,h3.no-margin-top,h4.no-margin-top,h5.no-margin-top,h6.no-margin-top{margin-top:0!important}.h1,h1{font-size:12vw;line-height:1.2}@media (min-width:410px){.h1,h1{font-size:42px}}@media (min-width:767px){.h1,h1{font-size:50px}}.h2,h2{font-size:36px;line-height:1.1}@media (min-width:768px){.h2,h2{font-size:40px}}.h3,h3{font-size:26px;line-height:1.1}@media (min-width:768px){.h3,h3{font-size:30px}}.h4,h4{font-size:22px}h5{font-size:20px}h6{font-size:18px}.pb-header .navbar{background:#333}@media (max-width:991px){.pb-header .navbar{padding-top:10px;padding-bottom:10px}}.pb-header .navbar-brand>img{display:block;max-width:140px;max-height:25px}.pb-header .dropdown-toggle:after{content:none}.pb-header .nav-item{padding-top:5px;padding-bottom:5px;margin-right:32px}.pb-header .nav-item:last-of-type{margin-right:0}@media (min-width:992px){.pb-header .nav-item{padding-top:34px;padding-bottom:24px}}.pb-header .nav-link{font-size:16px;text-decoration:none}@media (min-width:992px){.pb-header .nav-link[aria-expanded=true]:after{position:absolute;bottom:0;left:50%;height:0;width:0;border-color:transparent transparent #fff;border-style:solid;border-width:0 5.5px 8px;transform:translateX(-50%) translateY(0);z-index:5;content:""}}.pb-header .dropdown-menu{box-shadow:10px 10px 30px rgba(0,0,0,.16);-moz-column-rule:1px solid #dddfe3;column-rule:1px solid #dddfe3;padding:10px 0}@media (min-width:992px){.pb-header .dropdown-menu{padding:24px 0}.pb-header .dropdown-menu--product{-moz-columns:3;column-count:3;left:50%;transform:translateX(-50%)}.pb-header .dropdown-menu--support{-moz-columns:2;column-count:2;left:50%;transform:translateX(-50%)}.pb-header .dropdown-menu--resources{right:0;left:auto}.pb-header .dropdown-menu .dropdown-section{-moz-column-break-inside:avoid;break-inside:avoid-column}}.pb-header .dropdown-item{font-size:15px;text-decoration:none}.pb-header .dropdown-item--heading{font-weight:600;color:#333}.pb-header .dropdown-item--heading:hover{color:#ff6f00}@media (max-width:991px){.sidebar{margin-bottom:20px}}.sidebar a{text-decoration:none}.sidebar .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.sidebar .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.sidebar .collapse.is-active,.sidebar .list-group-item{display:block}.sidebar .list-group-item--level-0{position:relative;padding:9px 12px 11px 14px;border-top:1px solid #dddfe3;color:#797f90;font-size:20px}.sidebar .list-group-item--level-0:after{position:absolute;top:50%;right:12px;height:8px;width:15px;transform:translateY(-50%);background:url(/assets/images/icons/down-carrot-0.svg) no-repeat 0 0;content:""}.sidebar .list-group-item--level-0:last-of-type{border-bottom:1px solid #dddfe3}.sidebar .list-group-item--level-0>.pb-section-title{display:inline-block;padding-right:20px}.sidebar .list-group-item--level-0.is-active{background-color:#333;color:#fff}.sidebar .list-group-item--level-0.is-active:after{background-image:url(/assets/images/icons/up-carrot-0.svg)}.sidebar .list-group-item--level-0.is-active+.sidebar-submenu+.list-group-item{border-top:0}.sidebar .list-group-item--level-1{padding:8px 14px 9px;background-color:hsla(0,0%,100%,.25);border-bottom:1px solid #dddfe3;color:#797f90;font-size:18px}.sidebar .list-group-item--level-1.is-active{position:relative;color:#ff6f00}.sidebar .list-group-item--level-1.is-active:after{position:absolute;top:50%;right:15px;height:5px;width:10px;transform:translateY(-50%);background-image:url(/assets/images/icons/up-carrot-1.svg);background-repeat:no-repeat;background-position:0 0;content:""}.sidebar .list-group-item--level-1.is-active>.pb-section-subtitle{display:inline-block;padding-right:15px}.sidebar .list-group-item--level-1.is-active+.sidebar-submenu{background-color:hsla(0,0%,100%,.25)}.sidebar .list-group-item--level-1>.menu-collapsed.pb-nav-item.is-active{color:#ff6f00}.sidebar .list-group-item--level-2{padding:11px 14px 4px;background-color:hsla(0,0%,100%,.5);color:#797f90;font-size:15px}.sidebar .list-group-item--level-2:last-child{padding-bottom:11px;border-bottom:1px solid #dddfe3}.sidebar .list-group-item--level-2.is-active{color:#ff6f00}.sidebar .list-group-item--level-2>.pb-nav-item--title{display:block;margin-bottom:-8px;padding-bottom:5px;border-bottom:1px solid #999;color:#333}.pb-footer{padding-top:50px;padding-bottom:30px;background:#fff;font-size:12px;line-height:1.2}.banner--medium .card{background:none;border-color:hsla(0,0%,100%,.8)}.card-media{display:flex;justify-content:center;align-items:center}.card-deck--products .card-media{min-height:96px;margin-top:6px}.card-deck--products .card-title{margin-top:30px}.card-deck--md .card{margin-bottom:10px}@media (min-width:768px){.card-deck--md{display:flex;flex-flow:row wrap;margin-right:-10px;margin-left:-10px}.card-deck--md .card{flex:1 0 0%;margin-right:10px;margin-bottom:0;margin-left:10px}}.card-deck--formats .card{margin-bottom:10px;z-index:2}.card-deck--formats .card-body{display:flex;flex-flow:column-reverse;justify-content:space-around}.card-deck--formats .card-title{font-weight:600;margin-top:24px;margin-bottom:0;font-size:22px;line-height:1.2;color:#1ba9e1;text-decoration:none}.card-deck--formats .card-title:hover{color:#fff;z-index:2}.card-deck--formats .card-title:hover:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;background-color:#ff6f00;content:""}.card-deck--formats .card-title:hover+.card-media{cursor:pointer;pointer-events:none}.card-deck--formats .card-title:hover+.card-media path{stroke:#fff}.card-deck--formats .card-title:hover+.card-media path[fill="#ff6f00"]{fill:#fff}.card-deck--formats .card-title+.card-media{position:relative;z-index:2}@media (min-width:576px){.card-deck--formats{display:flex;flex-flow:row wrap;justify-content:center;margin-right:-10px;margin-left:-10px}.card-deck--formats .card{flex:1 0 0%;min-width:180px;max-width:200px;margin-right:10px;margin-bottom:20px;margin-left:10px}}.banner--medium .card-deck .card{z-index:2}.banner--medium .card-deck .card-body{display:flex;flex-flow:column;justify-content:space-around}.banner--medium .card-deck .card-title{margin-top:24px;margin-bottom:0}.banner--medium .card-deck .card-title a{color:#fff;font-size:26px;text-decoration:none}.banner--medium .card-deck .card-title a:before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:#ff6f00;opacity:0;z-index:-1;content:""}.banner--medium .card-deck .card-title a:hover:before{opacity:1}.banner{padding-top:4rem;padding-bottom:5.5rem}.banner--medium{background:#7e8c97;color:#fff}.banner--light{background:#fff;padding-bottom:0}.banner--light hr{margin-top:30px;border:0;border-top:1px solid rgba(221,223,227,.49);background:none}.btn-outline-brand{color:#1ba9e1;font-weight:700;padding:18px 32px 15px;border-color:#dddfe3;font-size:18px;text-decoration:none}.btn-outline-brand:hover{color:#fff;background-color:#1ba9e1;border-color:#1ba9e1}.btn-outline-brand.focus,.btn-outline-brand:focus{box-shadow:0 0 0 .2rem rgba(27,169,225,.5)}.btn-outline-brand.disabled,.btn-outline-brand:disabled{color:#1ba9e1;background-color:transparent}.btn-outline-brand:not(:disabled):not(.disabled).active,.btn-outline-brand:not(:disabled):not(.disabled):active,.show>.btn-outline-brand.dropdown-toggle{color:#fff;background-color:#1ba9e1;border-color:#1ba9e1}.btn-outline-brand:not(:disabled):not(.disabled).active:focus,.btn-outline-brand:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-brand.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(27,169,225,.5)}@media (min-width:992px){.btn-outline-brand{padding-right:68px;padding-left:68px}}.pb-lg-img{width:70%;height:70%}.row>.wrapper{display:flex;flex-wrap:wrap;margin-right:-10px;margin-left:-10px}@media (min-width:992px){.pb-docs-container>.row>.col-lg-3.sidebar{flex:0 0 22%;max-width:22%}.pb-docs-container>.row>.col-lg-3.sidebar+.col-lg-9{flex:0 0 78%;max-width:78%}}.pb-docs-container+.pb-footer{margin-top:180px}.pb-content{padding:22px 30px;border:1px solid #dddfe3;background-color:#fff;font-size:19px;line-height:1.5789473684}.pb-content>.pb-content{margin:0;padding:0;border:none}.pb-content h1{margin-bottom:20px;padding-bottom:14px;border-bottom:1px solid #dddfe3;font-size:46.379px}.pb-content h2{margin-top:35px;margin-bottom:16px;font-size:37.107px}.pb-content h3{margin-top:28px;font-size:29.697px}.pb-content h4{margin-top:20px;font-size:23.75px}.pb-content h5{margin-top:16px;font-size:19px;font-style:italic}.pb-content ul{padding-left:20px;list-style:none}.pb-content ul li:not(.ui-tab){position:relative}.pb-content ul li:not(.ui-tab):before{position:absolute;top:10px;left:-20px;height:7px;width:7px;border:1px solid #707070;border-radius:50%;background:#333;content:""}.pb-content table.pbTable,.pb-content table.table{font-size:16px;line-height:1.75}.pb-content table.pbTable th,.pb-content table.table th{padding-top:9px;padding-bottom:9px;font-weight:600}.pb-content table.pbTable td,.pb-content table.pbTable th,.pb-content table.table td,.pb-content table.table th{padding-right:15px;padding-left:15px}.pb-content .highlight,.pb-content .pb-code-hl{margin-top:20px;margin-bottom:20px;padding:20px 22px;border:1px solid #dddfe3;background:#f8f9f9;font-size:16px}.pb-content .highlight pre,.pb-content .pb-code-hl pre{margin-top:0;margin-bottom:0;padding:0;border:0;background:none}.pb-docs-container{margin-top:20px}@media (min-width:992px){.pb-docs-container{margin-top:65px}}.pb-alert{margin-top:10px}.social-media{display:flex;align-items:center}@media (min-width:992px){.social-media{justify-content:flex-end;margin-top:100px}}.social-media a,.social-media h5{margin-right:22px;margin-bottom:0}.social-media h5{font-size:18px}.social-media a:last-child{margin-right:0}table.pbTable,table.table{background:#fff}.pbTable thead td,.pbTable thead th,.table-bordered thead td,.table-bordered thead th{border-bottom-width:1px}.download-form{margin-bottom:20px}.download-form>.row{flex-flow:column}.download-form .adapters{display:flex;flex-flow:row wrap}.download-form__modal,.modal-backdrop.fade{opacity:0}.pb-content .autocomplete-filter{padding:10px 15px;border:1px solid #b3c1cc;background-color:rgba(236,243,245,.35)}.pb-content .autocomplete-filter:focus{outline:none}.pb-content .c-bidder-list-group h4{color:#797f90;font-size:19px;font-weight:700}.pb-content .c-bidder-list{padding-left:0;-moz-columns:2;column-count:2}.pb-content .c-bidder-list li{padding-bottom:5px}.pb-content .c-bidder-list li:before{content:none!important}.pb-content .c-bidder-list a{text-decoration:none}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{display:none!important}.c-search{position:relative}@media (max-width:990px){.c-search{float:left}}.c-search:after{position:absolute;top:50%;right:10px;height:20px;width:20px;transform:translateY(-50%);background:url(/assets/images/icons/search-icon2.svg);background-size:cover;content:""}.c-search input[type=search]{padding-right:8px;padding-left:8px;border:1px solid rgba(0,0,0,.125);max-width:120px;transition:max-width .2s ease-in-out}.c-search input[type=search]:focus,.c-search input[type=search]:hover{max-width:200px;outline:none}.c-search input[type=search]::-ms-clear,.c-search input[type=search]::-ms-reveal{display:none;width:0;height:0}.c-search input[type=search]::-webkit-search-cancel-button,.c-search input[type=search]::-webkit-search-decoration,.c-search input[type=search]::-webkit-search-results-button,.c-search input[type=search]::-webkit-search-results-decoration{display:none}.pb-homepage .h1,.pb-homepage h1{font-size:12vw;margin-bottom:.75rem}@media (min-width:768px){.pb-homepage .h1,.pb-homepage h1{font-size:40px}}.error404{width:100%;height:100%;text-align:center}.error404 h1{color:red;font-size:60px;font-weight:700} \ No newline at end of file diff --git a/assets/css/pb_style.scss b/assets/css/main-bundle.scss similarity index 100% rename from assets/css/pb_style.scss rename to assets/css/main-bundle.scss diff --git a/assets/css/prism.css b/assets/css/prism.css index 7375d36283..bd6730fb83 100644 --- a/assets/css/prism.css +++ b/assets/css/prism.css @@ -1,142 +1,130 @@ -/* PrismJS 1.16.0 -https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+go */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+diff+go+graphql+http+java+markup-templating+nginx+php+properties+scala+swift+typescript+yaml&plugins=diff-highlight */ code[class*="language-"], pre[class*="language-"] { - color: black; - background: none; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - font-size: 1em; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - + color: #000; + background: 0 0; + text-shadow: 0 1px #fff; + font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} +code[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +pre[class*="language-"]::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} +code[class*="language-"] ::selection, +code[class*="language-"]::selection, +pre[class*="language-"] ::selection, +pre[class*="language-"]::selection { + text-shadow: none; + background: #b3d4fc; +} @media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } } - -/* Code blocks */ pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; + padding: 1em; + margin: 0.5em 0; + overflow: auto; } - :not(pre) > code[class*="language-"], pre[class*="language-"] { - background: #f5f2f0; + background: #f5f2f0; } - -/* Inline code */ :not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; - white-space: normal; + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; } - +.token.cdata, .token.comment, -.token.prolog, .token.doctype, -.token.cdata { - color: slategray; +.token.prolog { + color: #708090; } - .token.punctuation { - color: #999; + color: #999; } - -.namespace { - opacity: .7; +.token.namespace { + opacity: 0.7; } - -.token.property, -.token.tag, .token.boolean, -.token.number, .token.constant, +.token.deleted, +.token.number, +.token.property, .token.symbol, -.token.deleted { - color: #905; +.token.tag { + color: #905; } - -.token.selector, .token.attr-name, -.token.string, -.token.char, .token.builtin, -.token.inserted { - color: #690; +.token.char, +.token.inserted, +.token.selector, +.token.string { + color: #690; } - -.token.operator, -.token.entity, -.token.url, .language-css .token.string, -.style .token.string { - color: #9a6e3a; - background: hsla(0, 0%, 100%, .5); +.style .token.string, +.token.entity, +.token.operator, +.token.url { + color: #9a6e3a; + background: hsla(0, 0%, 100%, 0.5); } - .token.atrule, .token.attr-value, .token.keyword { - color: #07a; + color: #07a; } - -.token.function, -.token.class-name { - color: #DD4A68; +.token.class-name, +.token.function { + color: #dd4a68; } - -.token.regex, .token.important, +.token.regex, .token.variable { - color: #e90; + color: #e90; } - -.token.important, -.token.bold { - font-weight: bold; +.token.bold, +.token.important { + font-weight: 700; } .token.italic { - font-style: italic; + font-style: italic; } - .token.entity { - cursor: help; + cursor: help; +} +pre.diff-highlight > code .token.deleted:not(.prefix), +pre > code.diff-highlight .token.deleted:not(.prefix) { + background-color: rgba(255, 0, 0, 0.1); + color: inherit; + display: block; +} +pre.diff-highlight > code .token.inserted:not(.prefix), +pre > code.diff-highlight .token.inserted:not(.prefix) { + background-color: rgba(0, 255, 128, 0.1); + color: inherit; + display: block; } - diff --git a/assets/css/style.css b/assets/css/style.css index 0af6a31a4c..7f63345730 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -37,12 +37,12 @@ h4 { /* Paragraph & Typographic */ p { - line-height: 28px; - margin-bottom: 25px; - font-family: 'Lato', sans-serif; - color: #222222; - font-size: 18px; - font-weight: 400;} + line-height: 28px; + margin-bottom: 25px; + font-family: 'Lato', sans-serif; + color: #222222; + font-size: 18px; + font-weight: 400;} .centered { text-align: center; @@ -130,228 +130,228 @@ hr { } .wrapper { - display: flex; - width: 100%; - align-items: stretch; + display: flex; + width: 100%; + align-items: stretch; } /* alerts */ .pb-alert { - padding:10px; - width:65wv; - margin: 10px 0; + padding:10px; + width:65wv; + margin: 10px 0; } .pb-alert-note { - background-color: #deecf7; - color: #4b6f8d; - border: 1px solid #4b6f8d; + background-color: #deecf7; + color: #4b6f8d; + border: 1px solid #4b6f8d; } .pb-alert-warning { - background-color: #f3ddde; - color: #a94443; - border: 1px solid #a94443; + background-color: #f3ddde; + color: #a94443; + border: 1px solid #a94443; } .pb-alert-important { - background-color: #ede5ba; - color: #85720f; - border: 1px solid #85720f; + background-color: #ede5ba; + color: #85720f; + border: 1px solid #85720f; } .pb-alert-tip { - background-color: #e3efd8; - color: #527542; - border: 1px solid #527542; + background-color: #e3efd8; + color: #527542; + border: 1px solid #527542; } /********************** - API + API *********************/ .pb-api-on { - display: block; + display: block; } .pb-api-off { - display: none; + display: none; } .pb-api-list ul { - list-style-type: none; - margin: 0; - padding: 0; - overflow: hidden; + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; } .pb-api-list-item li { - border-bottom: 1px solid #cccccc; - border-bottom-width: 75%; - background-color:transparent; - margin-bottom: 10px; + border-bottom: 1px solid #cccccc; + border-bottom-width: 75%; + background-color:transparent; + margin-bottom: 10px; } .pb-api-list-item-sans-border li { - background-color:transparent; - margin-bottom: 10px; + background-color:transparent; + margin-bottom: 10px; } .pb-api-categories { - margin-top:15px; + margin-top:15px; } .pb-api-categories li { - float: left; - margin-right: 15px; - background-color: #eeeeee; + float: left; + margin-right: 15px; + background-color: #eeeeee; } .pb-api-categories a { - color: #333333; - font-family: 'Verdana', sans-serif; - font-size: 17px; - font-weight: 400; - padding: 4px 10px; + color: #333333; + font-family: 'Verdana', sans-serif; + font-size: 17px; + font-weight: 400; + padding: 4px 10px; } .pb-api-categories a:hover { - color: #3498db; + color: #3498db; } .pb-api-search { - float:right; - margin-right: 30px; + float:right; + margin-right: 30px; } .pb-api-title { - color: #EA9622; - font-family: 'Verdana', sans-serif; - font-size: 22px; - font-weight: 400; - margin-bottom: 10px; - margin-top: 15px; + color: #EA9622; + font-family: 'Verdana', sans-serif; + font-size: 22px; + font-weight: 400; + margin-bottom: 10px; + margin-top: 15px; } .pb-api-code { - margin: 20px 0 20px 20px; + margin: 20px 0 20px 20px; } .pb-api-code-wrapper { - margin-left: 20px; + margin-left: 20px; } .pb-api-code-display { - margin: 20px 0 0 20px; - width: 70%; + margin: 20px 0 0 20px; + width: 70%; } .pb-api-code-block { - width: 70%; - backgeound-color: #333333; + width: 70%; + backgeound-color: #333333; } .pb-api-block { - margin: 20px 0 20px 20px; + margin: 20px 0 20px 20px; } .pb-api-doc-title { - color: #EA9622; - font-family: 'Verdana', sans-serif; - font-size: 20px; - font-weight: 400; - margin-bottom: 10px; + color: #EA9622; + font-family: 'Verdana', sans-serif; + font-size: 20px; + font-weight: 400; + margin-bottom: 10px; } .pb-api-doc-description { - color: #222222; - font-size: 16px; - font-family: 'Roboto', sans-serif; - font-weight: 300; - margin-bottom:10px; + color: #222222; + font-size: 16px; + font-family: 'Roboto', sans-serif; + font-weight: 300; + margin-bottom:10px; } .pb-api-doc-description ul, ol { - font-size: 15px; + font-size: 15px; } .pb-api-code-title-bar { - background-color: #E4E8ED; - text-align: left; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - padding-left: 5px; - margin-left: 20px; - margin-top: 10px; + background-color: #E4E8ED; + text-align: left; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + padding-left: 5px; + margin-left: 20px; + margin-top: 10px; } .pb-api-doc-sub-title { - color: #EA9622; - font-family: 'Verdana', sans-serif; - font-size: 17px; - font-weight: 400; - margin: 15px 0; + color: #EA9622; + font-family: 'Verdana', sans-serif; + font-size: 17px; + font-weight: 400; + margin: 15px 0; } .pb-api-doc-section-title { - font-size: 17px; - font-weight: 400; - color: #333333; - margin:15px 0; + font-size: 17px; + font-weight: 400; + color: #333333; + margin:15px 0; } .pb-api-list-item-description { - margin-top 5px; - font-size:17px; + margin-top 5px; + font-size:17px; } .pb-api-table { - margin-top: 20px; - width:70%; + margin-top: 20px; + width:70%; } .pb-api-table-title { - color: #333333; - font-family: 'Verdana', sans-serif; - font-size: 17px; - font-weight: 400; - text-align: center; - background-color: #aaaaaa; - border-top-left-radius: 5px; - border-top-right-radius: 5px; + color: #333333; + font-family: 'Verdana', sans-serif; + font-size: 17px; + font-weight: 400; + text-align: center; + background-color: #aaaaaa; + border-top-left-radius: 5px; + border-top-right-radius: 5px; } .pb-api-table-text { - color: #222222; - font-size: 16px; - font-family: 'Roboto', sans-serif; - font-weight: 300; + color: #222222; + font-size: 16px; + font-family: 'Roboto', sans-serif; + font-weight: 300; } .pb-api-spacing { - margin-top: 25px; + margin-top: 25px; } .pb-api-alert { - font-size:15px; + font-size:15px; } .pb-api-button { - width: 120px; - height: 30px; - background-color: #cccccc; - border: 1px solid #333333; - color: #33333; - font-size: 15px; - font-family: 'Roboto', sans-serif; - font-weight: 400; + width: 120px; + height: 30px; + background-color: #cccccc; + border: 1px solid #333333; + color: #33333; + font-size: 15px; + font-family: 'Roboto', sans-serif; + font-weight: 400; } @@ -393,17 +393,17 @@ hr { /* API */ .categoryBox { - background-color: #f3ddde; - color: #a94443; - border: 1px solid #a94443; + background-color: #f3ddde; + color: #a94443; + border: 1px solid #a94443; } /* NavBar */ .navbar { - z-index:100 - font-family: 'Roboto', sans-serif; + z-index:100 + font-family: 'Roboto', sans-serif; } .navbar-default { @@ -428,63 +428,63 @@ hr { } .navbar-brand img { - max-width: 200px; - max-height: 35px; + max-width: 200px; + max-height: 35px; } .navbar-brand{ - float:left; - height:50px; - padding:10px 15px; - font-size:18px; - line-height:20px + float:left; + height:50px; + padding:10px 15px; + font-size:18px; + line-height:20px } .pb-mobile-nav { - display: none; + display: none; } .pb-mobile-dropdown-header { - font-size: 13px; - font-weight: 500; - color: #3498db; + font-size: 13px; + font-weight: 500; + color: #3498db; } .pb-mobile-dropdown-item { - font-size: 13px; - font-weight: 400; + font-size: 13px; + font-weight: 400; } .navbar-default .navbar-nav > li > a.pb-mobile-dropdown { - font-size:13px; - margin:0; - padding-left:5px; - padding-top:2px; - padding-bottom:2px; + font-size:13px; + margin:0; + padding-left:5px; + padding-top:2px; + padding-bottom:2px; } .pb_menu_btn { - display: none; - float:left; - margin-right: 5px; - margin-top: 10px; + display: none; + float:left; + margin-right: 5px; + margin-top: 10px; } .pb-video-list-title { - margin-top: 15px; - font-weight: 700; + margin-top: 15px; + font-weight: 700; } .pb-video-list { - margin-top: 5px; - padding-top: 0; - list-style-type:none; - font-weight:400; + margin-top: 5px; + padding-top: 0; + list-style-type:none; + font-weight:400; } .pb-video-link { - font-weight: 400; + font-weight: 400; } /* DropDown*/ @@ -495,11 +495,11 @@ hr { } .dropdown-toggle { - font-weight: 400; + font-weight: 400; } .dropdown-menu>li>a { - font-weight: 400; + font-weight: 400; } .dropdown-submenu { @@ -534,23 +534,23 @@ hr { /* 404 error */ .error404 { - width:100%; - height: 100%; - text-align: center; - margin-top: 100px; + width:100%; + height: 100%; + text-align: center; + margin-top: 100px; } .error404 h1 { - color: #FF0000; - font-size: 60px; - font-weight: bold; + color: #FF0000; + font-size: 60px; + font-weight: bold; } /************** - Sidebar + Sidebar **************/ /* side bar */ @@ -570,62 +570,62 @@ hr { .sidebar { - min-width: 300px; - background-color: #f6f8fa; - padding-left: 50px; - padding-top: 20px; - padding-bottom: 10px; - padding-right:30px; - margin-left: 0px; - font-family: 'Verdana', sans-serif; + min-width: 300px; + background-color: #f6f8fa; + padding-left: 50px; + padding-top: 20px; + padding-bottom: 10px; + padding-right:30px; + margin-left: 0px; + font-family: 'Verdana', sans-serif; } .sidebar ul { - color: #333333; + color: #333333; } .pb-section-title { - display: inline-block; - font-size:17px; - padding-bottom: 10px; - margin-top:5px; - margin-bottom: 5px; - color: #3498db; + display: inline-block; + font-size:17px; + padding-bottom: 10px; + margin-top:5px; + margin-bottom: 5px; + color: #3498db; } .pb-section-subtitle { - font-size:16px; - padding-bottom: 10px; - margin-top:5px; - margin-bottom: 5px; + font-size:16px; + padding-bottom: 10px; + margin-top:5px; + margin-bottom: 5px; } .pb-nav-item { - display:inline-block; - font-size:14px; - padding-left: 5px; + display:inline-block; + font-size:14px; + padding-left: 5px; } .pb-first-item { - padding-top: 10px; + padding-top: 10px; } .pb-last-item { - padding-bottom: 10px; + padding-bottom: 10px; } .list-group-item-header { - font-weight: 400; - font-size: 20px; + font-weight: 400; + font-size: 20px; } .list-group-item { - font-weight: 400; - margin:0; - padding: 3px 0 3px 5px; - border-width:0; - font-size: 16px; - background-color: transparent; + font-weight: 400; + margin:0; + padding: 3px 0 3px 5px; + border-width:0; + font-size: 16px; + background-color: transparent; } @@ -650,65 +650,65 @@ pre { /************* Home Page ************/ .pb-homepage { - position: relative; - margin-top:70px; - width:100%; - height: 90%; + position: relative; + margin-top:70px; + width:100%; + height: 90%; } .pb-homepage-container { - text-align: center; + text-align: center; } .pb-message-box { - display: inline-block; - width: 70%; - border: 1px solid gray; - border-radius: 50px; - font-family: 'Roboto', sans-serif; - font-size: 16px; - padding: 4px; + display: inline-block; + width: 70%; + border: 1px solid gray; + border-radius: 50px; + font-family: 'Roboto', sans-serif; + font-size: 16px; + padding: 4px; } .pb-message-box a:link { - color: #dd9e21; + color: #dd9e21; } .pb-message-box a:hover { - color: #855a09; + color: #855a09; } .pb-message-box a:visited { - color: #1689db; + color: #1689db; } .pb-align-left { - text-align: start; + text-align: start; } .pb-align-right { - text-align: right; + text-align: right; } .pb-margin-top { - margin-top:20px; + margin-top:20px; } .pb-outline { - border: 1px dashed purple; + border: 1px dashed purple; } .pb-rule { - padding-top: 10px; + padding-top: 10px; } .pb-link-title { - font-family: 'Roboto', sans-serif; - font-weight: 700; - padding-top: 5px; - padding-bottom: 10px; - border-bottom-left-radius: 20px; - border-bottom-right-radius: 20px; + font-family: 'Roboto', sans-serif; + font-weight: 700; + padding-top: 5px; + padding-bottom: 10px; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; } @@ -717,295 +717,295 @@ pre { /**********Container****************/ .pb-container { - width:75%; - margin-left:auto; - margin-right:auto; + width:75%; + margin-left:auto; + margin-right:auto; } .pb-outer { - width:100%; - padding-top:25%; - position:relative + width:100%; + padding-top:25%; + position:relative } .pb-inner { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; } /*************Hover Effect***************/ .pb-home-links { - width: 75%; - font-family: 'Verdana', sans-serif; - margin-left:auto; - margin-right:auto; + width: 75%; + font-family: 'Verdana', sans-serif; + margin-left:auto; + margin-right:auto; } .pb-home-links-panel { - float:left; - margin-left:auto; - margin-right: auto; - width: 33%; - height: 100%; - text-align: center; + float:left; + margin-left:auto; + margin-right: auto; + width: 33%; + height: 100%; + text-align: center; } .pb-home-links-panel img { - display: inline-block; - width: 60%; - height: 60%; + display: inline-block; + width: 60%; + height: 60%; } .pb-home-links-outer-panel { - float:left; - margin-top:40px; - margin-left:auto; - margin-right: auto; - width: 33%; - height: 100%; - text-align: center; + float:left; + margin-top:40px; + margin-left:auto; + margin-right: auto; + width: 33%; + height: 100%; + text-align: center; } .pb-home-links-outer-panel img { - display: inline-block; - width: 50%; - height: 50%; + display: inline-block; + width: 50%; + height: 50%; } .pb-home-links-panel p { - margin-top:0px; + margin-top:0px; } .pb-panel-title { - display: block; - font-size:35px; - color: #ffffff; - margin-top: 30px; + display: block; + font-size:35px; + color: #ffffff; + margin-top: 30px; } .pb-center-title { - font-size:35px; - color: #ffffff; - margin-top: 20px; + font-size:35px; + color: #ffffff; + margin-top: 20px; } .pb-home-link-container:hover .pb-home-link-visible { - display: none; + display: none; } .pb-home-link-container:hover .pb-home-link-hidden { - display: block; + display: block; } .pb-home-link-hidden { - display:none; + display:none; } .pb-lg-homelink { - width: 40%; - height: 40%; + width: 40%; + height: 40%; } .pb-md-honelink { - width:30%; - height:3 0%; + width:30%; + height:3 0%; } /**********Message****************/ .pb-message-container { - margin-top: 140px; - width:75%; - margin-left:auto; - margin-right:auto; - text-align: center; + margin-top: 140px; + width:75%; + margin-left:auto; + margin-right:auto; + text-align: center; } .pb-message { - display: inline-block; - margin-left: auto; - margin-right: auto; - width: 100%; - background-color: white; - opacity: .8; - text-align: center; - padding: 5px; + display: inline-block; + margin-left: auto; + margin-right: auto; + width: 100%; + background-color: white; + opacity: .8; + text-align: center; + padding: 5px; } .pb--empty-message { - display: inline-block; - margin-left: auto; - margin-right: auto; - width: 100%; - opacity: .8; - text-align: center; - padding: 5px; + display: inline-block; + margin-left: auto; + margin-right: auto; + width: 100%; + opacity: .8; + text-align: center; + padding: 5px; } .pb-message > h3 { - color: #333333; - font-size:1.7vw; - font-family: 'Roboto', sans-serif; - margin-right: auto; - margin-left: auto; + color: #333333; + font-size:1.7vw; + font-family: 'Roboto', sans-serif; + margin-right: auto; + margin-left: auto; } /*===========Benefits===================*/ .pb_benefits { - background-color: #ffffff; - width: 80%; - padding-bottom: 40px; - margin-top:260px; - margin-left: auto; - margin-right: auto; - opacity:.80; - overflow:hidden; + background-color: #ffffff; + width: 80%; + padding-bottom: 40px; + margin-top:260px; + margin-left: auto; + margin-right: auto; + opacity:.80; + overflow:hidden; } .pb-benefits-title { - text-align: center; - padding-top:5px; - padding-bottom:5px; + text-align: center; + padding-top:5px; + padding-bottom:5px; } .pb-benefits-title > h2 { - font-family: 'Roboto', sans-serif; - color: #47547c; - font-size:3.5vw; - font-weight: 400; + font-family: 'Roboto', sans-serif; + color: #47547c; + font-size:3.5vw; + font-weight: 400; } .pb-benefits-container { - width: 100%; - height: 100%; + width: 100%; + height: 100%; } .pb-benefits-row { - display: inline-block; - width:100%; - height: 42%; + display: inline-block; + width:100%; + height: 42%; } .pb-benefits-panel { - width:100%; - height:100%; - margin-top:100px; + width:100%; + height:100%; + margin-top:100px; } .pb-benefits-panel-left { - float:left; - width:50%; + float:left; + width:50%; } .pb-benefits-panel-right { - float:right; - width:50%; - padding-right: 5%; + float:right; + width:50%; + padding-right: 5%; } .pb-benefits-panel-img { - float: left; - height: 100%; - width:30%; - text-align:right; - padding-right:10px; + float: left; + height: 100%; + width:30%; + text-align:right; + padding-right:10px; } .pb-benefits-panel-img > img { - max-width:60%; - max-height:60%; + max-width:60%; + max-height:60%; } .pb-benefits-panel-content { - float:right; - height: 100%; - width:70%; + float:right; + height: 100%; + width:70%; } .pb-benefits-panel-content-title { - font-family: 'Roboto', sans-serif; - color: #47547c; - font-size:2.5vw; - font-weight: 400; + font-family: 'Roboto', sans-serif; + color: #47547c; + font-size:2.5vw; + font-weight: 400; } .pb-benefits-panel-content-text { - font-family: 'Lato', sans-serif; - color: #47547c; - font-size:1.7vw; - font-weight: 400; + font-family: 'Lato', sans-serif; + color: #47547c; + font-size:1.7vw; + font-weight: 400; } /************ Carousel ****************/ .pb_home_belowfold_carousel { - border-top-left-radius: 12px; - border-top-right-radius: 12px; - padding-top: 20px; - text-align:center; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + padding-top: 20px; + text-align:center; } .pb_carousel_title { - margin-top:100px; - margin-bottom:50px; - margin-left:auto; - margin-right:auto; - padding-bottom: 10px; - color: #ffffff; - font-family: 'Roboto', sans-serif; - font-size: 4vw; - font-weight: 700; + margin-top:100px; + margin-bottom:50px; + margin-left:auto; + margin-right:auto; + padding-bottom: 10px; + color: #ffffff; + font-family: 'Roboto', sans-serif; + font-size: 4vw; + font-weight: 700; } .carousel-item > h3 { - font-family: 'Roboto', sans-serif; - font-size: 2.4vw; - padding-top: 5px; - padding-bottom:3px; - border-top-left-radius: 12px; - border-top-right-radius: 12px; - background-color: #47547c; - color: #ffffff; - margin:0; + font-family: 'Roboto', sans-serif; + font-size: 2.4vw; + padding-top: 5px; + padding-bottom:3px; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + background-color: #47547c; + color: #ffffff; + margin:0; } .carousel-item > h4 { - font-family: 'Lato', sans-serif; - font-size: 1.7vw; - color: #47547c; - padding-left: 10px; - padding-right: 10px; + font-family: 'Lato', sans-serif; + font-size: 1.7vw; + color: #47547c; + padding-left: 10px; + padding-right: 10px; } .slide { - background-color: #ffffff; - width: 70%; - height:250px; - margin-left: auto; - margin-right: auto; - border-top-left-radius: 12px; - border-top-right-radius: 12px; + background-color: #ffffff; + width: 70%; + height:250px; + margin-left: auto; + margin-right: auto; + border-top-left-radius: 12px; + border-top-right-radius: 12px; } .item { - text-align: center; + text-align: center; } .pb_carousel_indicators { - margin-top: 150px; + margin-top: 150px; } @@ -1106,58 +1106,58 @@ pre { /************ Partners ****************/ .partners { - text-align: center; + text-align: center; } .partners div.title { - width:100%; - padding-top: 30px; + width:100%; + padding-top: 30px; } .partners div.tableTitle { - width:100%; - padding-top: 30px; - padding-bottom: 30px; + width:100%; + padding-top: 30px; + padding-bottom: 30px; } .partners h3 { - margin:0; - padding: 0; - font-size:large; + margin:0; + padding: 0; + font-size:large; } .partners img.founders { - width: 100px; + width: 100px; } .partners img.standard { - width: 125px; + width: 125px; } .pb_tbl_title h3 { - padding-bottom: 20px; + padding-bottom: 20px; } .pb_standard_tbl td { - padding-left: 10px; - padding-right: 10px; + padding-left: 10px; + padding-right: 10px; } .partners ul { - list-style-type: none; + list-style-type: none; display: table; - width: 100%; + width: 100%; } .partners li { - display: table-cell; - text-align: center; + display: table-cell; + text-align: center; } .partners a[href^="http://"]:after, @@ -1166,7 +1166,7 @@ pre { } .pb-sm-img { - width: 50%; + width: 50%; height: 50%; } @@ -1177,7 +1177,7 @@ pre { } .pb-lg-img { - width: 70%; + width: 70%; height: 70%; } @@ -1186,105 +1186,105 @@ pre { } /**************************** - Blog + Blog ***************************/ .pb-blog { - margin-left:50px; - font-family: 'Verdana', sans-serif; - font-size: 34px; - font-weight: 400; + margin-left:50px; + font-family: 'Verdana', sans-serif; + font-size: 34px; + font-weight: 400; } .pb-blog h1 { - display: table; - padding: 3px 8px; - font-family: 'Verdana', sans-serif; - color: #ffffff; - font-size: 34px; - font-weight: 400; + display: table; + padding: 3px 8px; + font-family: 'Verdana', sans-serif; + color: #ffffff; + font-size: 34px; + font-weight: 400; } /******************************** - Content Pages + Content Pages *********************************/ .bs-docs-container { - margin-top: 70px; - margin-left:0; + margin-top: 70px; + margin-left:0; } .col-sm-9 { - padding-top: 20px; - margin:0; + padding-top: 20px; + margin:0; } .pb-content { - padding: 20px; - margin-left: 20px; + padding: 20px; + margin-left: 20px; } .pb-blog p { - font-family: 'Lato', sans-serif; - color: #222222; - font-size: 16px; - font-weight: 400; + font-family: 'Lato', sans-serif; + color: #222222; + font-size: 16px; + font-weight: 400; } .pb-content h1 { - /*background-color: #EA9622;*/ - display: table; - padding: 3px 0px; - font-family: 'Verdana', sans-serif; - color: #EA9622; - font-size: 34px; - font-weight: 400; - width:75wv; + /*background-color: #EA9622;*/ + display: table; + padding: 3px 0px; + font-family: 'Verdana', sans-serif; + color: #EA9622; + font-size: 34px; + font-weight: 400; + width:75wv; } .pb-content, .pb-blog h2 { - font-family: 'Verdana', sans-serif; - color: #000000; - font-size: 27px; - font-weight: 400; + font-family: 'Verdana', sans-serif; + color: #000000; + font-size: 27px; + font-weight: 400; } .pb-content, .pb-blog h3 { - font-family: 'Verdana', sans-serif; - color: #333333; - font-size: 24px; - font-weight: 400; + font-family: 'Verdana', sans-serif; + color: #333333; + font-size: 24px; + font-weight: 400; } .pb-content, .pb-blog h4 { - font-family: 'Verdana', sans-serif; - color: #333333; - font-size: 20px; - font-weight: 400; + font-family: 'Verdana', sans-serif; + color: #333333; + font-size: 20px; + font-weight: 400; } .pb-content, .pb-blog h5 { - font-family: 'Verdana', sans-serif; - color: #333333; - font-size: 18px; - font-weight: 400; + font-family: 'Verdana', sans-serif; + color: #333333; + font-size: 18px; + font-weight: 400; } .pb-content, .pb-blog ul, ol, li { - font-family: 'Lato', sans-serif; - font-size: 18px; + font-family: 'Lato', sans-serif; + font-size: 18px; } .pb-img, ,pb-blog { @@ -1297,633 +1297,633 @@ pre { /************* - Footer + Footer ******************/ .pb_footer { - display: block; - width: 75%; - font-family: 'Dosis', sans-serif; - font-weight: 400; - font-size:21px; - padding-top: 30px 0; - margin-left: auto; - margin-right: auto; - text-align: center; + display: block; + width: 75%; + font-family: 'Dosis', sans-serif; + font-weight: 400; + font-size:21px; + padding-top: 30px 0; + margin-left: auto; + margin-right: auto; + text-align: center; } /************ Was This Helpful Form ****************/ .wthHeader { - background-color: #EA9622; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - height: 10px; - width: 100%; - margin-bottom: 15px; + background-color: #EA9622; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + height: 10px; + width: 100%; + margin-bottom: 15px; } .wthBordered { - border: 1px solid #cccccc; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - margin-top: 10px; - padding-left: 7px; + border: 1px solid #cccccc; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + margin-top: 10px; + padding-left: 7px; } .wthForm { - padding-left: 15px; + padding-left: 15px; } .wthForm.input { - margin-top: 5px; - margin-bottom: 5px; + margin-top: 5px; + margin-bottom: 5px; } .wthSubmit { - margin-top: 5px; - margin-bottom: 5px; + margin-top: 5px; + margin-bottom: 5px; } .wthLabel { - font-family: 'Lato', sans-serif; - font-weight: 400; - font-size:18px; - color: #EA9622; - margin-top: 5px; - margin-bottom: 5px; + font-family: 'Lato', sans-serif; + font-weight: 400; + font-size:18px; + color: #EA9622; + margin-top: 5px; + margin-bottom: 5px; } .wthTitle { - font-family: 'Lato', sans-serif; - font-weight: 700; - font-size:24px; - color: #3498db; + font-family: 'Lato', sans-serif; + font-weight: 700; + font-size:24px; + color: #3498db; } /* - Responsive - There are 3 trigger levels, 1024, 768 and 480 + Responsive + There are 3 trigger levels, 1024, 768 and 480 */ /*small browsers*/ @media screen and (max-width: 1300px) { - .pb-top-text h1 { - font-size:60px; - } + .pb-top-text h1 { + font-size:60px; + } - .pb-top-text h2 { - font-size:30px; - } + .pb-top-text h2 { + font-size:30px; + } - .pb-panel-title { - font-size:33px; - } + .pb-panel-title { + font-size:33px; + } - .slide { - height: 140px; - } + .slide { + height: 140px; + } - } + } - /*iPad Pro*/ - @media screen and (max-width: 1024px) { + /*iPad Pro*/ + @media screen and (max-width: 1024px) { - .pb-message-container { - margin-top: 100px; - } + .pb-message-container { + margin-top: 100px; + } - .pb_benefits { - margin-top: 50px; - } + .pb_benefits { + margin-top: 50px; + } - .pb-benefits-panel { - margin-top:0px; + .pb-benefits-panel { + margin-top:0px; - .carousel-inner h3 { - font-size: 30px; - } + .carousel-inner h3 { + font-size: 30px; + } - .carousel-inner h4 { - padding-top: 20px; - font-size: 24px; - } + .carousel-inner h4 { + padding-top: 20px; + font-size: 24px; + } - .pb_carousel_indicators { - margin-top: 100px; - } + .pb_carousel_indicators { + margin-top: 100px; + } - .bs-docs-section { - line-height: 1.6; - font-size: large; - margin-right: 10em; - } + .bs-docs-section { + line-height: 1.6; + font-size: large; + margin-right: 10em; + } - .slide { - height: 160px; - } + .slide { + height: 160px; + } - .container { - width: 88%; - } + .container { + width: 88%; + } - } + } - /*iPad */ - @media screen and (max-width: 768px) { + /*iPad */ + @media screen and (max-width: 768px) { - .pb-top-text h1 { - font-size:40px; - } + .pb-top-text h1 { + font-size:40px; + } - .pb-top-text h2 { - font-size:20px; - } + .pb-top-text h2 { + font-size:20px; + } - .pb-panel-title { - font-size:30px; - } + .pb-panel-title { + font-size:30px; + } - .pb_benefits { - margin-top: 50px; - } + .pb_benefits { + margin-top: 50px; + } - .pb_carousel_title { - margin-top:50px; - margin-bottom:10px; - } + .pb_carousel_title { + margin-top:50px; + margin-bottom:10px; + } - .slide { - height: 110px; - } + .slide { + height: 110px; + } - .pb_carousel_indicators { - margin-top: 150px; - } + .pb_carousel_indicators { + margin-top: 150px; + } - } + } - /*iPhone Plus */ - @media screen and (max-width: 414px) { + /*iPhone Plus */ + @media screen and (max-width: 414px) { - /* hide side nav on phone devices*/ - #sidebar { - display: none; - } + /* hide side nav on phone devices*/ + #sidebar { + display: none; + } - .pb-top-text h1 { - font-size:20px; - } + .pb-top-text h1 { + font-size:20px; + } - .pb-top-text h2 { - font-size:12px; - } + .pb-top-text h2 { + font-size:12px; + } - .pb-home-links-panel { - margin-top: -10px; - } + .pb-home-links-panel { + margin-top: -10px; + } - .pb-outer-title { - margin-top: 5px; - } + .pb-outer-title { + margin-top: 5px; + } - .pb-home-links { - margin-top:-10px; - } + .pb-home-links { + margin-top:-10px; + } - .pb-home-links-outer-panel { - margin-top:20px; - } + .pb-home-links-outer-panel { + margin-top:20px; + } - .pb-panel-title { - font-size:14px; - } + .pb-panel-title { + font-size:14px; + } - .pb-message-container { - margin-top: 50px; - } + .pb-message-container { + margin-top: 50px; + } - .pb_benefits { - margin-top: 20px; - } + .pb_benefits { + margin-top: 20px; + } - .pb_carousel_title { - margin-top:-10px; - margin-bottom:20px; - } + .pb_carousel_title { + margin-top:-10px; + margin-bottom:20px; + } - .slide { - height: 70px; - } + .slide { + height: 70px; + } - .pb-main-nav { - display:none; - } + .pb-main-nav { + display:none; + } - .pb-mobile-nav { - display: block; - } + .pb-mobile-nav { + display: block; + } - .pb_carousel_indicators { - margin-top: 10px; - height: 10px; - } + .pb_carousel_indicators { + margin-top: 10px; + height: 10px; + } - .pb-content { - width: 85%; - margin-left: -20px; - } + .pb-content { + width: 85%; + margin-left: -20px; + } - .pb-content p { - font-size: 15px; - font-weight: 400; - line-height: inherit; - width: 85%; - } + .pb-content p { + font-size: 15px; + font-weight: 400; + line-height: inherit; + width: 85%; + } - } + } - /* iPhone X*/ - @media screen and (max-width: 375px) { + /* iPhone X*/ + @media screen and (max-width: 375px) { - .pb-top-text h1 { - font-size:22px; - } + .pb-top-text h1 { + font-size:22px; + } - .pb-top-text h2 { - font-size:11px; - margin-top: 0px; - } + .pb-top-text h2 { + font-size:11px; + margin-top: 0px; + } - .pb-panel-title { - font-size:12px; - } + .pb-panel-title { + font-size:12px; + } - .pb-home-links-panel { - margin-top: -15px; - } + .pb-home-links-panel { + margin-top: -15px; + } - .pb_benefits { - margin-top: 40px; - } + .pb_benefits { + margin-top: 40px; + } - .pb_home_belowfold_carousel { - padding-top: 60px; - } + .pb_home_belowfold_carousel { + padding-top: 60px; + } - .pb_carousel_title { - margin-top:-20px; - margin-bottom:0px; - } + .pb_carousel_title { + margin-top:-20px; + margin-bottom:0px; + } - .slide { - height: 80px; - } + .slide { + height: 80px; + } - .pb_carousel_indicators { - margin-top: 0px; - height: 22px; - } + .pb_carousel_indicators { + margin-top: 0px; + height: 22px; + } - .carousel-indicators { - padding-top: 140px; - } + .carousel-indicators { + padding-top: 140px; + } - } + } - /* iPhone 6, 7, 8 Galaxy S5 (different width) */ - @media screen and (max-width: 360px) { + /* iPhone 6, 7, 8 Galaxy S5 (different width) */ + @media screen and (max-width: 360px) { - .pb-top-text h1 { - font-size:18px; - } + .pb-top-text h1 { + font-size:18px; + } - .pb-top-text > h2 { - font-size:9px; - margin-top: 0px; - } + .pb-top-text > h2 { + font-size:9px; + margin-top: 0px; + } - .pb-home-links-outer-panel { - margin-top:10px; - } + .pb-home-links-outer-panel { + margin-top:10px; + } - .pb_benefits { - margin-top: 70px; - } + .pb_benefits { + margin-top: 70px; + } - } + } - /*iPhone 5*/ - @media screen and (max-width: 320px) { + /*iPhone 5*/ + @media screen and (max-width: 320px) { - .pb-home-links-outer-panel { - margin-top:3px; - } + .pb-home-links-outer-panel { + margin-top:3px; + } - .pb_benefits { - margin-top: 50px; - } + .pb_benefits { + margin-top: 50px; + } - } + } @media screen and (max-width: 768px) { - .col-sm-9 { - padding-top: 10px; - } + .col-sm-9 { + padding-top: 10px; + } - .pb-content { + .pb-content { - font-size: 15px; - font-weight: 400; - width: 85%; - margin-left: 0px; - - } - - .pb-content p { - font-size: 15px; - font-weight: 400; - line-height: inherit; - width: 85%; - } - - .pb-content li { - font-size: 15px; - font-weight: 400; - } - - .pb-content h1 { - font-size: 24px; - } - - .pb-content h2 { - font-size: 20px; - } - - .pb-content h3 { - font-size: 18px; - } - - .pb_footer { - display: block; - font-size:15px; - } - - /*Previous @media*/ - - #pb-home-demo { - margin-top: 30px; - } - - #pb-home-demo .col-sm-7 .lead { - margin-left: 0; - padding-left: 0; - } - - .pb-sm-left { - text-align: left; - } - - .pb-sm-center { - text-align: center; - } - - .pb-sm-right { - text-align: right; - } - - .pb-img { - -webkit-box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); - -moz-box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); - box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); - margin-top: 10px; - margin-bottom: 10px; - } - - - .blog-related-posts { - color: #aaa; - margin-top: 40px; - } - - .bs-callout code { - background-color: transparent; - } - - .bs-docs-footer { - margin-top: 60px; - } - - - .nav.nav-tabs { - margin-bottom: 15px; - font-weight: bold; - } - - .bs-callout { - padding-top: 0px; - padding-bottom: 10px; - } - - #chart_div { - height: 400px; - } - - .docs-sidebar { - margin-top: 20px; - padding: 20px; - padding-top: 10px; - padding-bottom: 10px; - border-radius: 2px; - } - - .docs-sidebar .nav>li>a{ - padding: 0px; - padding-bottom: 10px; - color: #555; - } - - .docs-sidebar .nav>li>a:hover{ - color: #337ab7; - background: transparent; - } - - .docs-sidebar .nav>li>a.selected { - color: #337ab7; - } - - .docs-sidebar h5 { - font-weight: 700; - font-size: 13px; - margin-top: 15px; - } - - .bs-docs-nav { - border-bottom: solid 1px #AAA; - } - - .bg-info { - padding: 10px; - border-radius: 5px; - } - - .bg-warning { - padding: 10px; - border-radius: 5px; - margin-bottom: 5px; - } - - .bg-danger { - padding: 10px; - border-radius: 5px; - } - - table.jsfiddle-line-number { - width: 100%; - border: 0; - } - - table.jsfiddle-line-number .line-number { - padding-top: 61px; - vertical-align: text-top; - line-height: 21px; - width: 17px; - color: #aaa; - font-size: 13px; - text-align: right; - } - - .blog-date { - margin-top: 45px; - text-align: right; - width: 80%; - font-size: 20px; - color: #aaa; - } - - #example-tab { - padding-left:10px; - } - - #example-tab li { - margin-bottom: 6px; - } - - table:not(.jsfiddle-line-number) { - table-layout: fixed; - word-wrap: break-word; - } - - div.pl-doc-entry{ - position: absolute; - } - - .prebid-mobile-notice { - margin-top: 2em; - } - - .pb-lg-img { - width: 85%; - height: 85%; - } - - .pb-xlg-img { + font-size: 15px; + font-weight: 400; + width: 85%; + margin-left: 0px; + + } + + .pb-content p { + font-size: 15px; + font-weight: 400; + line-height: inherit; + width: 85%; + } + + .pb-content li { + font-size: 15px; + font-weight: 400; + } + + .pb-content h1 { + font-size: 24px; + } + + .pb-content h2 { + font-size: 20px; + } + + .pb-content h3 { + font-size: 18px; + } + + .pb_footer { + display: block; + font-size:15px; + } + + /*Previous @media*/ + + #pb-home-demo { + margin-top: 30px; + } + + #pb-home-demo .col-sm-7 .lead { + margin-left: 0; + padding-left: 0; + } + + .pb-sm-left { + text-align: left; + } + + .pb-sm-center { + text-align: center; + } + + .pb-sm-right { + text-align: right; + } + + .pb-img { + -webkit-box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); + -moz-box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); + box-shadow: 2px 2px 8px -2px rgba(0,0,0,0.35); + margin-top: 10px; + margin-bottom: 10px; + } + + + .blog-related-posts { + color: #aaa; + margin-top: 40px; + } + + .bs-callout code { + background-color: transparent; + } + + .bs-docs-footer { + margin-top: 60px; + } + + + .nav.nav-tabs { + margin-bottom: 15px; + font-weight: bold; + } + + .bs-callout { + padding-top: 0px; + padding-bottom: 10px; + } + + #chart_div { + height: 400px; + } + + .docs-sidebar { + margin-top: 20px; + padding: 20px; + padding-top: 10px; + padding-bottom: 10px; + border-radius: 2px; + } + + .docs-sidebar .nav>li>a{ + padding: 0px; + padding-bottom: 10px; + color: #555; + } + + .docs-sidebar .nav>li>a:hover{ + color: #337ab7; + background: transparent; + } + + .docs-sidebar .nav>li>a.selected { + color: #337ab7; + } + + .docs-sidebar h5 { + font-weight: 700; + font-size: 13px; + margin-top: 15px; + } + + .bs-docs-nav { + border-bottom: solid 1px #AAA; + } + + .bg-info { + padding: 10px; + border-radius: 5px; + } + + .bg-warning { + padding: 10px; + border-radius: 5px; + margin-bottom: 5px; + } + + .bg-danger { + padding: 10px; + border-radius: 5px; + } + + table.jsfiddle-line-number { + width: 100%; + border: 0; + } + + table.jsfiddle-line-number .line-number { + padding-top: 61px; + vertical-align: text-top; + line-height: 21px; + width: 17px; + color: #aaa; + font-size: 13px; + text-align: right; + } + + .blog-date { + margin-top: 45px; + text-align: right; + width: 80%; + font-size: 20px; + color: #aaa; + } + + #example-tab { + padding-left:10px; + } + + #example-tab li { + margin-bottom: 6px; + } + + table:not(.jsfiddle-line-number) { + table-layout: fixed; + word-wrap: break-word; + } + + div.pl-doc-entry{ + position: absolute; + } + + .prebid-mobile-notice { + margin-top: 2em; + } + + .pb-lg-img { + width: 85%; + height: 85%; + } + + .pb-xlg-img { width: 100%; } - .pb-md-img { - width: 60%; - height: 60%; - } + .pb-md-img { + width: 60%; + height: 60%; + } - #pb-home-demo { - margin-top: 30px; - } + #pb-home-demo { + margin-top: 30px; + } - #pb-home-demo .col-sm-7 .lead { - margin-left: 0; - padding-left: 0; - } + #pb-home-demo .col-sm-7 .lead { + margin-left: 0; + padding-left: 0; + } - .pb-sm-left { - text-align: left; - } + .pb-sm-left { + text-align: left; + } - .pb-sm-center { - text-align: center; - } + .pb-sm-center { + text-align: center; + } - .pb-sm-right { - text-align: right; - } + .pb-sm-right { + text-align: right; + } } @media screen and (max-width: 414px) { - #wrapper { - padding-left: 0; - -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; - } - - #wrapper.toggled { - padding-left: 250px; - } - - #sidebar-wrapper { - z-index: 1000; - position: fixed; - left: 250px; - width: 0; - height: 100%; - margin-left: -250px; - overflow-y: auto; - background: #f6f8fa; - -webkit-transition: all 0.5s ease; - -moz-transition: all 0.5s ease; - -o-transition: all 0.5s ease; - transition: all 0.5s ease; - } - - #wrapper.toggled #sidebar-wrapper { - width: 250px; - } - - .pb-lg-img { - width: 65%; - height: 65%; - } - - .pb-xlg-img { + #wrapper { + padding-left: 0; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; + } + + #wrapper.toggled { + padding-left: 250px; + } + + #sidebar-wrapper { + z-index: 1000; + position: fixed; + left: 250px; + width: 0; + height: 100%; + margin-left: -250px; + overflow-y: auto; + background: #f6f8fa; + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; + } + + #wrapper.toggled #sidebar-wrapper { + width: 250px; + } + + .pb-lg-img { + width: 65%; + height: 65%; + } + + .pb-xlg-img { width: 100%; } - .pb-md-img { - width: 45%; - height: 45%; - } + .pb-md-img { + width: 45%; + height: 45%; + } - .pb_footer { - display: block; - font-size:10px; - } + .pb_footer { + display: block; + font-size:10px; + } } @@ -2113,21 +2113,21 @@ div.pl-doc-entry{ } /******************* - API + API .categoryBox { - display:block; - float: left; - margin-right:10px; - line-height:40px; - height: 40px; - padding-left: 15px; - padding-right: 15px; - background-color:#f6f8fa; - text-align:center; + display:block; + float: left; + margin-right:10px; + line-height:40px; + height: 40px; + padding-left: 15px; + padding-right: 15px; + background-color:#f6f8fa; + text-align:center; } diff --git a/assets/images/ad-ops/dfp-native/add-targeting.png b/assets/images/ad-ops/dfp-native/add-targeting.png deleted file mode 100644 index 0ffaa4f1a6..0000000000 Binary files a/assets/images/ad-ops/dfp-native/add-targeting.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/create_prebid_native.png b/assets/images/ad-ops/dfp-native/create_prebid_native.png deleted file mode 100644 index 665cad8a5f..0000000000 Binary files a/assets/images/ad-ops/dfp-native/create_prebid_native.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/creative-click-through-url.png b/assets/images/ad-ops/dfp-native/creative-click-through-url.png deleted file mode 100644 index 762b3c573f..0000000000 Binary files a/assets/images/ad-ops/dfp-native/creative-click-through-url.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/gam-creative-type.png b/assets/images/ad-ops/dfp-native/gam-creative-type.png deleted file mode 100644 index bd35cf0c0d..0000000000 Binary files a/assets/images/ad-ops/dfp-native/gam-creative-type.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/gam-line-item.png b/assets/images/ad-ops/dfp-native/gam-line-item.png deleted file mode 100644 index 43689e2e85..0000000000 Binary files a/assets/images/ad-ops/dfp-native/gam-line-item.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/gam-native-format.png b/assets/images/ad-ops/dfp-native/gam-native-format.png deleted file mode 100644 index 03981dcfd6..0000000000 Binary files a/assets/images/ad-ops/dfp-native/gam-native-format.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/gam-new-creative.png b/assets/images/ad-ops/dfp-native/gam-new-creative.png deleted file mode 100644 index 14d1561e81..0000000000 Binary files a/assets/images/ad-ops/dfp-native/gam-new-creative.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/native-ad-unit.png b/assets/images/ad-ops/dfp-native/native-ad-unit.png deleted file mode 100644 index b54604b596..0000000000 Binary files a/assets/images/ad-ops/dfp-native/native-ad-unit.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/native-content-ad.png b/assets/images/ad-ops/dfp-native/native-content-ad.png deleted file mode 100644 index d114ec7fba..0000000000 Binary files a/assets/images/ad-ops/dfp-native/native-content-ad.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/new-creative.png b/assets/images/ad-ops/dfp-native/new-creative.png deleted file mode 100644 index 8d6b5ffd68..0000000000 Binary files a/assets/images/ad-ops/dfp-native/new-creative.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/new-line-item.png b/assets/images/ad-ops/dfp-native/new-line-item.png deleted file mode 100644 index c899105603..0000000000 Binary files a/assets/images/ad-ops/dfp-native/new-line-item.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/new-order-and-line-item.png b/assets/images/ad-ops/dfp-native/new-order-and-line-item.png deleted file mode 100644 index 1c735fb793..0000000000 Binary files a/assets/images/ad-ops/dfp-native/new-order-and-line-item.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/prebid_native_html_option.png b/assets/images/ad-ops/dfp-native/prebid_native_html_option.png deleted file mode 100644 index d2444ccfe8..0000000000 Binary files a/assets/images/ad-ops/dfp-native/prebid_native_html_option.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/prebid_native_settings.png b/assets/images/ad-ops/dfp-native/prebid_native_settings.png deleted file mode 100644 index 5662f2d914..0000000000 Binary files a/assets/images/ad-ops/dfp-native/prebid_native_settings.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/prebid_native_styling.png b/assets/images/ad-ops/dfp-native/prebid_native_styling.png deleted file mode 100644 index fae3240690..0000000000 Binary files a/assets/images/ad-ops/dfp-native/prebid_native_styling.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/select-native-ad-format.png b/assets/images/ad-ops/dfp-native/select-native-ad-format.png deleted file mode 100644 index 5901af0399..0000000000 Binary files a/assets/images/ad-ops/dfp-native/select-native-ad-format.png and /dev/null differ diff --git a/assets/images/ad-ops/dfp-native/select-the-appropriate-native-format.png b/assets/images/ad-ops/dfp-native/select-the-appropriate-native-format.png deleted file mode 100644 index 9893105092..0000000000 Binary files a/assets/images/ad-ops/dfp-native/select-the-appropriate-native-format.png and /dev/null differ diff --git a/assets/images/ad-ops/gam-hbt-sbs/hbt-bidders.png b/assets/images/ad-ops/gam-hbt-sbs/hbt-bidders.png new file mode 100644 index 0000000000..c435d774cf Binary files /dev/null and b/assets/images/ad-ops/gam-hbt-sbs/hbt-bidders.png differ diff --git a/assets/images/ad-ops/gam-hbt-sbs/hbt-run-prebid.png b/assets/images/ad-ops/gam-hbt-sbs/hbt-run-prebid.png new file mode 100644 index 0000000000..11b29a7cac Binary files /dev/null and b/assets/images/ad-ops/gam-hbt-sbs/hbt-run-prebid.png differ diff --git a/assets/images/ad-ops/gam-hbt-sbs/hbt-setup-finished.png b/assets/images/ad-ops/gam-hbt-sbs/hbt-setup-finished.png new file mode 100644 index 0000000000..aa0e9a5c42 Binary files /dev/null and b/assets/images/ad-ops/gam-hbt-sbs/hbt-setup-finished.png differ diff --git a/assets/images/ad-ops/gam-hbt-sbs/hbt-start.png b/assets/images/ad-ops/gam-hbt-sbs/hbt-start.png new file mode 100644 index 0000000000..f29bae8705 Binary files /dev/null and b/assets/images/ad-ops/gam-hbt-sbs/hbt-start.png differ diff --git a/assets/images/ad-ops/dfp-creative-setup/appnexus_vast_tag.png b/assets/images/ad-ops/gam-sbs/appnexus_vast_tag.png similarity index 100% rename from assets/images/ad-ops/dfp-creative-setup/appnexus_vast_tag.png rename to assets/images/ad-ops/gam-sbs/appnexus_vast_tag.png diff --git a/assets/images/ad-ops/gam-sbs/associated-creatives.png b/assets/images/ad-ops/gam-sbs/associated-creatives.png new file mode 100644 index 0000000000..89e8a124ea Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/associated-creatives.png differ diff --git a/assets/images/ad-ops/gam-sbs/banner-creative-settings.png b/assets/images/ad-ops/gam-sbs/banner-creative-settings.png new file mode 100644 index 0000000000..4d49b93492 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/banner-creative-settings.png differ diff --git a/assets/images/ad-ops/gam-sbs/creative-filter.png b/assets/images/ad-ops/gam-sbs/creative-filter.png new file mode 100644 index 0000000000..3c15ef75ff Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/creative-filter.png differ diff --git a/assets/images/ad-ops/gam-sbs/custom-targeting-format.png b/assets/images/ad-ops/gam-sbs/custom-targeting-format.png new file mode 100644 index 0000000000..2cc81af54e Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/custom-targeting-format.png differ diff --git a/assets/images/ad-ops/gam-sbs/custom-targeting-pb.png b/assets/images/ad-ops/gam-sbs/custom-targeting-pb.png new file mode 100644 index 0000000000..2d1b207129 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/custom-targeting-pb.png differ diff --git a/assets/images/ad-ops/gam-sbs/delivery-settings.png b/assets/images/ad-ops/gam-sbs/delivery-settings.png new file mode 100644 index 0000000000..577995a987 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/delivery-settings.png differ diff --git a/assets/images/ad-ops/gam-sbs/duplicate-creatives.png b/assets/images/ad-ops/gam-sbs/duplicate-creatives.png new file mode 100644 index 0000000000..0f013d0120 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/duplicate-creatives.png differ diff --git a/assets/images/ad-ops/gam-sbs/gam-hierarchy.png b/assets/images/ad-ops/gam-sbs/gam-hierarchy.png new file mode 100644 index 0000000000..b46b7305e3 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/gam-hierarchy.png differ diff --git a/assets/images/ad-ops/gam-sbs/gam-native-format.png b/assets/images/ad-ops/gam-sbs/gam-native-format.png new file mode 100644 index 0000000000..8ea4c21c59 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/gam-native-format.png differ diff --git a/assets/images/ad-ops/dfp-native/gam-native-template.png b/assets/images/ad-ops/gam-sbs/gam-native-template.png similarity index 100% rename from assets/images/ad-ops/dfp-native/gam-native-template.png rename to assets/images/ad-ops/gam-sbs/gam-native-template.png diff --git a/assets/images/ad-ops/dfp-native/gam-new-creative-part2.png b/assets/images/ad-ops/gam-sbs/gam-new-creative-part2.png similarity index 100% rename from assets/images/ad-ops/dfp-native/gam-new-creative-part2.png rename to assets/images/ad-ops/gam-sbs/gam-new-creative-part2.png diff --git a/assets/images/ad-ops/gam-sbs/line-item-settings.png b/assets/images/ad-ops/gam-sbs/line-item-settings.png new file mode 100644 index 0000000000..2f20a948b0 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/line-item-settings.png differ diff --git a/assets/images/ad-ops/gam-sbs/native-format.png b/assets/images/ad-ops/gam-sbs/native-format.png new file mode 100644 index 0000000000..822bed01b7 Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/native-format.png differ diff --git a/assets/images/ad-ops/gam-sbs/select-creative.png b/assets/images/ad-ops/gam-sbs/select-creative.png new file mode 100644 index 0000000000..f3156e368b Binary files /dev/null and b/assets/images/ad-ops/gam-sbs/select-creative.png differ diff --git a/assets/images/ad-ops/mopub/full/mopub-lineitem-full-adunit.png b/assets/images/ad-ops/mopub/full/mopub-lineitem-full-adunit.png deleted file mode 100644 index 45485964f3..0000000000 Binary files a/assets/images/ad-ops/mopub/full/mopub-lineitem-full-adunit.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/full/mopub_lineitem_full_vasttag.png b/assets/images/ad-ops/mopub/full/mopub_lineitem_full_vasttag.png deleted file mode 100644 index ec952a815c..0000000000 Binary files a/assets/images/ad-ops/mopub/full/mopub_lineitem_full_vasttag.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-advanced.png b/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-advanced.png deleted file mode 100644 index 423d9e4eac..0000000000 Binary files a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-advanced.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded copy.png b/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded copy.png deleted file mode 100644 index 5bf220d953..0000000000 Binary files a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded copy.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded.png b/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded.png deleted file mode 100644 index dafdbd7081..0000000000 Binary files a/assets/images/ad-ops/mopub/rewarded/mopub-lineitem-rewarded.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag.png b/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag.png deleted file mode 100644 index cda6243ce5..0000000000 Binary files a/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag.png and /dev/null differ diff --git a/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag2.png b/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag2.png deleted file mode 100644 index b5eadf1500..0000000000 Binary files a/assets/images/ad-ops/mopub/rewarded/mopub_lineitem_vasttag2.png and /dev/null differ diff --git a/assets/images/ad-ops/planning/ad-ops-planning.png b/assets/images/ad-ops/planning/ad-ops-planning.png new file mode 100644 index 0000000000..38093ef397 Binary files /dev/null and b/assets/images/ad-ops/planning/ad-ops-planning.png differ diff --git a/assets/images/ad-ops/planning/pg-line-items-required.png b/assets/images/ad-ops/planning/pg-line-items-required.png new file mode 100644 index 0000000000..a94216005b Binary files /dev/null and b/assets/images/ad-ops/planning/pg-line-items-required.png differ diff --git a/assets/images/dev-docs/modules/permutiveRtdProvider-integration-create.png b/assets/images/dev-docs/modules/permutiveRtdProvider-integration-create.png new file mode 100644 index 0000000000..ec8737cc22 Binary files /dev/null and b/assets/images/dev-docs/modules/permutiveRtdProvider-integration-create.png differ diff --git a/assets/images/dev-docs/modules/permutiveRtdProvider-integration-update.png b/assets/images/dev-docs/modules/permutiveRtdProvider-integration-update.png new file mode 100644 index 0000000000..aec9fbbb1b Binary files /dev/null and b/assets/images/dev-docs/modules/permutiveRtdProvider-integration-update.png differ diff --git a/favicon.png b/assets/images/favicon.png similarity index 100% rename from favicon.png rename to assets/images/favicon.png diff --git a/assets/images/flowcharts/prebid-server/pbs-basic-flow.png b/assets/images/flowcharts/prebid-server/pbs-basic-flow.png index 0d5c5b09de..6d7624fcef 100644 Binary files a/assets/images/flowcharts/prebid-server/pbs-basic-flow.png and b/assets/images/flowcharts/prebid-server/pbs-basic-flow.png differ diff --git a/assets/images/flowcharts/prebid-server/pbs-dooh-flow.png b/assets/images/flowcharts/prebid-server/pbs-dooh-flow.png new file mode 100644 index 0000000000..7241c07ef7 Binary files /dev/null and b/assets/images/flowcharts/prebid-server/pbs-dooh-flow.png differ diff --git a/assets/images/icons/latency-blocking-1.png b/assets/images/icons/latency-blocking-1.png deleted file mode 100644 index 93314028b4..0000000000 Binary files a/assets/images/icons/latency-blocking-1.png and /dev/null differ diff --git a/assets/images/icons/latency-blocking-2.png b/assets/images/icons/latency-blocking-2.png deleted file mode 100644 index d0712510fb..0000000000 Binary files a/assets/images/icons/latency-blocking-2.png and /dev/null differ diff --git a/assets/images/icons/latency-concurrent.png b/assets/images/icons/latency-concurrent.png deleted file mode 100644 index d1ab1ed64d..0000000000 Binary files a/assets/images/icons/latency-concurrent.png and /dev/null differ diff --git a/assets/images/intros/Sincera_Logo_Black_Green-small.png b/assets/images/intros/Sincera_Logo_Black_Green-small.png new file mode 100644 index 0000000000..f047cd9c55 Binary files /dev/null and b/assets/images/intros/Sincera_Logo_Black_Green-small.png differ diff --git a/assets/images/intros/ad-server-black-box.png b/assets/images/intros/ad-server-black-box.png new file mode 100644 index 0000000000..b95865cd6d Binary files /dev/null and b/assets/images/intros/ad-server-black-box.png differ diff --git a/assets/images/intros/header-bidding-intro.png b/assets/images/intros/header-bidding-intro.png new file mode 100644 index 0000000000..faab245a8e Binary files /dev/null and b/assets/images/intros/header-bidding-intro.png differ diff --git a/assets/images/intros/prebid-benefits.png b/assets/images/intros/prebid-benefits.png new file mode 100644 index 0000000000..10f4d16c6e Binary files /dev/null and b/assets/images/intros/prebid-benefits.png differ diff --git a/assets/images/intros/prebid-intro.png b/assets/images/intros/prebid-intro.png new file mode 100644 index 0000000000..d93b643b90 Binary files /dev/null and b/assets/images/intros/prebid-intro.png differ diff --git a/assets/images/partners/community/Adomik-logo.png b/assets/images/partners/community/Adomik-logo.png deleted file mode 100644 index df8ddc2611..0000000000 Binary files a/assets/images/partners/community/Adomik-logo.png and /dev/null differ diff --git a/assets/images/partners/leader/AssertiveYield_logo.png b/assets/images/partners/leader/AssertiveYield_logo.png new file mode 100644 index 0000000000..ad979743b3 Binary files /dev/null and b/assets/images/partners/leader/AssertiveYield_logo.png differ diff --git a/assets/images/partners/leader/mile.png b/assets/images/partners/leader/mile.png new file mode 100644 index 0000000000..670611009c Binary files /dev/null and b/assets/images/partners/leader/mile.png differ diff --git a/assets/images/partners/leader/pubx.png b/assets/images/partners/leader/pubx.png new file mode 100644 index 0000000000..d8bacea947 Binary files /dev/null and b/assets/images/partners/leader/pubx.png differ diff --git a/assets/images/partners/publisher/sortable.png b/assets/images/partners/publisher/sortable.png deleted file mode 100644 index e2a7297f35..0000000000 Binary files a/assets/images/partners/publisher/sortable.png and /dev/null differ diff --git a/assets/images/partners/tech/conversant_logo.png b/assets/images/partners/tech/conversant_logo.png deleted file mode 100644 index 419c51ffb4..0000000000 Binary files a/assets/images/partners/tech/conversant_logo.png and /dev/null differ diff --git a/assets/images/partners/tech/epsilon_logo.png b/assets/images/partners/tech/epsilon_logo.png new file mode 100644 index 0000000000..45667e1bc2 Binary files /dev/null and b/assets/images/partners/tech/epsilon_logo.png differ diff --git a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub1.png b/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub1.png deleted file mode 100644 index dafdbd7081..0000000000 Binary files a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub1.png and /dev/null differ diff --git a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub2.png b/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub2.png deleted file mode 100644 index 33f9729029..0000000000 Binary files a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub2.png and /dev/null differ diff --git a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub3.png b/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub3.png deleted file mode 100644 index a960770821..0000000000 Binary files a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub3.png and /dev/null differ diff --git a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub4.png b/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub4.png deleted file mode 100644 index 9773ab05ea..0000000000 Binary files a/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub4.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-MoPub.png b/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-MoPub.png deleted file mode 100644 index cc55054819..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-MoPub.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-custom.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-custom.jpg new file mode 100644 index 0000000000..b37e680b6a Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-custom.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-default.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-default.jpg new file mode 100644 index 0000000000..66d980c7ff Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-default.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-custom.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-custom.jpg new file mode 100644 index 0000000000..add3ef836d Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-custom.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-default.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-default.jpg new file mode 100644 index 0000000000..2dd95eda59 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-default.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-custom.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-custom.jpg new file mode 100644 index 0000000000..767fae5f83 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-custom.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-default.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-default.jpg new file mode 100644 index 0000000000..2a69b370c2 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-default.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-custom.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-custom.jpg new file mode 100644 index 0000000000..4f80bfadd4 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-custom.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-default.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-default.jpg new file mode 100644 index 0000000000..7d48a5942d Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-default.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/android-sound-button.jpg b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-sound-button.jpg new file mode 100644 index 0000000000..5e1dafd983 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/android-sound-button.jpg differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png new file mode 100644 index 0000000000..a1b280f5c5 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-020.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-020.png new file mode 100644 index 0000000000..af4e77b3aa Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-020.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-possition-top-left.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-possition-top-left.png new file mode 100644 index 0000000000..0c24a12aa0 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-possition-top-left.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-mute-button-visible.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-mute-button-visible.png new file mode 100644 index 0000000000..ee40361c4c Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-mute-button-visible.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-left.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-left.png new file mode 100644 index 0000000000..7de8a093d4 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-left.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-right.png b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-right.png new file mode 100644 index 0000000000..003e076329 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-right.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/max-ad-unit-setup.png b/assets/images/prebid-mobile/modules/rendering/max-ad-unit-setup.png new file mode 100644 index 0000000000..c8976389f0 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/max-ad-unit-setup.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/max-cusom-network-setup.png b/assets/images/prebid-mobile/modules/rendering/max-cusom-network-setup.png new file mode 100644 index 0000000000..e2a921992d Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/max-cusom-network-setup.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-ad-units.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-ad-units.png new file mode 100644 index 0000000000..30b9f78d81 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-ad-units.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-ad-sources.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-ad-sources.png new file mode 100644 index 0000000000..02971e529a Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-ad-sources.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-adapter-name.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-adapter-name.png new file mode 100644 index 0000000000..488c4a3c48 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-adapter-name.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-name.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-name.png new file mode 100644 index 0000000000..58208cdfc0 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-add-custom-event-name.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-list-custom-events.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-list-custom-events.png new file mode 100644 index 0000000000..6aaba5e421 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-list-custom-events.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create-properties.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create-properties.png new file mode 100644 index 0000000000..3f7e845c8a Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create-properties.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-admob-create.png b/assets/images/prebid-mobile/modules/rendering/order-admob-create.png new file mode 100644 index 0000000000..163b749129 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/order-admob-create.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-create.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-create.png deleted file mode 100644 index eccdb4f6cc..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-create.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-creative-native.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-creative-native.png deleted file mode 100644 index 8390fc608e..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-creative-native.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-ad-unit.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-li-ad-unit.png deleted file mode 100644 index 494bc1b600..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-ad-unit.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-audience.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-li-audience.png deleted file mode 100644 index 3f5593f958..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-audience.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-type.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-li-type.png deleted file mode 100644 index 7cbe9f6644..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-li-type.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-creative.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-creative.png deleted file mode 100644 index 7a2f63867b..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-creative.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-li.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-li.png deleted file mode 100644 index 3d02f09ef4..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-native-ad-li.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/order-mopub-order-native.png b/assets/images/prebid-mobile/modules/rendering/order-mopub-order-native.png deleted file mode 100644 index 2829e93800..0000000000 Binary files a/assets/images/prebid-mobile/modules/rendering/order-mopub-order-native.png and /dev/null differ diff --git a/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-admob.png b/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-admob.png new file mode 100644 index 0000000000..d0d5a42877 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-admob.png differ diff --git a/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-max.png b/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-max.png new file mode 100644 index 0000000000..d849ce0c50 Binary files /dev/null and b/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-max.png differ diff --git a/assets/images/prebid-mobile/prebid-in-app-bidding-overview-mediation.png b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-mediation.png new file mode 100644 index 0000000000..0907d3448f Binary files /dev/null and b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-mediation.png differ diff --git a/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original-gam.png b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original-gam.png new file mode 100644 index 0000000000..d039f43b48 Binary files /dev/null and b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original-gam.png differ diff --git a/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original.png b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original.png new file mode 100644 index 0000000000..f758bf36cd Binary files /dev/null and b/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original.png differ diff --git a/assets/images/prebid-mobile/prebid-plugin-renderer-ad-view-injection.png b/assets/images/prebid-mobile/prebid-plugin-renderer-ad-view-injection.png new file mode 100644 index 0000000000..6fce19a655 Binary files /dev/null and b/assets/images/prebid-mobile/prebid-plugin-renderer-ad-view-injection.png differ diff --git a/assets/images/prebid-mobile/prebid-plugin-renderer-event-listeners.png b/assets/images/prebid-mobile/prebid-plugin-renderer-event-listeners.png new file mode 100644 index 0000000000..8944cf98e6 Binary files /dev/null and b/assets/images/prebid-mobile/prebid-plugin-renderer-event-listeners.png differ diff --git a/assets/images/prebid-mobile/prebid-plugin-renderer.png b/assets/images/prebid-mobile/prebid-plugin-renderer.png new file mode 100644 index 0000000000..3306b26348 Binary files /dev/null and b/assets/images/prebid-mobile/prebid-plugin-renderer.png differ diff --git a/assets/images/prebid-server/json-logic-screenshot.png b/assets/images/prebid-server/json-logic-screenshot.png new file mode 100644 index 0000000000..456429c61b Binary files /dev/null and b/assets/images/prebid-server/json-logic-screenshot.png differ diff --git a/assets/images/prebid-server/module-example.png b/assets/images/prebid-server/module-example.png index 24e419909c..3b1433eb5a 100644 Binary files a/assets/images/prebid-server/module-example.png and b/assets/images/prebid-server/module-example.png differ diff --git a/assets/images/prebid-server/pbs-floors-basic.png b/assets/images/prebid-server/pbs-floors-basic.png new file mode 100644 index 0000000000..202bf65b79 Binary files /dev/null and b/assets/images/prebid-server/pbs-floors-basic.png differ diff --git a/assets/images/prebid-server/pbs-floors-detailed.png b/assets/images/prebid-server/pbs-floors-detailed.png new file mode 100644 index 0000000000..5ad7fc00ef Binary files /dev/null and b/assets/images/prebid-server/pbs-floors-detailed.png differ diff --git a/assets/images/tools/professor-prebid-10.png b/assets/images/tools/professor-prebid-10.png new file mode 100644 index 0000000000..3fa52b65eb Binary files /dev/null and b/assets/images/tools/professor-prebid-10.png differ diff --git a/assets/images/tools/professor-prebid-11.png b/assets/images/tools/professor-prebid-11.png new file mode 100644 index 0000000000..435e513fb7 Binary files /dev/null and b/assets/images/tools/professor-prebid-11.png differ diff --git a/assets/images/tools/professor-prebid-12.png b/assets/images/tools/professor-prebid-12.png new file mode 100644 index 0000000000..f8af4c6b07 Binary files /dev/null and b/assets/images/tools/professor-prebid-12.png differ diff --git a/assets/images/tools/professor-prebid-13.png b/assets/images/tools/professor-prebid-13.png new file mode 100644 index 0000000000..0e4f874be1 Binary files /dev/null and b/assets/images/tools/professor-prebid-13.png differ diff --git a/assets/images/tools/professor-prebid-14.png b/assets/images/tools/professor-prebid-14.png new file mode 100644 index 0000000000..937b56ace6 Binary files /dev/null and b/assets/images/tools/professor-prebid-14.png differ diff --git a/assets/images/tools/professor-prebid-2.png b/assets/images/tools/professor-prebid-2.png new file mode 100644 index 0000000000..525131827e Binary files /dev/null and b/assets/images/tools/professor-prebid-2.png differ diff --git a/assets/images/tools/professor-prebid-3.png b/assets/images/tools/professor-prebid-3.png new file mode 100644 index 0000000000..077da6865b Binary files /dev/null and b/assets/images/tools/professor-prebid-3.png differ diff --git a/assets/images/tools/professor-prebid-4.png b/assets/images/tools/professor-prebid-4.png new file mode 100644 index 0000000000..869b862115 Binary files /dev/null and b/assets/images/tools/professor-prebid-4.png differ diff --git a/assets/images/tools/professor-prebid-5.png b/assets/images/tools/professor-prebid-5.png new file mode 100644 index 0000000000..7d604d39fa Binary files /dev/null and b/assets/images/tools/professor-prebid-5.png differ diff --git a/assets/images/tools/professor-prebid-6.png b/assets/images/tools/professor-prebid-6.png new file mode 100644 index 0000000000..d4de1c3e63 Binary files /dev/null and b/assets/images/tools/professor-prebid-6.png differ diff --git a/assets/images/tools/professor-prebid-7.png b/assets/images/tools/professor-prebid-7.png new file mode 100644 index 0000000000..401c7665ea Binary files /dev/null and b/assets/images/tools/professor-prebid-7.png differ diff --git a/assets/images/tools/professor-prebid-8.png b/assets/images/tools/professor-prebid-8.png new file mode 100644 index 0000000000..04d565f479 Binary files /dev/null and b/assets/images/tools/professor-prebid-8.png differ diff --git a/assets/images/tools/professor-prebid-9.png b/assets/images/tools/professor-prebid-9.png new file mode 100644 index 0000000000..5cc93c21d8 Binary files /dev/null and b/assets/images/tools/professor-prebid-9.png differ diff --git a/assets/images/tools/professor-prebid-icon.png b/assets/images/tools/professor-prebid-icon.png new file mode 100644 index 0000000000..c471404b46 Binary files /dev/null and b/assets/images/tools/professor-prebid-icon.png differ diff --git a/assets/js/download.js b/assets/js/download.js new file mode 100644 index 0000000000..09197ae3e7 --- /dev/null +++ b/assets/js/download.js @@ -0,0 +1,215 @@ +(function () { + var currentUrl = new URL(window.location); + var searchParams = currentUrl.searchParams; + + getVersionList(); + + $(function () { + // show all adapters + $(".adapters .col-md-4").show(); + setPrepickedModules(); + + document.getElementById('download-button').addEventListener('click', function (event) { + event.preventDefault(); + submit_download(); + }); + }); + + function getVersionList() { + $.ajax({ + type: "GET", + url: "https://js-download.prebid.org/versions", + }) + .success(function (data) { + try { + data = JSON.parse(data); + var versions = data.versions; + if (!versions || versions.length === 0) { + showError(); + return; + } + versions.forEach(function (version, index) { + if (index === 0) { + $(".selectpicker").append( + '" + ); + } else { + if (version.match(/\d\.\d+\.\d+/i)) { + $(".selectpicker").append( + '" + ); + } else { + // $('.selectpicker').append(''); + } + } + }); + setPrepickedVersion(); + } catch (e) { + console.log(e); + showError(); + } + }) + .fail(function (e) { + console.log(e); + showError(); + }); + function showError() { + $(".selectpicker").append( + '' + ); + } + } + + function submit_download() { + $('#download-button').html(' Sending Request...').addClass('disabled'); + + var form_data = get_form_data(); + $.ajax({ + type: "POST", + url: "https://js-download.prebid.org/download", + dataType: "text", + data: form_data, + }) + .success(function (data, textStatus, jqXHR) { + $('#download-button').html(' Prebid.js download successfully prepared!'); + setTimeout(function () { + $('#download-button').html(' Download Prebid.js').removeClass('disabled'); + }, 5000); + // Try to find out the filename from the content disposition `filename` value + var filename = "prebid" + form_data["version"] + ".js"; + // this doens't work in our current jquery version. + var disposition = jqXHR.getResponseHeader("Content-Disposition"); + if (disposition && disposition.indexOf("attachment") !== -1) { + var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; + var matches = filenameRegex.exec(disposition); + if (matches != null && matches[1]) + filename = matches[1].replace(/['"]/g, ""); + } + // The actual download + var blob = new Blob([data], { type: "text/javascript" }); + var link = document.createElement("a"); + link.href = window.URL.createObjectURL(blob); + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + if (form_data["removedModules"].length > 0) { + alert( + "The following modules were removed from your download because they aren't present in Prebid.js version " + + form_data["version"] + + ": " + + JSON.stringify(form_data["removedModules"]) + ); + } + }) + .fail(function (e) { + console.log(e); + alert("Ran into an issue."); + }); + } + + function get_form_data() { + var modules = []; + var version = $(".selectpicker").val(); + var removedModules = []; + + document + .querySelectorAll("input[type=checkbox][moduleCode]:checked") + .forEach(function (box) { + var moduleCode = box.getAttribute("moduleCode"); + var minVersion = box.getAttribute("minVersion"); + modules.push(moduleCode); + + if (minVersion) { + var module_version_array = minVersion.split("."); + var pbjs_version_array = version.split("."); + if ( + Number(pbjs_version_array[0]) < Number(module_version_array[0]) || + (Number(pbjs_version_array[0]) == Number(module_version_array[0]) && + Number(pbjs_version_array[1]) < Number(module_version_array[1])) + ) { + removedModules.push(moduleCode); + } + } + }); + + return { + modules, + version, + removedModules, + }; + } + + function setPrepickedModules() { + var moduleCheckboxes = document.querySelectorAll(".module-check-box"); + var modules = []; + var modulesParam = searchParams.get("modules"); + if (modulesParam) { + modules = modulesParam.split(","); + } + if (modules && modules.length) { + moduleCheckboxes.forEach(function (checkbox) { + checkbox.checked = false; + }); + modules.forEach(function (module) { + var checkbox = document.getElementById(module); + if (checkbox) { + checkbox.checked = true; + } + }); + } + + moduleCheckboxes.forEach(function (checkbox) { + if (checkbox.checked) { + var module = checkbox.id; + if (!modules.includes(module)) { + modules.push(module); + } + } + checkbox.addEventListener("change", function (event) { + var module = event.target.id; + if (event.target.checked) { + modules.push(module); + } else { + modules = modules.filter(function (m) { + return m !== module; + }); + } + if (modules.length) { + searchParams.set("modules", modules.join(",")); + } else { + searchParams.delete("modules"); + } + window.history.replaceState(null, "", currentUrl); + }); + }); + } + + function setPrepickedVersion() { + var version = searchParams.get("version"); + if (version) { + var versionOption = document.querySelector( + '#version_selector option[value="' + version + '"]' + ); + if (versionOption) { + versionOption.selected = true; + } + } + var versionSelector = document.getElementById("version_selector"); + if (versionSelector) { + versionSelector.addEventListener("change", function (event) { + var version = event.target.value; + searchParams.set("version", version); + window.history.replaceState( + null, + "", + window.location.pathname + "?" + searchParams.toString() + ); + }); + } + } +})(); diff --git a/assets/js/prism.js b/assets/js/prism.js index e420b03b29..1825be36cd 100644 --- a/assets/js/prism.js +++ b/assets/js/prism.js @@ -1,8 +1,23 @@ -/* PrismJS 1.16.0 -https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+go */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(g){var c=/\blang(?:uage)?-([\w-]+)\b/i,a=0,C={manual:g.Prism&&g.Prism.manual,disableWorkerMessageHandler:g.Prism&&g.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof M?new M(e.type,C.util.encode(e.content),e.alias):Array.isArray(e)?e.map(C.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(k instanceof M)){if(f&&y!=a.length-1){if(c.lastIndex=v,!(x=c.exec(e)))break;for(var b=x.index+(h?x[1].length:0),w=x.index+x[0].length,A=y,P=v,O=a.length;A"+n.content+""},!g.document)return g.addEventListener&&(C.disableWorkerMessageHandler||g.addEventListener("message",function(e){var a=JSON.parse(e.data),n=a.language,t=a.code,r=a.immediateClose;g.postMessage(C.highlight(t,C.languages[n],n)),r&&g.close()},!1)),C;var e=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return e&&(C.filename=e.src,C.manual||e.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(C.highlightAll):window.setTimeout(C.highlightAll,16):document.addEventListener("DOMContentLoaded",C.highlightAll))),C}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var i={};i[a]={pattern:RegExp("(<__[\\s\\S]*?>)(?:\\s*|[\\s\\S])*?(?=<\\/__>)".replace(/__/g,a),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",i)}}),Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; -!function(s){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var e=s.languages.markup;e&&(e.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:e.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:s.languages.css}},alias:"language-css"}},e.tag))}(Prism); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; -Prism.languages.go=Prism.languages.extend("clike",{keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/,boolean:/\b(?:_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,string:{pattern:/(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0}}),delete Prism.languages.go["class-name"]; +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+diff+go+graphql+http+java+kotlin+markup-templating+nginx+php+properties+scala+swift+typescript+yaml&plugins=diff-highlight */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i",unchanged:" ",diff:"!"};Object.keys(n).forEach((function(a){var i=n[a],r=[];/^\w+$/.test(a)||r.push(/\w+/.exec(a)[0]),"diff"===a&&r.push("bold"),e.languages.diff[a]={pattern:RegExp("^(?:["+i+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(a)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:n})}(Prism); +Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]; +Prism.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:Prism.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},Prism.hooks.add("after-tokenize",(function(n){if("graphql"===n.language)for(var t=n.tokens.filter((function(n){return"string"!=typeof n&&"comment"!==n.type&&"scalar"!==n.type})),e=0;e0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var u=e;u=0&&b(p,"variable-input")}}}}function l(n){return t[e+n]}function c(n,t){t=t||0;for(var e=0;e=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +!function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism); +!function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism); +!function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;e.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(Prism); +!function(e){var a=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:a,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:a,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(a){/<\?/.test(a.code)&&e.languages["markup-templating"].buildPlaceholders(a,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"php")}))}(Prism); +Prism.languages.properties={comment:/^[ \t]*[#!].*$/m,value:{pattern:/(^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?: *[=:] *(?! )| ))(?:\\(?:\r\n|[\s\S])|[^\\\r\n])+/m,lookbehind:!0,alias:"attr-value"},key:{pattern:/^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?= *[=:]| )/m,alias:"attr-name"},punctuation:/[=:]/}; +Prism.languages.scala=Prism.languages.extend("java",{"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/<-|=>|\b(?:abstract|case|catch|class|def|derives|do|else|enum|extends|extension|final|finally|for|forSome|given|if|implicit|import|infix|inline|lazy|match|new|null|object|opaque|open|override|package|private|protected|return|sealed|self|super|this|throw|trait|transparent|try|type|using|val|var|while|with|yield)\b/,number:/\b0x(?:[\da-f]*\.)?[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e\d+)?[dfl]?/i,builtin:/\b(?:Any|AnyRef|AnyVal|Boolean|Byte|Char|Double|Float|Int|Long|Nothing|Short|String|Unit)\b/,symbol:/'[^\d\s\\]\w*/}),Prism.languages.insertBefore("scala","triple-quoted-string",{"string-interpolation":{pattern:/\b[a-z]\w*(?:"""(?:[^$]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*?"""|"(?:[^$"\r\n]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*")/i,greedy:!0,inside:{id:{pattern:/^\w+/,greedy:!0,alias:"function"},escape:{pattern:/\\\$"|\$[$"]/,greedy:!0,alias:"symbol"},interpolation:{pattern:/\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,greedy:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:Prism.languages.scala}}},string:/[\s\S]+/}}}),delete Prism.languages.scala["class-name"],delete Prism.languages.scala.function,delete Prism.languages.scala.constant; +Prism.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp('(^|[^"#])(?:"(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^(])|[^\\\\\r\n"])*"|"""(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|[^(])|[^\\\\"]|"(?!""))*""")(?!["#])'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp('(^|[^"#])(#+)(?:"(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^#])|[^\\\\\r\n])*?"|"""(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|[^#])|[^\\\\])*?""")\\2'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp("#(?:(?:elseif|if)\\b(?:[ \t]*(?:![ \t]*)?(?:\\b\\w+\\b(?:[ \t]*\\((?:[^()]|\\([^()]*\\))*\\))?|\\((?:[^()]|\\([^()]*\\))*\\))(?:[ \t]*(?:&&|\\|\\|))?)+|(?:else|endif)\\b)"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Prism.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=Prism.languages.swift})); +!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism); +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +!function(){if("undefined"!=typeof Prism){var e=/^diff-([\w-]+)/i,i=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g,a=RegExp("(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))".replace(/__/g,(function(){return i.source})),"gi"),s=!1;Prism.hooks.add("before-sanity-check",(function(i){var a=i.language;e.test(a)&&!i.grammar&&(i.grammar=Prism.languages[a]=Prism.languages.diff)})),Prism.hooks.add("before-tokenize",(function(i){s||Prism.languages.diff||Prism.plugins.autoloader||(s=!0,console.warn("Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js).Make sure the language definition is loaded or use Prism's Autoloader plugin."));var a=i.language;e.test(a)&&!Prism.languages[a]&&(Prism.languages[a]=Prism.languages.diff)})),Prism.hooks.add("wrap",(function(s){var r,n;if("diff"!==s.language){var g=e.exec(s.language);if(!g)return;r=g[1],n=Prism.languages[r]}var f=Prism.languages.diff&&Prism.languages.diff.PREFIXES;if(f&&s.type in f){var u,l=s.content.replace(i,"").replace(/</g,"<").replace(/&/g,"&"),t=l.replace(/(^|[\r\n])./g,"$1");u=n?Prism.highlight(t,n,r):Prism.util.encode(t);var o,m=new Prism.Token("prefix",f[s.type],[/\w+/.exec(s.type)[0]]),d=Prism.Token.stringify(m,s.language),c=[];for(a.lastIndex=0;o=a.exec(u);)c.push(d+o[0]);/(?:^|[\r\n]).$/.test(l)&&c.push(d),s.content=c.join(""),n&&s.classes.push("language-"+r)}}))}}(); diff --git a/assets/js/video/pb-code-highlight.js b/assets/js/video/pb-code-highlight.js deleted file mode 100644 index 419ff085f0..0000000000 --- a/assets/js/video/pb-code-highlight.js +++ /dev/null @@ -1,335 +0,0 @@ - -var arrCodeElems = document.getElementsByClassName("pb-code-hl"); - -for(i=0; i -1) { - s = str.search(start); - e = str.indexOf(end, s); - if (e == -1) {e = str.length;} - if (repl) { - a.push(func(str.substring(s, e + (end.length)))); - str = str.substring(0, s) + repl + str.substr(e + (end.length)); - } else { - d += str.substring(0, s); - d += func(str.substring(s, e + (end.length))); - str = str.substr(e + (end.length)); - } - } - this.rest = d + str; - this.arr = a; - } - function htmlMode(txt) { - var rest = txt, done = "", php, comment, angular, startpos, endpos, note, i; - comment = new extract(rest, "<!--", "-->", commentMode, "W3HTMLCOMMENTPOS"); - rest = comment.rest; - while (rest.indexOf("<") > -1) { - note = ""; - startpos = rest.indexOf("<"); - if (rest.substr(startpos, 9).toUpperCase() == "<STYLE") {note = "css";} - if (rest.substr(startpos, 10).toUpperCase() == "<SCRIPT") {note = "javascript";} - endpos = rest.indexOf(">", startpos); - if (endpos == -1) {endpos = rest.length;} - done += rest.substring(0, startpos); - done += tagMode(rest.substring(startpos, endpos + 4)); - rest = rest.substr(endpos + 4); - if (note == "css") { - endpos = rest.indexOf("</style>"); - if (endpos > -1) { - done += cssMode(rest.substring(0, endpos)); - rest = rest.substr(endpos); - } - } - if (note == "javascript") { - endpos = rest.indexOf("</script>"); - if (endpos > -1) { - done += jsMode(rest.substring(0, endpos)); - rest = rest.substr(endpos); - } - } - } - rest = done + rest; - for (i = 0; i < comment.arr.length; i++) { - rest = rest.replace("W3HTMLCOMMENTPOS", comment.arr[i]); - } - return rest; - } - function tagMode(txt) { - var rest = txt, done = "", startpos, endpos, result; - while (rest.search(/(\s|
    )/) > -1) { - startpos = rest.search(/(\s|
    )/); - endpos = rest.indexOf(">"); - if (endpos == -1) {endpos = rest.length;} - done += rest.substring(0, startpos); - done += attributeMode(rest.substring(startpos, endpos)); - rest = rest.substr(endpos); - } - result = done + rest; - result = "<" + result.substring(4); - if (result.substr(result.length - 4, 4) == ">") { - result = result.substring(0, result.length - 4) + ">"; - } - return "" + result + ""; - } - function attributeMode(txt) { - var rest = txt, done = "", startpos, endpos, singlefnuttpos, doublefnuttpos, spacepos; - while (rest.indexOf("=") > -1) { - endpos = -1; - startpos = rest.indexOf("="); - singlefnuttpos = rest.indexOf("'", startpos); - doublefnuttpos = rest.indexOf('"', startpos); - spacepos = rest.indexOf(" ", startpos + 2); - if (spacepos > -1 && (spacepos < singlefnuttpos || singlefnuttpos == -1) && (spacepos < doublefnuttpos || doublefnuttpos == -1)) { - endpos = rest.indexOf(" ", startpos); - } else if (doublefnuttpos > -1 && (doublefnuttpos < singlefnuttpos || singlefnuttpos == -1) && (doublefnuttpos < spacepos || spacepos == -1)) { - endpos = rest.indexOf('"', rest.indexOf('"', startpos) + 1); - } else if (singlefnuttpos > -1 && (singlefnuttpos < doublefnuttpos || doublefnuttpos == -1) && (singlefnuttpos < spacepos || spacepos == -1)) { - endpos = rest.indexOf("'", rest.indexOf("'", startpos) + 1); - } - if (!endpos || endpos == -1 || endpos < startpos) {endpos = rest.length;} - done += rest.substring(0, startpos); - done += attributeValueMode(rest.substring(startpos, endpos + 1)); - rest = rest.substr(endpos + 1); - } - return "" + done + rest + ""; - } - function attributeValueMode(txt) { - return "" + txt + ""; - } - function commentMode(txt) { - return "" + txt + ""; - } - function cssMode(txt) { - var rest = txt, done = "", s, e, comment, i, midz, c, cc; - comment = new extract(rest, /\/\*/, "*/", commentMode, "W3CSSCOMMENTPOS"); - rest = comment.rest; - while (rest.search("{") > -1) { - s = rest.search("{"); - midz = rest.substr(s + 1); - cc = 1; - c = 0; - for (i = 0; i < midz.length; i++) { - if (midz.substr(i, 1) == "{") {cc++; c++} - if (midz.substr(i, 1) == "}") {cc--;} - if (cc == 0) {break;} - } - if (cc != 0) {c = 0;} - e = s; - for (i = 0; i <= c; i++) { - e = rest.indexOf("}", e + 1); - } - if (e == -1) {e = rest.length;} - done += rest.substring(0, s + 1); - done += cssPropertyMode(rest.substring(s + 1, e)); - rest = rest.substr(e); - } - rest = done + rest; - rest = rest.replace(/{/g, "{"); - rest = rest.replace(/}/g, "}"); - for (i = 0; i < comment.arr.length; i++) { - rest = rest.replace("W3CSSCOMMENTPOS", comment.arr[i]); - } - return "" + rest + ""; - } - function cssPropertyMode(txt) { - var rest = txt, done = "", s, e, n, loop; - if (rest.indexOf("{") > -1 ) { return cssMode(rest); } - while (rest.search(":") > -1) { - s = rest.search(":"); - loop = true; - n = s; - while (loop == true) { - loop = false; - e = rest.indexOf(";", n); - if (rest.substring(e - 5, e + 1) == " ") { - loop = true; - n = e + 1; - } - } - if (e == -1) {e = rest.length;} - done += rest.substring(0, s); - done += cssPropertyValueMode(rest.substring(s, e + 1)); - rest = rest.substr(e + 1); - } - return "" + done + rest + ""; - } - function cssPropertyValueMode(txt) { - var rest = txt, done = "", s; - rest = ":" + rest.substring(1); - while (rest.search(/!important/i) > -1) { - s = rest.search(/!important/i); - done += rest.substring(0, s); - done += cssImportantMode(rest.substring(s, s + 10)); - rest = rest.substr(s + 10); - } - result = done + rest; - if (result.substr(result.length - 1, 1) == ";" && result.substr(result.length - 6, 6) != " " && result.substr(result.length - 4, 4) != "<" && result.substr(result.length - 4, 4) != ">" && result.substr(result.length - 5, 5) != "&") { - result = result.substring(0, result.length - 1) + ";"; - } - return "" + result + ""; - } - function cssImportantMode(txt) { - return "" + txt + ""; - } - function jsMode(txt) { - var rest = txt, done = "", esc = [], i, cc, tt = "", sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, numpos, mypos, dotpos, y; - for (i = 0; i < rest.length; i++) { - cc = rest.substr(i, 1); - if (cc == "\\") { - esc.push(rest.substr(i, 2)); - cc = "W3JSESCAPE"; - i++; - } - tt += cc; - } - rest = tt; - y = 1; - while (y == 1) { - sfnuttpos = getPos(rest, "'", "'", jsStringMode); - dfnuttpos = getPos(rest, '"', '"', jsStringMode); - compos = getPos(rest, /\/\*/, "*/", commentMode); - comlinepos = getPos(rest, /\/\//, "
    ", commentMode); - numpos = getNumPos(rest, jsNumberMode); - keywordpos = getKeywordPos("js", rest, jsKeywordMode); - dotpos = getDotPos(rest, jsPropertyMode); - if (Math.max(numpos[0], sfnuttpos[0], dfnuttpos[0], compos[0], comlinepos[0], keywordpos[0], dotpos[0]) == -1) {break;} - mypos = getMinPos(numpos, sfnuttpos, dfnuttpos, compos, comlinepos, keywordpos, dotpos); - if (mypos[0] == -1) {break;} - if (mypos[0] > -1) { - done += rest.substring(0, mypos[0]); - done += mypos[2](rest.substring(mypos[0], mypos[1])); - rest = rest.substr(mypos[1]); - } - } - rest = done + rest; - for (i = 0; i < esc.length; i++) { - rest = rest.replace("W3JSESCAPE", esc[i]); - } - return "" + rest + ""; - } - function jsStringMode(txt) { - return "" + txt + ""; - } - function jsKeywordMode(txt) { - return "" + txt + ""; - } - function jsNumberMode(txt) { - return "" + txt + ""; - } - function jsPropertyMode(txt) { - return "" + txt + ""; - } - function getDotPos(txt, func) { - var x, i, j, s, e, arr = [".","<", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%"]; - s = txt.indexOf("."); - if (s > -1) { - x = txt.substr(s + 1); - for (j = 0; j < x.length; j++) { - cc = x[j]; - for (i = 0; i < arr.length; i++) { - if (cc.indexOf(arr[i]) > -1) { - e = j; - return [s + 1, e + s + 1, func]; - } - } - } - } - return [-1, -1, func]; - } - function getMinPos() { - var i, arr = []; - for (i = 0; i < arguments.length; i++) { - if (arguments[i][0] > -1) { - if (arr.length == 0 || arguments[i][0] < arr[0]) {arr = arguments[i];} - } - } - if (arr.length == 0) {arr = arguments[i];} - return arr; - } - function getKeywordPos(typ, txt, func) { - var words, i, pos, rpos = -1, rpos2 = -1, patt; - if (typ == "js") { - words = ["abstract","arguments","boolean","break","byte","case","catch","char","class","const","continue","debugger","default","delete", - "do","double","else","enum","eval","export","extends","false","final","finally","float","for","function","goto","if","implements","import", - "in","instanceof","int","interface","let","long","NaN","native","new","null","package","private","protected","public","return","short","static", - "super","switch","synchronized","this","throw","throws","transient","true","try","typeof","var","void","volatile","while","with","yield"]; - } - for (i = 0; i < words.length; i++) { - pos = txt.indexOf(words[i]); - if (pos > -1) { - patt = /\W/g; - if (txt.substr(pos + words[i].length,1).match(patt) && txt.substr(pos - 1,1).match(patt)) { - if (pos > -1 && (rpos == -1 || pos < rpos)) { - rpos = pos; - rpos2 = rpos + words[i].length; - } - } - } - } - return [rpos, rpos2, func]; - } - function getPos(txt, start, end, func) { - var s, e; - s = txt.search(start); - e = txt.indexOf(end, s + (end.length)); - if (e == -1) {e = txt.length;} - return [s, e + (end.length), func]; - } - function getNumPos(txt, func) { - var arr = ["
    ", " ", ";", "(", "+", ")", "[", "]", ",", "&", ":", "{", "}", "/" ,"-", "*", "|", "%", "="], i, j, c, startpos = 0, endpos, word; - for (i = 0; i < txt.length; i++) { - for (j = 0; j < arr.length; j++) { - c = txt.substr(i, arr[j].length); - if (c == arr[j]) { - if (c == "-" && (txt.substr(i - 1, 1) == "e" || txt.substr(i - 1, 1) == "E")) { - continue; - } - endpos = i; - if (startpos < endpos) { - word = txt.substring(startpos, endpos); - if (!isNaN(word)) {return [startpos, endpos, func];} - } - i += arr[j].length; - startpos = i; - i -= 1; - break; - } - } - } - return [-1, -1, func]; - } -} - diff --git a/bower.json b/bower.json deleted file mode 100755 index d484f76bec..0000000000 --- a/bower.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "prebid.js", - "version": "1.1.0", - - "dependencies": { - - } -} \ No newline at end of file diff --git a/cookies.html b/cookies.html new file mode 100644 index 0000000000..ee74f1b400 --- /dev/null +++ b/cookies.html @@ -0,0 +1,5 @@ + + +Redirecting to https://docs.prebid.org/policies/cookies.html + + diff --git a/cookies.md b/cookies.md deleted file mode 100644 index 33fa7dbdde..0000000000 --- a/cookies.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: page_v2 -title: Cookies Used on Prebid.org -description: Cookies Used on Prebid.org -sidebarType: 0 ---- - -# Cookie Declaration - -The docs.prebid.org website may store or retrieve information on your browser in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. The information does not usually directly identify you, but it can give you a more personalized web experience. Because we respect your right to privacy, you can choose not to allow some types of cookies. However, blocking cookies may impact your experience of the site and the services we are able to offer. - - -Cookie Settings - - -
    - - - - - diff --git a/debugging/debugging.md b/debugging/debugging.md index 906dba744c..4b0d0fe192 100644 --- a/debugging/debugging.md +++ b/debugging/debugging.md @@ -1,23 +1,27 @@ --- layout: page_v2 -title: Debugging | Prebid -description: Debugging Prebid Extension +title: Debugging | Prebid.js +description: Debugging Prebid.js sidebarType: 1 --- -# Chrome Extension for Debugging Prebid.js +# Debugging Prebid.js -Prebid.Org supports the Chrome extension [Headerbid Expert](https://chrome.google.com/webstore/detail/headerbid-expert/cgfkddgbnfplidghapbbnngaogeldmop). Web publishers can use this tool to understand how their Prebid.js header bidding partners are doing: +{:.no_toc} -1. What's the latency from each header bidding partner? -1. Do they load asynchronously or are they blocking my pages? -1. Are they all loaded together in parallel? +- TOC +{:toc} -Use the tool to determine whether a page might be under-monetized or could -benefit from implementation improvements. +## Professor Prebid Chrome Extension for Debugging Prebid.js -Further Reading +Prebid has a Chrome extension that can be utilized for debugging called [Professor Prebid](https://chrome.google.com/webstore/detail/professor-prebid/kdnllijdimhbledmfdbljampcdphcbdc). Publishers are able to utilize this extension to view Adunits, Bids, Auction Timeline, User IDs, and other details of the ad auctions on a given page. This information can be easily viewed in the various tabs of the extension itself or through a debug page that opens with all the details inside a single page format. In the Professor Prebid ***Tools*** tab you will find this feature along with the ability to easily enable the Prebid.js Debbugging Module (described below) that can also be helpful in debugging. To learn more about all the features and how to utilize this extension please refer to [Professor Prebid](https://docs.prebid.org/tools/professor-prebid.html). -+ [Prebid.js Troubleshooting Guide](/dev-docs/prebid-troubleshooting-guide.html) +## Debugging Module + +The Prebid.js debugging module enables the "intercepting" of bids and replacing of the contents with data for testing purposes. To learn more about how to utilize this module please refer to the [Debugging Module](https://docs.prebid.org/dev-docs/modules/debugging.html). + +## Related Reading + +- [Prebid.js Troubleshooting Guide](/dev-docs/prebid-troubleshooting-guide.html) diff --git a/deprecated/old_index_md_content.html b/deprecated/old_index_md_content.html index a2552234c5..cfe3a01a2d 100644 --- a/deprecated/old_index_md_content.html +++ b/deprecated/old_index_md_content.html @@ -93,7 +93,7 @@

    Partners that work with Prebid

    SmartyAds

    Meme Global

    Underdog Media

    -

    Conversant

    +

    Epsilon

    Adblade

    Piximedia

    GetIntent

    diff --git a/dev-docs/activity-controls.md b/dev-docs/activity-controls.md new file mode 100644 index 0000000000..ef227c9d9b --- /dev/null +++ b/dev-docs/activity-controls.md @@ -0,0 +1,405 @@ +--- +layout: page_v2 +title: Activity Controls +description: How to stop Prebid.js from doing things you don't want +sidebarType: 1 +pbjs_version: 7.52 +--- + +# Prebid.js Activity Controls +{: .no_toc } + +Starting with version 7.52, Prebid.js introduced a centralized control mechanism for privacy-sensitive _activities_ - such as accessing device storage or sharing data with partners. +These controls are intended to serve as building blocks for privacy protection mechanisms, allowing module developers or publishers to directly specify what should be permitted or avoided in any given regulatory environment. + +* TOC +{: toc } + +## Overview + +There are many privacy regulations that Prebid publishers need to accommodate. Prebid supplies [modules](/dev-docs/faq.html#how-does-prebid-support-privacy-regulations) to help Publishers implement their legal policies, but there are scenarios where extra control is needed: + +* a Publisher's lawyers want to make a particular exception +* a module hasn't been built for a regulation the Publisher needs to support + +Several, but not all, of the popular consent strings have modules (eg [Prebid Activity Controls -- GPP control module - usnat](/dev-docs/modules/gppControl_usnat.html)) that translate their contents into activity controls. These modules may have some overrides to default string interpretations available. When these overrides are insufficient for a publisher, or case law has abruptly changed, publishers may prefer direct control. + +### Prebid Is a Toolkit + +{% include legal-warning.html %} + +1. Get a privacy lawyer. +2. Consider all the privacy regulations your content business is subject to. +3. Come up with a plan. +4. Use Prebid.js modules and these Activity Controls as ways to help implement your privacy plan with respect to header bidding. +5. Let us know if there are tools missing from the Prebid toolkit. + +### What is an Activity? + +We did an analysis of the things Prebid.js does and identified those related to privacy regulations. We call these things "potentially restricted activities", or just "activities" for short. Here are some: + +* Setting a cookie +* Syncing ID cookies +* Transmitting user first-party data +* etc. + +The [full list of activities Prebid.js supports](#activities) is below. + +Think of an activity control as a 'gatekeeper' that makes the decision about whether the activity should be allowed in this specific context: + +* Should I allow this cookie to be set for bidderA? +* Should I allow this usersync for bidderB? +* Is it ok for this data to be passed to bidderC and analyticsD? +* etc. + +Prebid.js core checks with the Activity Controls to see whether an activity is allowed. The configuration for the activity can come from modules, custom functions in the page, or a rule-based JSON config. + +### Example Activity Control + +{: .alert.alert-info :} +In this example, bidderX wants to set a cookie through StorageManager, which queries the Activity Control System to determine whether that's allowed. The publisher has set up configuration that specifically enables bidderX to do this. + +Here's an example JSON config that disables accessing local storage (including cookies) for everything except the bid adapter `bidderX`: + +```javascript +pbjs.setConfig({ + allowActivities: { + accessDevice: { + default: false, + rules: [{ + condition(params) { + return params.componentName === 'bidderX' + }, + allow: true + }] + } + } +}) +``` + + + +## Configuration + +`allowActivities` is a new option to [setConfig](/dev-docs/publisher-api-reference/setConfig.html). It contains a list of activity names -- see the [full list of activities below](#activities). Each activity is an object that can contain these attributes: + +{: .table .table-bordered .table-striped } +| Name | Type | Description | +|------|------|-------------| +| `default` | Boolean | Whether the activity should be allowed if no other rule applies. Defaults to true. | +| `rules` | Array of objects | Rules for this activity | +| `rules[].condition` | Function | Condition function to use for this rule; the rule applies only if this returns true. Receives a single object that contains [activity parameters](#parameters) as input. If omitted, the rule always applies. | +| `rules[].allow` | Boolean | Whether the activity should be allowed when this rule applies. Defaults to true. | +| `rules[].priority` | Number | Priority of this rule compared to other rules; a lower number means higher priority. See [note on rule priority](#priority) below. Defaults to 1. | + +`Rules` is an array of objects that a publisher can construct to provide fine-grained control over a given activity. For instance, you could set up a series of rules that says: + +* Amongst the bid adapters, BidderA is always allowed to receive user first-party data +* Always let analytics adapters receive user first-party data +* Otherwise, let the active privacy modules decide +* if they refuse to decide, then the overall default is to allow the transmitting of user first-party data + +There's more about [rules](#parameters) below. + + + +### Activities + +Here's the list of the 'potentially restricted activities' that Prebid.js core can restrict for Publishers: + +{: .table .table-bordered .table-striped } +| Name | Description | Effect when denied | Additional parameters | +|----------------|-------------|---------------------------|--------------------------------| +| `accessDevice` | A component wants to use device storage | Storage is disabled | [`storageType`](#params-accessDevice) | +| `enrichEids` | A user ID or RTD submodule wants to add user IDs to outgoing requests | User IDs are discarded | None | +| `enrichUfpd` | A Real-Time Data (RTD) submodule wants to add user first-party data to outgoing requests (`user.data` in ORTB) | User FPD is discarded | None | +| `fetchBids` | A bid adapter wants to participate in an auction | Bidder is removed from the auction | [`configName`](#params-fetchBids) | +| `reportAnalytics` | An analytics adapter is being enabled through `pbjs.enableAnalytics` | Adapter remains disabled | None | +| `syncUser` | A bid adapter wants to fetch a [user sync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) | User sync is skipped | [`syncType`, `syncUrl`](#params-syncUser) | +| `transmitEids` | A bid adapter or RTD submodule wants to access and/or transmit user IDs to their endpoint | User IDs are hidden from the component | [`configName`](#params-fetchBids) | +| `transmitPreciseGeo` | A bid adapter or RTD submodule wants to access and/or transmit precise geolocation data to their endpoint | Component is allowed only 2-digit precision for latitude and longitude | [`configName`](#params-fetchBids) | +| `transmitTid` | A bid adapter or RTD submodule wants to access and/or transmit globally unique transaction IDs to their endpoint | Transaction IDs are hidden from the component | [`configName`](#params-fetchBids) | +| `transmitUfpd` | A bid adapter or RTD submodule wants to access and/or transmit user FPD to their endpoint | User FPD is hidden from the component | [`configName`](#params-fetchBids) | + + + +### Rules + +There are three parts to an Activity Control's rule: + + 1. The priority + 2. The condition + 3. The allow flag + +For example, this rule would allow bidderX to perform the activity if no higher priority rules take precedence. + +```javascript +... + rules: [{ + priority: 10, // average priority + condition(params) { + return params.componentName === 'bidderX' + }, + allow: true + }] +... +``` + + + +#### Rule Priority + +Activity control rules in Prebid.js can be created by two main sources: + +* Publisher `setConfig({allowActivities})` as in the examples shown here. When set this way, rules are considered the highest priority value of 1. +* Modules can set activity control rules, e.g. [usersync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing), [bidderSettings](/dev-docs/publisher-api-reference/bidderSettings.html), the [GPP](/dev-docs/modules/consentManagementGpp.html) or [GDPR](/dev-docs/modules/gdprEnforcement.html) modules. Rules set by modules have a less urgent priority of 10. + +When rules are processed, they are sorted by priority, and all rules of the same priority are considered to happen at the same time. The details: + +1. The highest rule priority is 1 +2. There's no defined lowest priority other than MAXINT +3. Default priority for rules defined with setConfig is 1. The default priority for other rules is 10. +4. When processing, group the rules by priority +5. Then, in descending order of priority: + 1. If any rule that matches the condition defines `allow: false`, the activity is DENIED. + 2. Otherwise, if at least one rule that matches the condition defines `allow: true`, the activity is ALLOWED. + 3. If any rule matches, break out of the priority loop. +6. If none of the rules match, and the activity defines `default: false`, the activity is DENIED. +7. Otherwise, the activity is ALLOWED. + +So this means that when `priority` is omitted from `allowActivities` configuration, it acts as an override over other control mechanisms. For example: + +```javascript +pbjs.setConfig({ + accessDevice: false, // this would have the effect of disabling device storage, but... + allowActivities: { + accessDevice: { + rules: [ + {allow: true} // ... it's overridden by this condition-less rule with a default priority of 1 + ] + } + } +}) +``` + +If a priority number greater than 10 is specified, the rule only takes effect when all other controls have allowed the activity. For example: + +```javascript +pbjs.setConfig({ + allowActivities: { + accessDevice: { + // the intent here is to disable cookies but allow HTML5 localStorage + // because this defines priority > 10, other controls will be checked first + // e.g. if GDPR is in-scope and there's no consent, this priority 20 rule won't be processed + default: false, + rules: [{ + condition({storageType}) { + return storageType === 'html5' + }, + allow: true, + priority: 20 + }] + } + } +}) +``` + +#### Rule Conditions + +A `condition` is a javascript function that receives information about the activity that is about to be performed. If a condition evaluates to true, the `allow` attribute of the rule will be utilized. If there's no condition specified, the rule's `allow` attribute will always be utilized. + +These are the parameters available to the condition function: + +{: .table .table-bordered .table-striped } +| Name | Type | Available for | Description | +|------|------|-------------|---------------| +| `componentType` | String | All activities | One of: `'bidder'`, `'userId'`, `'rtd'`, `'analytics'`, or `'prebid'`; identifies the type of component (usually a module) that wishes to perform the activity. `'prebid'` is reserved for Prebid core itself and a few "privileged" modules such as the [PBS adapter](/dev-docs/modules/prebidServer.html). | +| `componentName` | String | All activities | Name of the component; this is (depending on the type) either a bidder code, user ID or RTD submodule name, analytics provider code, or module name. | +| `component` | String | All activities | This is always a dot-separated concatenation of `componentType` and `componentName`; for example, with `{componentType: 'bidder', componentName: 'bidderX'}`, `component` is `'bidder.bidderX'`. | +| `adapterCode` | String | All activities | If `componentType` is `'bidder'`, and `componentName` is an [alias](/dev-docs/publisher-api-reference/aliasBidder.html), then `adapterCode` is the bidder code that was aliased; or identical to `componentName` if the bidder is not an alias. This is undefined when the component is not a bidder.| +| `configName` | String | `fetchBids` | When the Prebid Server adapter is part of an auction, this is the name given to its [s2s configuration](/dev-docs/modules/prebidServer.html), if any. | +| `storageType` | String | `accessDevice` | Either `'html5'` or `'cookie'` - the device storage mechanism being accessed. | +| `syncType` | String | `syncUser` | Either `'iframe'` or `'image'` - the type of user sync. | +| `syncUrl` | String | `syncUser` | URL of the user sync. | + +#### Allow Flag + +If the rule's condition matches, this attribute defines whether the rule 'votes' to allow (true) or disallow (false) the activity in question. + +As noted in the priority section, **disallow** (false) takes precedence amongst rules at the same priority level. + +If `allow` is not defined, the rule is assumed to assert **true** (i.e. allow the activity to take place). + +### More examples + +#### Always include a particular bidder in auctions + +This is similiar to the 'vendor exception' feature of the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html). This would always allow bidderA to participate in the auction, even without explicit consent in GDPR scenarios. It might indicate, for instance, that this is a 'first party bidder'. + +```javascript +pbjs.setConfig({ + allowActivities: { + fetchBids: { + rules: [{ + condition: ({componentName}) => componentName === 'bidderA', + allow: true + }] + } + } +}) +``` + +#### Disable all user syncs except for specific domains + +```javascript +const DOMAINLIST = [ + 'https://example-domain.org', + 'https://other-domain.com', +]; + +pbjs.setConfig({ + allowActivities: { + syncUser: { + default: false, + rules: [{ + condition({syncUrl}) { + return DOMAINLIST.some(domain => syncUrl.startsWith(domain)); + }, + allow: true + }] + } + } +}) +``` + +#### Deny a particular vendor access to user IDs + +```javascript +pbjs.setConfig({ + allowActivities: { + transmitEids: { + rules: [{ + condition: ({componentName}) => componentName === 'exampleVendor', + allow: false, + }] + } + } +}) +``` + +#### __uspapi CCPA/CPRA based control + +Reference: [US Privacy User Signal Mechanism “USP API” Specification](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/USP%20API.md) + +```javascript +function isCCPAConsentDenied() { +### assumes uspapi is properly implemented and available in your environment. +### check usp string for the second character (notice) is not 'Y' or third character (opt out) is not 'N' or first character (version) is not '1' + __uspapi('getUSPData', 1 , (uspData, success) => { if(uspData.uspString.charAt(2) ==='Y' || uspData.uspString.charAt(1) !=='Y'|| uspData.uspString.charAt(0) !=='1') { return true } else { return false }}); +} + +pbjs.setConfig({ + allowActivities: { + enrichUfpd: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + enrichEids: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + reportAnalytics: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + syncUser: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + transmitEids: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + transmitPreciseGeo: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + }, + transmitUfpd: { + rules: [{ + condition: isCCPAConsentDenied, + allow: false + }] + } + + } +}) +``` + +#### When there's a GPP CMP active, anonymize everything + +This example might be useful for publishers using a version +of Prebid.js that supports activity controls but does not support +the [USNat module](/dev-docs/modules/gppControl_usnat.html). + +```javascript +if (in-page code to detect that GPP SID 7 through 12 are in-scope or if the GPC flag is set) { + pbjs.setConfig({ + allowActivities: { + enrichEids: { + default: false + }, + transmitEids: { + default: false + }, + … see other activities in https://docs.prebid.org/dev-docs/activity-controls.html … + } + }); +} +``` + +#### Always allow sharedId to be passed, others determined by privacy regs + +To make exceptions for certain IDs, there are two steps: + +1. Always allow the transmitEids activity to take place +1. Configure the enrichEids activity to allow only the desired IDs + +This approach works in conjunction with other activity-control compiant modules (like the [GPP USNat module](/dev-docs/modules/gppControl_usnat.html). + +```javascript + pbjs.setConfig({ + allowActivities: { + enrichEids: { + default: false, + priority: 1, + rules: [{ + condition(params) { + return params.componentName === 'sharedIdSystem' + }, + allow: true + }] + }, + transmitEids: { + rules: [{ + allow: true + }, + … see other activities in https://docs.prebid.org/dev-docs/activity-controls.html … + } + }); +``` + +## Further Reading + +* [FAQ: How does Prebid.js support privacy regulations](/dev-docs/faq.html#how-does-prebid-support-privacy-regulations) diff --git a/dev-docs/add-rtd-submodule.md b/dev-docs/add-rtd-submodule.md index fa041d2086..fbf85669cf 100644 --- a/dev-docs/add-rtd-submodule.md +++ b/dev-docs/add-rtd-submodule.md @@ -6,16 +6,17 @@ sidebarType: 1 --- # How to Add a Real Time Data Submodule + {:.no_toc} Sub-modules interact with the Real-Time Data (RTD) core module to add data to bid requests or add targeting values for the primary ad server. - * TOC {:toc } ## Overview + The point of the Real Time Data (RTD) infrastructure is to make configuration consistent for publishers. Rather than having dozens of different modules with disparate config approaches, being a Real-Time Data sub-module means plugging into a framework for publishers to control how sub-modules behave. For example, publishers can define how long the auction can be delayed and give some sub-modules priority over others. @@ -40,13 +41,13 @@ Here is the flow for how the RTD-core module interacts with its sub-modules: The activities performed by the RTD-core module are on the left-hand side, while the functions that can be provided by your RTD sub-module are on the right-hand side. Note that you don't need to implement all of the functions - you'll want to plan out your functionality and develop the appropriate functions. - ## Creating a Sub-Module When you create a Real-Time Data sub-module, you will be operating under the umbrella of the Real-Time Data core module. Here are the services core provides: -- your sub-module will be initialized as soon as pbjs.setConfig({realTimeData}) is called. If you can initialize at the time of code load, that can be done at the bottom of your javascript file. -- whenever any of your functions is called, it will be passed the config params provided by the publisher. As a result, you should not call getConfig(). -- your functions will also be passed all available privacy information. As a result, you do not need to query to get GDPR, US Privacy, or any other consent parameters. + +* your sub-module will be initialized as soon as pbjs.setConfig({realTimeData}) is called. If you can initialize at the time of code load, that can be done at the bottom of your javascript file. +* whenever any of your functions is called, it will be passed the config params provided by the publisher. As a result, you should not call getConfig(). +* your functions will also be passed all available privacy information. As a result, you do not need to query to get GDPR, US Privacy, or any other consent parameters. Working with any Prebid project requires using Github. In general, we recommend the same basic workflow for any project: @@ -65,7 +66,8 @@ with the [module rules](/dev-docs/module-rules.html) that apply globally and to Create a markdown file under `modules` with the name of the module suffixed with 'RtdProvider', e.g., `exRtdProvider.md` Example markdown file: -{% highlight text %} + +```md # Overview Module Name: Ex Rtd Provider @@ -76,7 +78,7 @@ Maintainer: prebid@example.com RTD provider for Example.com. Contact prebid@example.com for information. -{% endhighlight %} +``` ### Step 2: Build the Module @@ -90,41 +92,45 @@ In order to let RTD-core know where to find the functions in your sub-module, cr | param name | type | Scope | Description | Params | | :------------ | :------------ | :------ | :------ | :------ | | name | string | required | must match the name provided by the publisher in the on-page config | n/a | -| init | function | required | defines the function that does any auction-level initialization required | config, userConsent | -| getTargetingData | function | optional | defines a function that provides ad server targeting data to RTD-core | adUnitArray, config, userConsent | -| getBidRequestData | function | optional | defines a function that provides bid request data to RTD-core | reqBidsConfigObj, callback, config, userConsent | -| onAuctionInitEvent | function | optional | listens to the AUCTION_INIT event and calls a sub-module function that lets it inspect and/or update the auction | auctionDetails, config, userConsent | -| onAuctionEndEvent | function |optional | listens to the AUCTION_END event and calls a sub-module function that lets it know when auction is done | auctionDetails, config, userConsent | -| onBidRequestEvent | function |optional | listens to the BID_REQUESTED event and calls a sub-module function that lets it know when a bid is about to be requested | bidRequest, config, userConsent | -| onBidResponseEvent | function |optional | listens to the BID_RESPONSE event and calls a sub-module function that lets it know when a bid response has been collected | bidResponse, config, userConsent | +| gvlid | number | optional | global vendor list ID for your submodule | n/a | +| init | function | required | defines the function that does any auction-level initialization required | config, userConsent | +| getTargetingData | function | optional | defines a function that provides ad server targeting data to RTD-core | adUnitArray, config, userConsent | +| getBidRequestData | function | optional | defines a function that provides bid request data to RTD-core | reqBidsConfigObj, callback, config, userConsent | +| onAuctionInitEvent | function | optional | listens to the AUCTION_INIT event and calls a sub-module function that lets it inspect and/or update the auction | auctionDetails, config, userConsent | +| onAuctionEndEvent | function |optional | listens to the AUCTION_END event and calls a sub-module function that lets it know when auction is done | auctionDetails, config, userConsent | +| onBidRequestEvent | function |optional | listens to the BID_REQUESTED event and calls a sub-module function that lets it know when a bid is about to be requested | bidRequest, config, userConsent | +| onBidResponseEvent | function |optional | listens to the BID_RESPONSE event and calls a sub-module function that lets it know when a bid response has been collected | bidResponse, config, userConsent | For example: -{% highlight text %} + +```javascript export const subModuleObj = { name: 'ExampleRTDModule', init: init, getTargetingData: sendDataToModule }; -{% endhighlight %} +``` #### Register the submodule Register submodule to RTD-core: -{% highlight text %} +```javascript submodule('realTimeData', subModuleObject); -{% endhighlight %} +``` #### User Consent Several of the interfaces get a `userConsent` object. It's an object that carries these attributes: -- [gdpr](/dev-docs/modules/consentManagement.html#bidder-adapter-gdpr-integration) - GDPR -- [usp](/dev-docs/modules/consentManagementUsp.html#bidder-adapter-us-privacy-integration) - US Privacy (aka CCPA) -- [coppa](/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa) - the Child Online Privacy Protection Act + +* [gdpr](/dev-docs/modules/consentManagement.html#bidder-adapter-gdpr-integration) - GDPR +* [usp](/dev-docs/modules/consentManagementUsp.html#bidder-adapter-us-privacy-integration) - US Privacy (aka CCPA) +* [coppa](/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa) - the Child Online Privacy Protection Act These are provided so you can do the right thing with respect to regulations. The only privacy requirement imposed by the RTD-core is that sub-modules make make use of the StorageManager instead of attempting to access cookies or localstorage directly. #### The init() function + 1. This function receives module configuration and userConsent parameters 2. If the function returns `false`, the submodule will be ignored. @@ -136,7 +142,8 @@ This is the function that will allow RTD sub-modules to merge ad server targetin 1. RTD-core will call this function with an array of adUnits, config, and userConsent as parameters 2. Your sub-module should respond with per-adslot data that should be set as key values on the ad server targeting in this format: -{% highlight text %} + +```json { "slotA":{ "p":0.56, // ad server targeting variable (e.g. p) for slotA is 0.56 @@ -145,11 +152,11 @@ This is the function that will allow RTD sub-modules to merge ad server targetin "p":0.824, // ad server targeting variable (e.g. p) for slotB is 0.824 } } -{% endhighlight %} +``` **Code Example** -{% highlight text %} +```javascript /** @type {RtdSubmodule} */ export const subModuleObj = { name: 'ExampleRTDModule', @@ -169,32 +176,49 @@ function returnTargetingData(adUnits, config, userConsent) { } submodule('realTimeData', subModuleObj); -{% endhighlight %} +``` #### getBidRequestData This is the function that will allow RTD sub-modules to modify the AdUnit object for each auction. It's called as part of the requestBids hook. 1. RTD-core will call this function with: - - reqBidsConfigObj: the object that's passed to [`pbjs.requestBids`](). Note that several auctions can happen concurrently, so the sub-module must be ready to support this. - - callback: lets RTD-core know which auction the sub-module is done with. - - config: the sub-module's config params provided by the publisher - - userConsent object (see above) + 1. reqBidsConfigObj: a slightly modified version of the object that's passed to `pbjs.requestBids` (see [below](#reqBidsConfigObj)). Note that several auctions can happen concurrently, so the sub-module must be ready to support this. + 2. callback: lets RTD-core know which auction the sub-module is done with. + 3. config: the sub-module's config params provided by the publisher + 4. userConsent object (see above) 2. Your sub-module may update the reqBidsConfigObj and hit the callback. To inject data into the bid requests, you should follow one of these conventions: - - Recommended: use one of these [First Party Data](/features/firstPartyData.html) conventions: - - For AdUnit-specific first party data, set AdUnit.fpd.context.data.ATTRIBUTES - - For global first party data, call 'pbjs.[getConfig](/dev-docs/publisher-api-reference/setConfig.html)({fpd.context})' or 'pbjs.getConfig({fpd.user})', merge in the new global data, and update with `pbjs.[setConfig](/dev-docs/publisher-api-reference/setConfig.html)()'. - - If the data is not meant to go to all bidders, the module should use 'pbjs.[setBidderConfig](/dev-docs/publisher-api-reference/setBidderConfig.html)()' and support a parameter to allow the publisher to define which bidders are to receive the data. - - Not recommended: Place your data in bidRequest.rtd.RTDPROVIDERCODE.ATTRIBUTES and then get individual adapters to specifically read that location. Note that this method won't pass data to Prebid Server adapters. + 1. Recommended: use one of these [First Party Data](/features/firstPartyData.html) conventions: + 1. For AdUnit-specific first party data, set AdUnit.ortb2Imp.ext.data.ATTRIBUTES + 2. For global first party data, including bidder-specific data, modify the `reqBidsConfigObj` as shown [below](#reqBidsConfigObj) + 2. Not recommended: Place your data in bidRequest.rtd.RTDPROVIDERCODE.ATTRIBUTES and then get individual adapters to specifically read that location. Note that this method won't pass data to Prebid Server adapters. + + + +The `reqBidsConfigObj` parameter is a copy of the object passed to [`requestBids`](/dev-docs/publisher-api-reference/requestBids.html), except for: + +* `adUnits` and `timeout` are always defined (if the publisher didn't provide them, the default values are filled in - `pbjs.adUnits` and `getConfig('bidderTimeout')` respectively) +* `ortb2` is replaced with an `ortb2Fragments` object, intended to be inspected and / or modified by your module. + +The `ortb2Fragments` parameter is an object containing two properties: + +* `global`, an object containing global (not bidder-specific) first party data in the same OpenRTB format used by `setConfig({ortb2})` +* `bidder`, a map from bidder code to bidder-specific, OpenRTB-formatted first party data. + +Your module may modify either or both with additional data. If adding bidder-specific data in `ortb2Fragments.bidder`, it should also support a parameter to allow the publisher to define which bidders are to receive the data. + +{: .alert.alert-warning :} +Before version 7, the pattern for first party data inspection and enrichment by RTD modules was `getConfig({ortb2])` / `mergeConfig({ortb2})`. With the introduction of [auction-specific data](/features/firstPartyData.html#supplying-auction-specific-data) in 7, the global `getConfig('ortb2')` is "frozen" +at the time `requestBids` is called, and RTD submodules that wish to modify it are required to work on `ortb2Fragments` instead - as any additional call to `mergeConfig` will only take effect on the *next* auction. **Code Example** -{% highlight text %} +```javascript /** @type {RtdSubmodule} */ export const subModuleObj = { name: 'ExampleRTDModule2', init: init, - setBidRequestsData: alterBidRequests + getBidRequestData: alterBidRequests }; function init(config, userConsent) { @@ -205,18 +229,25 @@ function init(config, userConsent) { function alterBidRequests(reqBidsConfigObj, callback, config, userConsent) { // do stuff - // put data in AdUnit.fpd.* or rtd.RTDPROVIDERCODE.* + // put data in adUnits' ortb2Imp: + reqBidsConfigObj.adUnits.forEach((adUnit) => mergeDeep(adUnit, 'ortb2Imp.ext', myCustomData); + // or in global first party data: + mergeDeep(reqBidsConfigObj.ortb2Fragments.global, myCustomData); + // or in bidder-specific first party data: + config.bidders.forEach((bidderCode) => mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, {[bidderCode]: myCustomData}); callback(); } submodule('realTimeData', subModuleObj); -{% endhighlight %} +``` #### beforeInit + 1. Use this function to take action to make sure data will be served as soon as possible (AJAX calls, pixels, etc..) 2. This function is **not** invoked by the RTD module, and should be invoked at the bottom of the submodule. #### Using event listeners + 1. The RTD-core module listens for 3 events - `AUCTION_INIT`, `AUCTION_END`, and `BID_RESPONSE`. 2. Each time one of the events fires, RTD-core will invoke the corresponding function on each sub-module, allowing the sub-module to make changes to the event object. 3. To use this on your sub-module, define the required functions as noted in the table above and the examples below. @@ -224,7 +255,8 @@ submodule('realTimeData', subModuleObj); **Code Example** Here is a code example with both mandatory and optional functions: -{% highlight text %} + +```javascript /** @type {RtdSubmodule} */ export const subModuleObj = { name: 'ExampleRTDModule3', @@ -263,8 +295,7 @@ function beforeInit(){ } beforeInit(); -{% endhighlight %} - +``` ### Step 3: Add unit tests @@ -282,7 +313,7 @@ Once everything looks good, submit the code, tests, and markdown as a pull reque 2. Create a new file for your RTD sub-module in dev-docs/modules/ExampleRtdProvider.md. Take a look at the other *RtdProvider.md files in that directory for the important header values. Specifically it requires the following: - ``` + ```markdown --- layout: page_v2 title: Example Module @@ -299,6 +330,7 @@ Once everything looks good, submit the code, tests, and markdown as a pull reque [Useful publisher-facing documentation] ``` + 3. Submit the pull request to the prebid.github.io repo. ### Step 6: Wait for Prebid volunteers to review diff --git a/dev-docs/add-video-submodule.md b/dev-docs/add-video-submodule.md new file mode 100644 index 0000000000..81aadb6eda --- /dev/null +++ b/dev-docs/add-video-submodule.md @@ -0,0 +1,180 @@ +--- +layout: page_v2 +title: How to Add a Prebid.js Video submodule +description: How to Add a Prebid.js Video submodule +sidebarType: 1 +--- + +# How to Add a Video Submodule + +{:.no_toc} + +Video submodules interact with the Video Module to integrate Prebid with Video Players, allowing Prebid to automatically: + +* render bids in the desired video player. +* mark used bids as won. +* trigger player and media events. +* populate the oRTB Video Impression and Content params in the bid request. + +* TOC +{:toc } + +## Overview + +The Prebid Video Module simplifies the way Prebid integrates with video players by acting as a single point of contact for everything video. +In order for the Video Module to connect to a video player, a submodule must be implemented. The submodule acts as a bridge between the Video Module and the video player. +The Video Module will route commands and tasks to the appropriate submodule instance. +A submodule is expected to work for a specific video player. i.e. the JW Player submodule is used to integrate Prebid with JW Player. The video.js submdule connects to video.js. +Publishers who use players from different vendors on the same page can use multiple video submodules. + +## Requirements + +The Video Module only supports integration with Video Players that meet the following requirements: + +* Must support parsing and reproduction of VAST ads. + * Input can be an ad tag URL or the actual Vast XML. +* Must expose an API that allows the procurement of [Open RTB params](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for Video (section 3.2.7) and Content (section 3.2.16). +* Must emit javascript events for Ads and Media. + * see [Event Registration](#event-registration). + +## Creating a Submodule + +Working with any Prebid project requires using Github. In general, we recommend the same basic workflow for any project: + +1. Fork the appropriate Prebid repository (e.g. [Prebid.js](https://github.com/prebid/Prebid.js)). +2. Create a branch in your fork for your proposed code change (e.g. feature/exampleVideoProvider). +3. Build and test your feature/bug fix in the branch. +4. Open a [pull request](https://help.github.com/en/desktop/contributing-to-projects/creating-a-pull-request) to the appropriate repository's master branch with a good description of the feature/bug fix. +5. If there's something that needs to change on the prebid.org website, follow the above steps for the [website repo](https://github.com/prebid/prebid.github.io). + +### Step 1: Add a Markdown File Describing the Submodule + +Create a markdown file under `modules` with the name of the module suffixed with 'VideoProvider', i.e. `exampleVideoProvider.md`. + +Example markdown file: + +```md +# Overview + +Module Name: Example Video Provider +Module Type: Video Submodule +Video Player: Example player +Player website: example-player.com +Maintainer: someone@example.com + +# Description + +Video provider for Example Player. Contact someone@example.com for information. + +# Requirements + +Your page must link the Example Player build from our CDN. Alternatively you can use npm to load the build. + +``` + +### Step 2: Add a Vendor Code + +Vendor codes are required to indicate which submodule type to instantiate. Add your vendor code constant to an export const in `vendorCodes.js` in Prebid.js under `libraries/video/constants/vendorCodes.js`. +i.e. in `vendorCodes.js`: + +```javascript +export const EXAMPLE_PLAYER_VENDOR = 3; +``` + +### Step 3: Build the Module + +Now create a javascript file under `modules` with the name of the module suffixed with 'VideoProvider', e.g., `exampleVideoProvider.js`. + +#### The Submodule factory + +The Video Module will need a submodule instance for every player instance registered with Prebid. You will therefore need to implement a submodule factory which is called with a `videoProviderConfig` argument and returns a Video Provider instance. +Your submodule should import your vendor code constant and set it to a `vendorCode` property on your submodule factory. +Your submodule should also import the `submodule` function from `src/hook.js` and should use it to register as a submodule of `'video'`. + +**Code Example** + +```javascript +import { submodule } from '../src/hook.js'; + +function exampleSubmoduleFactory(videoProviderConfig) { + const videoProvider = { + // implementation + }; + + return videoProvider; +} + +exampleSubmoduleFactory.vendorCode = EXAMPLE_VENDOR; +submodule('video', exampleSubmoduleFactory); +``` + +#### The Submodule object + +The submodule object must adhere to the following interface: + +{: .table .table-bordered .table-striped } +| param name | type | Scope | Description | Arguments | Return type | +| :---------- | :---- | :---- | :---------- | :-------- | :---------- | +| init | function | required | Initializes the submodule and the video player, if not already instantiated. | n/a | void | +| getId | function | required | Returns the divId (unique identifier) of the associated video player. | n/a | string | +| getOrtbVideo | function | required | Returns the oRTB Video object for the associated video player. See [oRTB spec’s](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) video section 3.2.7. | n/a | object | +| getOrtbContent | function | required | Returns the oRTB Content object for the associated video player and its media's metadata. See [oRTB spec’s](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) content section 3.2.16. | n/a | object | +| setAdTagUrl | function | required | Requests that the video player load and begin playing the given ad tag url. | adTagUrl: string | void | +| onEvent | function | required | Registers event listeners for the given event strings to the player instance. | externalEventName: string, callback: function, basePayload: object | void | +| offEvent | function | required | Removes event listeners for the given event strings to the player instance. | event: string, callback: function | void | +| destroy | function | required | Deallocates the submodule and destroys the associated video player. n/a | void | void | + +For example: + +```javascript +const exampleSubmodule = { + init: init, + getId: getId, + getOrtbVideo: getOrtbVideo, + getOrtbContent: getOrtbContent, + setAdTagUrl: setAdTagUrl, + onEvent: onEvent, + offEvent: offEvent, + destroy: destroy +}; +``` + + + +#### Event Registration + +Submodules must support attaching and detaching event listeners on the video player. The list of events and their respective params are defined in the [Video Module docs's Events section]({{site.github.url}}/prebid-video/video-module.html#events). + +##### onEvent + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| event | string | Name of event for which the listener should be added | +| callback | function | Function that will get called when the event is triggered. The function will be called with a payload argument containing metadata for the event | +| basePayload | object | Base payload for every event; includes common parameters such as divId and type. The event payload should be built on top of this | + +##### offEvent + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| event | string | name of event for which the attached listener should be removed | +| callback | function | function that was assigned as a callback when the listener was added | + +#### Update .submodules.json + +In prebid.js, add your new submodule to `.submodules.json` under the `videoModule` as such: + +```json +{ + "parentModules": { + "videoModule": [ + "exampleVideoProvider" + ] + } +} +``` + +## Shared Resources for Developers + +A video library containing reusable code and constants has been added to Prebid.js for your convenience. We encourage you to import from this library. +Constants such as event names can be found in the `libraries/video/constants/` folder. diff --git a/dev-docs/adfusion.md b/dev-docs/adfusion.md new file mode 100644 index 0000000000..9d3c71ddbe --- /dev/null +++ b/dev-docs/adfusion.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: AdFusion +biddercode: adfusion +tcfeu_supported: true +gvl_id: 844 +usp_supported: false +coppa_supported: false +gpp_supported: false +schain_supported: false +dchain_supported: false +safeframes_ok: false +deals_supported: true +userId: all +media_types: display, video +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +sidebarType: 1 +--- + +### Note + +The AdFusion Bidding adapter requires setup from the AdFusion team. Please contact us at [prebid@adfusion.pl](mailto:prebid@adfusion.pl). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `accountId` | required | The account ID provided by AdFusion | `1234` | `number` | diff --git a/dev-docs/adunit-reference.md b/dev-docs/adunit-reference.md index 266ca9b6c0..b745357059 100644 --- a/dev-docs/adunit-reference.md +++ b/dev-docs/adunit-reference.md @@ -6,18 +6,19 @@ sidebarType: 1 --- # Ad Unit Reference + {:.no_toc} The ad unit object is where you configure what kinds of ads you will show in a given ad slot on your page, including: -+ Allowed media types (e.g., banner, native, and/or video) -+ Allowed sizes -+ AdUnit-specific first party data +* Allowed media types (e.g., banner, native, and/or video) +* Allowed sizes +* AdUnit-specific first party data It's also where you will configure bidders, e.g.: -+ Which bidders are allowed to bid for that ad slot -+ What information is passed to those bidders via their [parameters]({{site.baseurl}}/dev-docs/bidders.html) +* Which bidders are allowed to bid for that ad slot +* What information is passed to those bidders via their [parameters]({{site.baseurl}}/dev-docs/bidders.html) This page describes the properties of the `adUnit` object. @@ -32,28 +33,36 @@ See the table below for the list of properties on the ad unit. For example ad u | Name | Scope | Type | Description | |--------------+----------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `code` | Required | String | An identifier you create and assign to this ad unit. Generally this is set to the ad slot name or the div element ID. Used by [setTargetingForGPTAsync()](/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) to match which auction is for which ad slot. | -| `sizes` | Required | Array[Number] or Array[Array[Number]] | All sizes this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. For 1.0 and later, define sizes within the appropriate `mediaTypes.{banner,native,video}` object. | -| `bids` | Required | Array[Object] | Array of bid objects representing demand partners and associated parameters for a given ad unit. See [Bids](#adUnit.bids) below. | +| `bids` | Optional | Array[Object] | Array of bid objects representing demand partners and associated parameters for a given ad unit. See [Bids](#adUnit.bids) below. | | `mediaTypes` | Optional | Object | Defines one or more media types that can serve into the ad unit. For a list of properties, see [`adUnit.mediaTypes`](#adUnit.mediaTypes) below. | | `labelAny` | Optional | Array[String] | Used for [conditional ads][conditionalAds]. Works with `sizeConfig` argument to [pbjs.setConfig][configureResponsive]. | | `labelAll` | Optional | Array[String] | Used for [conditional ads][conditionalAds]. Works with `sizeConfig` argument to [pbjs.setConfig][configureResponsive]. | -| `ortb2Imp` | Optional | Object | ortb2Imp is used to signal OpenRTB Imp objects at the adUnit grain. Similar to the global ortb2 field used for [global first party data configuration](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd), but specific to this adunit. The ortb2Imp object currently supports [first party data](#adUnit-fpd-example) including the [Prebid Ad Slot](/features/pbAdSlot.html) and the [interstitial](#adUnit-interstitial-example) signal. | +| `ortb2Imp` | Optional | Object | ortb2Imp is used to signal OpenRTB Imp objects at the adUnit grain. Similar to the global ortb2 field used for [global first party data configuration](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd), but specific to this adunit.| +| `ttlBuffer` | Optional | Number | TTL buffer override for this adUnit. See [setConfig({ttlBuffer})](/dev-docs/publisher-api-reference/setConfig.html#setConfig-ttlBuffer) | +| `renderer` | Optional | Object | Custom renderer, typically used for [outstream video](/dev-docs/show-outstream-video-ads.html) | +| `video` | Optional | Object | Used to link an Ad Unit to the [Video Module][videoModule]. For allowed params see the [adUnit.video reference](#adunitvideo). | +| `deferBilling` | Optional | Boolean | Used by a publisher to flag adUnits as being separately billable. This allows for a publisher to trigger billing manually for winning bids. See [pbjs.triggerBilling](/dev-docs/publisher-api-reference/triggerBilling.html) and [onBidBillable](/dev-docs/bidder-adaptor.html#registering-on-bid-billable) for more info. | - + ### adUnit.bids See the table below for the list of properties in the `bids` array of the ad unit. For example ad units, see the [Examples](#adUnit-examples) below. +Note that `bids` is optional only for [Prebid Server stored impressions](#stored-imp), and required in all other cases. + {: .table .table-bordered .table-striped } | Name | Scope | Type | Description | |------------+----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------| -| `bidder` | Required | String | Unique code identifying the bidder. For bidder codes, see the [bidder param reference]({{site.baseurl}}/dev-docs/bidders.html). | +| `bidder` | Optional | String | Unique code identifying the bidder. For bidder codes, see the [bidder param reference]({{site.baseurl}}/dev-docs/bidders.html). | +| `module` | Optional | String | Module code - for requesting bids from modules that are not bid adapters. See [Prebid Server stored impressions](#stored-imp). | | `params` | Required | Object | Bid request parameters for a given bidder. For allowed params, see the [bidder param reference]({{site.baseurl}}/dev-docs/bidders.html). | | `labelAny` | Optional | Array[String] | Used for [conditional ads][conditionalAds]. Works with `sizeConfig` argument to [pbjs.setConfig][configureResponsive]. | | `labelAll` | Optional | Array[String] | Used for [conditional ads][conditionalAds]. Works with `sizeConfig` argument to [pbjs.setConfig][configureResponsive]. | +| `ortb2Imp` | Optional | Object | OpenRTB first-party data specific to this bidder. This is merged with, and takes precedence over, `adUnit.ortb2Imp`.| +| `renderer` | Optional | Object | Custom renderer. Takes precedence over `adUnit.renderer`, but applies only to this bidder. | - + ### adUnit.mediaTypes @@ -66,119 +75,26 @@ See the table below for the list of properties in the `mediaTypes` object of the | [`native`](#adUnit.mediaTypes.native) | At least one of the `banner`, `native`, or `video` objects are required. | Object | Defines properties of a native ad. For properties, see [`adUnit.mediaTypes.native`](#adUnit.mediaTypes.native). | | [`video`](#adUnit.mediaTypes.video) | At least one of the `banner`, `native`, or `video` objects are required. | Object | Defines properties of a video ad. For examples, see [`adUnit.mediaTypes.video`](#adUnit.mediaTypes.video). | - + #### adUnit.mediaTypes.banner {: .table .table-bordered .table-striped } | Name | Scope | Type | Description | |---------+----------+---------------------------------------+-----------------------------------------------------------------------------------------| -| `sizes` | Required | Array[Number] or Array[Array[Number]] | All sizes this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. | +| `sizes` | Required | Array[Number] or Array[Array[Number]] | All sizes this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. Prebid recommends that the sizes auctioned by Prebid should be the same auctioned by AdX and GAM OpenBidding, which means AdUnit sizes should match the GPT sizes. | | `pos` | Optional | Integer | OpenRTB page position value: 0=unknown, 1=above-the-fold, 3=below-the-fold, 4=header, 5=footer, 6=sidebar, 7=full-screen | | `name` | Optional | String | Name for this banner ad unit. Can be used for testing and debugging. | - + #### adUnit.mediaTypes.native -The `native` object contains the following properties that correspond to the assets of the native ad. - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|---------------+----------+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `type` | Optional | String | A [pre-defined native type]({{site.baseurl}}/dev-docs/show-native-ads.html#pre-defined-native-types) used as a shorthand, e.g., `type: 'image'` implies required fields `image`, `title`, `sponsoredBy`, `clickUrl`. | -| `title` | Optional | Object | The title object is to be used for the title element of the native ad. For properties, see [`native.title`](#adUnit.mediaTypes.native.title). | -| `body` | Optional | Object | The body object is to be used for the body element of the native ad. For properties, see [`native.body`](#adUnit.mediaTypes.native.body). | -| `sponsoredBy` | Optional | Object | The name of the brand associated with the ad. For properties, see [`native.sponsoredBy`](#adUnit.mediaTypes.native.sponsoredby). | -| `icon` | Optional | Object | The brand icon that will appear with the ad. For properties, see [`native.icon`](#adUnit.mediaTypes.native.icon). | -| `image` | Optional | Object | The image object is to be used for the main image of the native ad. For properties, see [`native.image`](#adUnit.mediaTypes.native.image). | -| `clickUrl` | Optional | Object | Where the user will end up if they click the ad. For properties, see [`native.clickUrl`](#adUnit.mediaTypes.native.clickUrl). | -| `cta` | Optional | String | *Call to Action* text, e.g., "Click here for more information". | - - - -##### adUnit.mediaTypes.native.image - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|-----------------+----------+---------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------| -| `required` | Optional | Boolean | Whether this asset is required. | -| `sizes` | Optional | Array[Number] or Array[Array[Number]] | All sizes this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. | -| `aspect_ratios` | Optional | Array[Object] | Alongside `sizes`, you can define allowed aspect ratios. For properties, see [`image.aspect_ratios`](#adUnit.mediaTypes.native.image.aspect_ratios). | - - - -###### adUnit.mediaTypes.native.image.aspect_ratios - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|----------------+----------+---------+------------------------------------------------------------------------------------------------------| -| `min_height` | Optional | Integer | The minimum height required for an image to serve (in pixels). | -| `min_width` | Optional | Integer | The minimum width required for an image to serve (in pixels). | -| `ratio_height` | Required | Integer | This, combined with `ratio_width`, determines the required aspect ratio for an image that can serve. | -| `ratio_width` | Required | Integer | See above. | - - - -##### adUnit.mediaTypes.native.title - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|------------+----------+---------+------------------------------------------------------| -| `required` | Optional | Boolean | Whether a title asset is required on this native ad. | -| `len` | Optional | Integer | Maximum length of title text, in characters. | - - - -##### adUnit.mediaTypes.native.sponsoredBy - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|------------+----------+---------+-----------------------------------------------------------| -| `required` | Optional | Boolean | Whether a brand name asset is required on this native ad. | - - - -##### adUnit.mediaTypes.native.clickUrl - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|------------+----------+---------+----------------------------------------------------------| -| `required` | Optional | Boolean | Whether a click URL asset is required on this native ad. | - - - -##### adUnit.mediaTypes.native.body - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|------------+----------+---------+---------------------------------------------------| -| `required` | Optional | Boolean | Whether body text is required for this native ad. | -| `len` | Optional | Integer | Maximum length of body text, in characters. | - - +The `native` object contains properties that correspond to the assets of the native ad. -##### adUnit.mediaTypes.native.icon - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|-----------------+----------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------| -| `required` | Optional | Boolean | Whether an icon asset is required on this ad. | -| `sizes` | Optional | Array[Number] or Array[Array[Number]] | All sizes this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. | -| `aspect_ratios` | Optional | Array[Object] | Instead of `sizes`, you can define allowed aspect ratios. For properties, see [`icon.aspect_ratios`](#adUnit.mediaTypes.native.icon.aspect_ratios). | - - - -###### adUnit.mediaTypes.native.icon.aspect_ratios - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | -|----------------+----------+---------+------------------------------------------------------------------------------------------------------| -| `min_width` | Optional | Integer | The minimum width required for an image to serve (in pixels). | -| `ratio_height` | Required | Integer | This, combined with `ratio_width`, determines the required aspect ratio for an image that can serve. | -| `ratio_width` | Required | Integer | See above. | +See [Prebid Native Implementation](/prebid/native-implementation.html) for details. - + #### adUnit.mediaTypes.video @@ -187,31 +103,28 @@ The `native` object contains the following properties that correspond to the ass |------------------+-------------+------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `pos` | Optional | Integer | OpenRTB page position value: 0=unknown, 1=above-the-fold, 3=below-the-fold, 4=header, 5=footer, 6=sidebar, 7=full-screen | | `context` | Recommended | String | The video context, either `'instream'`, `'outstream'`, or `'adpod'` (for long-form videos). Example: `context: 'outstream'`. Defaults to 'instream'. | +| `useCacheKey` | Optional | Boolean | Defaults to `false`. While context `'instream'` always will return an vastUrl in bidResponse, `'outstream'` will not. Setting this `true` will use cache url defined in global options also for outstream responses. | | `placement` | Recommended | Integer | 1=in-stream, 2=in-banner, 3=in-article, 4=in-feed, 5=interstitial/floating. **Highly recommended** because some bidders require more than context=outstream. | +| `plcmt` | Recommended | Integer | 1=in-stream, 2=accompanying content, 3=interstitial, 4=no content/standalone. **Highly recommended** to comply with new IAB video specifications. See [AdCOM v1 spec](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/develop/AdCOM%20v1.0%20FINAL.md#list_plcmtsubtypesvideo) | | `playerSize` | Optional | Array[Integer,Integer] | The size (width, height) of the video player on the page, in pixels. Example: `playerSize: [640, 480]` | -| `api` | Recommended | Array[Integer] | List of supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. For list, see [OpenRTB spec][openRTB]. | +| `api` | Recommended | Array[Integer] | List of supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. For list, see [OpenRTB 2.5 spec][openRTB]. If your video player or video ads SDK supports [Open Measurement][OpenMeasurement], **recommended** to set `7` for OMID-1| | `mimes` | Recommended | Array[String] | Content MIME types supported, e.g., `"video/x-ms-wmv"`, `"video/mp4"`. **Required by OpenRTB when using [Prebid Server][pbServer]**. | -| `protocols` | Optional | Array[Integer] | Array of supported video protocols. For list, see [OpenRTB spec][openRTB]. **Required by OpenRTB when using [Prebid Server][pbServer]**. | -| `playbackmethod` | Optional | Array[Integer] | Allowed playback methods. If none specified, all are allowed. For list, see [OpenRTB spec][openRTB]. **Required by OpenRTB when using [Prebid Server][pbServer]**. | -| `minduration` | Recommended | Integer | Minimum video ad duration in seconds, see [OpenRTB spec][openRTB]. | -| `maxduration` | Recommended | Integer | Maximum video ad duration in seconds, see [OpenRTB spec][openRTB]. | -| `w` | Recommended | Integer | -Width of the video player in device independent pixels (DIPS)., see [OpenRTB spec][openRTB]. | -| `h` | Recommended | Integer | Height of the video player in device independent pixels (DIPS)., see [OpenRTB spec][openRTB]. | -| `startdelay` | Recommended | Integer | Indicates the start delay in seconds, see [OpenRTB spec][openRTB]. | -| `placement` | Optional | Integer | Placement type for the impression, see [OpenRTB spec][openRTB]. | -| `linearity` | Optional | Integer | Indicates if the impression must be linear, nonlinear, etc, see [OpenRTB spec][openRTB]. | -| `skip` | Optional | Integer | Indicates if the player will allow the video to be skipped, -where 0 = no, 1 = yes., see [OpenRTB spec][openRTB]. | -| `skipmin` | Optional | Integer | Videos of total duration greater than this number of seconds -can be skippable; only applicable if the ad is skippable., see [OpenRTB spec][openRTB]. | -| `skipafter` | Optional | Integer | Number of seconds a video must play before skipping is -enabled; only applicable if the ad is skippable., see [OpenRTB spec][openRTB]. | -| `minbitrate` | Optional | Integer | Minimum bit rate in Kbps., see [OpenRTB spec][openRTB]. | -| `maxbitrate` | Optional | Integer | Maximum bit rate in Kbps., see [OpenRTB spec][openRTB]. | -| `delivery` | Optional | Array[Integer] | Supported delivery methods (e.g., streaming, progressive), see [OpenRTB spec][openRTB]. | -| `pos` | Optional | Integer | Ad position on screen, see [OpenRTB spec][openRTB]. | -| `playbackend` | Optional | Integer | The event that causes playback to end, see [OpenRTB spec][openRTB]. | +| `protocols` | Optional | Array[Integer] | Array of supported video protocols. For list, see [OpenRTB 2.5 spec][openRTB]. **Required by OpenRTB when using [Prebid Server][pbServer]**. | +| `playbackmethod` | Optional | Array[Integer] | Allowed playback methods. If none specified, all are allowed. For list, see [OpenRTB 2.5 spec][openRTB]. **Required by OpenRTB when using [Prebid Server][pbServer]**. | +| `minduration` | Recommended | Integer | Minimum video ad duration in seconds, see [OpenRTB 2.5 spec][openRTB]. | +| `maxduration` | Recommended | Integer | Maximum video ad duration in seconds, see [OpenRTB 2.5 spec][openRTB]. | +| `w` | Recommended | Integer | Width of the video player in device independent pixels (DIPS)., see [OpenRTB 2.5 spec][openRTB]. | +| `h` | Recommended | Integer | Height of the video player in device independent pixels (DIPS)., see [OpenRTB 2.5 spec][openRTB]. | +| `startdelay` | Recommended | Integer | Indicates the start delay in seconds, see [OpenRTB 2.5 spec][openRTB]. | +| `linearity` | Optional | Integer | Indicates if the impression must be linear, nonlinear, etc, see [OpenRTB 2.5 spec][openRTB]. | +| `skip` | Optional | Integer | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes., see [OpenRTB 2.5 spec][openRTB]. | +| `skipmin` | Optional | Integer | Videos of total duration greater than this number of seconds can be skippable; only applicable if the ad is skippable., see [OpenRTB 2.5 spec][openRTB]. | +| `skipafter` | Optional | Integer | Number of seconds a video must play before skipping is enabled; only applicable if the ad is skippable., see [OpenRTB 2.5 spec][openRTB]. | +| `minbitrate` | Optional | Integer | Minimum bit rate in Kbps., see [OpenRTB 2.5 spec][openRTB]. | +| `maxbitrate` | Optional | Integer | Maximum bit rate in Kbps., see [OpenRTB 2.5 spec][openRTB]. | +| `delivery` | Optional | Array[Integer] | Supported delivery methods (e.g., streaming, progressive), see [OpenRTB 2.5 spec][openRTB]. | +| `pos` | Optional | Integer | Ad position on screen, see [OpenRTB 2.5 spec][openRTB]. | +| `playbackend` | Optional | Integer | The event that causes playback to end, see [OpenRTB 2.5 spec][openRTB]. | If `'video.context'` is set to `'adpod'` then the following parameters are also available. @@ -228,22 +141,41 @@ If `'video.context'` is set to `'adpod'` then the following parameters are also | `contentLengthSec` | Optional | Number | A number representing the length of the video in seconds. Example: `contentLengthSec = 1` | | `contentMode` | Optional | String | A string indicating the type of content being displayed in the video player. There are two options, `live` and `on-demand`. Example: `contentMode = 'on-demand'` | + - + + +### adUnit.video + +See the table below for the list of properties in the `video` object of the ad unit. For example ad units, see the [Example](#adUnit-video-module-example) below. + +**Note:** your Ad Unit must have `mediaTypes.video` defined and your prebid instance should be configured to use the [Video Module][videoModule]. +When using the Video Module, the mediaTypes.video properties get filled out automatically. Any values already set by the Publisher will not be replaced by the Video Module. + +{: .table .table-bordered .table-striped } +| Field | Scope | Type | Description | +|----------+--------------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------| +| `divId` | required | string | Unique identifier of the player provider, used to specify which player should be used to render the ad. Equivalent to the HTML Div Id of the player. | +| `adServer` | optional | object | Configuration for ad server integration. Supersedes `video.adServer` configurations defined in the Prebid Config. | +| `adServer.vendorCode` | required if `adServer` is defined | string | The identifier of the AdServer vendor (i.e. gam, etc). | +| `adServer.baseAdTagUrl` | required if `adServer.params` is not defined | string | Your AdServer Ad Tag. The targeting params of the winning bid will be appended. | +| `adServer.params` | required if `adServer.baseAdTagUrl` is not defined | object | Querystring parameters that will be used to construct the video ad tag URL. | ## Examples -+ [Banner](#adUnit-banner-example) -+ [Video](#adUnit-video-example) - - [Instream](#adUnit-video-example-instream) - - [Outstream](#adUnit-video-example-outstream) - - [Adpod (Long-Form)](#adUnit-video-example-adpod) -+ [Native](#adUnit-native-example) -+ [Multi-Format](#adUnit-multi-format-example) -+ [Twin Codes](#adUnit-twin-codes-example) -+ [First Party Data](#adUnit-fpd-example) +* [Banner](#adUnit-banner-example) +* [Video](#adUnit-video-example) + * [With the Video Module](#adUnit-video-module-example) + * [Instream Sound-On](#adUnit-video-example-instream) + * [Accompanying Content](#adUnit-video-example-accompanying) + * [No Content/Standalone](#adUnit-video-example-outstream) + * [Adpod (Long-Form)](#adUnit-video-example-adpod) +* [Native](#adUnit-native-example) +* [Multi-Format](#adUnit-multi-format-example) +* [Twin Codes](#adUnit-twin-codes-example) +* [First Party Data](#adUnit-fpd-example) - + ### Banner @@ -268,15 +200,43 @@ pbjs.addAdUnits({ }); ``` - + ### Video - + -#### Instream +#### With the Video Module -For an example of an instream video ad unit, see below. For more detailed instructions, see [Show Video Ads]({{site.baseurl}}/dev-docs/show-video-with-a-dfp-video-tag.html). +For an example of a video ad unit linked to the Video Module, see below. For more detailed instructions see the [Video Module docs][videoModule]. + +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + video: {}, + }, + video: { + divId: 'playerDiv', + adServer: { + vendorCode: 'gam', // constant variable is GAM_VENDOR - see vendorCodes.js in the video library + baseAdTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/12345/' + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361 + } + }] +}); +``` + + + +#### Instream Sound-On + +For an example of an instream video ad unit that you handle on your own, see below. For more detailed instructions, see [Show Video Ads]({{site.baseurl}}/dev-docs/show-video-with-a-dfp-video-tag.html). ```javascript pbjs.addAdUnits({ @@ -284,10 +244,11 @@ pbjs.addAdUnits({ mediaTypes: { video: { context: 'instream', + plcmt: 1, playerSize: [640, 480], mimes: ['video/mp4'], protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], + playbackmethod: [5], skip: 1 }, }, @@ -300,11 +261,42 @@ pbjs.addAdUnits({ }); ``` - + -#### Outstream +#### Player contains video content with sound off -For an example of an outstream video ad unit, see below. For more detailed instructions, see [Show Outstream Video Ads]({{site.baseurl}}/dev-docs/show-outstream-video-ads.html). +The IAB calls this scenario "Accompanying Content". Previously, this might have been called "instream with sound-off", but as of April 2023, the IAB has reclassified this scenario. + +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + video: { + context: 'instream', + plcmt: 2, + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [6], + skip: 1 + }, + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361 + } + }] +}); +``` + + + +#### Standalone ad wit no video content + +This is the scenario formerly known as Outstream. As of April 2023, the IAB now calls this scenario "No Content/Standalone". + +For an example of an outstream video ad unit that you handle on your own, see below. For more detailed instructions, see [Show Outstream Video Ads]({{site.baseurl}}/dev-docs/show-outstream-video-ads.html). ```javascript pbjs.addAdUnits({ @@ -312,7 +304,11 @@ pbjs.addAdUnits({ mediaTypes: { video: { context: 'outstream', - playerSize: [640, 480] + plcmt: 4, + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [6], } }, renderer: { @@ -327,11 +323,42 @@ pbjs.addAdUnits({ ... }); ``` - + +An example of an outstream video ad unit using useCacheKey: + +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + video: { + context: 'outstream', + plcmt: 4, + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [6], + useCacheKey: true, + } + }, + renderer: { + url: 'https://example.com/myVastVideoPlayer.js', + render: function(bid) { + let vastUrl = bid.vastUrl; + myVastVideoPlayer.setSrc({ + src: vastUrl, + ... + }); + } + }, + ... +}); +``` + + #### Adpod (Long-Form) -For an example of an adpod video ad unit, see below. For more detailed instructions, see [Show Long-Form Video Ads]({{site.baseurl}}/prebid-video/video-long-form.html). +For an example of an adpod video ad unit that you handle on your own, see below. For more detailed instructions, see [Show Long-Form Video Ads]({{site.baseurl}}/prebid-video/video-long-form.html). ```javascript var longFormatAdUnit = { @@ -361,7 +388,7 @@ var longFormatAdUnit = { } ``` - + ### Native @@ -372,28 +399,41 @@ pbjs.addAdUnits({ code: slot.code, mediaTypes: { native: { - image: { - required: true, - sizes: [150, 50] - }, - title: { - required: true, - len: 80 - }, - sponsoredBy: { - required: true - }, - clickUrl: { - required: true - }, - body: { - required: true - }, - icon: { - required: true, - sizes: [50, 50] - } + ortb: { + ver: "1.2", + assets: [{ + required: 1, + img: { + type: 1, + hmin: 50 + }, + },{ + required: 1, + title: { + len: 80 + }, + },{ + required: 1, + data: { + type: 1, + len: 30 + }, + },{ + required: 1, + data: { + type: 2, + len: 100 + }, + },{ + required: 1, + img: { + type: 3, + hmin: 200, + wmin: 267 + } + }] } + } }, bids: [ { @@ -406,13 +446,13 @@ pbjs.addAdUnits({ }); ``` - + ### Multi-Format For an example of a multi-format ad unit, see below. For more detailed instructions, see [Show Multi-Format Ads]({{site.baseurl}}/dev-docs/show-multi-format-ads.html). -{% highlight js %} +```javascript pbjs.addAdUnits([{ code: 'div-banner-native', @@ -423,7 +463,16 @@ pbjs.addAdUnits([{ ] }, native: { - type: 'image' + ortb: { + ver: "1.2", + assets: [{ + required: 1, + img: { + type: 1, + hmin: 50 + } + }] + } }, }, bids: [{ @@ -464,7 +513,16 @@ pbjs.addAdUnits([{ ] }, native: { - type: 'image' + ortb: { + ver: "1.2", + assets: [{ + required: 1, + img: { + type: 1, + hmin: 50 + } + }] + } }, video: { context: 'outstream', @@ -480,72 +538,73 @@ pbjs.addAdUnits([{ } ]); -{% endhighlight %} +``` - + ### Twin AdUnit Codes It's ok to have multiple AdUnits with the same `code`. This can be useful in scenarios where bidders have different capabilities for the same spot on the page. e.g. -- BidderA should receive both media types, while BidderB gets only one -- BidderA gets one size while BidderB gets another +* BidderA should receive both media types, while BidderB gets only one +* BidderA gets one size while BidderB gets another In this example, bidderA gets both banner and outstream, while bidderB gets only banner. -{% highlight js %} - var adUnits = [ - { - code: 'test-div', - mediaTypes: { - video: { - context: "outstream", - playerSize: [[300,250]] + +```javascript +var adUnits = [ + { + code: 'test-div', + mediaTypes: { + video: { + context: "outstream", + playerSize: [[300,250]] + } + }, + bids: [ + { + bidder: 'bidderA', + params: { + ... } - }, - bids: [ - { - bidder: 'bidderA', - params: { - ... - } - } - ] - }, - { - code: 'test-div', - mediaTypes: { - banner: { - sizes: [[300,250],[300,600],[728,90]] + } + ] + }, + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300,250],[300,600],[728,90]] + } + }, + bids: [ + { + bidder: 'bidderB', + params: { + ... } - }, - bids: [ - { - bidder: 'bidderB', - params: { - ... - } - },{ - bidder: 'bidderA', - params: { - ... - } - } - ] - } - ]; -{% endhighlight %} + },{ + bidder: 'bidderA', + params: { + ... + } + } + ] + } + ]; +``` In this example, bidderA receives 2 bidRequest objects while bidderB receives one. If a bidder provides more than one bid for the same AdUnit.code, Prebid.js will use the highest bid when it's time to set targeting. - + ### First Party Data Example of an adunit-specific block of first party data: -{% highlight js %} +```javascript pbjs.addAdUnits({ code: "test-div", mediaTypes: { @@ -554,28 +613,29 @@ pbjs.addAdUnits({ } }, ortb2Imp: { - ext: { - data: { - pbadslot: "homepage-top-rect", - adUnitSpecificContextAttribute: "123" - } - } + ext: { + data: { + pbadslot: "homepage-top-rect", + adUnitSpecificContextAttribute: "123" + } + } }, - ... + // ... }); -{% endhighlight %} +``` Notes: -- Only contextual data should be added on the AdUnit; user-related data goes in the [global first party data](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd) config. -- For additional help with analytics and reporting you can use the [Prebid Ad Slot](/features/pbAdSlot.html), a special type of first party data. - +* Only contextual data should be added on the AdUnit; user-related data goes in the [global first party data](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd) config. +* For additional help with analytics and reporting you can use the [Prebid Ad Slot](/features/pbAdSlot.html), a special type of first party data. + + ### Interstitial Ads Example of an adunit-specific interstitial signal: -{% highlight js %} +```javascript pbjs.addAdUnits({ code: "test-div", mediaTypes: { @@ -584,31 +644,95 @@ pbjs.addAdUnits({ } }, ortb2Imp: { - instl:1 + instl:1 }, - ... + // ... }); -{% endhighlight %} +``` -For more information on Interstitial ads, reference the [Interstitial feature page](/features/InterstitialAds.html). +For more information on Interstitial ads, reference the [Interstitial feature page](/features/InterstitialAds.html). Additionally, to assist with billing optimization and interstitial ads, the triggerBilling and onBidBillable functionality can be utilized. See [pbjs.triggerBilling](/dev-docs/publisher-api-reference/triggerBilling.html) and [onBidBillable](/dev-docs/bidder-adaptor.html#registering-on-bid-billable) for more info. -## Related Topics + -+ [Publisher API Reference]({{site.baseurl}}/dev-docs/publisher-api-reference) -+ [Conditional Ad Units][conditionalAds] -+ [Show Native Ads]({{site.baseurl}}/dev-docs/show-native-ads.html) -+ [Show Video Ads]({{site.baseurl}}/dev-docs/show-video-with-a-dfp-video-tag.html) -+ [Show Outstream Video Ads]({{site.baseurl}}/dev-docs/show-outstream-video-ads.html) -+ [Show Long-Form Video Ads]({{site.baseurl}}/prebid-video/video-long-form.html) -+ [Prebid.org Video Examples]({{site.baseurl}}/examples/video/) -+ [Prebid.org Native Examples](/dev-docs//examples/native-ad-example.html) +### Prebid Server stored impressions +When using [PBS stored impressions](/dev-docs/modules/prebidServer.html#stored-imp), `bids` is not required: + +```javascript +pbjs.addAdUnits({ + code: "test-div", + ortb2Imp: { + ext: { + prebid: { + storedrequest: { + id: 'stored-request-id' + } + } + } + } +}) +``` + +To use stored impressions together with client-side bidders - or stored impressions from other instances of Prebid Server - use `bids[].module`: + +```javascript +pbjs.addAdUnits({ + code: "test-div", + bids: [ + { + module: "pbsBidAdapter", + params: { + configName: "server-1" + }, + ortb2Imp: { + ext: { + prebid: { + storedrequest: { + id: 'stored-request-server-1' + } + } + } + } + }, + { + module: "pbsBidAdapter", + params: { + configName: "server-2" + }, + ortb2Imp: { + ext: { + prebid: { + storedrequest: { + id: 'stored-request-server-2' + } + } + } + } + }, + { + bidder: 'client-bidder', + // ... + } + ] +}); +``` + +## Related Topics +* [Publisher API Reference](/dev-docs/publisher-api-reference) +* [Conditional Ad Units][conditionalAds] +* [Show Native Ads](/prebid/native-implementation.html) +* [Show Video Ads](/dev-docs/show-video-with-a-dfp-video-tag.html) +* [Show Outstream Video Ads](/dev-docs/show-outstream-video-ads.html) +* [Show Long-Form Video Ads](/prebid-video/video-long-form.html) +* [Prebid.org Video Examples](/examples/video/) +* [Prebid.org Native Examples](/dev-docs//examples/native-ad-example.html) -[conditionalAds]: {{site.baseurl}}/dev-docs/conditional-ad-units.html -[setConfig]: {{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html -[configureResponsive]: {{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads +[conditionalAds]: /dev-docs/conditional-ad-units.html +[configureResponsive]: /dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads [openRTB]: https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf -[pbServer]: {{site.baseurl}}/prebid-server/overview/prebid-server-overview.html +[pbServer]: /prebid-server/overview/prebid-server-overview.html +[OpenMeasurement]: https://iabtechlab.com/standards/open-measurement-sdk/ +[videoModule]: {{site.github.url}}/prebid-video/video-module.html diff --git a/dev-docs/adzymic.md b/dev-docs/adzymic.md new file mode 100644 index 0000000000..585db1c6ee --- /dev/null +++ b/dev-docs/adzymic.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: Adzymic +description: Adzymic Bidder Adapter +biddercode: adzymic +pbjs: true +pbs: false +aliasCode: appnexus +gdpr_supported: true +media_types: banner, video, native +safeframes_ok: false +multiformat_supported: will-bid-on-any +gvl_id: 723 +schain_supported: true +userId: all +sidebarType: 1 +--- +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementID` | required | Placement id | `'11111'` | `string` | + +Adzymic is an aliased bidder for AppNexus. + +### Note + +For setup with Adzymic, please reach out to [anil@adzymic.co](mailto:anil@adzymic.co) / [travis@adzymic.co](mailto:travis@adzymic.co) diff --git a/dev-docs/analytics-ga.md b/dev-docs/analytics-ga.md index 6e9ebaa939..e1f580e411 100644 --- a/dev-docs/analytics-ga.md +++ b/dev-docs/analytics-ga.md @@ -12,14 +12,17 @@ nav_section: reference # Prebid Analytics with GA + {: .no_toc} * TOC {:toc } -### Code Example +## Notice: Deleted in Prebid 8 with the deprecation of GA by Google + +## Code Example -{% highlight js %} +```javascript // If you're using GA, this should already be in your page: (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ @@ -38,25 +41,25 @@ pbjs.que.push(function() { }); }); -{% endhighlight %} +``` -##### A Few Requirements +### A Few Requirements 1. This code snippet has to be inserted after the `'ga'` param is available. 2. This code snippet has to be inserted after pbjs.que has been defined. 3. You must include `"ga"` in the `"analytics"` array in `package.json`. -##### Distribution Data +### Distribution Data Note: we recommend disabling `enableDistribution` if you are using more than 4 bidders. This is because GA throttles the number of events that can be logged (20 initial + 2/second). Distribution data provides you with a histogram of CPM distribution and bid load time (latency) for each bidder. See distribution data [demo here](https://prebid.org/blog/header-bidding-analytics-coming-soon/#histogram-analysis-of-latency-and-cpm-distribution). See [this link](https://developers.google.com/analytics/devguides/collection/protocol/v1/limits-quotas) for details on GA's throttling. -##### Sampling +### Sampling To track a lower volume of traffic in Google Analytics, you may specify a sample rate in the options. For example, to set up a 5% sample rate: -{% highlight js %} +```javascript pbjs.que.push(function() { pbjs.enableAnalytics({ provider: 'ga', @@ -67,34 +70,33 @@ pbjs.que.push(function() { } }); }); -{% endhighlight %} +``` -At the start of each page, Prebid chooses a random number between 0 and 1 +At the start of each page, Prebid chooses a random number between 0 and 1 and logs the analytics only if the number is less than the supplied sample rate, which defaults to 1 (100%). Of course a smaller sample rate means that reported numbers will be correspondingly lower, so a scaling factor in reports may be useful, but is outside the scope of Prebid. It should also be noted that all events on a given page are subject to the same analytics behavior. This means that all requests, responses, and renders on a page are either logged or not logged. -### How Prebid.js uses GA's Events +## How Prebid.js uses GA's Events Prebid.js sends out GA-compatible [Events](https://support.google.com/analytics/answer/1033068). (For more information, see the GA docs on [Event Tracking](https://developers.google.com/analytics/devguides/collection/analyticsjs/events)). In this example, the page has 1 ad unit with 3 bidders. The timeout is set to 400ms. Let's go through what Prebid Analytics sends out to GA: {: .table .table-bordered .table-striped } -| Time | What Happened | GA Events Sent | +| Time | What Happened | GA Events Sent | | :---- |:--------| :-------| -| 15ms | Prebid.js sends out bid requests to bidders AppNexus, OpenX, and Pubmatic. | Event 1: Category=`Prebid.js Bids`, Action=`Requests`, Label=`appnexus`, Value=1.
    Event 2: Category=`Prebid.js Bids`, Action=`Requests`, Label=`openx`, Value=1.
    Event 3: Category=`Prebid.js Bids`, Action=`Requests`, Label=`pubmatic`, Value=1 | -| 203ms | AppNexus' bid came back with a CPM of $2.314 and a latency of 188ms. | Event 1: Category=`Prebid.js Bids`, Action=`Bids`, Label=`appnexus`, Value=231.
    Event 2: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`appnexus`, Value=188 | -| 274ms | Pubmatic's bid came back with a CPM of $0 and a latency of 259ms. | No bid event sent out because it is a no bid.
    Event 1: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`appnexus`, Value=259 | +| 15ms | Prebid.js sends out bid requests to bidders AppNexus, OpenX, and Pubmatic. | Event 1: Category=`Prebid.js Bids`, Action=`Requests`, Label=`appnexus`, Value=1.
    Event 2: Category=`Prebid.js Bids`, Action=`Requests`, Label=`openx`, Value=1.
    Event 3: Category=`Prebid.js Bids`, Action=`Requests`, Label=`pubmatic`, Value=1 | +| 203ms | AppNexus' bid came back with a CPM of $2.314 and a latency of 188ms. | Event 1: Category=`Prebid.js Bids`, Action=`Bids`, Label=`appnexus`, Value=231.
    Event 2: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`appnexus`, Value=188 | +| 274ms | Pubmatic's bid came back with a CPM of $0 and a latency of 259ms. | No bid event sent out because it is a no bid.
    Event 1: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`appnexus`, Value=259 | | 415ms | Timeout is up because 400ms has passed since bid requests were sent. OpenX has timed out. | Event 1: Category=`Prebid.js Bids`, Action=`Timeouts`, Label=`openx`, Value=1 | -| 476ms | OpenX's bid came back with a CPM of $2.831 and a latency of 461ms (a bid may still come back after a timeout). | Event 1: Category=`Prebid.js Bids`, Action=`Bids`, Label=`openx`, Value=283.
    Event 2: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`openx`, Value=461 | +| 476ms | OpenX's bid came back with a CPM of $2.831 and a latency of 461ms (a bid may still come back after a timeout). | Event 1: Category=`Prebid.js Bids`, Action=`Bids`, Label=`openx`, Value=283.
    Event 2: Category=`Prebid.js Bids`, Action=`Bid Load Time`, Label=`openx`, Value=461 | | 572ms | Google Ad Manager completed its auction and the AppNexus $2.314 bid won. | Event 3: Category=`Prebid.js Bids`, Action=`Wins`, Label=`appnexus`, Value=231 | - Note that a Win event is a true win, meaning that it is not just the highest bid in the header bidding auction, but the winning bid across the entire auction hosted by the ad server and its creative is served back to the page. -### How to Verify it Works +## How to Verify it Works After you've implemented the above code snippet, load the page a few times, wait 1-2 hours for GA's data pipeline to finish, and go to your GA Reporting screen. Navigate to **Behavior > Events**. You should be able to find the Prebid.js events (if you have many other events, filter **Event Category** by `Prebid.js`) @@ -102,28 +104,28 @@ After you've implemented the above code snippet, load the page a few times, wait ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/GA-event-categories.png) -
    +
    **GA Action:** ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/GA-event-actions.png) -
    +
    **GA Label:** ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/GA-event-labels.png) -As you can see, this reporting screen cannot help you answer questions such as: +As you can see, this reporting screen cannot help you answer questions such as: -+ What's the AppNexus bidder's avg. bid CPM -+ What's the AppNexus bidder's avg. bid load time? +* What's the AppNexus bidder's avg. bid CPM +* What's the AppNexus bidder's avg. bid load time? To see how to answer these questions, see the following sections. ### Better Reports within GA -With a custom report in GA, you can get: +With a custom report in GA, you can get: ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/GA-custom-report.png) @@ -148,8 +150,8 @@ Install the [Google Analytics Spreadsheet Add-on](https://developers.google.com/ Make a local copy of the [Demo Dashboard](https://docs.google.com/spreadsheets/d/11czzvF5wczKoWGMrGgz0NFEOM7wsnAISbp_MpmGzogU/edit?usp=sharing). ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/sheet-copy-dashboard.png){: .pb-lg-img :} -
    -
    +
    +
    #### Step 3. Update the GA Profile ID @@ -157,16 +159,14 @@ In your local copy, go to the **Report Configuration** tab, update the GA profil ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/sheet-report-config.png){: .pb-lg-img :} -
    +
    #### Step 4. Run the Report ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/sheet-run-report.png){: .pb-lg-img :} -
    +
    #### Step 5. (Optional) Schedule a Daily Report ![Prebid Diagram Image]({{ site.github.url }}/assets/images/dev-docs/sheet-schedule-report.png){: .pb-lg-img :} - - diff --git a/dev-docs/analytics/33across.md b/dev-docs/analytics/33across.md new file mode 100644 index 0000000000..d6edecc535 --- /dev/null +++ b/dev-docs/analytics/33across.md @@ -0,0 +1,78 @@ +--- +layout: analytics +title: 33Across +description: 33Across Analytics Adapter +modulecode: 33across +prebid_member: true +gdpr_supported: true +usp_supported: true +gpp_supported: true +coppa_supported: true +gvl_id: 58 +enable_download: true +--- + +#### About + +This analytics adapter collects data about the performance of your ad slots +for each auction run on your site. It also provides insight into how identifiers +from the +[33Across User ID Sub-module](https://docs.prebid.org/dev-docs/modules/userid-submodules/33across.html) +and other user ID sub-modules improve your monetization. The data is sent at +the earliest opportunity for each auction to provide a more complete picture of +your ad performance. + +The analytics adapter is free to use! +However, the publisher must work with our account management team to obtain a +Publisher/Partner ID (PID) and enable Analytics for their account. +To get a PID and to have the publisher account enabled for Analytics, +you can reach out to our team at the following email - + +If you are an existing publisher and you already use a 33Across PID, +you can reach out to +to have your account enabled for analytics. + +The 33Across privacy policy is at . + +#### Analytics Options + +{: .table .table-bordered .table-striped } +| Name | Scope | Example | Type | Description | +|-----------|----------|---------|----------|-------------| +| `pid` | required | abc123 | `string` | 33Across Publisher ID | +| `timeout` | optional | 10000 | `int` | Milliseconds to wait after last seen auction transaction before sending report (default 10000). | + +#### Configuration + +The data is sent at the earliest opportunity for each auction to provide +a more complete picture of your ad performance, even if the auction is interrupted +by a page navigation. At the latest, the adapter will always send the report +when the page is unloaded, at the end of the auction, or after the timeout, +whichever comes first. + +In order to guarantee consistent reports of your ad slot behavior, we recommend +including the GPT Pre-Auction Module (`gptPreAuction` if compiling from source). +This module is included by default when Prebid is downloaded. + +Enable the 33Across Analytics Adapter in Prebid.js using the analytics provider `33across` +and options as seen in the example below. + +#### Example Configuration + +```js +pbjs.enableAnalytics({ + provider: '33across', + options: { + /** + * The 33Across Publisher ID. + */ + pid: 'abc123', + /** + * Timeout in milliseconds after which an auction report + * will be sent regardless of auction state. + * [optional] + */ + timeout: 10000 + } +}); +``` diff --git a/dev-docs/analytics/adWMG.md b/dev-docs/analytics/adWMG.md index 7370dd57db..d159085d90 100644 --- a/dev-docs/analytics/adWMG.md +++ b/dev-docs/analytics/adWMG.md @@ -3,7 +3,7 @@ layout: analytics title: adWMG description: adWMG Analytics Adapter modulecode: adWMG -gdpr_supported: true +tcfeu_supported: true usp_supported: false coppa_supported: false prebid_member: false @@ -18,7 +18,6 @@ gvl_id: 959 | publisher_id | required | Publisher ID from WMG Dashboard | `'5abd0543ba45723db49d97ea'` | string | | site | required | Domain where Prebid.js working | `'test.com'` | string | - ### Example Configuration ``` @@ -29,6 +28,7 @@ gvl_id: 959 publisher_id: '5abd0543ba45723db49d97ea' }}); ``` + #### Registration -Please visit [https://adwmg.com/](https://adwmg.com/) for more information. +Please visit [adwmg.com](https://adwmg.com/) for more information. diff --git a/dev-docs/analytics/adagio.md b/dev-docs/analytics/adagio.md index e57ac297b8..ff442970bf 100644 --- a/dev-docs/analytics/adagio.md +++ b/dev-docs/analytics/adagio.md @@ -4,9 +4,23 @@ title: Adagio description: Adagio Analytics Adapter modulecode: adagio prebid_member: true +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gvl_id: 617 +enable_download: true --- #### Registration -Please visit [https://adagio.io/](https://adagio.io/) for more information. +The Adagio Analytics adapter requires setup and approval from the Adagio team. Please reach out to for more information. +#### Example Configuration + +```js + pbjs.que.push(function () { + pbjs.enableAnalytics({ + provider: 'adagio', + }); + }); +``` diff --git a/dev-docs/analytics/adkernelAdn.md b/dev-docs/analytics/adkernelAdn.md index c483625dde..6c53b999c4 100644 --- a/dev-docs/analytics/adkernelAdn.md +++ b/dev-docs/analytics/adkernelAdn.md @@ -3,7 +3,7 @@ layout: analytics title: Adkernel description: Adkernel Analytics Adapter modulecode: adkernelAdn -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true prebid_member: false @@ -12,5 +12,4 @@ gvl_id: 14 #### Registration -Please visit https://adkernel.com/dsp-suite/ for more information. - +Please visit [adkernel.com/dsp-suite/](https://adkernel.com/dsp-suite/) for more information. diff --git a/dev-docs/analytics/adloox.md b/dev-docs/analytics/adloox.md index 03f9e5f354..66d9339591 100644 --- a/dev-docs/analytics/adloox.md +++ b/dev-docs/analytics/adloox.md @@ -3,7 +3,7 @@ layout: analytics title: Adloox description: Adloox Prebid Analytics Adapter modulecode: adloox -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: false prebid_member: false @@ -19,7 +19,7 @@ The adapter adds an HTML `
    -### Full List +## Full List + +### #-A -#### #-A
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -46,7 +49,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### B-C +### B-C +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -57,7 +61,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### D-G +### D-G +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -68,7 +73,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### H-L +### H-L +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -79,7 +85,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### M-O +### M-O +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -90,7 +97,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### P-R +### P-R +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -101,7 +109,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### S-T +### S-T +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} @@ -112,7 +121,8 @@ var AutocompleteList = [{% for page in bidder_pages %}{ label: '{{ page.title }} {% endfor %}
    -#### U-Z +### U-Z +
      {% for page in bidder_pages %} {% assign firstletter = page.title | slice:0 | downcase %} diff --git a/dev-docs/bidders/1ad4good.md b/dev-docs/bidders/1ad4good.md deleted file mode 100644 index ce869099b1..0000000000 --- a/dev-docs/bidders/1ad4good.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: 1ad4good -description: Prebid One Ad for Good(1ad4good.org) Bidder Adaptor -pbjs: true -biddercode: 1ad4good -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -This adapter is for displaying free ads for various not profits. You can find more info at [1ad4good.org])(http://1ad4good.org). - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `placementId` | required | Meaningless, but required id | `234234` | `integer` | -| `cpm` | optional | forces bidder to insert custom cpm bid | 0.50 | `decimal` | diff --git a/dev-docs/bidders/33across.md b/dev-docs/bidders/33across.md index ceed5753a3..4076fae58b 100644 --- a/dev-docs/bidders/33across.md +++ b/dev-docs/bidders/33across.md @@ -6,12 +6,21 @@ pbjs: true pbs: true biddercode: 33across media_types: banner, video -gdpr_supported: true +tcfeu_supported: true floors_supported: true schain_supported: true +dchain_supported: false usp_supported: true +gpp_supported: true +coppa_supported: true +fpd_supported: true +multiformat_supported: will-bid-on-any +safeframes_ok: true +deals_supported: true +prebid_member: true userIds: all gvl_id: 58 +sidebarType: 1 --- ### Bid Params @@ -23,6 +32,7 @@ gvl_id: 58 | `productId` | required | 33Across Product ID that the Publisher has registered for (use `'siab'` for Banner or Outstream Video , `'inview'` for Adhesion, `'instream'` for Instream Video) | `'siab'` | `string` | ### Ad Unit Setup for Banner + ```javascript var adUnits = [ { @@ -43,9 +53,10 @@ var adUnits = [ } }] } -``` +``` ### Ad Unit Setup for Outstream Video + ```javascript var adUnits = [ { @@ -81,6 +92,7 @@ var adUnits = [ ``` ### Ad Unit Setup for Instream Video + ```javascript var adUnits = [ { @@ -117,6 +129,7 @@ var adUnits = [ ``` ### Ad Unit Setup for Multi-format: Banner, Video (Outstream) + ```javascript var adUnits = [ { @@ -156,9 +169,12 @@ var adUnits = [ ... } ``` + ### SRA Mode + We recommend using SRA mode to optimize the bidding process as this allows our adapter to group together bid requests for Ad Units pertaining to the same product and site ID thereby minimizing the number of http requests made to our endpoint. To enable SRA set the following bidder specific config under 33Across -``` + +```javascript pbjs.setBidderConfig({ bidders: ['33across'], config: { @@ -167,4 +183,4 @@ pbjs.setBidderConfig({ } } }); -``` \ No newline at end of file +``` diff --git a/dev-docs/bidders/7xbid.md b/dev-docs/bidders/7xbid.md deleted file mode 100644 index 75b539fdd3..0000000000 --- a/dev-docs/bidders/7xbid.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: 7xbid -description: Prebid 7xbid Bidder Adaptor -pbjs: true -biddercode: 7xbid -media_types: banner, native -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `placementId` | required | This is placement Id | `1425292` | `integer` | -| `currency` | optional | 3-letter ISO 4217 code defining the currency of the bid (currently support USD and JPY), default is JPY | `'USD'` | `string` | diff --git a/dev-docs/bidders/9MediaOnline.md b/dev-docs/bidders/9MediaOnline.md index 593bc91a00..3e337a1da8 100644 --- a/dev-docs/bidders/9MediaOnline.md +++ b/dev-docs/bidders/9MediaOnline.md @@ -5,12 +5,14 @@ description: Prebid 9 Media Online Bidder Adaptor biddercode: 9MediaOnline pbjs: true media_types: banner, video -gdpr_supported: true +gvl_id: 644 +tcfeu_supported: true tcf2_supported: true schain_supported: true usp_supported: true userIds: id5Id, unifiedId aliasCode: gamoshi +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/9dotsmedia.md b/dev-docs/bidders/9dotsmedia.md new file mode 100644 index 0000000000..d553a6d833 --- /dev/null +++ b/dev-docs/bidders/9dotsmedia.md @@ -0,0 +1,108 @@ +--- +layout: bidder +title: 9Dots Media +description: 9Dots Media Bidder Adapter +biddercode: 9dotsmedia +aliasCode: adtelligent +media_types: video,banner +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: false +deals_supported: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from 9Dots Media. | `12412` | `integer` | + +### Description + +9Dots Media header bidding adapter connects with 9Dots Media demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: '9dotsmedia', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: '9dotsmedia', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: '9dotsmedia', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: '9dotsmedia', + params: { + aid: 529814 + } + }] + } + ]; +``` diff --git a/dev-docs/bidders/a1media.md b/dev-docs/bidders/a1media.md new file mode 100644 index 0000000000..82d1158742 --- /dev/null +++ b/dev-docs/bidders/a1media.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: A1Media +description: Prebid A1Media Bidder Adapter +biddercode: a1media +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +gpp_supported: false +schain_supported: true +dchain_supported: false +media_types: banner, video, native +safeframes_ok: false +deals_supported: false +floors_supported: true +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: partial +sidebarType: 1 +--- + +### Note + +The A1Media Bidding adapter requires setup before beginning. Please contact us at . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------------------------------------|-------------------------------------|----------| +| `bidfloor` | optional | Bid Floor Price, It is used if the Floor Module is not available | `0.9` | `float` | +| `currency` | optional | Currency For Bid and Bid Floor, It is used if the Currency Module is not available | `'JPY'` | `string` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1']` | `string array` | +| `battr` | optional | Blocked creative attributes | `[ 13 ]` | `integer array` | diff --git a/dev-docs/bidders/a4g.md b/dev-docs/bidders/a4g.md index 0e6bf6c0dd..4f4aee6e68 100644 --- a/dev-docs/bidders/a4g.md +++ b/dev-docs/bidders/a4g.md @@ -4,7 +4,8 @@ title: A4G description: Prebid A4G Bidder Adaptor pbjs: true biddercode: a4g -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/aardvark.md b/dev-docs/bidders/aardvark.md deleted file mode 100644 index a435711ff4..0000000000 --- a/dev-docs/bidders/aardvark.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: Aardvark -description: Prebid Aardvark Bidder Adaptor -pbjs: true -biddercode: aardvark -gdpr_supported: true -usp_supported: true -schain_supported: true -userIds: unifiedId -gvl_id: 52 -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------|----------|--------------------|----------|----------| -| `ai` | required | The rtk auction ID | `'XBC1'` | `string` | -| `sc` | required | The rtk shortcode | `'AF2g'` | `string` | -| `categories` | optional | Deal ID Categories | `['news','sports']` | `array` | diff --git a/dev-docs/bidders/aax.md b/dev-docs/bidders/aax.md new file mode 100644 index 0000000000..67d7a46407 --- /dev/null +++ b/dev-docs/bidders/aax.md @@ -0,0 +1,128 @@ +--- +layout: bidder +title: AAX +description: Prebid Aax Bidder Adaptor +biddercode: aax +aliasCode : medianet +tcfeu_supported: true +media_types: banner,native,video +usp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +prebid_member: false +pbjs: true +gvl_id: 720 +schain_supported: true +floors_supported: true +fpd_supported: true +pbs: true +safeframes_ok: true +multiformat_supported: will-not-bid +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `cid` | required | The customer id provided by Aax. | `'aax_test_customer'` | `string` | +| `crid` | required | The placement id provided by Aax. | `'aax_crid'` | `string` | +| `video` | required for video Ad units | Object containing video targeting parameters. See [Video Object](#aax-video-object) for details.|`video: { maxduration: 60 }` | `object` | + + + +#### Video Object + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Example| +|------------|----------|--------------|--------| +|mimes|array of strings|(Recommended) Specifies the video content MIME types supported; for example, video/x-ms-wmv and video/x-flv.|["video/x-ms-wmv","video/x-flv"]| +|minduration|integer|(Recommended) Specifies the minimum video ad duration, in seconds.|10| +|maxduration|integer|(Recommended) Specifies the maximum video ad duration, in seconds.|60| +|w|integer|(Recommended) Specifies the width of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|640| +|h|integer|(Recommended) Specifies the height of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|480| +|startdelay |integer | (Recommended) Specifies the start delay of the video ad|0| +|battr| array of integers|Specifies the video creative attributes to block. Refer to section 5.3 of the IAB specification for a list of attributes.| [ 13, 14 ]| +playbackmethod| array of integers| Specifies the allowed playback methods. If not specified, all are assumed to be allowed. Currently supported values are: `1: Autoplay, sound on`; `2: Autoplay, sound off`; `3: Click to play`; `4: Mouse over to play`|[1, 3]| +|api| array of integers| Specifies the supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. Currently supported values are: `1: VPAID 1.0`; `2: VPAID 2.0`; `3: MRAID-1`; `4: ORMMA`; `5: MRAID-2`|[1, 2]| +|protocols |array of integers| Array of supported video protocols. Currently supported values are: `1: VAST 1.0`; `2: VAST 2.0`; `3: VAST 3.0`; `4: VAST 1.0 Wrapper`; `5: VAST 2.0 Wrapper`; `6: VAST 3.0 Wrapper`; `7: VAST 4.0`|[1, 2]| +|placement |integer|Placement type for the impression. Possible options: `1: In-Stream`; `2: In-banner`; `3: Outstream/In-article`; `4: In-feed`; `5: Interstitial/Slider/Floating`; `6: Long-Form`;|1| + +Besides the above-mentioned parameters, we support all other OpenRTB 2.x video objects as optional parameters. + +In addition to `bids[].params.video`, Aax adapter consumes parameters specified in the `mediaTypes.video`. + +#### Example of Instream Video Ad-unit + +```javascript +var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + context: "instream", + playerSize: [640, 480], + mimes: ['video/mp4'], + placement: 1 + } + }, + bids: [{ + bidder: 'aax', + params: { + cid: 'aax_test_customer', + crid: 'aax_crid', + } + }] +}; +``` + +#### Example of Native Ad-unit + +```javascript +var adUnits = [{ + code: 'div-gpt-ad-6874091242345-0', + mediaTypes: { + native: { + image: { + required: true, + sizes: [300, 250], + wmin: 50, + }, + title: { + required: true, + len: 80 + } + } + }, + bids: [{ + bidder: 'aax', + params: { + cid: 'aax_test_customer', + crid: 'aax_crid' + } + }] +}]; +``` + +#### Example of Banner Ad-unit + +```javascript +var adUnits = [{ + code: 'div-gpt-ad-6874091242345-0', + mediaTypes: { + banner: { + sizes: [ + [728, 90], + [300, 600], + [300, 250] + ], + } + }, + bids: [{ + bidder: 'aax', + params: { + cid: 'aax_test_customer', + crid: 'aax_crid' + } + }] +}]; +``` diff --git a/dev-docs/bidders/ablida.md b/dev-docs/bidders/ablida.md index 590cc756df..75ea5c3d3c 100644 --- a/dev-docs/bidders/ablida.md +++ b/dev-docs/bidders/ablida.md @@ -5,7 +5,8 @@ description: Prebid ablida Bidder Adaptor pbjs: true biddercode: ablida media_types: banner, native, video -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/aceex.md b/dev-docs/bidders/aceex.md index e380d3aa54..68968333f1 100644 --- a/dev-docs/bidders/aceex.md +++ b/dev-docs/bidders/aceex.md @@ -3,7 +3,7 @@ layout: bidder title: Aceex description: Prebid Aceex Bidder Adaptor biddercode: aceex -gdpr_supported: true +tcfeu_supported: false usp_supported: true coppa_supported: true schain_supported: true @@ -13,11 +13,12 @@ safeframes_ok: true deals_supported: true pbjs: false pbs: true +sidebarType: 1 --- -### Note: +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at tech@aceex.com +The Example Bidding adapter requires setup before beginning. Please contact us at ### Bid Params diff --git a/dev-docs/bidders/acuityads.md b/dev-docs/bidders/acuityads.md index 95d4784821..fc30eeaf58 100644 --- a/dev-docs/bidders/acuityads.md +++ b/dev-docs/bidders/acuityads.md @@ -3,26 +3,37 @@ layout: bidder title: AcuityAds description: Prebid AcuityAds Bidder Adaptor biddercode: acuityads -gdpr_supported: true +filename: acuityadsBidAdapter +gvl_id: 231 +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true +gpp_supported: true userId: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId media_types: banner, video, native safeframes_ok: true deals_supported: true -pbjs: false +pbjs: true pbs: true +sidebarType: 1 --- -### Note: +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at rafi.babler@acuityads.com +The Example Bidding adapter requires setup before beginning. Please contact us at -### Bid Params +### Prebid.JS Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement ID | `'123'` | `string` | + +### Prebid Server Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| | `host` | required | Region id | `'ep1'` | `string` | -| `accountid` | required | Endpoint id | `'hash'` | `string` | +| `accountid` | required | Endpoint id / Placement id | `'hash'` | `string` | diff --git a/dev-docs/bidders/ad2iction.md b/dev-docs/bidders/ad2iction.md new file mode 100644 index 0000000000..ae1300267e --- /dev/null +++ b/dev-docs/bidders/ad2iction.md @@ -0,0 +1,20 @@ +--- +layout: bidder +title: Ad2iction +description: Prebid Ad2iction Bidder Adapter +biddercode: ad2iction +pbjs: true +media_types: banner +safeframes_ok: false +sidebarType: 1 +--- + +### Note +The Ad2iction Bidding adapter requires setup before beginning. Please contact us on [https://www.ad2iction.com](https://www.ad2iction.com). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|--------------------|--------------------|----------------|----------| +| `id` | required(pbjs) | ad2iction id | `example-uuid` | `string` | diff --git a/dev-docs/bidders/adWMG.md b/dev-docs/bidders/adWMG.md index 0b9ff3c933..65709dfc74 100644 --- a/dev-docs/bidders/adWMG.md +++ b/dev-docs/bidders/adWMG.md @@ -5,10 +5,13 @@ description: Prebid adWMG Bidder Adapter pbjs: true biddercode: adWMG media_types: banner -gdpr_supported: true +gvl_id: 959 +tcfeu_supported: true +sidebarType: 1 --- ### BidParams + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |-----------------|----------|---------------------------------|------------------------------|--------------------| @@ -16,8 +19,8 @@ gdpr_supported: true | `IABCategories` | optional | IAB ad categories for adUnit | `['IAB1', 'IAB5']` | `array of strings` | | `floorCPM` | optional | Floor price for adUnit | `0.5` | `float` | - ### Ad Unit Setup for Banner + ```javascript var adUnits = [ { diff --git a/dev-docs/bidders/adagio.md b/dev-docs/bidders/adagio.md index 220d544cf7..1aa7b00cf4 100644 --- a/dev-docs/bidders/adagio.md +++ b/dev-docs/bidders/adagio.md @@ -5,49 +5,92 @@ description: Prebid Adagio Bidder Adaptor pbjs: true biddercode: adagio media_types: banner, native, video -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, pubProvidedId, sharedId, unifiedId +userIds: all floors_supported: true -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true usp_supported: true +gpp_supported: true coppa_supported: true schain_supported: true gvl_id: 617 prebid_member: true fpd_supported: false +sidebarType: 1 --- ### Note -The Adagio bidder adaptor requires setup and approval from the Adagio team. Please reach out to [contact@adagio.io](mailto:contact@adagio.io) for more information. +The Adagio bidder adapter requires setup and approval from the Adagio team. Please reach out to [contact@adagio.io](mailto:contact@adagio.io) for more information. + +### Configuration + +#### User Sync + +Adagio strongly recommends enabling user syncing through iFrames. This functionality improves DSP user match rates and increases the bid rate and bid price. Make sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Adagio. + +```js +// https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: ['adagio'], + filter: 'include' + } + } + } +}); +``` + +#### Bidder Settings + +The Adagio bid adapter uses browser local storage. Since Prebid.js 7.x, the access to it must be explicitly set. + +```js +// https://docs.prebid.org/dev-docs/publisher-api-reference/bidderSettings.html +pbjs.bidderSettings = { + adagio: { + storageAllowed: true + } +} +``` ### Bid Params **Important**: Adagio needs to collect attention data about the ads displayed on a page and must listen to some specifics ad-server events. Please refer to the [Adagio user guide](https://adagioio.notion.site/Adagio-Account-Setup-Guide-fbcd940649224cdfa10393d2f008792e) for details. {: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|--------------------|--------------------|----------------------------------------------------------------------------------------------------------------------|-----------------|-----------| -| `organizationId` | required | Id of the Organization. Handed out by Adagio. | `'1010'` | `string` | -| `site` | required | Name of the site. Handed out by Adagio.
      - max length: 50 | `'mysite-com'` | `string` | -| `placement`* | required | Refers to the placement of an adunit in a page.
      Must not contain any information about the type of device.
      - max length: 30
      - max distinctives values: 10 | `'ban_atf'` | `string` | -| `adUnitElementId` | required | Refers to the adunit html attribute id in a page. | `'gpt-ban-atf'` | `string` | -| `pagetype`* | highly recommended | Describes what kind of content will be present in the page.
      - max length: 30
      - max distinctives values: 50 | `'article'` | `string` | -| `environment`* | recommended | Environment where the page is displayed.
      - max length: 30
      - max distinctives values: 10 | `'desktop'` | `string` | -| `category`* | recommended | Category of the content displayed in the page.
      - max length: 30
      - max distinctives values: 50 | `'sport'` | `string` | -| `subcategory`* | optional | Subcategory of the content displayed in the page.
      - max length: 30
      - max distinctives values: 50 | `'handball'` | `string` | -| `video` | optional | OpenRTB 2.5 video options object.
      All options will override ones defined in mediaTypes.video | `{skip: 1, playbackmethod: [6]}` | `object` | -| `native` | optional | Partial OpenRTB Native 1.2 request object. Supported fields are:
      - context
      -plcmttype | `{context: 1, plcmttype: 2}` | `object` | - +| Name | Scope | Description | Example | Type | +| ----------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | -------- | +| `organizationId` | required | Id of the Organization. Handed out by Adagio. | `'1010'` | `string` | +| `site` | required | Name of the site. Handed out by Adagio.
      - max length: 50 | `'mysite-com'` | `string` | +| `placement`* | required | Refers to the placement of an adunit in a page.
      Must not contain any information about the type of device.
      - max length: 30
      - max distinctives values: 10 | `'ban_atf'` | `string` | +| `adUnitElementId` | required | Refers to the adunit html attribute id in a page. | `'gpt-ban-atf'` | `string` | +| `pagetype`* | highly recommended | Describes what kind of content will be present in the page.
      - max length: 30
      - max distinctives values: 50 | `'article'` | `string` | +| `category`* | recommended | Category of the content displayed in the page.
      - max length: 30
      - max distinctives values: 50 | `'sport'` | `string` | +| `video` | optional | OpenRTB 2.5 video options object. All options will override ones defined in mediaTypes video.
      Mandatory:
      - api (your video player must at least support the value 2)
      Highly recommended:
      - playbackmethod
      Not supported:
      `protocol`, `companionad`, `companiontype`, `ext` options| `{api: [2], playbackmethod: [6], skip: 1, startdelay: 0}` | `object` | +| `native` | optional | Partial OpenRTB Native 1.2 request object. Supported fields are:
      - context
      - plcmttype | `{context: 1, plcmttype: 2}` | `object` | +| `splitKeyword` | optional | Keyword that can later be used in a split rule targeting to trigger the rule (especially for Direct Seats AB testing) | `'splitrule-one'` | `string` | +| `dataLayer` | optional | A set of arbitrary key-value pairs. This can be used to configure mappings. The keys and values must be strings. | `{placement: 'my-placement', siteid: 'my-siteid'}` | `object` | *These parameters will have its accentuated characters converted to their non-accentuated version: `ĂŠ` => `e` ### Native Custom assets -| Name | description | -|--------------|-------------------------------------| -| `adagio_bvw` | Url to handle Measure beacon | +| Name | description | +| ------------ | ---------------------------- | +| `adagio_bvw` | Url to handle Measure beacon | ### First Party Data -Adagio does not support FPD for now. It will be added soon. +Adagio will use FPD data as fallback for the params below: + +- pagetype +- category + +If the FPD value is an array, the 1st value of this array will be used. + +### Video outstream + +The AdagioBidAdapter includes a default video player powered by [Blue Billywig](https://www.bluebillywig.com). This default player is used when no renderer is configured for the adUnit. diff --git a/dev-docs/bidders/adasta.md b/dev-docs/bidders/adasta.md index e69fbeef33..bcd9002420 100644 --- a/dev-docs/bidders/adasta.md +++ b/dev-docs/bidders/adasta.md @@ -5,6 +5,7 @@ description: Prebid Adasta Media Bidder Adaptor pbjs: true biddercode: adasta aliasCode : appnexus +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/adbite.md b/dev-docs/bidders/adbite.md index 07b2aa749f..7774c3aefb 100644 --- a/dev-docs/bidders/adbite.md +++ b/dev-docs/bidders/adbite.md @@ -2,17 +2,28 @@ layout: bidder title: Adbite description: Adbite LLC +biddercode: adbite pbjs: true pbs: false -biddercode: adbite media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 +tcfeu_supported: true usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The adbite Bidding adaptor requires setup and approval before beginning. Please reach out to for more details @@ -22,4 +33,4 @@ The adbite Bidding adaptor requires setup and approval before beginning. Please | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Our Host | `'cpm.adbite.com'` | `string` | -| `zoneId` | required | Example RTB zone id | `'12345'`| `string` | +| `zoneId` | required | Example RTB zone id | `12345`| `integer` | diff --git a/dev-docs/bidders/adblender.md b/dev-docs/bidders/adblender.md index 6f3edddf6a..f6c9af50a6 100644 --- a/dev-docs/bidders/adblender.md +++ b/dev-docs/bidders/adblender.md @@ -6,8 +6,10 @@ pbjs: true biddercode: adblender aliasCode: admixer media_types: video -gdpr_supported: true +gvl_id: 511 (admixer) +tcfeu_supported: true usp_supported: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/adbookpsp.md b/dev-docs/bidders/adbookpsp.md index 333c258630..edef5f1ed2 100644 --- a/dev-docs/bidders/adbookpsp.md +++ b/dev-docs/bidders/adbookpsp.md @@ -4,16 +4,17 @@ title: AdBookPSP description: Prebid AdBookPSP Bidder Adapter biddercode: adbookpsp media_types: banner, video -gdpr_supported: true +tcfeu_supported: false prebid_member: false schain_supported: true coppa_supported: true usp_supported: true pbjs: true pbs: false +sidebarType: 1 --- -*NOTE*: The AdBookPSP Bidder Adapter requires setup and approval before use. The adapter uses custom targeting keys that require a dedicated Google Ad Manager setup to work. Please reach out to your AdbookPSP representative for more details. +*NOTE*: The AdBookPSP Bidder Adapter requires setup and approval before use. The adapter uses custom targeting keys that require a dedicated Google Ad Manager setup to work. Please reach out to your AdbookPSP representative for more details. ### Bid Params @@ -117,7 +118,7 @@ var adUnits = [ #### Testing params -To test the adapter, either `placementId: 'example-placement-id'` or `orgId: 'example-org-id'` can be used. +To test the adapter, either `placementId: 'example-placement-id'` or `orgId: 'example-org-id'` can be used. *NOTE*: If any adUnit uses the testing params, all adUnits will receive testing responses. diff --git a/dev-docs/bidders/adbutler.md b/dev-docs/bidders/adbutler.md index 478bcc4db1..846b15be98 100644 --- a/dev-docs/bidders/adbutler.md +++ b/dev-docs/bidders/adbutler.md @@ -1,22 +1,27 @@ --- layout: bidder title: AdButler -description: Prebid AdButler Bidder Adaptor -pbjs: true +description: AdButler Bid Adapter biddercode: adbutler -enable_download: false -pbjs_version_notes: not ported to 5.x +pbjs: true +sidebarType: 1 +media_types: banner +safeframes_ok: true +tcfeu_supported: false +usp_supported: false +coppa_supported: false --- - -### Bid Params +### Bid params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|------------------------------------------------------|------------------|----------| -| `accountID` | required | Account ID | `'167283'` | `string` | -| `zoneID` | required | Zone ID | `'210093'` | `string` | -| `keyword` | optional | Keyword(s) used for custom targeting | `'green,orange'` | `string` | -| `minCPM` | optional | Minimum CPM value to accept | `'1.00'` | `string` | -| `maxCPM` | optional | Maximum CPM value to accept | `'5.00'` | `string` | -| `extra` | optional | Pass other AdButler parameters like 'tuid' or 'kw' | `{kw: "green"}` | `object` | + +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------------------------------------------------------------------------------------------|-------------------------------|---------------| +| `accountID` | required | Account ID | `'181556'` | `string` | +| `zoneID` | required | Zone ID | `'705374'` | `string` | +| `domain` | optional | Ad serving domain (set if using custom domains) | `'servedbyadbutler.com'` | `string` | +| `keyword` | optional | Keyword(s) used for custom targeting | `'green,orange'` | `string` | +| `minCPM` | optional | Minimum CPM value to accept | `'1.00'` | `string` | +| `maxCPM` | optional | Maximum CPM value to accept | `'5.00'` | `string` | +| `extra` | optional | Other ad request parameters [(API Docs)](https://www.adbutler.com/docs/api/#tag/AdServe/paths/~1adserve/get) | `{ _abdk: { bird: "duck" } }` | `object` | diff --git a/dev-docs/bidders/addefend.md b/dev-docs/bidders/addefend.md index 7f44121a4f..f0f7e1f5f3 100644 --- a/dev-docs/bidders/addefend.md +++ b/dev-docs/bidders/addefend.md @@ -5,13 +5,14 @@ description: AdDefend Prebid Adapter biddercode: addefend pbjs: true media_types: banner -gdpr_supported: true +tcfeu_supported: true gvl_id: 539 +sidebarType: 1 --- -### Note: +### Note -The bidder requires setup before usage. Please get in touch with our publisher team at publisher@addefend.com to get started. +The bidder requires setup before usage. Please get in touch with our publisher team at to get started. ### Bid Params diff --git a/dev-docs/bidders/adelement.md b/dev-docs/bidders/adelement.md new file mode 100644 index 0000000000..380269c670 --- /dev/null +++ b/dev-docs/bidders/adelement.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: AdElement +description: Prebid AdElement Bidder Adapter +biddercode: adelement +tcfeu_supported: true +gvl_id: 196 +usp_supported: true +coppa_supported: true +schain_supported: true +media_types: banner, native, video, audio +pbjs: false +pbs: true +pbs_app_supported: true +prebid_member: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Note + +Bidding adapter requires setup before beginning. +Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `supply_id` | required | Supply Id | `'1'` | `string` | diff --git a/dev-docs/bidders/adf.md b/dev-docs/bidders/adf.md index 7b5b1e6b73..fb79528c66 100644 --- a/dev-docs/bidders/adf.md +++ b/dev-docs/bidders/adf.md @@ -4,7 +4,9 @@ title: AdformOpenRTB description: Prebid Adform Bidder Adaptor biddercode: adf media_types: banner, native, video -gdpr_supported: true +coppa_supported: true +tcfeu_supported: true +dsa_supported: true usp_supported: true prebid_member: true pbjs: true @@ -14,7 +16,8 @@ userIds: all gvl_id: 50 prevBiddercode: adformOpenRTB floors_supported: true -fpd_supported: true +multiformat_supported: will-bid-on-one +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/adfinity.md b/dev-docs/bidders/adfinity.md deleted file mode 100644 index ce9b16a758..0000000000 --- a/dev-docs/bidders/adfinity.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Adfinity -description: Prebid Adfinity Bidder Adaptor -pbjs: true -biddercode: adfinity -media_types: banner, video, native -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|----------------------------------------------------------|------------|-----------| -| `placement_id` | required | Placement Id will be generated on Adfinity Platform. | `0` | `integer` | -| `traffic` | optional | Type traffic | `'banner'` | `string` | diff --git a/dev-docs/bidders/adform.md b/dev-docs/bidders/adform.md deleted file mode 100644 index 3676871ca8..0000000000 --- a/dev-docs/bidders/adform.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -layout: bidder -title: Adform -description: Prebid Adform Bidder Adaptor -biddercode: adform -media_types: banner, video -gdpr_supported: true -usp_supported: true -prebid_member: true -pbjs: true -pbs: true -userIds: all -gvl_id: 50 -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -**Adform bid adapter is deprecated since Prebid 5.0. Please refer to [AdformOpenRTB adapter](#adf) documentation to fetch bids from Adform demand sources.** - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|-----------------------------------------------|----------------------------|-----------| -| `mid` | required | | `12345` | `integer` | -| `adxDomain` | optional | The Adform domain | `'adx.adform.net'` | `string` | -| `priceType` | optional | An expected price type (net or gross) of bids | `'net'` | `string` | -| `mkv` | optional | Comma-separated key-value pairs | `'city:NY'` | `string` | -| `mkw` | optional | Comma-separated keywords | `'news,sport'` | `string` | -| `minp` | optional | Minimum CPM price | `2.55` | `number` | -| `cdims` | optional | Comma-separated creative dimentions | `'300x250'` | `string` | -| `url` | optional | Custom targeting URL | `'https://some.app/?home'` | `string` | - -Note: Spaces are not allowed between comma-separated list values. For example: -``` -// valid params -{ - mid: 12345, - mkv: 'city:NY,city:London', - mkv: 'news,sport', - cdims: '300x250,250x300' -} -// invalid params -{ - mid: 12345, - mkv: 'city:NY, city:London', - mkv: 'news, sport', - cdims: '300x250, 250x300' -} -``` diff --git a/dev-docs/bidders/adfusion.md b/dev-docs/bidders/adfusion.md new file mode 100644 index 0000000000..9d3c71ddbe --- /dev/null +++ b/dev-docs/bidders/adfusion.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: AdFusion +biddercode: adfusion +tcfeu_supported: true +gvl_id: 844 +usp_supported: false +coppa_supported: false +gpp_supported: false +schain_supported: false +dchain_supported: false +safeframes_ok: false +deals_supported: true +userId: all +media_types: display, video +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +sidebarType: 1 +--- + +### Note + +The AdFusion Bidding adapter requires setup from the AdFusion team. Please contact us at [prebid@adfusion.pl](mailto:prebid@adfusion.pl). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `accountId` | required | The account ID provided by AdFusion | `1234` | `number` | diff --git a/dev-docs/bidders/adgeneration.md b/dev-docs/bidders/adgeneration.md index 8ff03a0902..b998883a3f 100644 --- a/dev-docs/bidders/adgeneration.md +++ b/dev-docs/bidders/adgeneration.md @@ -5,7 +5,9 @@ description: Prebid Ad Generation Bidder Adaptor pbjs: true pbs: true biddercode: adgeneration +userIds: novatiq, criteo, id5Id media_types: native +sidebarType: 1 --- diff --git a/dev-docs/bidders/adglare.md b/dev-docs/bidders/adglare.md deleted file mode 100644 index 7e8f6db2d7..0000000000 --- a/dev-docs/bidders/adglare.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: AdGlare Ad Server -description: Prebid Adapter for AdGlare Ad Server -pbjs: true -biddercode: adglare -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|--------------------------------------|--------------------------------------|----------| -| `domain ` | required | Your (white label) ad serving domain | `'try.engine.adglare.net'` | `string` | -| `zID` | required | The zone ID | `'475579334'` | `string` | -| `type` | required | The zone type | `'banner'` | `string` | diff --git a/dev-docs/bidders/adhash.md b/dev-docs/bidders/adhash.md index f341d3e6de..cd1f26c285 100644 --- a/dev-docs/bidders/adhash.md +++ b/dev-docs/bidders/adhash.md @@ -4,27 +4,33 @@ title: AdHash description: Prebid AdHash Bidder Adapter pbjs: true biddercode: adhash +media_types: display, video safeframes_ok: false -gdpr_supported: true +tcfeu_supported: false +multiformat_supported: will-bid-on-any +sidebarType: 1 --- ### Note Here is what you need for Prebid integration with AdHash: + 1. Register with AdHash. 2. Once registered and approved, you will receive a Publisher ID and Platform URL. 3. Use the Publisher ID and Platform URL as parameters in params. Please note that a number of AdHash functionalities are not supported in the Prebid.js integration: -* Cookie-less frequency and recency capping; -* Audience segments; -* Price floors and passback tags, as they are not needed in the Preebid.js setup; -* Reservation for direct deals only, as bids are evaluated based on their price. + +* Price floors and passback tags, as they are not needed in the Prebid.js setup; +* Reservation for direct deals only, as bids are evaluated based on their price; +* Fill rate reporting, as unfilled impressions can be filled by any other bidder; +* CPC deals, as bidding happens only on CPM pricing. ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------|------------------------------------------------|----------| -| `publisherId` | required | Publisher ID | `'0x1234567890123456789012345678901234567890'` | `string` | -| `platformURL` | required | Platform URL | `'https://adhash.org/p/example/'` | `string` | +| Name | Scope | Description | Example | Type | +|----------------|----------|----------------|------------------------------------------------|-----------| +| `publisherId` | required | Publisher ID | `'0x1234567890123456789012345678901234567890'` | `string` | +| `platformURL` | required | Platform URL | `'https://adhash.com/p/example/'` | `string` | +| `bidderURL` | optional | Bidder URL | `'https://bidder.adhash.com'` | `string` | diff --git a/dev-docs/bidders/adhese.md b/dev-docs/bidders/adhese.md index d0bcaea03c..cc2d9499f0 100644 --- a/dev-docs/bidders/adhese.md +++ b/dev-docs/bidders/adhese.md @@ -6,18 +6,19 @@ pbjs: true pbs: true biddercode: adhese media_types: banner, video -gdpr_supported: true +tcfeu_supported: true userIds: id5Id gvl_id: 553 pbs_app_supported: true +sidebarType: 1 --- ### Registration -The Adhese bid adapter may require an additional setup from the Adhese team, even for existing Adhese customers. Please reach out to your support team or info@adhese.com for more information. +The Adhese bid adapter may require an additional setup from the Adhese team, even for existing Adhese customers. Please reach out to your support team or for more information. Prebid Server host companies need to work with Adhese for each additional publisher. - + ### Bid Params {: .table .table-bordered .table-striped } @@ -30,7 +31,7 @@ Prebid Server host companies need to work with Adhese for each additional publis ### Configuration -Adhese supports 'iframe' UserSync configuration only. +Adhese supports 'iframe' UserSync configuration only. For Prebid.js v1.15.0 and later: diff --git a/dev-docs/bidders/adkernel.md b/dev-docs/bidders/adkernel.md index 83dc8256c2..5c2be852bf 100644 --- a/dev-docs/bidders/adkernel.md +++ b/dev-docs/bidders/adkernel.md @@ -6,16 +6,23 @@ pbjs: true pbs: true biddercode: adkernel media_types: banner, native, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true +gpp_supported: true pbs_app_supported: true gvl_id: 14 schain_supported: true userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +sidebarType: 1 --- -### Note: +### Note The Adkernel Bidding adaptor requires setup and approval before beginning. Please reach out to for more details @@ -25,4 +32,4 @@ The Adkernel Bidding adaptor requires setup and approval before beginning. Pleas | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Ad network's RTB host | `'cpm.metaadserving.com'` | `string` | -| `zoneId` | required | RTB zone id | `'30164'` | `string` | +| `zoneId` | required | RTB zone id | `30164` | `integer` | diff --git a/dev-docs/bidders/adkernelAdn.md b/dev-docs/bidders/adkernelAdn.md index 0971133f06..3380c05df3 100644 --- a/dev-docs/bidders/adkernelAdn.md +++ b/dev-docs/bidders/adkernelAdn.md @@ -6,14 +6,15 @@ pbjs: true pbs: true biddercode: adkernelAdn media_types: banner, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true gvl_id: 14 +sidebarType: 1 --- -### Note: +### Note The AdkernelAdn Header Bidding adaptor requires setup and approval before beginning. Please reach out to for more details diff --git a/dev-docs/bidders/adlive.md b/dev-docs/bidders/adlive.md deleted file mode 100644 index 3501fa5b02..0000000000 --- a/dev-docs/bidders/adlive.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -layout: bidder -title: Adlive -description: adlive bid adapter -pbjs: true -biddercode: adlive -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------+----------+-------------------------------------------+----------------------------------------------|------| -| `hashes` | required | Array of hashes, provided by adlive | ['1e100887dd614b0909bf6c49ba7f69fdd1360437'] | Array of strings | diff --git a/dev-docs/bidders/adliveconnect.md b/dev-docs/bidders/adliveconnect.md new file mode 100644 index 0000000000..d52f486b17 --- /dev/null +++ b/dev-docs/bidders/adliveconnect.md @@ -0,0 +1,38 @@ +--- +layout: bidder +title: Adliveconnect +description: Adliveconnect Bidder Adaptor +biddercode: adliveconnect +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +enable_download: false +pbjs_version_notes: removed in 8.14 +--- + +### Note + +The Adlive bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.adlive.io'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/adliveplus.md b/dev-docs/bidders/adliveplus.md new file mode 100644 index 0000000000..242e3931e7 --- /dev/null +++ b/dev-docs/bidders/adliveplus.md @@ -0,0 +1,53 @@ +--- +layout: bidder +title: Adlive Plus +description: Adlive Plus adapter +biddercode: adliveplus +aliasCode: lucead +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +media_types: banner +safeframes_ok: true +deals_supported: true +floors_supported: true +fpd_supported: true +pbjs: true +pbs: false +prebid_member: true/false +ortb_blocking_supported: false +privacy_sandbox: paapi +sidebarType: 1 +--- +### Note + +The Adlive Plus adapter requires setup before beginning. Please contact us at [support@adlive.io](mailto:support@adlive.io). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement id | `'11111'` | `string` | + +### Test Parameters + +```javascript +const adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'adliveplus', + params: { + placementId: '1', + } + } + ] + } + ]; +``` diff --git a/dev-docs/bidders/adlivetech.md b/dev-docs/bidders/adlivetech.md index 5d4a40b8c2..7e6ffe90f4 100644 --- a/dev-docs/bidders/adlivetech.md +++ b/dev-docs/bidders/adlivetech.md @@ -6,7 +6,8 @@ pbjs: true biddercode: adlivetech aliasCode: grid media_types: banner, video -gdpr_supported: true +gvl_id: 686 (grid) +tcfeu_supported: true usp_supported: true schain_supported: true floors_supported: true @@ -14,8 +15,17 @@ userIds: all tcf2_supported: true coppa_supported: true fpd_supported: true +sidebarType: 1 --- +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [Bidder Config](#bidder-config) +- [First Party Data](#first-party-data) + + ### Bid Params @@ -25,3 +35,41 @@ fpd_supported: true | `uid` | required | Represents the Adlivetech bidder system Ad Slot ID associated with the respective div id from the site page. | `1` | `integer` | | `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | | `bidFloor` | optional | Floor of the impression opportunity. If present in the request overrides XML info. | `0.8` | `float` | + + + +### Bidder Config + +You can allow writing in localStorage `pbjs.setBidderConfig` for the bidder `adlivetech` + +```javascript +pbjs.setBidderConfig({ + bidders: ["adlivetech"], + config: { + localStorageWriteAllowed: true + } +}) +``` + +If it will be "true" this allow Adlivetech Bid Adapter to write userId in first party localStorage + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.ext.device`: Non standard arbitrary user device +- `ortb2.user.keywords`: Standard IAB OpenRTB 2.5 user.keywords field. It will be included in ext.keywords.user.ortb2 +- `ortb2.site.keywords`: Standard IAB OpenRTB 2.5 site.keywords field. It will be included in ext.keywords.site.ortb2 +- `ortb2.site.cat[]`: Standard IAB OpenRTB 2.5 site.cat field. It will be sent as part of site.cat array +- `ortb2.site.pagecat[]`: Standard IAB OpenRTB 2.5 site.pagecat field. It will be sent as part of site.cat array +- `ortb2.site.content.genre`: Standard IAB OpenRTB 2.5 site.content.genre field + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` +- `ortb2.imp[].instl` diff --git a/dev-docs/bidders/adman.md b/dev-docs/bidders/adman.md index 82de98d951..e132b58f40 100644 --- a/dev-docs/bidders/adman.md +++ b/dev-docs/bidders/adman.md @@ -5,15 +5,18 @@ description: Prebid Adman Bidder Adapter pbjs: true pbs: true biddercode: adman -gdpr_supported: true +gvl_id: 149 +tcfeu_supported: true usp_supported: true +schain_supported: true media_types: banner, video, native -userIds: uid2, lotamePanoramaId +userIds: uid2, lotamePanoramaId, idx +sidebarType: 1 --- -### Note: +### Note -The Adman Bidding adapter requires setup before beginning. Please contact us at prebid@admanmedia.com +The Adman Bidding adapter requires setup before beginning. Please contact us at Due to different integration API prebid.js and prebid-server api params are different ### Prebid.JS Bid Params @@ -23,7 +26,6 @@ Due to different integration API prebid.js and prebid-server api params are diff |---------------|----------|-----------------------|-----------|-----------| | `placementId` | required | Adman placement id | `'1234asdf'` | `'string'` | - ### Prebid server Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/admaru.md b/dev-docs/bidders/admaru.md new file mode 100644 index 0000000000..1809b52ece --- /dev/null +++ b/dev-docs/bidders/admaru.md @@ -0,0 +1,45 @@ +--- +layout: bidder +title: Admaru +description: Admaru Bidder Adapter +pbjs: true +biddercode: admaru +media_types: banner +tcfeu_supported: false +schain_supported: false +usp_supported: false +sidebarType: 1 +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|------------------|------------------------------|----------| +| `pub_id` | required | Publisher id | `'ap4m2b6m8'` | `string` | +| `adspace_id` | required | Adspace id | `'a3j5n6b1'` | `string` | + +### Test Parameters + +``` +var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "admaru", + params: { + pub_id: '1234', // string - required + adspace_id: '1234' // string - required + } + } + ] + } +]; +``` diff --git a/dev-docs/bidders/admatic.md b/dev-docs/bidders/admatic.md new file mode 100644 index 0000000000..5f34a21702 --- /dev/null +++ b/dev-docs/bidders/admatic.md @@ -0,0 +1,89 @@ +--- +layout: bidder +title: AdMatic +description: Prebid AdMatic Bidder Adapter. +pbjs: true +pbs: true +biddercode: admatic +media_types: banner,video,native +gvl_id: 1281 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_sids: tcfeu, tcfca, usnat, usstate_all, usp +schain_supported: true +dchain_supported: false +userIds: criteo, id5Id, sharedId, unifiedId +safeframes_ok: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Description + +AdMatic header bidding adapter connects with AdMatic demand sources to fetch bids for banner network ID. Please reach out to your account manager or for more information. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|----------|------------------------------------|------------|----------| +| `networkId` | required | The network ID from AdMatic | `12345` | `number` | +| `host` | required | RTB Host | `layer.serve.admatic.com.tr` | `string` | + +### Test Parameters + +300x250 banner test + +```javascript +var adUnits = [{ + code: 'your-slot_1-div', + mediaTypes: { + banner: { sizes: [[300, 250]] }, + }, + bids: [{ + bidder: 'admatic', + params: { + networkId: 12345, + host: 'layer.serve.admatic.com.tr' + } + }] +},{ + code: 'your-slot_2-div', + mediaTypes: { + native: { ... }, + }, + bids: [{ + bidder: 'admatic', + params: { + networkId: 12345, + host: 'layer.serve.admatic.com.tr' + } + }] +},{ + code: 'your-slot_3-div', + mediaTypes: { + video: { ... }, + }, + bids: [{ + bidder: 'admatic', + params: { + networkId: 12345, + host: 'layer.serve.admatic.com.tr' + } + }] +}]; +``` + +## UserSync example + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncEnabled: true, + syncDelay: 1 + } +}); +``` diff --git a/dev-docs/bidders/admedia.md b/dev-docs/bidders/admedia.md index d9530b2d31..03553c404f 100644 --- a/dev-docs/bidders/admedia.md +++ b/dev-docs/bidders/admedia.md @@ -1,19 +1,19 @@ --- layout: bidder -title: AdMedia -description: Prebid AdMedia Bidder Adaptor +title: admedia +description: Prebid admedia Bidder Adaptor pbjs: true biddercode: admedia media_types: banner -gdpr_supported: false -enable_download: false -pbjs_version_notes: not ported to 5.x +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|------------------------------------|----------|----------| -| `aid` | required | The Affiliate ID for the Publisher | `'1234'` | `string` | +| Name | Scope | Description | Example | Type | +|-----------------|----------|--------------------------|--------------|----------| +| `placementId` | required | The placement ID provided by admedia | `'1234567'` | `string` | +| `aid` | required | The aid provided by admedia | `'1234'` | `string` | +| `referrrInfo` | required | The referring page url to be sent by the publisher | `'https://test.com/abc'` | `string` | diff --git a/dev-docs/bidders/admixer.md b/dev-docs/bidders/admixer.md index 28d99d7c9f..f7271f31f3 100644 --- a/dev-docs/bidders/admixer.md +++ b/dev-docs/bidders/admixer.md @@ -6,13 +6,14 @@ pbjs: true pbs: true biddercode: admixer media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true -fpd_supported: true gvl_id: 511 userIds: AdmixerID prebid_member: true +floors_supported: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/admixeradx.md b/dev-docs/bidders/admixeradx.md new file mode 100644 index 0000000000..d07a13e283 --- /dev/null +++ b/dev-docs/bidders/admixeradx.md @@ -0,0 +1,24 @@ +--- +layout: bidder +title: AdmixerADX +description: Prebid AdmixerADX Bidder Adaptor +pbjs: true +biddercode: admixeradx +aliasCode: admixer +media_types: banner, video, native +tcfeu_supported: true +usp_supported: true +schain_supported: true +gvl_id: 511 +userIds: AdmixerID +prebid_member: true +floors_supported: true +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------|----------| +| `zone` | required | The unique identifier of the ad placement. Could be obtained from the AdBlender UI or from your account manager. | "e5ff8e48-4bd0-4a2c-9236-55530ab8981d" | `string` | +| `kvTargeting` | optional | Key/Value - a pair of the unique values that will be used for the custom targeting option. | {key1: value2, key2: value2} | `object` | diff --git a/dev-docs/bidders/admixerwl.md b/dev-docs/bidders/admixerwl.md new file mode 100644 index 0000000000..8232989500 --- /dev/null +++ b/dev-docs/bidders/admixerwl.md @@ -0,0 +1,28 @@ +--- +layout: bidder +title: AdmixerWL +description: Prebid AdMixer Bidder Adaptor +pbjs: true +biddercode: admixerwl +aliasCode: admixer +media_types: banner, video, native +tcfeu_supported: true +usp_supported: true +schain_supported: true +gvl_id: 511 +userIds: AdmixerID +prebid_member: true +floors_supported: true +sidebarType: 1 +multiformat_supported: will-bid-on-any +safeframes_ok: true +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------------|----------|--------------------------------------------------------------------------------------------|------------------------------|----------| +| `endpointId` | required | Unique Entity ID. Could be obtained from your account manager. | 51772 | `int` | +| `clientId` | required | Unique Entity ID. Could be obtained from your account manager. | 312 | `int` | +| `kvTargeting` | optional | Key/Value - a pair of the unique values that will be used for the custom targeting option. | {key1: value2, key2: value2} | `object` | diff --git a/dev-docs/bidders/adnow.md b/dev-docs/bidders/adnow.md index be7944b160..f8c65c1a26 100644 --- a/dev-docs/bidders/adnow.md +++ b/dev-docs/bidders/adnow.md @@ -5,9 +5,12 @@ description: Prebid AdNow Bidder Adaptor biddercode: adnow pbjs: true media_types: native, banner +sidebarType: 1 --- -### Note: -The Example Bidding adapter requires setup before beginning. Please contact us at support@adnow.com + +### Note + +The Example Bidding adapter requires setup before beginning. Please contact us at ### Bid Params diff --git a/dev-docs/bidders/adnuntius.md b/dev-docs/bidders/adnuntius.md index 1ddbe27415..d0a04091e8 100644 --- a/dev-docs/bidders/adnuntius.md +++ b/dev-docs/bidders/adnuntius.md @@ -5,10 +5,16 @@ description: Prebid Adnuntius Bidder Adaptor pbjs: true pbs: true biddercode: adnuntius -media_types: banner -gdpr_supported: true +media_types: banner, video +tcfeu_supported: true fpd_supported: true gvl_id: 855 +safeframes_ok: false +multiformat_supported: will-bid-on-any +ortb_blocking_supported: false +floors_supported: false +sidebarType: 1 + --- ### Bid Params @@ -18,7 +24,12 @@ gvl_id: 855 |-------------|----------|----------------------------------------------------------------------|----------|----------| | `auId` | required | The ad unit ID `'0000000000072345'` leading zeros can be omitted. | `'0000000000072345'` | `string` | | `network` | optional | Used if you want to make requests to multiple networks in adnuntius. | `'adnuntius'` | `string`| +| `userId` | optional | Allows you to set a specific user id in the request. | `'userId'` | `string`| | `targeting` | optional | Targeting to be sent through to adnuntius with the request. | `{ c: ['prebids'] }` | `string`| +| `maxDeals` | optional | The maximum number of deal bids to include. Default 0. | `1` | `Integer` | +| `bidType` | optional | Whether to use `grossBid` or `netBid` from the server response as the cpm bid. Default is `grossBid`. | `grossBid` | `string` | + +The `bidType` can also be set under `config` in the bidderSettings. #### Targeting @@ -28,22 +39,23 @@ The [Adnuntius Documentation](https://docs.adnuntius.com/adnuntius-advertising/r Here's an example of sending targeting information about categories to adnuntius via the bid request: -``` +```json { - code: "0000000000072345", - mediaTypes: { - banner: { - sizes: [[980, 360], [980, 300], [980, 240], [980, 120]] + "code": "0000000000072345", + "mediaTypes": { + "banner": { + "sizes": [[980, 360], [980, 300], [980, 240], [980, 120]] } }, - bids: [ + "bids": [ { - bidder: "adnuntius", - params: { - auId: "8b6bc", - network: "adnuntius", - targeting: { - c: ['prebids'] + "bidder": "adnuntius", + "params": { + "auId": "8b6bc", + "network": "adnuntius", + "userId": "", + "targeting": { + "c": ["prebids"] } } } @@ -55,7 +67,7 @@ Here's an example of sending targeting information about categories to adnuntius There's an option to send segment id in the bidder config that will be picked up and sent to the ad server. Below is an example on how to do this: -``` +```js pbjs.setBidderConfig({ bidders: ['adnuntius', 'bidderB'], config: { @@ -78,8 +90,7 @@ pbjs.setBidderConfig({ You have the option to tell adnuntius not to set cookies in your browser. This does not mean that third party ads being served through the ad server will not set cookies. Just that Adnuintius will not set it for internal ads. -``` - +```js pbjs.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -94,22 +105,75 @@ Use cookie will always be set to true by default. Changing it to false will disa The following test parameters can be used to verify that Prebid Server is working properly with the server-side Adnuntius adapter. the `auId` below will not return a creative. Please substitute it with your own. +```json +{ + "imp": [{ + "id": "impression-id", + "banner": { + "format": [{ + "w": 980, + "h": 240 + }, { + "w": 980, + "h": 360 + }] + }, + "ext": { + "adnuntius": { + "auId": "abc123", + "maxDeals": 2 // Optional + } + } + }] +} ``` -"imp": [{ - "id": "impression-id", - "banner": { - "format": [{ - "w": 980, - "h": 240 - }, { - "w": 980, - "h": 360 - }] - }, - "ext": { - "adnuntius": { - "auId": "abc123" + +### Passing no Cookie in Prebid Server request + +As a publisher you have the option to set no cookie in the device request to let Adnuntius adserver know not to set cookies in the client's browser. In order to do that you just need to pass this in the request: + +```json +{ + "device": { + "ext": { + "noCookies": true } } -}] +} +``` + +### First Party Data + +publishers can use the `ortb2` configuration parameter to provide First Party Data. We accept all standard OpenRTB fields for both: + +- `ortb2.site` +- `ortb2.user` + +These fields are optional and only needed for user identification and contextual targeting. How to use it can be read here: [Prebid ortb2](https://docs.prebid.org/features/firstPartyData.html). Currently we only support this for our prebid server bidder, but will add it to the client bidder in the future. + +### Video requests + +Currently we only support client requests and instream context. An example request would look like this: + +```json +{ + "code": "video1", + "mediaTypes": { + "video": { + "playerSize": [640, 480], + "context": "instream" + } + }, + "bids": [{ + "bidder": "adnuntius", + "params": { + "auId": "00000000001cd429", //put your placement id here + + "video": { + "skippable": true, + "playback_method": ["auto_play_sound_off"] + } + } + }] +}; ``` diff --git a/dev-docs/bidders/adocean.md b/dev-docs/bidders/adocean.md index 0396275100..689ea32ecf 100644 --- a/dev-docs/bidders/adocean.md +++ b/dev-docs/bidders/adocean.md @@ -5,13 +5,16 @@ description: Prebid AdOcean Bidder Adaptor pbjs: true pbs: true biddercode: adocean -gdpr_supported: true +tcfeu_supported: true +gvl_id: 328 +sidebarType: 1 --- ### Note + The AdOcean bid adapter may require an additional setup from the AdOcean team. Please contact with your local Technical Support team or by visiting [AdOcean website](https://adocean-global.com/en/contact/). -### Bid Params +### Prebid.JS Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | @@ -19,3 +22,12 @@ The AdOcean bid adapter may require an additional setup from the AdOcean team. P | slaveId | required | slave ID | `'adoceanmyaozpniqismex'` | `string` | | masterId | required | master ID | `'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7'` | `string` | | emiter | required | traffic source id | `'myao.adocean.pl'` | `string` | + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------------------------------------------------|----------------------------------------------------|----------| +| slaveId | required | slave ID | `'adoceanmyaozpniqismex'` | `string` | +| masterId | required | master ID | `'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7'` | `string` | +| emitterPrefix | required | AdOcean emitter prefix | `'myao'` | `string` | diff --git a/dev-docs/bidders/adomega.md b/dev-docs/bidders/adomega.md index 96d8301c51..a5493d68ea 100644 --- a/dev-docs/bidders/adomega.md +++ b/dev-docs/bidders/adomega.md @@ -2,19 +2,28 @@ layout: bidder title: adOmega description: adOmega Bidder Adaptor -pbjs: true -pbs: true biddercode: adomega +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The adOmega bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/adoppler.md b/dev-docs/bidders/adoppler.md index ed306762b6..9a3e39ad5e 100644 --- a/dev-docs/bidders/adoppler.md +++ b/dev-docs/bidders/adoppler.md @@ -4,6 +4,7 @@ title: Adoppler pbs: true media_types: video biddercode: adoppler +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/adot.md b/dev-docs/bidders/adot.md index a7aa51a606..5fcb375f3a 100644 --- a/dev-docs/bidders/adot.md +++ b/dev-docs/bidders/adot.md @@ -4,10 +4,14 @@ title: Adot description: Prebid Adot Bidder Adapter biddercode: adot media_types: banner, video, native -gdpr_supported: true +userIds: pubProvidedId +tcfeu_supported: true gvl_id: 272 pbjs: true pbs: true +floors_supported: true +schain_supported: true +sidebarType: 1 --- ### Prebid JS @@ -18,22 +22,17 @@ pbs: true | Name | Scope | Description | Example | Type | |---------------------|-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------| | `placementId` | optional | The placement ID from Adot. | `'adot_placement_224521'` | `string` | -| `position` | optional | Specify the position of the ad as a relative measure of visibility or prominence. Allowed values: Unknown: `0` (default); Above the fold: `1` ; Below the fold: `3`. | `0` | `integer-` | -| `video` | required if the adUnit is a video | Object containing video targeting parameters. See [Video Object](#adot-video-object) for details. | `video: { mimes: ['video/mp4'] }` | `object` | +| `video` | optional | Object containing video targeting parameters. See [Video Object](#adot-video-object) for details. | | `object` | #### Video Object {: .table .table-bordered .table-striped } | Name | Scope | Description | Type | |-------------------|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------| -| `mimes` | required | Array of strings listing the content MIME types supported, e.g., `['video/mp4']`. | `Array` | -| `minduration` | optional | Integer that defines the minimum video ad duration in seconds. | `integer` | -| `maxduration` | optional | Integer that defines the maximum video ad duration in seconds. | `integer` | -| `protocols` | required | Array of supported video protocols, e.g., `[2, 3]` | `Array` | | `container` | optional | Selector used for finding the element in which the video player will be displayed, e.g., `#div-1`. The `ad unit code` will be used if no `container` is provided. | `string` | -| `instreamContext` | required if `video.context` is `instream` | String used to define the type of instream video. Allowed values: Pre-roll: `pre-roll`; Mid-roll: `mid-roll` ; Post-roll: `post-roll`. | `string` | #### Bid Config + #### PublisherId You can set a publisherId using `pbjs.setBidderConfig` for the bidder `adot` @@ -69,7 +68,6 @@ pbjs.setBidderConfig({ }); ``` - ### Prebid server #### Bid Params @@ -79,10 +77,11 @@ pbjs.setBidderConfig({ |---------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------| | `placementId` | optional | An ID which identifies this placement of the impression. | `'adot_placement_224521'` | `string` | | `parallax` | optional (only for prebid-server) | Specify if the wanted advertising's creative is a parallax. | `true/false` | `boolean` | +| `publisherPath` | optional | Specific to each integration. Do not use until asked by someone from adot. | `/hubvisor` | `string` | #### Testing Bid Request -The following test parameters can be used to verify that Prebid Server is working properly with the +The following test parameters can be used to verify that Prebid Server is working properly with the server-side adot adapter. This is a mobile Bid-request example. ``` diff --git a/dev-docs/bidders/adpartner.md b/dev-docs/bidders/adpartner.md index ead43860ca..91ba3353bc 100644 --- a/dev-docs/bidders/adpartner.md +++ b/dev-docs/bidders/adpartner.md @@ -5,6 +5,7 @@ description: Prebid AdPartner Bidder Adaptor pbjs: true biddercode: adpartner media_types: banner +sidebarType: 1 --- ### Bid Params @@ -12,4 +13,4 @@ media_types: banner {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |-------------|----------|-------------|----------------------|-----------| -| `partnerId` | required | Partner ID. | `5809` | `integer` | +| `partnerId` | required | Partner ID. | `5809` | `integer` | diff --git a/dev-docs/bidders/adplus.md b/dev-docs/bidders/adplus.md index 976e0131d5..58112efcb7 100644 --- a/dev-docs/bidders/adplus.md +++ b/dev-docs/bidders/adplus.md @@ -5,10 +5,12 @@ description: Prebid AdPlus Bidder Adapter biddercode: adplus media_types: banner pbjs: true +sidebarType: 1 --- -### Note: -The AdPlus Bidding adapter requires setup before beginning. Please contact us at adplus.destek@yaani.com.tr +### Note + +The AdPlus Bidding adapter requires setup before beginning. Please contact us at . ### Bid Params @@ -16,4 +18,4 @@ The AdPlus Bidding adapter requires setup before beginning. Please contact us at | Name | Scope | Description | Example | Type | |---------------|----------|---------------|-------------------------------------------|-----------| | `adUnitId` | required | Ad Unit ID | `'-3'` | `string` | -| `inventoryId` | required | Inventory ID | `'-1'` | `string` | \ No newline at end of file +| `inventoryId` | required | Inventory ID | `'-1'` | `string` | diff --git a/dev-docs/bidders/adpluto.md b/dev-docs/bidders/adpluto.md new file mode 100644 index 0000000000..af0212872d --- /dev/null +++ b/dev-docs/bidders/adpluto.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: AdPluto +description: AdPluto Bidder Adaptor +biddercode: adpluto +pbjs: true +pbs: false +media_types: banner, native, video +tcfeu_supported: false +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The AdPluto bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.adpluto.com'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/adpluto_dsp.md b/dev-docs/bidders/adpluto_dsp.md new file mode 100644 index 0000000000..26210e0aae --- /dev/null +++ b/dev-docs/bidders/adpluto_dsp.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: AdPluto DSP +description: AdPluto DSP Bidder Adaptor +biddercode: adpluto_dsp +pbjs: true +pbs: false +media_types: banner, native, video +tcfeu_supported: true +gvl_id: 14 (adkernel) +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernelAdn +sidebarType: 1 +--- + +### Note + +The AdPluto DSP bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------|----------|-----------------|----------------------|-----------| +| `host` | optional | Ad network host | `'rtb2-useast.adpluto.com'` | `string` | +| `pubId` | required | Publisher Id | `102` | `integer` | diff --git a/dev-docs/bidders/adpone.md b/dev-docs/bidders/adpone.md index c2da708ebd..5813e37280 100644 --- a/dev-docs/bidders/adpone.md +++ b/dev-docs/bidders/adpone.md @@ -8,6 +8,7 @@ biddercode: adpone deals_supported: false media_types: banner gvl_id: 799 +sidebarType: 1 --- diff --git a/dev-docs/bidders/adprime.md b/dev-docs/bidders/adprime.md index 4452ddfc97..e8e43a74c2 100644 --- a/dev-docs/bidders/adprime.md +++ b/dev-docs/bidders/adprime.md @@ -3,25 +3,34 @@ layout: bidder title: Adprime description: Prebid Adprime Bidder Adapter biddercode: adprime -gdpr_supported: true +tcfeu_supported: false usp_supported: true media_types: banner, video, native tcf2_supported: true pbjs: true pbs: true pbs_app_supported: true +sidebarType: 1 --- -### Note: +### Note -The Adprime Bidding adapter requires setup before beginning. Please contact us at rafal@adprime.com +The Adprime Bidding adapter requires setup before beginning. Please contact us at -### Bid Params +### Prebid.js Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | Adprime placement id | `'1234asdf'` | `string` | +| `placementId` | required | Adprime placement id | `'1234asdf'` | `string` | | `keywords` | optional | page context keywords | ['car','sport'] | `array` | -| `audiences` | optional | publisher audiences | ['aud1','aud2'] | `array` | +| `audiences` | optional | publisher audiences | ['aud1','aud2'] | `array` | +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `TagID` | required | Adprime ad tag id | `'1234asdf'` | `string` | +| `keywords` | optional | page context keywords | ['car','sport'] | `array` | +| `audiences` | optional | publisher audiences | ['aud1','aud2'] | `array` | diff --git a/dev-docs/bidders/adquery.md b/dev-docs/bidders/adquery.md index 8ab327d42b..c7099a031b 100644 --- a/dev-docs/bidders/adquery.md +++ b/dev-docs/bidders/adquery.md @@ -3,17 +3,21 @@ layout: bidder title: Adquery description: Prebid Adquery Bidder Adaptor pbjs: true +pbs: true biddercode: adquery -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true gvl_id: 902 +userIds: adQuery QiD +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|---------------|-------------------------------------------|-----------| -| `placementId` | required | Placement ID | `6d93f2a0e5f0fe2cc3a6e9e3ade964b43b07f897`| `string` | -| `type` | required | Ad Type | `banner300x250` | `string` | +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------|--------------------------------------------------------------------------|-----------| +| `placementId` | required | Placement ID | `6d93f2a0e5f0fe2cc3a6e9e3ade964b43b07f897` | `string` | +| `type` | required | Ad Type | `banner` | `string` | +| `sizes` | required | Allowed sizes | `320x100,300x250,336x280,300x50,300x100,320x50,320x480,300x150,320x180` | `string` | diff --git a/dev-docs/bidders/adrelevantis.md b/dev-docs/bidders/adrelevantis.md index 1d132f2b03..b3d7d00978 100644 --- a/dev-docs/bidders/adrelevantis.md +++ b/dev-docs/bidders/adrelevantis.md @@ -6,10 +6,12 @@ biddercode: adrelevantis media_types: banner, video, native fpd_supported: true pbjs: true +sidebarType: 1 --- -### Note: -This adapter is for displaying ads relevant to page content. Page content is analyzed dynamically in realtime to get its IAB Categories and keywords. The IAB Categories and keywords are sent as First Party Data of the bidder. DSP can, then, bid on the IAB Categories and keywords. You can find more info at (https://adrelevantis.xyz/2020/06/28/content-driven-header-bidding-with-prebid-js/). +### Note + +This adapter is for displaying ads relevant to page content. Page content is analyzed dynamically in realtime to get its IAB Categories and keywords. The IAB Categories and keywords are sent as First Party Data of the bidder. DSP can, then, bid on the IAB Categories and keywords. You can find more info at (). ### Bid Params @@ -20,18 +22,23 @@ This adapter is for displaying ads relevant to page content. Page content is ana | `cpm` | optional | forces bidder to insert custom cpm bid | 0.50 | `decimal` | #### First Party Data + Page content is analyzed at DOMContentLoaded event. The results (keywords and categories) are set as fpd of the bidder prior to requesting bids. -``` +```javascript pbjs.setBidderConfig({ - bidders: ['adrelevantis'], - config: { - ortb2: { - context: { - keywords: keywords, - category: categories - } - } - } + bidders: ['adrelevantis'], + config: { + ortb2: { + site: { + keywords: keywords, + ext: { + data: { + category: categories + } + } + } + } + } }); ``` diff --git a/dev-docs/bidders/adrino.md b/dev-docs/bidders/adrino.md new file mode 100644 index 0000000000..2f1f0a32c0 --- /dev/null +++ b/dev-docs/bidders/adrino.md @@ -0,0 +1,57 @@ +--- +layout: bidder +title: Adrino +description: Prebid Adrino Bidder Adapter +pbjs: true +pbs: true +biddercode: adrino +media_types: banner, native +tcfeu_supported: true +gvl_id: 1072 +sidebarType: 1 +--- + +### Note + +The Adrino bidder adapter requires setup and approval from the Adrino team. Please reach out to [wydawcy@adrino.pl](mailto:wydawcy@adrino.pl) for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------|----------|--------------------------------------|------------------|----------| +| `hash` | required | Identifier for specific ad placement | `'abcdef123456'` | `string` | + +### Native example + +``` +var adUnits = [ + code: '/12345678/prebid_native_example_1', + mediaTypes: { + native: { + image: { + required: true, + sizes: [[300, 210],[300,150],[140,100]] + }, + title: { + required: true + }, + sponsoredBy: { + required: false + }, + body: { + required: false + }, + icon: { + required: false + } + } + }, + bids: [{ + bidder: 'adrino', + params: { + hash: 'abcdef123456' + } + }] +]; +``` diff --git a/dev-docs/bidders/adriver.md b/dev-docs/bidders/adriver.md index 1a69fb4108..48efba8e07 100644 --- a/dev-docs/bidders/adriver.md +++ b/dev-docs/bidders/adriver.md @@ -5,8 +5,9 @@ description: Adriver adapter biddercode: adriver pbjs: true deals_supported: true -userIds: sharedId, id5Id, uid2Id +userIds: sharedId, id5Id, uid2Id, adriverId floors_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/adsinteractive.md b/dev-docs/bidders/adsinteractive.md new file mode 100644 index 0000000000..5cc2695efb --- /dev/null +++ b/dev-docs/bidders/adsinteractive.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: AdsInteractive +description: Prebid AdsInteractive Bidder Adapter +biddercode: adsinteractive +media_types: banner +pbjs: true +pbs: true +deals_supported: false +gpp_supported: true +tcfeu_supported: true +gvl_id: 1212 +usp_supported: false +coppa_supported: false +userIds: all +schain_supported: false +dchain_supported: false +safeframes_ok: false +floors_supported: false +fpd_supported: false +pbs_app_supported: false +prebid_member: false +multiformat_supported: will-not-bid +ortb_blocking_supported: false +--- + +### Registration + +The AdsInteractive adapter requires setup and approval. Please reach out to to setup your account. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `adUnit` | required | adUnit tag name | `'example_adunit_1'` | `string` | diff --git a/dev-docs/bidders/adsolut.md b/dev-docs/bidders/adsolut.md index 95fc34dd89..6019899486 100644 --- a/dev-docs/bidders/adsolut.md +++ b/dev-docs/bidders/adsolut.md @@ -2,12 +2,28 @@ layout: bidder title: adsolut description: Prebid adsolut Bidder Adaptor -pbjs: true biddercode: adsolut +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The adsolut Bidding adaptor requires setup and approval before beginning. Please reach out to for more details @@ -17,4 +33,4 @@ The adsolut Bidding adaptor requires setup and approval before beginning. Please | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Ad network's RTB host | `'cpm.adsolut.in'` | `string` | -| `zoneId` | required | RTB zone id | `'30164'` | `string` | +| `zoneId` | required | RTB zone id | `30164` | `integer` | diff --git a/dev-docs/bidders/adsparc.md b/dev-docs/bidders/adsparc.md index 5893688282..b4006e58bb 100644 --- a/dev-docs/bidders/adsparc.md +++ b/dev-docs/bidders/adsparc.md @@ -5,6 +5,7 @@ description: Prebid Adsparc Bidder Adaptor pbjs: true biddercode: adsparc aliasCode: aardvark +sidebarType: 1 --- ### bid params diff --git a/dev-docs/bidders/adspend.md b/dev-docs/bidders/adspend.md deleted file mode 100644 index bc836ffd91..0000000000 --- a/dev-docs/bidders/adspend.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: AdSpend -description: Prebid AdSpend Bidder Adaptor -pbjs: true -biddercode: adspend -media_types: banner -gdpr_supported: false -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|---------------|----------|----------------------------------------------------------------------------|------------------------|-----------------| -| `pubcid` | required | Publisher ID. | `0` | `string` | -| `bidfloor` | required | Minimum bid for this impression expressed in CPM. | `0.03` | `float` | - -Please note that cookie support is required diff --git a/dev-docs/bidders/adspirit.md b/dev-docs/bidders/adspirit.md index b94887380f..4bf7ec15a0 100644 --- a/dev-docs/bidders/adspirit.md +++ b/dev-docs/bidders/adspirit.md @@ -4,6 +4,7 @@ title: AdSpirit description: Prebid AdSpirit Bidder Adapter pbjs: true biddercode: adspirit +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/adstir.md b/dev-docs/bidders/adstir.md new file mode 100644 index 0000000000..463b0f6878 --- /dev/null +++ b/dev-docs/bidders/adstir.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: adstir +description: Prebid adstir Bidder Adapter +pbjs: true +pbs: false +biddercode: adstir +media_types: banner +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +schain_supported: true +dchain_supported: false +safeframes_ok: false +deals_supported: true +floors_supported: true +fpd_supported: false +prebid_member: false +ortb_blocking_supported: true +sidebarType: 1 +--- + +### Note + +The adstir Bidding adapter is available from Prebid.js version 8.24.0 and above. + +It requires setup before beginning. Please contact us at [sales@ad-stir.com](mailto:sales@ad-stir.com) + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------|----------|----------| +| `appId` | required | The AppID from adstir | `'TEST-MEDIA'` | `string` | +| `adSpaceNo` | required | The AdSpaceNo from adstir | `1` | `integer` | diff --git a/dev-docs/bidders/adsyield.md b/dev-docs/bidders/adsyield.md index f8e7b1b758..e1968b5567 100644 --- a/dev-docs/bidders/adsyield.md +++ b/dev-docs/bidders/adsyield.md @@ -2,17 +2,40 @@ layout: bidder title: AdsYield description: Prebid AdsYield Bidder Adaptor -pbjs: true biddercode: adsyield -aliasCode: admixer -media_types: video -gdpr_supported: true +pbjs: true +pbs: true +media_types: video, banner +userIds: all +fpd_supported: false +tcfeu_supported: false usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------|----------| -| `zone` | required | The unique identifier of the ad placement. Could be obtained from the AdsYield UI or from your account manager. | "e5ff8e48-4bd0-4a2c-9236-55530ab8981d" | `string` | + +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------------------------------------|-----------------------|-----------| +| `host` | required | Ad network's RTB host | `'open-adsyield.com'` | `string` | +| `adUnitId` | required | Ad Unit Id will be generated on AdsYield Platform. | `42` | `integer` | +| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | +| `custom1` | optional | Custom targeting field 1 | `'custom1'` | `string` | +| `custom2` | optional | Custom targeting field 2 | `'custom2'` | `string` | +| `custom3` | optional | Custom targeting field 3 | `'custom3'` | `string` | +| `custom4` | optional | Custom targeting field 4 | `'custom4'` | `string` | +| `custom5` | optional | Custom targeting field 5 | `'custom5'` | `string` | + +Adsyield server-side Prebid Server adapter requires only `publisherId` and `host` parameters. But Adsyield client-side Prebid.js adapter requires only `host`, `adUnitId`, `adUnitType`. + +Adsyield server-side Prebid Server adapter supports only `banner`, `video`, `audio`, `native` media types. But Adsyield client-side Prebid.js adapter supports only `banner` and `video` media types, doesn't support `audio` and `native`. diff --git a/dev-docs/bidders/adtarget.md b/dev-docs/bidders/adtarget.md index f8e832bfff..2dcadd245f 100644 --- a/dev-docs/bidders/adtarget.md +++ b/dev-docs/bidders/adtarget.md @@ -4,18 +4,20 @@ title: Adtarget description: Adtarget Bidder Adapter biddercode: adtarget media_types: banner, video -gdpr_supported: true +gvl_id: 779 +tcfeu_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId schain_supported: true coppa_supported: true usp_supported: true pbjs: true pbs: true +sidebarType: 1 --- ### Registration -To use the Adtarget bidder you will need an aid from an exchange account on [https://adtarget.com.tr](https://adtarget.com.tr). For further information, please contact kamil@adtarget.com.tr. +To use the Adtarget bidder you will need an aid from an exchange account on [adtarget.com.tr](https://adtarget.com.tr). For further information, please contact . ### Bid params @@ -24,62 +26,61 @@ To use the Adtarget bidder you will need an aid from an exchange account on [htt |-------|----------|---------------------------------|----------|-----------| | `aid` | required | The source ID from Adtarget platform. | `529814` | `integer` | - -# Description +### Description Provides a solution for accessing Video demand and display demand from Adtarget ### Test Parameters -``` - var adUnits = [ +```javascript +var adUnits = [ - // Video adUnit - { - code: 'videoPlayer', - mediaTypes: { - video: { - playerSize:[640,480] - context: 'instream' - } - }, - bids: [{ - bidder: 'adtarget', - params: { - aid: 331133 - } - }] - }, + // Video adUnit + { + code: 'videoPlayer', + mediaTypes: { + video: { + playerSize:[640,480] + context: 'instream' + } + }, + bids: [{ + bidder: 'adtarget', + params: { + aid: 331133 + } + }] + }, - // Banner adUnit - { - code: 'bannerAd', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [{ - bidder: 'adtarget', - params: { - aid: 529814 - } - }] + // Banner adUnit + { + code: 'bannerAd', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'adtarget', + params: { + aid: 529814 } - ]; + }] + } +]; ``` ### Additional Configuration -It is possible to configure requests to be splitted in chunks to have less bid requests in single http request +It is possible to configure requests to be splitted in chunks to have less bid requests in single http request (default value is 10) -``` - pbjs.setBidderConfig({ - config: { - adtarget: { - chunkSize: 1 // makes 1 http request per 1 adunit configured - } +```javascript +pbjs.setBidderConfig({ + config: { + adtarget: { + chunkSize: 1 // makes 1 http request per 1 adunit configured } - }); + } +}); ``` diff --git a/dev-docs/bidders/adtelligent.md b/dev-docs/bidders/adtelligent.md index dba4b76aa0..dc0d80ef12 100644 --- a/dev-docs/bidders/adtelligent.md +++ b/dev-docs/bidders/adtelligent.md @@ -4,8 +4,9 @@ title: Adtelligent description: Prebid Adtelligent Bidder Adapter biddercode: adtelligent media_types: video,banner -gdpr_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +gpp_supported: true +userIds: all (with commercial activation) schain_supported: true coppa_supported: true usp_supported: true @@ -14,8 +15,13 @@ prebid_member: true pbjs: true pbs: true gvl_id: 410 +sidebarType: 1 --- +### Prebid Server Note + +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} + ### Bid params {: .table .table-bordered .table-striped } @@ -24,15 +30,17 @@ gvl_id: 410 | `aid` | required | The source ID from Adtelligent. | `350975` | `integer` | ### Description + Get access to multiple demand partners across Adtelligent AdExchange and maximize your yield with Adtelligent header bidding adapter. Adtelligent header bidding adapter connects with Adtelligent demand sources in order to fetch bids. This adapter provides a solution for accessing Video demand and display demand. -Adtelligent now supports adpod. +Adtelligent now supports adpod. ### Test Parameters -``` + +``` javascript var adUnits = [ // Video instream adUnit @@ -107,10 +115,10 @@ Adtelligent now supports adpod. ### Additional Configuration -It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request +It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request (default value is 10). -``` +``` javascript pbjs.setBidderConfig({ config: { adtelligent: { diff --git a/dev-docs/bidders/adtrgtme.md b/dev-docs/bidders/adtrgtme.md new file mode 100644 index 0000000000..4b03e6916f --- /dev/null +++ b/dev-docs/bidders/adtrgtme.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Adtarget.me +description: Prebid Adtarget.me bidder adapter +biddercode: adtrgtme +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +media_types: banner +safeframes_ok: true +deals_supported: false +floors_supported: false +fpd_supported: true +pbjs: true +pbs: true +pbs_app_supported: true +prebid_member: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Note + +The Adtrgtme bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|-----------|----------|-------------|--------------|----------| +| `site_id` | required | Site ID | `1234567890` | `uint64` | diff --git a/dev-docs/bidders/adtrue.md b/dev-docs/bidders/adtrue.md index c01ea18ef5..f55019420c 100644 --- a/dev-docs/bidders/adtrue.md +++ b/dev-docs/bidders/adtrue.md @@ -5,9 +5,10 @@ description: AdTrue Exchange Bidder Adapter pbjs: true biddercode: adtrue media_types: banner -gdpr_supported: true +tcfeu_supported: false schain_supported: true usp_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/aduptech.md b/dev-docs/bidders/aduptech.md index 2e1a092b21..4a935edf43 100644 --- a/dev-docs/bidders/aduptech.md +++ b/dev-docs/bidders/aduptech.md @@ -3,17 +3,18 @@ layout: bidder title: AdUp Technology description: Prebid Bidder Adapter for AdUp Technology biddercode: aduptech -gdpr_supported: true +tcfeu_supported: true +floors_supported: true gvl_id: 647 media_types: banner, native pbjs: true +sidebarType: 1 --- ### Registration To use, our bidding adapter requires proper setup, including an existing publisher account, as well as approval from AdUp Technology.
      For more information visit [www.adup-tech.com](https://www.adup-tech.com/en) or contact [info@adup-tech.com](mailto:info@adup-tech.com). - ### Bid params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/advangelists.md b/dev-docs/bidders/advangelists.md index 79fdaca310..36436023c4 100644 --- a/dev-docs/bidders/advangelists.md +++ b/dev-docs/bidders/advangelists.md @@ -5,17 +5,19 @@ description: Prebid Advangelists Bidder Adapter pbjs: true pbs: true biddercode: advangelists +sidebarType: 1 --- -### Note: -For more information about [Advangelists https://advangelists.com], please contact lokesh@advangelists.com +### Note + +For more information about [Advangelists https://advangelists.com], please contact ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------------|----------|------------------|------------------------------------------|-------------------| -| `placement ` | required | | `'263'` | `string` | +| `placement` | required | | `'263'` | `string` | | `pubid` | required | | `'0cf8d6d643e13d86a5b6374148a4afac'` | `string` | | `mimes` | optional | video only | `['video/mp4', 'application/javascript']`| `array of strings`| | `playbackmethod` | optional | video only | `[2,6]` | `array of numbers`| diff --git a/dev-docs/bidders/advenue.md b/dev-docs/bidders/advenue.md deleted file mode 100644 index 7e4559328c..0000000000 --- a/dev-docs/bidders/advenue.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: Advenue -description: Prebid Advenue Bidder Adaptor -pbjs: true -biddercode: advenue -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example |type| -| :----------- | :--------- | :------------ | :----------------- |:---| -| `placementId` | required | Placement Id will be generated on Advenue Platform. | 0 |integer| -| `traffic` | optional | Type traffic | 'banner' |string| diff --git a/dev-docs/bidders/advertly.md b/dev-docs/bidders/advertly.md deleted file mode 100644 index 016a67b285..0000000000 --- a/dev-docs/bidders/advertly.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: advertly -description: Prebid ADVERTLY Bidder Adapter -pbjs: true -biddercode: advertly -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|----------------------------------------------------------------------------------------|-----------------------------|-----------| -| `publisherId` | required | Publisher id associated with Advertly | `1` | `integer` | diff --git a/dev-docs/bidders/adview.md b/dev-docs/bidders/adview.md index a69b21ce4b..221dd52c0c 100644 --- a/dev-docs/bidders/adview.md +++ b/dev-docs/bidders/adview.md @@ -3,27 +3,29 @@ layout: bidder title: AdView description: Prebid AdView Bidder Adapter biddercode: AdView -gdpr_supported: true +tcfeu_supported: true gvl_id: 1022 usp_supported: true coppa_supported: true +gpp_sids: tcfeu, usca schain_supported: true dchain_supported: false -userId: media_types: banner, video, native -safeframes_ok: true +floors_supported: true bidder_supports_deals: true pbjs: false pbs: true pbs_app_supported: true prebid_member: false +safeframes_ok: true +multiformat_supported: will-bid-on-any +ortb_blocking_supported: true +sidebarType: 1 --- -### Note: - -Currently adapter doesn’t support multi impression and can not perform impression splitting, so only the first impression will be delivered. +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at partner@adview.com +The Example Bidding adapter requires setup before beginning. Please contact us at ### Bid Params @@ -31,4 +33,4 @@ The Example Bidding adapter requires setup before beginning. Please contact us a | Name | Scope | Description | Example | Type | |---------------|----------|--------------|-----------|----------| | `placementId` | required | Placement ID | `'posid00001'` | `string` | -| `accountId` | required | Account ID | `'accountid01'` | `string` | \ No newline at end of file +| `accountId` | required | Account ID | `'accountid01'` | `string` | diff --git a/dev-docs/bidders/adxcg.md b/dev-docs/bidders/adxcg.md index f7803f0ac5..1bf59ed8af 100644 --- a/dev-docs/bidders/adxcg.md +++ b/dev-docs/bidders/adxcg.md @@ -8,13 +8,16 @@ pbs: true pbs_app_supported: true biddercode: adxcg media_types: native, video -gdpr_supported: true +tcfeu_supported: false userIds: id5Id, identityLink, pubCommonId, unifiedId +sidebarType: 1 --- ### Note -Prebid-server activation requires setup and approval before beginning. Please reach out to your account manager or info@adxcg.com for more details. +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} + +Prebid-server activation requires setup and approval before beginning. Please reach out to your account manager or for more details. ### Bid Params diff --git a/dev-docs/bidders/adyoulike.md b/dev-docs/bidders/adyoulike.md index a8f6b5a454..156146f52e 100644 --- a/dev-docs/bidders/adyoulike.md +++ b/dev-docs/bidders/adyoulike.md @@ -6,20 +6,24 @@ pbjs: true pbs: true media_types: banner, video, native biddercode: adyoulike -gdpr_supported: true +userIds: criteo, sharedId +tcfeu_supported: true +gvl_id: 259 usp_supported: true floors_supported: true +schain_supported: true +sidebarType: 1 --- -### Note: -The Adyoulike Header Bidding adaptor requires setup and approval from the Adyoulike team. Please reach out to your account manager or prebid@adyoulike.com for more information. +### Note + +The Adyoulike Header Bidding adaptor requires setup and approval from the Adyoulike team. Please reach out to your account manager or for more information. ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |-------------|----------|----------------------------------|--------------------------------------|----------| | `placement` | required | The placement ID from Adyoulike. | `'194f787b85c829fb8822cdaf1ae64435'` | `string` | - Same 'placement' parameter can be used from either prebid JS or prebid server. diff --git a/dev-docs/bidders/afp.md b/dev-docs/bidders/afp.md index 07e3d197ea..3525385197 100644 --- a/dev-docs/bidders/afp.md +++ b/dev-docs/bidders/afp.md @@ -6,6 +6,7 @@ pbjs: true media_types: banner, video biddercode: afp safeframes_ok: false +sidebarType: 1 --- ### Note @@ -14,7 +15,6 @@ You can use this adapter to get a bid from AFP. Please reach out to your AFP account team before using this plugin to get placeId. The code below returns a demo ad. - ### Bid Params {: .table .table-bordered .table-striped } @@ -23,178 +23,177 @@ The code below returns a demo ad. | `placeId` | required | Place id. | '5af45ad34d506ee7acad0c26' | `string` | | `placeType` | required | Place type. | 'In-image', 'In-image Max', 'In-content Banner', 'In-content Video', 'Out-content Video', 'In-content Stories', 'Action Scroller', 'Action Scroller Light', 'Just Banner' | `string` | | `placeContainer` | required (if the frame is not safe) | The container of the place where the ad will be displayed. The css selector is specified as the value. | '#container' | `string` | -| `imageUrl` | required (for 'In-image', 'In-image Max' placeType) | URL of the image on which the banner will be displayed. | 'https://creative.astraone.io/files/default_image-1-600x400.jpg' | `string` | +| `imageUrl` | required (for 'In-image', 'In-image Max' placeType) | URL of the image on which the banner will be displayed. | '' | `string` | | `imageWidth` | required (for 'In-image', 'In-image Max' placeType) | Image width. | 600 | `integer` | | `imageHeight` | required (for 'In-image', 'In-image Max' placeType) | Image height. | 400 | `integer` | - ### InImage Example page - ```html - - Prebid.js In-image Example - - + + Prebid.js In-image Example + +

      In-image

      -
      - -
      - +
      + +
      +

      Just Banner

      -
      - +
      +
      ``` + ### InImage Example page with GPT ```html - - Prebid.js In-image Example - - - + + Prebid.js In-image Example + + +

      In-image

      -
      - -
      -
      - -
      +
      + +
      +
      + +
      diff --git a/dev-docs/bidders/aidem.md b/dev-docs/bidders/aidem.md new file mode 100644 index 0000000000..ea8ba9b2ed --- /dev/null +++ b/dev-docs/bidders/aidem.md @@ -0,0 +1,218 @@ +--- +layout: bidder +title: AIDEM +description: AIDEM Bidder Adapter +biddercode: aidem +tcfeu_supported: true +gvl_id: 1218 +usp_supported: true +coppa_supported: true +schain_supported: false +dchain_supported: false +userId: none +media_types: banner, video +safeframes_ok: true +deals_supported: true +floors_supported: true +fpd_supported: true +pbjs: true +pbs: true +prebid_member: true +ortb_blocking_supported: false +sidebarType: 1 +--- + +## Description + +This module connects publishers to AIDEM demand. + +This module is GDPR and CCPA compliant, and no 3rd party userIds are allowed. + +### Global Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------|------------|----------| +| `siteId` | required | Unique site ID | `'ABCDEF'` | `String` | +| `publisherId` | required | Unique publisher ID | `'FEDCBA'` | `String` | +| `placementId` | optional | Unique publisher tag ID | `'ABCDEF'` | `String` | +| `rateLimit` | optional | Limit the volume sent to AIDEM. Must be between 0 and 1 | `0.6` | `Number` | + +#### Banner Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|--------------------------|---------------------------|---------| +| `sizes` | required | List of the sizes wanted | `[[300, 250], [300,600]]` | `Array` | + +#### Video Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------------------------|-----------------|-----------| +| `context` | required | One of instream, outstream, adpod | `'instream'` | `String` | +| `playerSize` | required | Width and height of the player | `'[640, 480]'` | `Array` | +| `maxduration` | required | Maximum video ad duration, in seconds | `30` | `Integer` | +| `minduration` | required | Minimum video ad duration, in seconds | `5` | `Integer` | +| `mimes` | required | List of the content MIME types supported by the player | `["video/mp4"]` | `Array` | +| `protocols` | required | An array of supported video protocols. At least one supported protocol must be specified, where: `2` = VAST 2.0 `3` = VAST 3.0 `5` = VAST 2.0 wrapper `6` = VAST 3.0 wrapper | `2` | `Array` | + +#### Additional Config + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------------|----------|---------------------------------------------------------|---------|-----------| +| `coppa` | optional | Child Online Privacy Protection Act | `true` | `Boolean` | +| `consentManagement` | optional | [Consent Management Object](#consent-management-object) | `{}` | `Object` | + +#### Consent Management Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------|----------|--------------------------------------------------------------------------------------------------|---------|----------| +| `gdpr` | optional | GDPR Object see [Prebid.js doc](https://docs.prebid.org/dev-docs/modules/consentManagement.html) | `{}` | `Object` | +| `usp` | optional | USP Object see [Prebid.js doc](https://docs.prebid.org/dev-docs/modules/consentManagementUsp.html) | `{}` | `Object` | + +#### Example Banner ad unit + +```javascript +var adUnits = [{ + code: 'banner-prebid-test-site', + mediaTypes: { + banner: { + sizes: [ + [300, 600], + [300, 250] + ] + } + }, + bids: [{ + bidder: 'aidem', + params: { + siteId: 'prebid-test-siteId', + publisherId: 'prebid-test-publisherId', + }, + }] +}]; +``` + +#### Example Video ad unit + +```javascript +var adUnits = [{ + code: 'video-prebid-test-site', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + maxduration: 30, + minduration: 5, + mimes: ["video/mp4"], + protocols: 2 + } + }, + bids: [{ + bidder: 'aidem', + params: { + siteId: 'prebid-test-siteId', + publisherId: 'prebid-test-publisherId', + }, + }] +}]; +``` + +#### Example GDPR Consent Management + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function (){ + pbjs.setConfig({ + consentManagement: { + gdpr:{ + cmpApi: 'iab' + } + } + }); +}) +``` + +#### Example USP Consent Management + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function (){ + pbjs.setConfig({ + consentManagement: { + usp:{ + cmpApi: 'static', + consentData:{ + getUSPData:{ + uspString: '1YYY' + } + } + } + } + }); +}) +``` + +#### Setting First Party Data (FPD) + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function (){ + pbjs.setConfig({ + ortb2: { + site: { + cat: ['IAB2'], + sectioncat: ['IAB2-2'], + keywords: 'power tools, drills' + }, + } + }); +}) +``` + +### Supported Media Types + +{: .table .table-bordered .table-striped } +| Type | Support | +|--------|--------------------------------------------------------------------| +| Banner | Support all [AIDEM Sizes](https://kb.aidem.com/ssp/lists/adsizes/) | +| Video | Support all [AIDEM Sizes](https://kb.aidem.com/ssp/lists/adsizes/) | + +## Setup / Dev Guide + +```shell +nvm use + +npm install + +gulp build --modules=aidemBidAdapter + +gulp serve --modules=aidemBidAdapter + +# Open a chrome browser with no ad blockers enabled, and paste in this URL. The `pbjs_debug=true` is needed if you want to enable `loggerInfo` output on the `console` tab of Chrome Developer Tools. +http://localhost:9999/integrationExamples/gpt/hello_world.html?pbjs_debug=true +``` + +If you need to run the tests suite but do *not* want to have to build the full adapter and serve it, simply run: + +```shell +gulp test --file "test/spec/modules/aidemBidAdapter_spec.js" +``` + +For video: gulp serve --modules=aidemBidAdapter,dfpAdServerVideo + +## FAQs + +#### How do I view AIDEM bid request? + +Navigate to a page where AIDEM is setup to bid. In the network tab, +search for requests to `zero.aidemsrv.com/bid/request`. diff --git a/dev-docs/bidders/aja.md b/dev-docs/bidders/aja.md index 11233433ec..419d28e224 100644 --- a/dev-docs/bidders/aja.md +++ b/dev-docs/bidders/aja.md @@ -2,11 +2,23 @@ layout: bidder title: AJA description: Prebid AJA Bidder Adaptor -userIds: criteo, unifiedId, imuid pbjs: true pbs: true biddercode: aja -media_types: video, native +media_types: banner +tcfeu_supported: false +floors_supported: false +schain_supported: true +dchain_supported: false +usp_supported: false +gpp_supported: false +coppa_supported: false +fpd_supported: false +multiformat_supported: false +safeframes_ok: true +deals_supported: false +userIds: criteo, unifiedId, imuid +sidebarType: 1 --- ### Note diff --git a/dev-docs/bidders/algorix.md b/dev-docs/bidders/algorix.md index 1ac9335c56..705586e6c0 100644 --- a/dev-docs/bidders/algorix.md +++ b/dev-docs/bidders/algorix.md @@ -3,7 +3,7 @@ layout: bidder title: AlgoriX description: Prebid AlgoriX Bidder Adapter biddercode: algorix -gdpr_supported: false +tcfeu_supported: true gvl_id: usp_supported: true coppa_supported: true @@ -13,11 +13,12 @@ pbjs: false pbs: true pbs_app_supported: true prebid_member: true +sidebarType: 1 --- -### Note: +### Note -AlgoriX adapter requires setup and approval from the AlgoriX team, even for existing in-app developers and publishers. Please reach out to your account team or email to prebid@algorix.co for more information. +AlgoriX adapter requires setup and approval from the AlgoriX team, even for existing in-app developers and publishers. Please reach out to your account team or email to for more information. ### Bid Params @@ -28,9 +29,10 @@ AlgoriX adapter requires setup and approval from the AlgoriX team, even for exis | `token` | required | Token | `'028bca2d3b5c4f0ba155fa34864b0c4d'` | `string` | | `placementId` | optional | Placement Id | `'123456'` | `string` | | `appId` | optional | App Id | `'asdasdasd'` | `string` | -| `region` | optional | Server Region | `'APAC' or 'USE'` | `string` | +| `region` | optional | Server Region | `'APAC', 'USE', 'EUC'` | `string` | Note: + * Prebid Server adapter only checks for and uses first imp bid params. All other imp bid params are ignored. * placementId and appId will be generated on AlgoriX Platform. -* region is optional param, which determine the AlgoriX server. APAC for SG endpoint, USE for US endpoint, Other for Global endpoint. +* region is optional param, which determine the AlgoriX server. APAC for SG endpoint, USE for US endpoint, EUC for EU endpoint, Other for Global endpoint. diff --git a/dev-docs/bidders/alkimi.md b/dev-docs/bidders/alkimi.md new file mode 100644 index 0000000000..cd90e9a85b --- /dev/null +++ b/dev-docs/bidders/alkimi.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Alkimi +description: Prebid Alkimi Bidder Adapter +biddercode: alkimi +media_types: banner, video +pbjs: true +pbs: true +schain_supported: true +gvl_id: 1169 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +userIds: all +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|-----------| +| `token` | required | The ID issued by Alkimi to the publisher | `'8a80d8e9-0cf9-4329-8486-6f5bbcd8a61a'` | `string` | +| `bidFloor` | optional | Minimum bid for this impression expressed in CPM. | `0` | `float` | +| `instl` | optional | Set to 1 if using interstitial (default: 0) | `1` | `integer` | +| `exp` | optional | Advisory as to the number of seconds that may elapse between the auction and the actual impression. | `10` | `integer` | diff --git a/dev-docs/bidders/ampliffy.md b/dev-docs/bidders/ampliffy.md new file mode 100644 index 0000000000..653794a1fd --- /dev/null +++ b/dev-docs/bidders/ampliffy.md @@ -0,0 +1,108 @@ +--- +layout: bidder +title: Ampliffy +description: Prebid Ampliffy Bidder Adapter +biddercode: ampliffy +pbjs: true +tcfeu_supported: true +gvl_id: 1258 +media_types: banner, video, native +sidebarType: 1 +multiformat_supported: will-bid-on-one +safeframes_ok: true +--- + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Supported media types](#supported-media-types) +* [Modules to include in your build process](#modules-to-include-in-your-build-process) +* [Bid request parameters](#bid-request-parameters) + * [Banner](#banner) + * [Video](#video) +* [Examples](#examples) + +## Introduction + +Publishers can use Prebid.js to call Ampliffy through our client-side adapter: Prebid.js calls ampliffy directly from the browser using our client-side adapter. For configuration instructions, see the below on this page. + +### Example + +## Supported media types + +The following table lists the media types that Ampliffy supports. + +{: .table .table-bordered .table-striped } + +| Type | +|--------| +| banner | +| video | +| native | + +## Modules to include in your build process + +If you are building the JS binary on your own from source code, follow the instructions in [Prebid.js project README](https://github.com/prebid/Prebid.js/blob/master/README.md#build-optimization). You will need to include the `ampliffyBidAdapter`. To show video ads with Google Ad Manager, you need to include the `dfpAdServerVideo` module. We highly recommend adding the `gptPreAuction` module as well, which improves a DSP's ability to bid accurately on your supply. The following is an example build command that include these modules:
      +`gulp build --modules=ampliffyBidAdapter,dfpAdServerVideo,gptPreAuction` + +If you are using a JSON file to specify modules, add `ampliffyBidAdapter` and `dfpAdServerVideo` to the modules array as follows: + +```javascript +[ + "ampliffyBidAdapter", + "dfpAdServerVideo", + "gptPreAuction" +] +``` + +## Bid request parameters + +### Banner + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Type | Description | +|---|----------|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `placementId` | Required | String | An Ampliffy-specific identifier that is associated with this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'3723'`, `'6482'`, `'3639'` | +| `format` | Required | String | specify 'display' for this kind of inventory` | +| `server` | Optional | String | An Ampliffy-specific identifier that is associated with this ad unit` | + +### Video + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Type | Description | +|---|---|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `placementId` | Required | String | An Ampliffy-specific identifier that is associated with this ad unit. It will be associated with the single size, if the size is provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'3723'`, `'6482'`, `'3639'`
      **Note:** You can re-use the existing `siteId` within the same flex position or video size, if the video adapts to the containing `
      ` element. | +| `format` | Required | String | specify 'video' for this kind of inventory` | +| `server` | Optional | String | An Ampliffy-specific identifier that is associated with this ad unit` | + +## Examples + +**Video (instream):**
      + +```javascript +var adUnits = [{ + code: 'video1', + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'instream' + }, + }, + bids: [{ + bidder: 'ampliffy', + params: { + server: 'bidder.ampliffy.com', + placementId: '1213213/example/vrutal_/', + format: 'video' + } + }] +}]; + +``` diff --git a/dev-docs/bidders/amx-server.md b/dev-docs/bidders/amx-server.md new file mode 100644 index 0000000000..31d232b5e9 --- /dev/null +++ b/dev-docs/bidders/amx-server.md @@ -0,0 +1,81 @@ +--- +layout: bidder +title: AMX RTB +description: AMX RTB Bid Adapter +hide: true +schain_supported: true +tcfeu_supported: true +usp_supported: true +coppa_supported: true +userIds: all +biddercode: amx +safeframes_ok: true +media_types: banner, video, native +pbjs: false +pbs: true +pbs_app_supported: true +fpd_supported: true +multiformat_supported: true +ortb_blocking_supported: true +gpp_supported: true +gvl_id: 737 +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------------------------------------------|---------------------------------|----------| +| `tagId` | required | Tag ID | `'cHJlYmlkLm9yZw'` | `string` | +| `testMode` | optional | Activate 100% fill ads | `true` | `boolean`| +| `adUnitId` | optional | Ad Unit ID used in reporting. Will default to `bid.adUnitCode` | `'sticky_banner'` | `string` | + +### Test Parameters + +To enable 100% fill test ads, you can use the following `params`: + +```javascript +{ + testMode: true, + tagId: "cHJlYmlkLm9yZw" +} +``` + +This will produce a bid at $10 with a test creative. + +Note that the `tagId` is case-sensitive. Do not use `cHJlYmlkLm9yZw` in production environments: this ID is for testing only. + +### First Party Data + +From Prebid.js >= 4.30, publishers can use the `ortb2` configuration parameter to provide First Party Data. We accept all standard OpenRTB fields for both: + +- `ortb2.site` +- `ortb2.user` + +Note that all fields are optional. For contextual data (e.g. categories), standard IAB taxonomies are supported. We do not support passing first party data via bid parameters. + +#### Example - Setting ortb2.site and ortb2.user fields + +```javascript +pbjs.setBidderConfig({ + bidders: ["amx"], + config: { + ortb2: { + site: { + keywords: "kw1,kw2", + cat: ["IAB2"], + sectioncat: ["IAB2-1"], + pagecat: ["IAB2-22"], + content: { + context: 5, + }, + }, + user: { + yob: 1981, + keywords: "kw3", + }, + }, + }, +}); +``` diff --git a/dev-docs/bidders/amx.md b/dev-docs/bidders/amx.md index f8f3ff6574..b19d3bdce9 100644 --- a/dev-docs/bidders/amx.md +++ b/dev-docs/bidders/amx.md @@ -1,31 +1,48 @@ --- layout: bidder title: AMX RTB -description: AMX RTB Prebid Bid Adapter +description: AMX RTB Bid Adapter hide: true schain_supported: true -gdpr_supported: true +tcfeu_supported: true +floors_supported: true usp_supported: true coppa_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId, amxId +userIds: all biddercode: amx safeframes_ok: true media_types: banner, video pbjs: true -pbs: true -pbs_app_supported: true +pbs: false fpd_supported: true +gpp_supported: true +multiformat_supported: true +ortb_blocking_supported: true gvl_id: 737 +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |-------------|----------|-----------------------------------------------------------------|---------------------------------|----------| -| `tagId` | required | Tag ID | `'cHJlYmlkLm9yZw'` | `string` | -| `testMode` | optional | Activate 100% fill ads | `true` | `boolean`| -| `adUnitId` | optional | Ad Unit ID used in reporting. Will default to `bid.adUnitCode` | `'sticky_banner'` | `string` | +| `tagId` | required | Tag ID | `'cHJlYmlkLm9yZw'` | `string` | +| `testMode` | optional | Activate 100% fill ads | `true` | `boolean`| +| `adUnitId` | optional | Ad Unit ID used in reporting. Will default to `bid.adUnitCode` | `'sticky_banner'` | `string` | + +### Bidder Settings + +The AMX RTB bid adapter uses local storage. Please add `storageAllowed` in your bidder settings: + +```js +// https://docs.prebid.org/dev-docs/publisher-api-reference/bidderSettings.html +pbjs.bidderSettings = { + amx: { + storageAllowed: true, + }, +}; +``` ### Test Parameters @@ -41,3 +58,37 @@ To enable 100% fill test ads, you can use the following `params`: This will produce a bid at $10 with a test creative. Note that the `tagId` is case-sensitive. Do not use `cHJlYmlkLm9yZw` in production environments: this ID is for testing only. + +### First Party Data + +From Prebid.js >= 4.30, publishers can use the `ortb2` configuration parameter to provide First Party Data. We accept all standard OpenRTB fields for both: + +- `ortb2.site` +- `ortb2.user` + +Note that all fields are optional. For contextual data (e.g. categories), standard IAB taxonomies are supported. We do not support passing first party data via bid parameters. + +#### Example - Setting ortb2.site and ortb2.user fields + +```javascript +pbjs.setBidderConfig({ + bidders: ["amx"], + config: { + ortb2: { + site: { + keywords: "kw1,kw2", + cat: ["IAB2"], + sectioncat: ["IAB2-1"], + pagecat: ["IAB2-22"], + content: { + context: 5, + }, + }, + user: { + yob: 1981, + keywords: "kw3", + }, + }, + }, +}); +``` diff --git a/dev-docs/bidders/andBeyondMedia.md b/dev-docs/bidders/andBeyondMedia.md new file mode 100644 index 0000000000..edb9066190 --- /dev/null +++ b/dev-docs/bidders/andBeyondMedia.md @@ -0,0 +1,22 @@ +--- +layout: bidder +title: AndBeyond.Media +description: Prebid AndBeyond.Media Bidder Adapter +biddercode: beyondmedia +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +pbjs: true +pbs: true +sidebarType: 1 +--- + +### Prebid Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement Id | `'0'` | `'string'` | diff --git a/dev-docs/bidders/andbeyond.md b/dev-docs/bidders/andbeyond.md deleted file mode 100644 index 66964793fc..0000000000 --- a/dev-docs/bidders/andbeyond.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: bidder -title: Andbeyond Media -description: Andbeyond Media -pbjs: true -pbs: true -biddercode: andbeyond -media_types: banner, native, video -gdpr_supported: true -usp_supported: true -schain_supported: true -aliasCode : adkernel ---- - -### Note: - -The andbeyond Bidding adaptor requires setup and approval before beginning. Please reach out to for more details - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-----------------------|---------------------------|----------| -| `host` | required | Our Host | `'cpm.andbeyond.media'` | `string` | -| `zoneId` | required | Example RTB zone id | `'12345'` | `string` | diff --git a/dev-docs/bidders/aniview.md b/dev-docs/bidders/aniview.md index a51cc6f840..bf101762d3 100644 --- a/dev-docs/bidders/aniview.md +++ b/dev-docs/bidders/aniview.md @@ -5,15 +5,17 @@ description: Prebid ANIVIEW Bidder Adapter pbjs: true biddercode: aniview media_types: banner, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true gvl_id: 780 +sidebarType: 1 --- -### Note: -For more information about [Aniview Ad Server](https://www.aniview.com/), please contact info@aniview.com. +### Note + +For more information about [Aniview Ad Server](https://www.aniview.com/), please contact . ### Bid Params @@ -24,8 +26,9 @@ For more information about [Aniview Ad Server](https://www.aniview.com/), please | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` -videoAdUnit = [ + +```javascript +const videoAdUnit = [ { code: 'video1', mediaTypes: { diff --git a/dev-docs/bidders/anyclip.md b/dev-docs/bidders/anyclip.md new file mode 100644 index 0000000000..e4ae4913cb --- /dev/null +++ b/dev-docs/bidders/anyclip.md @@ -0,0 +1,61 @@ +--- +layout: bidder +title: AnyClip +description: AnyClip Bidder Adapter +biddercode: anyclip +tcfeu_supported: false +usp_supported: true +coppa_supported: true +gpp_sids: usp +schain_supported: true +dchain_supported: false +userId: pubProvidedId, unifiedId +media_types: banner +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-not-bid +ortb_blocking_supported: true +privacy_sandbox: no +safeframes_ok: true +sidebarType: 1 +--- + +### Note + +For more information about [AnyClip](https://www.anyclip.com), please contact [support@anyclip.com](support@anyclip.com). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|--------------------------|-----------| +| `publisherId` | required | Publisher ID | `'12345'` | `string` | +| `supplyTagId` | required | Supply Tag ID | `'-mptNo0BycUG4oCDgGrU'` | `string` | +| `floor` | optional | Floor Price | `0.5` | `float` | + +#### Sample Banner only Ad Unit + +```js +var adUnits = [{ + code: 'adunit1', // ad slot HTML element ID + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'anyclip', + params: { + publisherId: '12345', // required, string + supplyTagId: '-mptNo0BycUG4oCDgGrU', // required, string + floor: 0.5 // optional, floor + } + }] +}] +``` diff --git a/dev-docs/bidders/aol.md b/dev-docs/bidders/aol.md index 6e162546aa..bb5afc9aee 100644 --- a/dev-docs/bidders/aol.md +++ b/dev-docs/bidders/aol.md @@ -4,16 +4,23 @@ title: AOL description: Prebid AOL Bidder Adaptor pbjs: true biddercode: aol -gdpr_supported: true +tcfeu_supported: false usp_supported: true gvl_id: 25 userIds: connectId +sidebarType: 1 --- -### IMPORTANT NOTICE! +### Disclosure + +This adapter may not handle user syncs for TCF2 or GPP correctly. The user sync consent querystring parameters are generated at the time of the bid request and might be stale at the time of the user sync. See + +### IMPORTANT NOTICE + **TL;DR** -1. The `aol` adapter is scheduled to be depreciated. -2. Our New `yahoossp` is available for early adoption. + +1. The `aol` adapter is scheduled to be deprecated. +2. Our New `yahoossp` is available for adoption. 3. Please contact your Account Manager/Executive for migration details. Dear Publishers & Partners, @@ -24,7 +31,8 @@ FYI - The oneVideo adapter is scheduled for depreciation in the upcoming months. Thanks in advance, Yahoo SSP -### Note: +### Note + This adapter allows use of both ONE by AOL: Display and ONE by AOL: Mobile platforms. In order to differentiate these sources of demand in your ad server and reporting, you may use the optional `onedisplay` and `onemobile` adapter aliases instead. ### Bid Params diff --git a/dev-docs/bidders/apacdex.md b/dev-docs/bidders/apacdex.md index 9a29acd80c..cb9ad73772 100644 --- a/dev-docs/bidders/apacdex.md +++ b/dev-docs/bidders/apacdex.md @@ -5,25 +5,27 @@ description: Prebid APAC Digital Exchange Bidder Adapter pbjs: true biddercode: apacdex media_types: banner, video -gdpr_supported: true +tcfeu_supported: false schain_supported: true usp_supported: true userIds: all floors_supported: true pbs: true pbs_app_supported: true +sidebarType: 1 --- ### Table of Contents -- [Bid Params](#apacdex-bid-params) -- [Geo Object](#apacdex-geo-object) -- [Video Ad Unit](#apacdex-video-ad-unit) -- [Sample Banner Ad Unit](#apacdex-sample-banner-ad-unit) -- [Sample Video Ad Unit: Instream](#apacdex-sample-instream-ad-unit) -- [Sample Video Ad Unit: Outstream](#apacdex-sample-outstream-ad-unit) +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [Geo Object](#geo-object) +- [Video Ad Unit](#video-ad-unit) +- [Sample Banner Ad Unit](#sample-banner-ad-unit) +- [Sample Video Ad Unit: Instream](#sample-video-ad-unit-instream) +- [Sample Video Ad Unit: Outstream](#sample-video-ad-unit-outstream) - + ### Bid Params @@ -37,7 +39,7 @@ pbs_app_supported: true (*) Please do not use `placementId` and `siteId` at the same time. - + ### Geo Object @@ -52,7 +54,7 @@ If the publisher has GEO data of the user's device. Make it available through th | `lastfix` | optional | Number of seconds since this geolocation fix was established. Note that devices may cache location data across multiple fetches. Ideally, this value should be from the time the actual fix was taken. | `30` | `integer` | | `utcoffset` | optional | Local time as the number +/- of minutes from UTC. | `-420` | `integer` | - + ### Video Ad Unit @@ -78,10 +80,11 @@ Publishers declare video inventory by passing the following parameters via media Lists of values are in the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) documentation as referenced above. - + ### Sample Banner Ad Unit -``` + +```javascript var adUnits = [ { code: 'test-div', @@ -103,10 +106,11 @@ var adUnits = [ ]; ``` - + ### Sample Video Ad Unit: Instream -``` + +```javascript var instreamAdUnit = { code: 'test-div', sizes: [[640, 480]], @@ -137,13 +141,15 @@ var instreamAdUnit = { ] }; ``` -mediaTypes.video object reference to section 3.2.7 Object: Video in the OpenRTB 2.5 document + +`mediaTypes.video` object reference to section 3.2.7 Object: Video in the OpenRTB 2.5 document You must review all video parameters to ensure validity for your player and DSPs - + ### Sample Video Ad Unit: Outstream -``` + +```javascript var outstreamAdUnit = { code: 'test-div', sizes: [[410, 231]], @@ -173,5 +179,6 @@ var outstreamAdUnit = { ] }; ``` -mediaTypes.video object reference to section 3.2.7 Object: Video in the OpenRTB 2.5 document + +`mediaTypes.video` object reference to section 3.2.7 Object: Video in the OpenRTB 2.5 document You must review all video parameters to ensure validity for your player and DSPs diff --git a/dev-docs/bidders/apester.md b/dev-docs/bidders/apester.md new file mode 100644 index 0000000000..068a7cb90c --- /dev/null +++ b/dev-docs/bidders/apester.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Apester +description: Apester Bidder Adaptor +biddercode: apester +pbjs: true +pbs: false +media_types: video, banner +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:-------------|:---------|:--------------------------------------------------|:-------------------------|:----------| +| `host` | required | Ad network's RTB host | `'apester-exchange.com'` | `string` | +| `adUnitId` | required | Ad Unit Id will be generated on Apester Platform. | `42` | `integer` | +| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` | `string` | +| `custom1` | optional | Custom targeting field 1 | `'custom1'` | `string` | +| `custom2` | optional | Custom targeting field 2 | `'custom2'` | `string` | +| `custom3` | optional | Custom targeting field 3 | `'custom3'` | `string` | +| `custom4` | optional | Custom targeting field 4 | `'custom4'` | `string` | +| `custom5` | optional | Custom targeting field 5 | `'custom5'` | `string` | diff --git a/dev-docs/bidders/appaloosa.md b/dev-docs/bidders/appaloosa.md deleted file mode 100644 index 442af1934e..0000000000 --- a/dev-docs/bidders/appaloosa.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -layout: bidder -title: Appaloosa -description: Prebid Appaloosa Bidder Adapter -biddercode: appaloosa -aliasCode: adtelligent -media_types: video,banner -gdpr_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId -schain_supported: true -coppa_supported: true -usp_supported: true -safeframes_ok: true -prebid_member: true -pbjs: true -pbs: false ---- - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|---------------------------------|----------|-----------| -| `aid` | required | The source ID from Appaloosa. | `529814` | `integer` | - -### Description -Get access to multiple demand partners across Appaloosa AdExchange and maximize your yield with Appaloosa header bidding adapter. - -Appaloosa header bidding adapter connects with Appaloosa demand sources in order to fetch bids. -This adapter provides a solution for accessing Video demand and display demand. - -Appaloosa now supports adpod. - -### Test Parameters -``` - var adUnits = [ - - // Video instream adUnit - { - code: 'test-div', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'appaloosa', - params: { - aid: 472386 - } - }] - }, - - // Video outstream adUnit - { - code: 'test-div', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'appaloosa', - params: { - aid: 472386 - } - }] - }, - - // Video ADPOD adUnit - { - code: 'test-div', - sizes: [[640, 480]], - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'appaloosa', - params: { - aid: 472386 - } - }] - }, - - // Banner adUnit - { - code: 'test-div', - mediaTypes:{ - banner:{ - sizes: [[300, 250]] - } - } - bids: [{ - bidder: 'appaloosa', - params: { - aid: 529814 - } - }] - } - ]; -``` - -### Additional Configuration - -It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request -(default value is 10). - -``` - pbjs.setBidderConfig({ - config: { - appaloosa: { - chunkSize: 1 // makes 1 http request per 1 adunit configured - } - } - }); -``` - -Appaloosa is an aliased bidder for Adtelligent diff --git a/dev-docs/bidders/appier.md b/dev-docs/bidders/appier.md index b34eb02690..c442883abf 100644 --- a/dev-docs/bidders/appier.md +++ b/dev-docs/bidders/appier.md @@ -5,10 +5,12 @@ description: Prebid Appier Bidder Adapter biddercode: appier pbjs: true media_types: banner -gdpr_supported: true +gvl_id: 728 +tcfeu_supported: true +sidebarType: 1 --- - + #### Bid Params @@ -17,14 +19,13 @@ gdpr_supported: true |-----------|----------|---------------------------|------------|----------| | `hzid` | required | The zone ID from Appier. | `"WhM5WIOp"` | `string` | - - + #### Custom Settings (Optional) Set the "farm" to use region-specific server -``` +```javascript pbjs.que.push(function() { // use the bid server in Taiwan (country code: tw) pbjs.setConfig({ @@ -37,7 +38,7 @@ pbjs.que.push(function() { Explicitly override the bid server used for bidding -``` +```javascript pbjs.que.push(function() { pbjs.setConfig({ appier: { diff --git a/dev-docs/bidders/appierBR.md b/dev-docs/bidders/appierBR.md index acb2e213f2..789c7b1bb0 100644 --- a/dev-docs/bidders/appierBR.md +++ b/dev-docs/bidders/appierBR.md @@ -6,7 +6,9 @@ biddercode: appierBR aliasCode: appier pbjs: true media_types: banner -gdpr_supported: true +gvl_id: 728 (appier) +tcfeu_supported: true +sidebarType: 1 --- #### Bid Params @@ -20,7 +22,7 @@ gdpr_supported: true Set the "farm" to use region-specific server -``` +```javascript pbjs.que.push(function() { // use the bid server in Taiwan (country code: tw) pbjs.setConfig({ @@ -33,7 +35,7 @@ pbjs.que.push(function() { Explicitly override the bid server used for bidding -``` +```javascript pbjs.que.push(function() { pbjs.setConfig({ appier: { @@ -42,4 +44,5 @@ pbjs.que.push(function() { }); }); ``` + AppierBR is an aliased bidder for Appier diff --git a/dev-docs/bidders/appierExt.md b/dev-docs/bidders/appierExt.md index b016d3098b..8814803c60 100644 --- a/dev-docs/bidders/appierExt.md +++ b/dev-docs/bidders/appierExt.md @@ -6,7 +6,9 @@ biddercode: appierExt aliasCode: appier pbjs: true media_types: banner -gdpr_supported: true +gvl_id: 728 (appier) +tcfeu_supported: true +sidebarType: 1 --- #### Bid Params @@ -20,7 +22,7 @@ gdpr_supported: true Set the "farm" to use region-specific server -``` +```javascript pbjs.que.push(function() { // use the bid server in Taiwan (country code: tw) pbjs.setConfig({ @@ -33,7 +35,7 @@ pbjs.que.push(function() { Explicitly override the bid server used for bidding -``` +```javascript pbjs.que.push(function() { pbjs.setConfig({ appier: { @@ -42,4 +44,5 @@ pbjs.que.push(function() { }); }); ``` + AppierExt is an aliased bidder for Appier diff --git a/dev-docs/bidders/appierGM.md b/dev-docs/bidders/appierGM.md index e7d87e0de4..0fc448edc9 100644 --- a/dev-docs/bidders/appierGM.md +++ b/dev-docs/bidders/appierGM.md @@ -6,7 +6,9 @@ biddercode: appierGM aliasCode: appier pbjs: true media_types: banner -gdpr_supported: true +gvl_id: 728 (appier) +tcfeu_supported: true +sidebarType: 1 --- #### Bid Params @@ -20,7 +22,7 @@ gdpr_supported: true Set the "farm" to use region-specific server -``` +```javascript pbjs.que.push(function() { // use the bid server in Taiwan (country code: tw) pbjs.setConfig({ @@ -33,7 +35,7 @@ pbjs.que.push(function() { Explicitly override the bid server used for bidding -``` +```javascript pbjs.que.push(function() { pbjs.setConfig({ appier: { @@ -42,4 +44,5 @@ pbjs.que.push(function() { }); }); ``` + AppierGM is an aliased bidder for Appier diff --git a/dev-docs/bidders/applogy.md b/dev-docs/bidders/applogy.md index 6042fb4da2..c78d97e67c 100644 --- a/dev-docs/bidders/applogy.md +++ b/dev-docs/bidders/applogy.md @@ -4,6 +4,7 @@ title: Applogy pbs: true media_types: banner biddercode: applogy +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/appnexus.md b/dev-docs/bidders/appnexus.md index 676b133110..a8dff8af88 100644 --- a/dev-docs/bidders/appnexus.md +++ b/dev-docs/bidders/appnexus.md @@ -4,32 +4,40 @@ title: AppNexus description: Prebid AppNexus Bidder Adaptor biddercode: appnexus media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true prebid_member: true -userIds: criteo, unifiedId, netId, identityLink, flocId, uid2 +userIds: all (with commercial activation) schain_supported: true coppa_supported: true usp_supported: true +gpp_supported: true floors_supported: true -fpd_supported: true +fpd_supported: false pbjs: true +pbjs_version_notes: please avoid using v7.15 and v7.16 pbs: true gvl_id: 32 +sidebarType: 1 --- ### Table of Contents -- [Bid Params](#appnexus-bid-params) -- [Video Object](#appnexus-video-object) -- [User Object](#appnexus-user-object) -- [App Object](#appnexus-app-object) -- [Custom Targeting keys](#custom-targeting-keys) -- [Auction Level Keywords](#appnexus-auction-keywords) -- [Passing Keys Without Values](#appnexus-no-value) -- [User Sync in AMP](#appnexus-amp) -- [Debug Auction](#appnexus-debug-auction) - - +- [Table of Contents](#table-of-contents) + - [Bid Params](#bid-params) + - [Video Object](#video-object) + - [User Object](#user-object) + - [App Object](#app-object) + - [Custom Targeting keys](#custom-targeting-keys) + - [Auction Level Keywords](#auction-level-keywords) + - [Passing Keys Without Values](#passing-keys-without-values) + - [First Party Data](#first-party-data) + - [User Sync in AMP](#user-sync-in-amp) + - [Mobile App Display Manager Version](#mobile-app-display-manager-version) + - [Debug Auction](#debug-auction) + - [Prebid Server Test Request](#prebid-server-test-request) + + {: .alert.alert-danger :} All AppNexus (Xandr) placements included in a single call to `requestBids` must belong to the same parent Publisher. If placements from two different publishers are included in the call, the AppNexus bidder will not return any demand for those placements.
      @@ -37,31 +45,35 @@ All AppNexus (Xandr) placements included in a single call to `requestBids` must #### Bid Params +{: .alert.alert-danger :} +Starting with Prebid.js version 7.36.0, an update was made to the `appnexusBidAdapter.js` file to support bid params in a lower-case underscore format (eg `invCode` to `inv_code`) similar to how the params are formatted for the Prebid Server AppNexus bidder. This change was implemented to streamline publisher setups for both projects instead of maintaining separate versions of the same params depending on what setup is used. +To avoid breaking changes, the old 'camelCase' format is still currently supported for all AppNexus bid params in the `appnexusBidAdapter.js` file. If you are using an older version of Prebid.js, you will need to continue to use the older 'camelCase' format as appropriate. +The table below will reflect both formats, though it's recommended to use the lower-case underscore format where possible going forward (assuming you're using a compatible version of Prebid.js). + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------| -| `placement_id` (PBS) or `placementID` (PBJS) | required | The placement ID from AppNexus. You may identify a placement using the `invCode` and `member` instead of a placement ID. This parameter can be either a `string` or `integer` for Prebid.js, however `integer` is preferred. Legacy code can retain the `string` value. **Prebid Server requires an integer value.** | `234234` | `integer` | +| `placement_id` (PBS+PBJS) or `placementId` (PBJS) | required | The placement ID from AppNexus. You may identify a placement using the `invCode` and `member` instead of a placement ID. This parameter can be either a `string` or `integer` for Prebid.js, however `integer` is preferred. Legacy code can retain the `string` value. **Prebid Server requires an integer value.** | `234234` | `integer` | | `member` | optional | The member ID from AppNexus. Must be used with `invCode`. | `'12345'` | `string` | -| `invCode` | optional | The inventory code from AppNexus. Must be used with `member`. | `'abc123'` | `string` | -| `publisherId` | optional | The publisher ID from AppNexus. It is used by the AppNexus end point to identify the publisher when placement id is not provided and `invCode` goes wrong. The `publisherId` parameter can be either a `string` or `integer` for Prebid.js, however `integer` is preferred. | `12345` | `integer` | -| `frameworks` | optional | Array of integers listing API frameworks for Banner supported by the publisher. | `integer` | +| `invCode` or `inv_code` | optional | The inventory code from AppNexus. Must be used with `member`. | `'abc123'` | `string` | +| `publisherId` or `publisher_id` | optional | The publisher ID from AppNexus. It is used by the AppNexus end point to identify the publisher when placement id is not provided and `invCode` goes wrong. The `publisherId` parameter can be either a `string` or `integer` for Prebid.js, however `integer` is preferred. | `12345` | `integer` | +| `frameworks` | optional | Array of integers listing API frameworks for Banner supported by the publisher. | `[1,2]` | `array of integer` | | `user` | optional | Object that specifies information about an external user. See [User Object](#appnexus-user-object) for details. | `user: { age: 25, gender: 0, dnt: true}` | `object` | -| `allowSmallerSizes` | optional | If `true`, ads smaller than the values in your ad unit's `sizes` array will be allowed to serve. Defaults to `false`. | `true` | `boolean` | -| `usePaymentRule` (PBJS) or `use_pmt_rule` (PBS) | optional | If `true`, Appnexus will return net price to Prebid.js after publisher payment rules have been applied. | `true` | `boolean` | -| `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Mapped to [buy-side segment targeting](https://monetize.xandr.com/docs/segment-targeting) (login required). Values can be empty. See [Passing Keys Without Values](#appnexus-no-value) below for examples. If you want to pass keywords for all adUnits, see [Auction Level Keywords](#appnexus-auction-keywords) for an example. Note that to use keyword with the Prebid Server adapter, that feature must be enabled for your account by an AppNexus account manager. | `keywords: { genre: ['rock', 'pop'] }` | `object` | +| `allowSmallerSizes` or `allow_smaller_sizes` | optional | If `true`, ads smaller than the values in your ad unit's `sizes` array will be allowed to serve. Defaults to `false`. | `true` | `boolean` | +| `usePaymentRule` (PBJS) or `use_pmt_rule` (PBS+PBJS) | optional | If `true`, Appnexus will return net price to Prebid.js after publisher payment rules have been applied. | `true` | `boolean` | +| `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Mapped to [buy-side segment targeting](https://monetize.xandr.com/docs/segment-targeting) (login required). A maximum of 100 key/value pairs can be defined at the page level. Each tag can have up to 100 additional key/value pairs defined. Values can be empty. See [Passing Keys Without Values](#appnexus-no-value) below for examples. If you want to pass keywords for all adUnits, see [Auction Level Keywords](#appnexus-auction-keywords) for an example. Note that to use keyword with the Prebid Server adapter, that feature must be enabled for your account by an AppNexus account manager. | `keywords: { genre: ['rock', 'pop'] }` | `object` | | `video` | optional | Object containing video targeting parameters. See [Video Object](#appnexus-video-object) for details. | `video: { playback_method: ['auto_play_sound_off'] }` | `object` | | `app` | optional | Object containing mobile app parameters. See the [App Object](#appnexus-app-object) for details. | `app : { id: 'app-id'}` | `object` | | `reserve` | optional | Sets a floor price for the bid that is returned. If floors have been configured in the AppNexus Console, those settings will override what is configured here unless 'Reserve Price Override' is checked. See [Xandr docs](https://docs.xandr.com/bundle/monetize_monetize-standard/page/topics/create-a-floor-rule.html) | `0.90` | `float` | | `position` | optional | Identify the placement as above or below the fold. Allowed values: Unknown: `unknown`; Above the fold: `above`; Below the fold: `below` | `'above'` | `string` | -| `trafficSourceCode` | optional | Specifies the third-party source of this impression. | `'my_traffic_source'` | `string` | -| `supplyType` | optional | Indicates the type of supply for this placement. Possible values are `web`, `mobile_web`, `mobile_app` | `'web'` | `string` | -| `supplyType` | optional | Indicates the type of supply for this placement. Possible values are `web`, `mobile_web`, `mobile_app` | `'web'` | `string` | -| `pubClick` | optional | Specifies a publisher-supplied URL for third-party click tracking. This is just a placeholder into which the publisher can insert their own click tracker. This parameter should be used for an unencoded tracker. This parameter is expected to be the last parameter in the URL. Please note that the click tracker placed in this parameter will only fire if the creative winning the auction is using AppNexus click tracking properly. | `'http://click.adserver.com/'` | `string` | -| `extInvCode` | optional | Specifies predefined value passed on the query string that can be used in reporting. The value must be entered into the system before it is logged. | `'10039'` | `string` | -| `externalImpId` | optional | Specifies the unique identifier of an externally generated auction. | `'bacbab02626452b097f6030b3c89ac05'` | `string` | +| `trafficSourceCode` or `traffic_source_code` | optional | Specifies the third-party source of this impression. | `'my_traffic_source'` | `string` | +| `supplyType` or `supply_type` | optional | Indicates the type of supply for this placement. Possible values are `web`, `mobile_web`, `mobile_app` | `'web'` | `string` | +| `pubClick` or `pub_click` | optional | Specifies a publisher-supplied URL for third-party click tracking. This is just a placeholder into which the publisher can insert their own click tracker. This parameter should be used for an unencoded tracker. This parameter is expected to be the last parameter in the URL. Please note that the click tracker placed in this parameter will only fire if the creative winning the auction is using AppNexus click tracking properly. | `'http://click.adserver.com/'` | `string` | +| `extInvCode` or `ext_inv_code` | optional | Specifies predefined value passed on the query string that can be used in reporting. The value must be entered into the system before it is logged. | `'10039'` | `string` | +| `externalImpId` or `external_imp_id` | optional | Specifies the unique identifier of an externally generated auction. | `'bacbab02626452b097f6030b3c89ac05'` | `string` | | `generate_ad_pod_id` | optional | Signal to AppNexus to split impressions by ad pod and add unique ad pod id to each request. Specific to long form video endpoint only. Supported by Prebid Server, not Prebid JS. | `true` | `boolean` | - + #### Video Object @@ -76,8 +88,7 @@ All AppNexus (Xandr) placements included in a single call to `requestBids` must | `playback_method` | A string that sets the playback method supported by the publisher. Allowed values: `"auto_play_sound_on"`; `"auto_play_sound_off"`; `"click_to_play"`; `"mouse_over"`; `"auto_play_sound_unknown"`. | `string` | | `frameworks` | Array of integers listing API frameworks supported by the publisher. Allowed values: None: `0`; VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; MRAID 2.0: `4`; ORMMA: `5`; OMID 1.0 `6`. | `Array` | - - + #### User Object @@ -85,14 +96,13 @@ All AppNexus (Xandr) placements included in a single call to `requestBids` must | Name | Description | Example | Type | |-------------------|---------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|------------------| | `age` | The age of the user. | `35` | `integer` | -| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | +| `externalUid` or `external_uid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | | `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array` | | `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` | | `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | | `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | - - + #### App Object @@ -105,13 +115,13 @@ AppNexus supports using prebid within a mobile app's webview. If you are interes | `device_id` | Object that contains the advertising identifiers of the user (`idfa`, `aaid`, `md5udid`, `sha1udid`, or `windowsadid`). | `{ aaid: "38400000-8cf0-11bd-b23e-10b96e40000d" }` | `object` | | `geo` | Object that contains the latitude (`lat`) and longitude (`lng`) of the user. | `{ lat: 40.0964439, lng: -75.3009142 }` | `object` | - + #### Custom Targeting keys AppNexus returns custom keys that can be sent to the adserver through bidderSettings: buyerMemberId, dealPriority, and dealCode. The following snippet demonstrates how to add these custom keys as key-value pairs. -``` +```javascript pbjs.bidderSettings = { appnexus: { adserverTargeting: [ @@ -137,14 +147,15 @@ pbjs.bidderSettings = { } ``` - + #### Auction Level Keywords It's possible to pass a set of keywords for the whole request, rather than a particular adUnit. Though they would apply to all adUnits (which include the appnexus bidder) in an auction, these keywords can work together with the bidder level keywords (if for example you want to have specific targeting for a particular adUnit). Below is an example of how to define these auction level keywords for the appnexus bidder: -``` + +```javascript pbjs.setConfig({ appnexusAuctionKeywords: { genre: ['classical', 'jazz'], @@ -155,14 +166,13 @@ pbjs.setConfig({ Like in the bidder.params.keywords, the values here can be empty. Please see the section immediately below for more details. - + #### Passing Keys Without Values It's possible to use the `keywords` parameter to define keys that do not have any associated values. Keys with empty values can be created in Prebid.js and can also be sent through Prebid Server to AppNexus. The following are examples of sending keys with empty values: - -``` +```javascript keywords: { myKeyword: '', myOtherKeyword: [''] @@ -173,20 +183,30 @@ The preceding example passes the key `myKeyword` with an empty value. The key `m You can define keys with values and without values in the same `keywords` definition. In this next example, we've defined the key `color` with an array of values: `red`, `blue`, and `green`. We've followed that with the key `otherKeyword` with an empty value array. -``` +```javascript keywords: { color: ['red', 'blue', 'green'], otherKeyword: [''] } ``` - + + +#### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +At this time however, the `appnexus` bidder fully reads the First Party Data when using the Prebid Server and Prebid Server Premium endpoints. The client-side version of the `appnexus` bidder has partial support to read all the various keywords parameters from the First Party Data fields. There is also some special support with the segment fields but only from known sources which are specifically configured. All other First Party Data fields are not read at this time. + +PBS/PSP supports all first party data fields: site, user, segments, and imp-level first party data. + + #### User Sync in AMP If you are syncing user id's with Prebid Server and are using AppNexus' managed service, see [AMP Implementation Guide cookie-sync instructions](/dev-docs/show-prebid-ads-on-amp-pages.html#user-sync) for details. - + #### Mobile App Display Manager Version @@ -204,9 +224,9 @@ Enabling the AppNexus Debug Auction feature should only be done for diagnosing t To understand what is happening behind the scenes during an auction, you can enable a debug auction by adding an `apn_prebid_debug` cookie with a JSON string. For example: -{% highlight js %} +```javascript { "enabled": true, "dongle": "QWERTY", "debug_timeout": 1000, "member_id": 958 } -{% endhighlight %} +``` To view the results of the debug auction, add the `pbjs_debug=true` query string parameter and open your browser's developer console. @@ -224,22 +244,22 @@ The following test parameters can be used to verify that Prebid Server is workin server-side Appnexus adapter. This example includes an `imp` object with an Appnexus test placement ID and sizes that would match with the test creative. -``` - "imp": [{ - "id": "some-impression-id", - "banner": { - "format": [{ - "w": 600, - "h": 500 - }, { - "w": 300, - "h": 600 - }] - }, - "ext": { - "appnexus": { - "placement_id": 13144370 - } - } - }] +```json +"imp": [{ + "id": "some-impression-id", + "banner": { + "format": [{ + "w": 600, + "h": 500 + }, { + "w": 300, + "h": 600 + }] + }, + "ext": { + "appnexus": { + "placement_id": 13144370 + } + } +}] ``` diff --git a/dev-docs/bidders/appstock.md b/dev-docs/bidders/appstock.md new file mode 100644 index 0000000000..5c3601f48e --- /dev/null +++ b/dev-docs/bidders/appstock.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Appstock +description: Prebid Appstock Bidder Adaptor +biddercode: appstock +pbjs: false +pbs: true +media_types: banner, video, audio, native +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Note + +The Appstock Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:----------------------|:------------------|:----------| +| `host` | required | Ad network's RTB host | `'pre.vr-tb.com'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | diff --git a/dev-docs/bidders/appush.md b/dev-docs/bidders/appush.md new file mode 100644 index 0000000000..94bb59ced3 --- /dev/null +++ b/dev-docs/bidders/appush.md @@ -0,0 +1,24 @@ +--- +layout: bidder +title: Appush +description: Prebid Appush Bidder Adapter +biddercode: appush +media_types: banner, video, native +pbjs: true +pbs: true +gvl_id: 879 +safeframes_ok: true +floors_supported: true +fpd_supported: false +multiformat_supported: will-not-bid +ortb_blocking_supported: partial +sidebarType: 1 +--- + +### Prebid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | diff --git a/dev-docs/bidders/apstream.md b/dev-docs/bidders/apstream.md index ce01e7f18d..a0463382c8 100644 --- a/dev-docs/bidders/apstream.md +++ b/dev-docs/bidders/apstream.md @@ -5,10 +5,15 @@ description: AP Stream Bidder Adapter biddercode: apstream pbjs: true media_types: banner -gdpr_supported: true +tcfeu_supported: false gvl_id: 394 +sidebarType: 1 --- +### Disclosure + +Note: This bidder passes consent strings but not the gdprApplies flag to its backend. This may result in some incorrect TCF2 processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/arteebee.md b/dev-docs/bidders/arteebee.md index a37182738a..658187ee56 100644 --- a/dev-docs/bidders/arteebee.md +++ b/dev-docs/bidders/arteebee.md @@ -4,8 +4,9 @@ title: Arteebee description: Prebid Arteebee Bidder Adaptor pbjs: true biddercode: arteebee -gdpr_supported: true +tcfeu_supported: false coppa_supported: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/aseal.md b/dev-docs/bidders/aseal.md index 604623a724..76d476693a 100644 --- a/dev-docs/bidders/aseal.md +++ b/dev-docs/bidders/aseal.md @@ -5,6 +5,7 @@ description: Prebid Aseal Bidder Adapter pbjs: true biddercode: aseal media_types: banner +sidebarType: 1 --- ### BidParams @@ -14,7 +15,7 @@ media_types: banner |-----------------|----------|---------------------------------|------------------------------------------|--------------------| | `placeUid` | required | The Place UID from Aotter | `'f4a74f73-9a74-4a87-91c9-545c6316c23d'` | `string` | -# Configuration +### Configuration Following configuration is required: @@ -26,7 +27,7 @@ pbjs.setConfig({ }); ``` -# Ad Unit Example +### Ad Unit Example ```js var adUnits = [ diff --git a/dev-docs/bidders/aso.md b/dev-docs/bidders/aso.md index 8e4fae6934..3f87d72d84 100644 --- a/dev-docs/bidders/aso.md +++ b/dev-docs/bidders/aso.md @@ -3,25 +3,32 @@ layout: bidder title: Adserver.Online description: Prebid Adserver.Online Bidder Adapter biddercode: aso -gdpr_supported: true +tcfeu_supported: false usp_supported: true -media_types: video +media_types: video, native safeframes_ok: true -deals_supported: false pbjs: true -pbs: false +pbs: true +pbs_app_supported: true floors_supported: true +schain_supported: true +fpd_supported: true +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +userIds: all +sidebarType: 1 --- -### Note: +### Note -For more information about [Adserver.Online](https://adserver.online), please contact support@adsrv.org. +For more information about [Adserver.Online](https://adserver.online), please contact . ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-----------------------|-----------|-----------| -| `zone` | required | Zone ID | `73815` | `integer` | +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------------------|--------------------------|-----------| +| `zone` | required | Zone ID | `73815` | `Integer` | +| `server` | optional | Custom bidder endpoint | `https://endpoint.url` | `String` | ### Test Parameters @@ -50,7 +57,6 @@ Note that the Adserver.Online adapter expects a client-side Prebid Cache to be e ```js pbjs.setConfig({ - usePrebidCache: true, cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' } diff --git a/dev-docs/bidders/astraone.md b/dev-docs/bidders/astraone.md index 4db8f5dc7f..e0950adc4b 100644 --- a/dev-docs/bidders/astraone.md +++ b/dev-docs/bidders/astraone.md @@ -5,7 +5,8 @@ description: Prebid AstraOne Bidder Adapter pbjs: true media_types: banner biddercode: astraone -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Note @@ -14,28 +15,25 @@ You can use this adapter to get a bid from AstraOne. Please reach out to your AstraOne account team before using this plugin to get placeId. The code below returns a demo ad. - ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------------|---------------------|-------------------------------------------------------------------|-------------------------------------------------------------------------------|----------| | `placeId` | required | The place id. | '5af45ad34d506ee7acad0c26' | `string` | -| `imageUrl` | required | URL of the image on which the banner will be displayed. | 'https://creative.astraone.io/files/default_image-1-600x400.jpg' | `string` | +| `imageUrl` | required | URL of the image on which the banner will be displayed. | `'https://creative.astraone.io/files/default_image-1-600x400.jpg'` | `string` | | `placement` | required | Adunit placement, possible values: inImage | 'inImage' | `string` | - ### InImage Example page - ```html - - Prebid.js Banner Example - - - + + Prebid.js Banner Example + + + + -

      Prebid.js InImage Banner Test

      +

      Prebid.js InImage Banner Test

      -
      - +
      + - -
      + +
      ``` diff --git a/dev-docs/bidders/atomx.md b/dev-docs/bidders/atomx.md deleted file mode 100644 index ddca88bbbc..0000000000 --- a/dev-docs/bidders/atomx.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -layout: bidder -title: Atomx -description: Prebid Atomx Bidder Adaptor -pbjs: true -biddercode: atomx -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------|----------|--------------------|---------|-----------| -| `id` | required | Atomx placement ID | `1234` | `integer` | diff --git a/dev-docs/bidders/audienceNetwork.md b/dev-docs/bidders/audienceNetwork.md index 2eab49eb69..b383836360 100644 --- a/dev-docs/bidders/audienceNetwork.md +++ b/dev-docs/bidders/audienceNetwork.md @@ -5,6 +5,7 @@ description: Prebid Audience Network Bidder Adaptor pbs: true biddercode: audienceNetwork media_types: native, video +sidebarType: 1 --- ### Registration diff --git a/dev-docs/bidders/audiencemedia.md b/dev-docs/bidders/audiencemedia.md index 67c3b6a83b..c81575e8ee 100644 --- a/dev-docs/bidders/audiencemedia.md +++ b/dev-docs/bidders/audiencemedia.md @@ -2,11 +2,25 @@ layout: bidder title: Audience Media description: Prebid Audience Media Bidder Adaptor -pbjs: true -media_types: banner, video -gdpr_supported: true biddercode: audiencemedia -aliasCode : adkernel +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- ### Bid Params @@ -15,4 +29,4 @@ aliasCode : adkernel | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Ad network's RTB host | `'cpm.audience.media'` | `string` | -| `zoneId` | required | Zone ID | `'76156'` | `string` | +| `zoneId` | required | Zone ID | `76156` | `integer` | diff --git a/dev-docs/bidders/audiencerun.md b/dev-docs/bidders/audiencerun.md index d582380046..4e74836c77 100644 --- a/dev-docs/bidders/audiencerun.md +++ b/dev-docs/bidders/audiencerun.md @@ -5,34 +5,46 @@ description: Prebid AudienceRun Bidder Adaptor pbjs: true biddercode: audiencerun media_types: banner -gdpr_supported: true +gvl_id: 944 +tcfeu_supported: true +usp_supported: true +schain_supported: true +safeframes_ok: false +prebid_member: false +userIds: all +floors_supported: true +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `zoneId` | required | | | `string` | +| Name | Scope | Description | Example | Type | +| ---------- | -------- | --------------------------------------------------------------------------- | -------------- | -------- | +| `zoneId` | required | The zone id provided by AudienceRun | `'xtov2mgij0'` | `string` | +| `bidfloor` | optional | The bid floor for the zone id provided by AudienceRun in USD (default: 0.0) | `0.5` | `float` | -### Description +### Registration -Module that connects to AudienceRun demand sources. +The AudienceRun Header Bidding adaptor requires setup and approval from the AudienceRun team. Please reach out to our team on for more details. -Use `audiencerun` as bidder. +### Example -`zoneId` is required and must be 10 alphanumeric characters. +Use `audiencerun` as bidder. Note that `zoneId` is required and must be 10 alphanumeric characters. -### AdUnits configuration example -``` - var adUnits = [{ - code: 'test-div', - sizes: [[300, 600]], - bids: [{ - bidder: 'audiencerun', - params: { - zoneId: 'xtov2mgij0' - } - }] - }]; +```js +var adUnits = [ + { + code: "test-div", + sizes: [[300, 600]], + bids: [ + { + bidder: "audiencerun", + params: { + zoneId: "xtov2mgij0", + }, + }, + ], + }, +]; ``` diff --git a/dev-docs/bidders/automatad.md b/dev-docs/bidders/automatad.md index e7f7a9c860..d5038a7776 100644 --- a/dev-docs/bidders/automatad.md +++ b/dev-docs/bidders/automatad.md @@ -4,15 +4,25 @@ title: Automatad OpenRTB Bid Adapter description: Automatad OpenRTB Bid Adapter biddercode: automatad pbjs: true +pbs: true media_types: banner fpd_supported: false +sidebarType: 1 --- -#### Bid Params +#### Prebid.js Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |-----------|----------|---------------------------|------------|----------| | `siteId` | required | The site ID from automatad. | `"12adf45c"` | `string` | -| `placementId` | required | The placement ID from automatad. | `"a34gh6d"` | `string` | +| `placementId` | optional | The placement ID from automatad. | `"a34gh6d"` | `string` | + +### Prebid-Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------|---------|----------| +| `position` | optional | Position field from automatad | `22390678` | `string` | +| `placementId` | optional | The placement ID from automatad. | `"a34gh6d"` | `string` | diff --git a/dev-docs/bidders/avantisvideo.md b/dev-docs/bidders/avantisvideo.md index bdc5ae4dd9..6ce3a41fdb 100644 --- a/dev-docs/bidders/avantisvideo.md +++ b/dev-docs/bidders/avantisvideo.md @@ -6,14 +6,17 @@ pbjs: true biddercode: avantisvideo aliasCode: aniview media_types: banner, video -gdpr_supported: true +gvl_id: 780 (aniview) +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true +sidebarType: 1 --- -### Note: -For more information about [Avantis Video](https://www.avantisvideo.com/), please contact contact@avantisvideo.com. +### Note + +For more information about [Avantis Video](https://www.avantisvideo.com/), please contact . ### Bid Params @@ -24,9 +27,9 @@ For more information about [Avantis Video](https://www.avantisvideo.com/), pleas | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` -videoAdUnit = [ -{ + +```javascript +const videoAdUnit = [{ code: 'video1', mediaTypes: { video: { diff --git a/dev-docs/bidders/avct.md b/dev-docs/bidders/avct.md index c3bff8e441..41d0ae0141 100644 --- a/dev-docs/bidders/avct.md +++ b/dev-docs/bidders/avct.md @@ -6,15 +6,16 @@ pbjs: true pbs: true biddercode: avct aliasCode: avocet -gdpr_supported: true +tcfeu_supported: false media_types: banner, video schain_supported: true usp_supported: true +sidebarType: 1 --- ### Registration -Please contact Avocet at info@avocet.io if you would like to get started selling inventory via the Avocet platform. +Please contact Avocet at if you would like to get started selling inventory via the Avocet platform. ### Bid Params diff --git a/dev-docs/bidders/axis.md b/dev-docs/bidders/axis.md new file mode 100644 index 0000000000..7ada3260f2 --- /dev/null +++ b/dev-docs/bidders/axis.md @@ -0,0 +1,33 @@ +--- +layout: bidder +title: Axis +description: Prebid Axis Bidder Adapter +biddercode: axis +media_types: banner, video, native +pbjs: true +pbs: true +safeframes_ok: true +fpd_supported: false +multiformat_supported: will-not-bid +ortb_blocking_supported: partial +usp_supported: true +tcfeu_supported: true +coppa_supported: true +schain_supported: true +floors_supported: true +gvl_id: 1197 +sidebarType: 1 +--- + +### Overview + +For more information, visit the [axis-marketplace website](https://platform.axis-marketplace.com) + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------------|------------|------------| +| `integration` | required | Integration | `'000000'` | `'string'` | +| `token` | required | Token | `'000000'` | `'string'` | +| `iabCat` | optional | (Prebid.js only) Array of IAB content categories that describe the content producer | `['IAB1-1', 'IAB3-1', 'IAB4-3']` | `Array(string)` | diff --git a/dev-docs/bidders/axonix.md b/dev-docs/bidders/axonix.md index 84ffe5dcd6..9d9c16f6a5 100644 --- a/dev-docs/bidders/axonix.md +++ b/dev-docs/bidders/axonix.md @@ -7,16 +7,19 @@ media_types: banner, video pbjs: true pbs: true gvl_id: 678 +sidebarType: 1 --- -### Prebid Server Note: -The Axonix Bidding adapter requires setup before beginning. Please contact us at support.axonix@emodoinc.com. +### Prebid Server Note + +The Axonix Bidding adapter requires setup before beginning. Please contact us at . ### Bid Params -| Name | Scope | Description | Example | -| :------------ | :------- | :---------------------------------------------- | :------------------------------------- | -| `supplyId` | required | Supply UUID | `'2c426f78-bb18-4a16-abf4-62c6cd0ee8de'` | -| `region` | optional | Cloud region | `'us-east-1'` | -| `endpoint` | optional | Supply custom endpoint | `'https://open-rtb.axonix.com/custom'` | -| `instl` | optional | Set to 1 if using interstitial (default: 0) | `1` | +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|-------|----------------------------------------------|-------------------------------------|------| +| `supplyId` | required | Supply UUID | `'2c426f78-bb18-4a16-abf4-62c6cd0ee8de'` | string | +| `region` | optional | Cloud region | `'us-east-1'` | string | +| `endpoint` | optional | Supply custom endpoint | `'https://open-rtb.axonix.com/custom'` | string | +| `instl` | optional | Set to 1 if using interstitial (default: 0) | `1` | integer | diff --git a/dev-docs/bidders/bcm.md b/dev-docs/bidders/bcm.md index 18b02bcafd..1f1de2e6b9 100644 --- a/dev-docs/bidders/bcm.md +++ b/dev-docs/bidders/bcm.md @@ -2,19 +2,30 @@ layout: bidder title: BCM description: BCM Bid Adapter -pbjs: true biddercode: bcm +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: - -The BCM adapter requires approval and setup. Please reach out to contact@bcm.ltd or visit us at bcm.ltd for more details. +### Note +The BCM adapter requires approval and setup. Please reach out to or visit us at bcm.ltd for more details. ### Bid Params @@ -22,4 +33,4 @@ The BCM adapter requires approval and setup. Please reach out to contact@bcm.ltd | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Our Host - Do Not Change | `'serve.datacygnal.io'` | `string` | -| `zoneId` | required | Example RTB zone id | `'12345'` | `string` | +| `zoneId` | required | Example RTB zone id | `12345` | `integer` | diff --git a/dev-docs/bidders/bcmint.md b/dev-docs/bidders/bcmint.md new file mode 100644 index 0000000000..2fd3001dac --- /dev/null +++ b/dev-docs/bidders/bcmint.md @@ -0,0 +1,44 @@ +--- +layout: bidder +title: BCM International +description: BCM International Bid Adapter +biddercode: bcmint +tcfeu_supported: false +usp_supported: true +media_types: video, native +safeframes_ok: true +pbjs: true +pbs: true +pbs_app_supported: true +floors_supported: true +schain_supported: true +fpd_supported: true +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +userIds: all +sidebarType: 1 +aliasCode: aso +--- +### Note + +The BCM International adapter requires approval and setup. Please reach out to or visit us at [bcm.ltd](https://bcm.ltd) for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------|-----------------------------|-----------| +| `server` | required | Server endpoint | `https://srv.datacygnal.io` | `String` | +| `zone` | required | Zone ID | `73815` | `Integer` | + +#### Video Caching + +Note that the BCM International adapter expects a client-side Prebid Cache to be enabled for video bidding. + +```js +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); +``` diff --git a/dev-docs/bidders/beachfront.md b/dev-docs/bidders/beachfront.md index 02885121b9..afd897fdfd 100644 --- a/dev-docs/bidders/beachfront.md +++ b/dev-docs/bidders/beachfront.md @@ -6,8 +6,9 @@ biddercode: beachfront media_types: video floors_supported: true fpd_supported: true -gdpr_supported: true +tcfeu_supported: true usp_supported: true +gpp_supported: true userIds: unifiedId, identityLink, uid2, hadronId schain_supported: true prebid_member: true @@ -15,6 +16,7 @@ pbjs: true pbs: true pbs_app_supported: true gvl_id: 335 +sidebarType: 1 --- ### Registration @@ -22,64 +24,93 @@ gvl_id: 335 To use the beachfront bidder you will need an appId (Exchange Id) from an exchange account on [platform.beachfront.io](https://platform.beachfront.io). -For further information, please contact adops@beachfront.com. +For further information, please contact . ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |------------|----------|---------------------------------------------------------------------------------------------|------------------------------------------|----------| -| `appId` | required | Beachfront Exchange ID | `'11bc5dd5-7421-4dd8-c926-40fa653bec76'` | `string` | -| `bidfloor` | required | Bid floor | `0.01` | `float` | -| `video` | optional | Object with video parameters. See the [video section below](#beachfront-video) for details. | | `object` | -| `banner` | optional | Object with banner parameters. See the [banner section below](#beachfront-banner) for details. | | `object` | -| `player` | optional | Object with outstream player parameters. See the [player section below](#beachfront-player) for details. | | `object` | +| `appId` | required | Beachfront Exchange ID | `'11bc5dd5-7421-4dd8-c926-40fa653bec76'` | `string` | +| `bidfloor` | required | Bid floor. The floor price module will take priority over this value. | `0.01` | `float` | +| `video` | optional | Object with video parameters. See the [video section below](#beachfront-video) for details. | | `object` | +| `banner` | optional | Object with banner parameters. See the [banner section below](#beachfront-banner) for details. | | `object` | +| `player` | optional | Object with outstream player parameters. See the [player section below](#beachfront-player) for details. | | `object` | -### video params +#### video params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |------------------|----------|------------------------------------------------|-------------------------------------------|-----------------| -| `appId` | optional | Beachfront Exchange ID for video bids. | `'11bc5dd5-7421-4dd8-c926-40fa653bec76'` | `string` | -| `bidfloor` | optional | Bid floor for video bids. | `0.01` | `float` | -| `tagid` | optional | Tag ID | `'placement-name'` | `string` | -| `responseType` | optional | Video response type.
      `both`: VAST URL and VAST XML
      `nurl`: VAST URL only
      `adm`: VAST XML only | `'both'` | `string` | -| `mimes` | optional | Array of strings listing supported MIME types. | `["video/mp4", "application/javascript"]` | `Array` | +| `appId` | optional | Beachfront Exchange ID for video bids. | `'11bc5dd5-7421-4dd8-c926-40fa653bec76'` | `string` | +| `bidfloor` | optional | Bid floor for video bids. | `0.01` | `float` | +| `tagid` | optional | Tag ID | `'placement-name'` | `string` | +| `responseType` | optional | Video response type.
      `both`: VAST URL and VAST XML
      `nurl`: VAST URL only
      `adm`: VAST XML only | `'both'` | `string` | +| `mimes` | optional | Array of strings listing supported MIME types. | `["video/mp4", "application/javascript"]` | `Array` | | `playbackmethod` | optional | Playback method supported by the publisher.
      `1`: Auto-play sound on
      `2`: Auto-play sound off
      `3`: Click-to-play
      `4`: Mouse-over | `1` | `integer` | -| `maxduration` | optional | Maximum video ad duration in seconds. | `30` | `integer` | -| `placement` | optional | Placement type for the impression.
      `1`: In-Stream
      `2`: In-Banner
      `3`: In-Article
      `4`: In-Feed
      `5`: Interstitial/Slider/Floating | `1` | `integer` | -| `skip` | optional | Indicates if the player will allow the video to be skipped. | `1` | `integer` | -| `skipmin` | optional | Videos of total duration greater than this number of seconds can be skippable. | `15` | `integer` | -| `skipafter` | optional | Number of seconds a video must play before skipping is enabled. | `5` | `integer` | +| `maxduration` | optional | Maximum video ad duration in seconds. | `30` | `integer` | +| `placement` | optional | Placement type for the impression.
      `1`: In-Stream
      `2`: In-Banner
      `3`: In-Article
      `4`: In-Feed
      `5`: Interstitial/Slider/Floating | `1` | `integer` | +| `skip` | optional | Indicates if the player will allow the video to be skipped. | `1` | `integer` | +| `skipmin` | optional | Videos of total duration greater than this number of seconds can be skippable. | `15` | `integer` | +| `skipafter` | optional | Number of seconds a video must play before skipping is enabled. | `5` | `integer` | -### banner params +#### banner params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |------------|----------|-----------------------------------------|------------------------------------------|----------| -| `appId` | optional | Beachfront Exchange ID for banner bids. | `'3b16770b-17af-4d22-daff-9606bdf2c9c3'` | `string` | +| `appId` | optional | Beachfront Exchange ID for banner bids. | `'3b16770b-17af-4d22-daff-9606bdf2c9c3'` | `string` | | `bidfloor` | optional | Bid floor for banner bids. | `0.01` | `float` | -| `tagid` | optional | Tag ID | `'placement-name'` | `string` | +| `tagid` | optional | Tag ID | `'placement-name'` | `string` | -### player params +#### player params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |------------|----------|-----------------------------------------|------------------------------------------|----------| | `progressColor` | optional | The color of the progress bar formatted as a CSS value. | `'#50A8FA'` | `string` | | `adPosterColor` | optional | The color of the ad poster formatted as a CSS value. | `'#FFFFFF'` | `string` | | `expandInView` | optional | Defines whether to expand the player when the ad slot is in view. Defaults to `false`. | `false` | `boolean` | | `collapseOnComplete` | optional | Defines whether to collapse the player when ad playback has completed. Defaults to `true`. | `true` | `boolean` | +### First Party Data + +Publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: + +- ortb2.site.\* +- ortb2.app.\* +- ortb2.user.\* + +Example first party data that's available to all bidders and all adunits: + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + keywords: "kw1,kw2", + content: { + title: "title1", + series: "series1" + } + }, + user: { + keywords: "a,b", + gender: "M", + yob: 1984 + } + } +}); +``` + ### Prebid Server -As seen in the JSON response from \{your PBS server\}\/bidder\/params [(example)](https://prebid.adnxs.com/pbs/v1/bidders/params), the beachfront +As seen in the JSON response from \{your PBS server\}\/bidder\/params, the beachfront bidder can take either an "appId" parameter, or an "appIds" parameter. If the request is for one media type, the appId parameter should be used with the value of the Exchange Id on the Beachfront platform. @@ -88,4 +119,4 @@ configured exchanges on the platform. The appIds parameter can be sent with just If the request includes an appId configured for a video response, the videoResponseType parameter can be defined as "nurl", "adm" or "both". These will apply to all video returned. If it is not defined, the response type will be a nurl. The definitions for "nurl" vs. "adm" are -here: (https://github.com/mxmCherry/openrtb/blob/master/openrtb2/bid.go). +here: (). diff --git a/dev-docs/bidders/bedigitech.md b/dev-docs/bidders/bedigitech.md new file mode 100644 index 0000000000..a1e7719567 --- /dev/null +++ b/dev-docs/bidders/bedigitech.md @@ -0,0 +1,23 @@ +--- +layout: bidder +title: BEdigitech +description: Prebid BEdigitech Bidder Adapter +pbjs: true +pbs: false +biddercode: bedigitech +tcfeu_supported: false +usp_supported: false +media_types: banner, native +--- + +### Note + +The BEdigitech Bidding adapter requires setup before beginning. Please contact us at +Due to different integration API prebid.js and prebid-server api params are different + +### Prebid.JS Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | bedigitech placement | `'1234'` | `'string'`| diff --git a/dev-docs/bidders/beintoo.md b/dev-docs/bidders/beintoo.md index 613575934d..c5b20e07f3 100644 --- a/dev-docs/bidders/beintoo.md +++ b/dev-docs/bidders/beintoo.md @@ -7,9 +7,11 @@ pbs: true biddercode: beintoo aliasCode : appnexus gvl_id: 618 +sidebarType: 1 --- ### Bid Params + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------|---------|----------| diff --git a/dev-docs/bidders/bematterfull b/dev-docs/bidders/bematterfull new file mode 100644 index 0000000000..8119a83509 --- /dev/null +++ b/dev-docs/bidders/bematterfull @@ -0,0 +1,25 @@ +--- +layout: bidder +title: Bematterfull +description: Bematterfull Bidder Adapter +biddercode: bematterfull +media_types: banner, video, native +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: false +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-------------------------------|------------------------------------|-----------| +| `env` | required | Environment name | `mtflll-stage` | `string` | +| `pid` | required | unique placement ID | `cs230510321b516f0eb9a10e5913d3b1` | `string` | diff --git a/dev-docs/bidders/beop.md b/dev-docs/bidders/beop.md index 3f7786d8b7..ef0799f8ac 100644 --- a/dev-docs/bidders/beop.md +++ b/dev-docs/bidders/beop.md @@ -3,14 +3,25 @@ layout: bidder title: BeOp description: BeOp Bidder Adaptor pbjs: true +pbs: false +media_types: banner biddercode: beop -fpd_supported: true +tcfeu_supported: true +gvl_id: 666 +usp_supported: false +floors_supported: true +schain_supported: true +sidebarType: 1 --- +### Disclosure + +The BeOp bidder adaptor needs an account id that you can find as a publisher, a reseller or a media group directly in your BeOp platform access. We also need to approve your account to be available for BeOp demand, so don't hesitate to reach your account manager or for more information. + ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |---------------|----------|-------------|---------|----------| -| `accountId` or `networkId` | required | Your BeOp account ID | `'5a8af500c9e77c00017e4cad'` | `string` | -| `currency` | optional | Your currency | `'EUR'` (default) or `'USD'` | `string` | +| `accountId` or `networkId` | required | Your BeOp account ID | `'5a8af500c9e77c00017e4cad'` | `string` | +| `currency` | optional | Your currency | `'EUR'` (default) or `'USD'` | `string` | diff --git a/dev-docs/bidders/between.md b/dev-docs/bidders/between.md index b37304b1b5..67caef4dfc 100644 --- a/dev-docs/bidders/between.md +++ b/dev-docs/bidders/between.md @@ -6,12 +6,13 @@ pbjs: true pbs: true biddercode: between schain_supported: true -gdpr_supported: true +tcfeu_supported: true pbs_app_supported: true userIds: all gvl_id: 724 usp_supported: true safeframes_ok: false +sidebarType: 1 --- ### Prebid.js Bid Params @@ -20,6 +21,7 @@ safeframes_ok: false | Name | Scope | Description | Example | Type | |---------------|----------|-------------|---------|----------| | `s` | required | Section ID from Between SSP control panel | 999999 | `integer` | +| `cur` | optional | 3-letter ISO 4217 code defining the currency of the bid (currently support USD and EUR), default is USD | `'USD'` | `string` | ### Prebid-Server Bid Params @@ -28,4 +30,3 @@ safeframes_ok: false |---------------|----------|-------------|---------|----------| | `host` | required | Between SSP host url prefix. Defines data center where requests will be sent. Choose the closest one to the prebid-server you are using. Allowed values: `lbs-eu1.ads`, `lbs-ru1.ads`, `lbs-asia1.ads`, `lbs-us-east1.ads` | `'lbs-eu1.ads'` | `string` | | `publisher_id` | required | Publisher ID from Between SSP control panel | `'123'` | `string` | - diff --git a/dev-docs/bidders/bidbuddy.md b/dev-docs/bidders/bidbuddy.md new file mode 100644 index 0000000000..0cafaa8a77 --- /dev/null +++ b/dev-docs/bidders/bidbuddy.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Bidbuddy +description: Bidbuddy Bidder Adaptor +biddercode: bidbuddy +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Bidbuddy bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.bidbuddy.co.in'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/biddo.md b/dev-docs/bidders/biddo.md new file mode 100644 index 0000000000..b23d03ef6d --- /dev/null +++ b/dev-docs/bidders/biddo.md @@ -0,0 +1,24 @@ +--- +layout: bidder +title: Biddo +description: Prebid Biddo Bidder Adapter +pbjs: true +biddercode: biddo +safeframes_ok: false +sidebarType: 1 +--- + +### Note + +Here is what you need for Prebid integration with Biddo: + +1. Register with Biddo. +2. Once registered and approved, you will receive a Zone ID. +3. Use the Zone ID as parameters in params. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|------------------------------------------------|----------| +| `zoneId` | required | Zone ID | `379783` | `number` | diff --git a/dev-docs/bidders/bidfluence.md b/dev-docs/bidders/bidfluence.md deleted file mode 100644 index 4b90d41086..0000000000 --- a/dev-docs/bidders/bidfluence.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Bidfluence -description: Bidfluence Adaptor for Prebidjs -pbjs: true -biddercode: bidfluence -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|--------------|------------------------------------------|----------| -| `placementId` | required | Placement Id | `'1000'` | `string` | -| `publisherId` | required | Publisher Id | `'1000'` | `string` | -| `reservePrice` | optional | Floor price | `'0.5"` | `string` | diff --git a/dev-docs/bidders/bidgency.md b/dev-docs/bidders/bidgency.md new file mode 100644 index 0000000000..541557fc33 --- /dev/null +++ b/dev-docs/bidders/bidgency.md @@ -0,0 +1,44 @@ +--- +layout: bidder +title: Bidgency Group +description: Bidgency Group Bid Adapter +biddercode: bidgency +tcfeu_supported: false +usp_supported: true +media_types: video, native +safeframes_ok: true +pbjs: true +pbs: true +pbs_app_supported: true +floors_supported: true +schain_supported: true +fpd_supported: true +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +userIds: all +sidebarType: 1 +aliasCode: aso +--- +### Note + +The Bidgency Group adapter requires approval and setup. Please reach out to or visit us at [bidgency.com](https://bidgency.com) for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------|-----------------------------|-----------| +| `server` | required | Server endpoint | `https://srv.bidgx.com` | `String` | +| `zone` | required | Zone ID | `73815` | `Integer` | + +#### Video Caching + +Note that the Bidgency Group adapter expects a client-side Prebid Cache to be enabled for video bidding. + +```js +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } +}); +``` diff --git a/dev-docs/bidders/bidglass.md b/dev-docs/bidders/bidglass.md index a5bc551eef..2cf1087082 100644 --- a/dev-docs/bidders/bidglass.md +++ b/dev-docs/bidders/bidglass.md @@ -4,6 +4,7 @@ title: Bid Glass description: Bid Glass Bidder Adaptor pbjs: true biddercode: bidglass +sidebarType: 1 --- diff --git a/dev-docs/bidders/bidlab.md b/dev-docs/bidders/bidlab.md deleted file mode 100644 index 0dbc539640..0000000000 --- a/dev-docs/bidders/bidlab.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: bidder -title: Bidlab -description: Prebid Bidlab Bidder Adapter -pbjs: true -biddercode: bidlab -gdpr_supported: true -media_types: banner, video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: - -The Bidlab Bidding adapter requires setup before beginning. Please contact us at hello@bidlab.ai - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | Bidlab placement id | `'1234asdf'` | `'string'` | diff --git a/dev-docs/bidders/bidmachine.md b/dev-docs/bidders/bidmachine.md index 82f1dd997e..627c29d249 100644 --- a/dev-docs/bidders/bidmachine.md +++ b/dev-docs/bidders/bidmachine.md @@ -3,7 +3,7 @@ layout: bidder title: Bidmachine description: Prebid Bidmachine Bidder Adapter biddercode: bidmachine -gdpr_supported: true +tcfeu_supported: true gvl_id: 736 usp_supported: true coppa_supported: true @@ -16,10 +16,12 @@ pbjs: false pbs: true pbs_app_supported: true prebid_member: false +sidebarType: 1 --- -### Prebid Server Note: -The Bidmachine Bidding adapter requires setup before beginning. Please contact us at hi@bidmachine.io . +### Prebid Server Note + +The Bidmachine Bidding adapter requires setup before beginning. Please contact us at . ### Bid Params diff --git a/dev-docs/bidders/bidmyadz.md b/dev-docs/bidders/bidmyadz.md new file mode 100644 index 0000000000..d5a67523f7 --- /dev/null +++ b/dev-docs/bidders/bidmyadz.md @@ -0,0 +1,24 @@ +--- +layout: bidder +title: BidMyAdz +description: Prebid Bidmyadz Bidder Adapter +biddercode: bidmyadz +usp_supported: true +schain_supported: true +media_types: banner, video, native +tcfeu_supported: false +pbjs: false +pbs: true +pbs_app_supported: true +pbjs_version_notes: not in 5.x +sidebarType: 1 +--- + +### Prebid Server Bid Params + +Currently adapter doesn't support multiimpression, so only the first impression will be delivered + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|----------|----------------------------------------------------------|------------|-----------| +| `placementId` | required | Placement Id will be generated on BidMyAdz Platform. | `'1234'` | `string` | diff --git a/dev-docs/bidders/bidphysics.md b/dev-docs/bidders/bidphysics.md deleted file mode 100644 index d9dae7f143..0000000000 --- a/dev-docs/bidders/bidphysics.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: bidder -title: BidPhysics -description: Prebid BidPhysics Bidder Adaptor -pbjs: true -biddercode: bidphysics -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: - -The BidPhysics Header Bidding adaptor requires approval from the BidPhysics team. Please reach out to for more information. - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------|----------|--------------------|-------------|-----------| -| `unitId` | optional | Unit Id | `'13000'` | `string` | -| `networkId` | optional | Network Id | `'2300000'` | `string` | -| `publisherId` | optional | Publisher Id | `'8ba96b13-540d-4f8a-9f1b-2a7e804769cc'` | `string` | diff --git a/dev-docs/bidders/bidscube.md b/dev-docs/bidders/bidscube.md index 594f454522..cf094e4b62 100644 --- a/dev-docs/bidders/bidscube.md +++ b/dev-docs/bidders/bidscube.md @@ -6,13 +6,14 @@ pbs: true pbjs: true biddercode: bidscube media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: false pbs_app_supported: true +sidebarType: 1 --- -### Note: +### Note -The BidsCube Bidding adapter requires setup before beginning. Please contact us at support@bidscube.com +The BidsCube Bidding adapter requires setup before beginning. Please contact us at ### Bid Params diff --git a/dev-docs/bidders/bidstack.md b/dev-docs/bidders/bidstack.md new file mode 100644 index 0000000000..763b295dd8 --- /dev/null +++ b/dev-docs/bidders/bidstack.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: Bidstack +description: Prebid Bidstack Bidder Adapter +biddercode: bidstack +tcfeu_supported: true +gvl_id: 462 +usp_supported: false +coppa_supported: false +schain_supported: true +dchain_supported: false +media_types: video +safeframes_ok: false +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: false +pbs: true +pbs_app_supported: true +prebid_member: false +sidebarType: 1 +--- + +### Registration + +The Bidstack Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `publisherId` | required | Publisher ID | `'be224bf2-fd3f-4afb-b6fc-4a97718be2f5'` | `string` | +| `placementId` | optional | Placement ID | `'some_placement_id'` | `string` | +| `consent` | optional | User EULA consent | `true` | `boolean` | diff --git a/dev-docs/bidders/bidsxchange.md b/dev-docs/bidders/bidsxchange.md index 2c8484db9b..f06f2c4bb1 100644 --- a/dev-docs/bidders/bidsxchange.md +++ b/dev-docs/bidders/bidsxchange.md @@ -5,7 +5,9 @@ description: Prebid Bidsxchange Bidder Adapter biddercode: bidsxchange aliasCode: adtelligent media_types: video,banner -gdpr_supported: true +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId schain_supported: true coppa_supported: true @@ -14,6 +16,9 @@ safeframes_ok: true prebid_member: true pbjs: true pbs: false +sidebarType: 1 +enable_download: false +pbjs_version_notes: removed in 8.13.0 --- ### Bid params @@ -24,15 +29,17 @@ pbs: false | `aid` | required | The source ID from bidsxchange. | `529814` | `integer` | ### Description + Get access to multiple demand partners across Bidsxchange AdExchange and maximize your yield with Bidsxchange header bidding adapter. Bidsxchange header bidding adapter connects with Bidsxchange demand sources in order to fetch bids. This adapter provides a solution for accessing Video demand and display demand. -Bidsxchange now supports adpod. +Bidsxchange now supports adpod. ### Test Parameters -``` + +``` javascript var adUnits = [ // Video instream adUnit @@ -107,15 +114,15 @@ Bidsxchange now supports adpod. ### Additional Configuration -It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request +It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request (default value is 10). -``` - pbjs.setBidderConfig({ - config: { - bidsxchange: { - chunkSize: 1 // makes 1 http request per 1 adunit configured - } +``` javascript +pbjs.setBidderConfig({ + config: { + bidsxchange: { + chunkSize: 1 // makes 1 http request per 1 adunit configured } - }); + } +}); ``` diff --git a/dev-docs/bidders/big-richmedia.md b/dev-docs/bidders/big-richmedia.md new file mode 100644 index 0000000000..48c41a3599 --- /dev/null +++ b/dev-docs/bidders/big-richmedia.md @@ -0,0 +1,56 @@ +--- +layout: bidder +title: BigRichMedia +description: Prebid Big Richmedia Bidder Adapter +biddercode: big-richmedia +pbjs: true +media_types: banner, video +userIds: criteo, unifiedId, netId, identityLink, uid2 +schain_supported: true +coppa_supported: true +usp_supported: true +floors_supported: true +fpd_supported: true +tcfeu_supported: true +gvl_id: 32 +sidebarType: 1 +--- + +#### Global Settings + +Set the publisherId for using bigRichemedia + +``` +pbjs.que.push(function() { + // use the bid server in Taiwan (country code: tw) + pbjs.setConfig({ + bigRichmedia: { + 'publisherId': 'A7FN99NZ98F5ZD4G' + } + }); +}); +``` + +#### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-----------|----------|---------------------------|------------|----------| +| `placementId` | required | The placement ID. You may identify a placement using the `invCode` and `member` instead of a placement ID. | `234234` | `integer` | +| `member` | optional | The member ID from AppNexus. Must be used with `invCode`. | `'12345'` | `string` | +| `invCode` | optional | The inventory code from AppNexus. Must be used with `member`. | `'abc123'` | `string` | +| `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. | `keywords: { genre: ['rock', 'pop'] }` | `object` | + +#### Video Object + +Those configuration parameters are read from mediaTypes.video + +{: .table .table-bordered .table-striped } +| Name | Description | Type | +|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------| +| `minduration` | Integer that defines the minimum video ad duration in seconds. | `integer` | +| `maxduration` | Integer that defines the maximum video ad duration in seconds. | `integer` | +|`context` | A string that indicates the type of video ad requested. Allowed values: `"pre_roll"`; `"mid_roll"`; `"post_roll"`; `"outstream"`. | `string` | +| `skippable` | Boolean which, if `true`, means the user can click a button to skip the video ad. Defaults to `false`. | `boolean` | +|`skipoffset`| Integer that defines the number of seconds until an ad can be skipped. Assumes `skippable` setting was set to `true`. | `integer` | +| `frameworks` | Array of integers listing API frameworks supported by the publisher. Allowed values: None: `0`; VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; MRAID 2.0: `4`; ORMMA: `5`; OMID 1.0 `6`. | `Array` | diff --git a/dev-docs/bidders/bizzclick.md b/dev-docs/bidders/bizzclick.md index 694d56e3b0..15872a4126 100644 --- a/dev-docs/bidders/bizzclick.md +++ b/dev-docs/bidders/bizzclick.md @@ -3,7 +3,7 @@ layout: bidder title: BizzClick description: Prebid BizzClick Bidder Adaptor biddercode: bizzclick -gdpr_supported: true +tcfeu_supported: false usp_supported: true coppa_supported: true schain_supported: true @@ -12,16 +12,36 @@ safeframes_ok: true deals_supported: true pbjs: true pbs: true +pbs_app_supported: true +sidebarType: 1 +floors_supported: true +prebid_member: false +fpd_supported: false +gvl_id: none +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +userIds: all --- -### Note: +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at support@bizzclick.com .BizzClick will only respond to the first impression and that multiple ad formats of that single impression are not supported. +The Example Bidding adapter requires setup before beginning. Please contact us at .BizzClick will only respond to the first impression and that multiple ad formats of that single impression are not supported. -### Bid Params +### Bid Params for Prebid Server and Prebid Mobile {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | placement id | `'hash'` | `string` | -| `accountId` | required | account id | `'bizzclickTest'` | `string` | +| `sourceId` | required | Unique hash provided by bizzclick | `'6dllcEHSxYdSb6yLmCqE'` | `string` | +| `accountId` | required | Unique name provided by bizzclick | `'bizzclick-test'` | `string` | +| `host` | optional | Bizzclick server region. US East by default | `'us-e-node1'` | `string` | +| `placementId` | required | Deprecated parameter. Please use sourceId instead |`'6dllcEHSxYdSb6yLmCqE'`|`string` | + +### Bid Params for Prebid.js + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `sourceId` | required | Unique hash provided by bizzclick | `'6dllcEHSxYdSb6yLmCqE'` | `string` | +| `accountId` | required | Unique name provided by bizzclick | `'bizzclick-test'` | `string` | +| `host` | optional | Bizzclick server region. US East by default | `'us-e-node1'` | `string` | diff --git a/dev-docs/bidders/bliink.md b/dev-docs/bidders/bliink.md index 5344187d2b..3d96886874 100644 --- a/dev-docs/bidders/bliink.md +++ b/dev-docs/bidders/bliink.md @@ -3,14 +3,17 @@ layout: bidder title: BLIINK description: Prebid BLIINK Bidder Adaptor pbjs: true -pbs: false +pbs: true media_types: video, banner biddercode: bliink -gdpr_supported: true +gvl_id: 658 +tcfeu_supported: true usp_supported: false +sidebarType: 1 --- -### Note: +### Note + The BLIINK Header Bidding adaptor requires setup and approval from the BLIINK team. Please reach out to your account manager for more informations. ### Bid Params @@ -19,7 +22,5 @@ The BLIINK Header Bidding adaptor requires setup and approval from the BLIINK te | Name | Scope | Description | Example | Type | |-------------|----------|----------------------------------|--------------------------------------|----------| | `tagId` | required | The TagID from BLIINK. | `'32'` | `string` | -| `placement` | required | The placement from BLIINK. | `'video'` | `string` | - - -Same 'placement' parameter can be used from either prebid JS or prebid server. +| `imageUrl` | optional | The image url on which the ad is displayed in case of in-image ad. | `'https://image.png'` | `string` | +| `videoUrl` | optional | The Video url on which the ad is displayed in case of video ad. | `'https://video.mp4'` | `string` | diff --git a/dev-docs/bidders/blockthrough.md b/dev-docs/bidders/blockthrough.md new file mode 100644 index 0000000000..fbb9f4e845 --- /dev/null +++ b/dev-docs/bidders/blockthrough.md @@ -0,0 +1,94 @@ +--- +layout: bidder +title: Blockthrough +description: Prebid BT Bidder Adapter +biddercode: blockthrough +gvl_id: 815 +usp_supported: true +coppa_supported: false +gpp_sids: usp +schain_supported: true +dchain_supported: false +userId: pubProvidedId, id5Id, criteo, sharedId, identityLink, unifiedId, userId +media_types: banner +floors_supported: true +fpd_supported: true +pbjs: true +pbs: true +multiformat_supported: will-not-bid +ortb_blocking_supported: false +sidebarType: 1 +--- + +### Note + +The BT Bid Adapter makes requests to the BT Server which supports OpenRTB. + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). The BT adapter requires setup and approval from the Blockthrough team. Please reach out to [marketing@blockthrough.com](mailto:marketing@blockthrough.com) for more information. + +### Prebid JS + +#### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| -------- | -------- | --------------------------- | ------- | --------- | +| `bidderCode` | required | Bidder configuration. Could configure several bidders this way. | `bidderA: {publisherId: 55555}` | `object` | + +#### Bid Config + +Make sure to set required orgID, websiteID values received after approval using `pbjs.setBidderConfig`. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ----------- | -------- | ---------------------------------- | ------------------ | --------- | +| `orgID` | required | A unique ID for your organization provided by the Blockthrough team. | `4829301576428910` | `string` | +| `websiteID` | required | A unique ID for your site provided by the Blockthrough team. | `5654012389765432` | `string` | + +#### Example + +```javascript +pbjs.setBidderConfig({ + bidders: ['blockthrough'], + config: { + ortb2: { + site: { + ext: { + blockthrough: { + orgID: '4829301576428910', + websiteID: '5654012389765432', + }, + }, + }, + }, + }, +}); +``` + +#### AdUnits configuration example + +```javascript +var adUnits = [ + { + code: 'banner-div-1', + mediaTypes: { + banner: { + sizes: [[728, 90]], + }, + }, + bids: [ + { + bidder: 'blockthrough', + params: { + bidderA: { + publisherId: 55555, + }, + bidderB: { + zoneId: 12, + }, + }, + }, + ], + }, +]; +``` diff --git a/dev-docs/bidders/blue.md b/dev-docs/bidders/blue.md new file mode 100644 index 0000000000..f7200c9154 --- /dev/null +++ b/dev-docs/bidders/blue.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: Blue +description: Prebid Blue Bidder Adapter +tcfeu_supported: true +pbjs: true +pbs: true +biddercode: blue +prebid_member: false +floors_supported: true +safeframes_ok: true +media_types: banner +schain_supported: true +userIds: id5Id, identityLink, pubProvidedId +pbs_app_supported: true +gvl_id: 620 +sidebarType: 1 +--- + +### Note + +The bidder requires setup before usage. Please get in touch with our publisher team at to get started. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------|---------------|----------| +| `publisherId` | required | Unique publisher ID | `'ABCDEF'` | `string` | diff --git a/dev-docs/bidders/bluebillywig.md b/dev-docs/bidders/bluebillywig.md index de7698da89..33c8a43772 100644 --- a/dev-docs/bidders/bluebillywig.md +++ b/dev-docs/bidders/bluebillywig.md @@ -5,11 +5,13 @@ description: Prebid Blue Billywig Bidder Adaptor biddercode: bluebillywig pbjs: true media_types: video -gdpr_supported: true +gvl_id: 684 +tcfeu_supported: true schain_supported: true coppa_supported: true usp_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +sidebarType: 1 --- #### Bid Params diff --git a/dev-docs/bidders/bluesea.md b/dev-docs/bidders/bluesea.md new file mode 100644 index 0000000000..3f6bbd7839 --- /dev/null +++ b/dev-docs/bidders/bluesea.md @@ -0,0 +1,39 @@ +--- +layout: bidder +title: Bluesea +description: Prebid Bluesea Bidder Adapter +biddercode: bluesea +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +media_types: banner, video, native +safeframes_ok: false +floors_supported: true +pbjs: false +pbs: true +pbs_app_supported: true +fpd_supported: true +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +--- + +### Registration + +If you have any question regarding the set up, please reach out to your account manager or for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `pubid` | required | Unique partner account id | `'254673'` | `string` | +| `token` | required | Token for certification | `'3l2l2mbl2knw2ggc'` | `string` | + +### First Party Data + +Publishers can use the ortb2 configuration to provide First Party Data. The following fields are supported: + +* ortb2.site.* +* ortb2.user.* diff --git a/dev-docs/bidders/bmtm.md b/dev-docs/bidders/bmtm.md index 3d99a82779..5e218bcfe9 100644 --- a/dev-docs/bidders/bmtm.md +++ b/dev-docs/bidders/bmtm.md @@ -9,6 +9,7 @@ schain_supported: true pbjs: true pbs: true userIds: id5Id, sharedId +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/boldwin.md b/dev-docs/bidders/boldwin.md index 084e923814..b0fdb9fb11 100644 --- a/dev-docs/bidders/boldwin.md +++ b/dev-docs/bidders/boldwin.md @@ -3,18 +3,31 @@ layout: bidder title: Boldwin description: Prebid Boldwin Bidder Adapter pbjs: true +pbs: true biddercode: boldwin -gdpr_supported: true +gvl_id: 1151 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +floors_supported: true +pbs_app_supported: true +gpp_supported: true media_types: banner, video, native +multiformat_supported: will-bid-on-one +safeframes_ok: true +sidebarType: 1 --- -### Note: +### Note -The Boldwin Bidding adapter requires setup before beginning. Please contact us at wls_team@smartyads.com +The Boldwin Bidding adapter requires setup before beginning. Please contact us at ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | Boldwin placement id | `'1234asdf'` | `'string'` | +| `endpointId` | required | Endpoint Id | `'0'` | `string` | + +For both the Prebid Server and Prebid.js integrations it is required to use only one parameter: `endpointId`. +`endpointId` - should be sent in the Prebid bid request to Boldwin in case you integrate with Boldwin bidder. diff --git a/dev-docs/bidders/brainy.md b/dev-docs/bidders/brainy.md index 39ee2f3be3..c265e031ac 100644 --- a/dev-docs/bidders/brainy.md +++ b/dev-docs/bidders/brainy.md @@ -4,6 +4,7 @@ title: brainy description: Prebid brainy Bidder Adaptor pbjs: true biddercode: brainy +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/brave.md b/dev-docs/bidders/brave.md index e26f0f7249..6b4d155256 100644 --- a/dev-docs/bidders/brave.md +++ b/dev-docs/bidders/brave.md @@ -3,7 +3,7 @@ layout: bidder title: Brave description: Prebid Brave Bidder Adapter biddercode: brave -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true @@ -11,16 +11,22 @@ media_types: banner, video, native safeframes_ok: true deals_supported: true pbjs: true -pbs: false +pbs: true +gvl_id: 869 +floors_supported: true +pbs_app_supported: true +fpd_supported: false +dchain_supported: false +ortb_blocking_supported: true +sidebarType: 1 --- -### Note: +### Note -The Brave Header Bidding adapter requires setup and approval from the Brave team. Please reach out to your account manager or support@thebrave.io for more information +The Brave Header Bidding adapter requires setup and approval from the Brave team. Please reach out to your account manager or for more information ### Bid Params -{: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------------------------|-------------------------------------|-----------| | `placementId` | required | Brave's platform placement id | `'to0QI2aPgkbBZq6vgf0oHitouZduz0qw'` | `string` | diff --git a/dev-docs/bidders/brid.md b/dev-docs/bidders/brid.md new file mode 100644 index 0000000000..b9daa92dae --- /dev/null +++ b/dev-docs/bidders/brid.md @@ -0,0 +1,20 @@ +--- +layout: bidder +title: Brid +description: Prebid Brid Bidder Adapter +biddercode: brid +media_types: video +tcfeu_supported: true +usp_supported: true +schain_supported: true +pbjs: true +gvl_id: 934 +sidebarType: 1 +--- + +#### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------| +| `placementId` | required | The placement ID from Brid. The `placementID` parameter can be either a `string` or `integer` for Prebid.js, however `integer` is preferred. Legacy code can retain the `string` value. **Prebid Server requires an integer value.** | `12345` | `integer` | diff --git a/dev-docs/bidders/bridgewell.md b/dev-docs/bidders/bridgewell.md index 4ee73587de..8b66d069b4 100644 --- a/dev-docs/bidders/bridgewell.md +++ b/dev-docs/bidders/bridgewell.md @@ -6,6 +6,7 @@ pbjs: true biddercode: bridgewell media_types: display, native userIds: all +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/brightcom.md b/dev-docs/bidders/brightcom.md index 1b89899157..2953aba6a7 100644 --- a/dev-docs/bidders/brightcom.md +++ b/dev-docs/bidders/brightcom.md @@ -6,16 +6,18 @@ top_nav_section: dev_docs nav_section: reference pbjs: true biddercode: brightcom -gdpr_supported: true +gvl_id: 883 +tcfeu_supported: true +sidebarType: 1 --- -### Note: +### Note The Brightcom bidder adapter requires setup and approval from the Brightcom team. Please reach out to your account manager for more information and to start using it. ### Bid params -{: .table .table-bordered .table-striped } +{: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | | ---- | ----- | ----------- | ------- | ---- | diff --git a/dev-docs/bidders/brightcomssp.md b/dev-docs/bidders/brightcomssp.md new file mode 100644 index 0000000000..d78e661a67 --- /dev/null +++ b/dev-docs/bidders/brightcomssp.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Brightcom SSP +description: Prebid Brightcom SSP Bidder Adaptor +top_nav_section: dev_docs +nav_section: reference +pbjs: true +biddercode: bcmssp +filename: brightcomSSPBidAdapter +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +sidebarType: 1 +gvl_id: 883 +floors_supported: true +--- + +### Note + +The Brightcom SSP bidder adapter requires setup and approval from the Brightcom team. Please reach out to your account manager for more information and to start using it. + +### Bid params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +| ---- | ----- | ----------- | ------- | ---- | +| `publisherId` | required | The publisher ID from Brightcom | `2141020` | `integer` | +| `bidFloor` | optional | The minimum bid value desired | `1.23` | `float` | diff --git a/dev-docs/bidders/brightroll.md b/dev-docs/bidders/brightroll.md index aa67bc4598..c6dfc0d3f4 100644 --- a/dev-docs/bidders/brightroll.md +++ b/dev-docs/bidders/brightroll.md @@ -2,21 +2,25 @@ layout: bidder title: Brightroll description: Prebid Brightroll(Verizon Media) S2S Bidder Adaptor -pbs: true +pbs: false media_types: display, video biddercode: brightroll prebid_member: true -gdpr_supported: true +tcfeu_supported: false coppa_supported: true ccpa_supported: true schain_supported: true pbs_app_supported: false +sidebarType: 1 --- +{: .alert.alert-warning :} +The brightroll bid adapter is no longer supported and will not respond to bids. + ### Registration Brightroll requires registration for each Prebid Server host company -and each publisher. Contact dsp-supply-prebid@verizonmedia.com +and each publisher. Contact ### Bid Params diff --git a/dev-docs/bidders/browsi.md b/dev-docs/bidders/browsi.md new file mode 100644 index 0000000000..7f548f0b90 --- /dev/null +++ b/dev-docs/bidders/browsi.md @@ -0,0 +1,48 @@ +--- +layout: bidder +title: Browsi +description: Prebid Browsi Bidder Adapter +biddercode: browsi +pbjs: true +gvl_id: 329 +tcfeu_supported: true +usp_supported: true +media_types: no-display, video +schain_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Note + +For more information about [Browsi](https://www.browsi.com), please contact [support@browsi.com](mailto:support@browsi.com). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|------------------|------------------------------|----------| +| `pubId` | required | Publisher ID | `'117a476f-9791-4a82-80db-4c01c1683db0'` | `string` | +| `tagId` | required | Tag ID | `'1'` | `string` | + +# Sample Ad Unit: For Publishers + +```javascript +let videoAdUnit = [ + { + code: 'videoAdUnit', + mediaTypes: { + video: { + playerSize: [[300, 250]], + context: 'outstream' + }, + }, + bids: [{ + bidder: 'browsi', + params: { + pubId: '117a476f-9791-4a82-80db-4c01c1683db0', // Publisher ID provided by Browsi + tagId: '1' // Tag ID provided by Browsi + } + }] + }]; +``` diff --git a/dev-docs/bidders/bucksense.md b/dev-docs/bidders/bucksense.md index e276f7724b..7471157988 100644 --- a/dev-docs/bidders/bucksense.md +++ b/dev-docs/bidders/bucksense.md @@ -4,6 +4,9 @@ title: Bucksense description: Prebid Bucksense Bidder Adapter pbjs: true biddercode: bucksense +gvl_id: 235 +tcfeu_supported: true +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/buzzoola.md b/dev-docs/bidders/buzzoola.md index fa1107c611..e03c0cea32 100644 --- a/dev-docs/bidders/buzzoola.md +++ b/dev-docs/bidders/buzzoola.md @@ -5,10 +5,11 @@ description: Prebid Buzzoola Bidder Adaptor pbjs: true biddercode: buzzoola media_types: banner, video, native -gdpr_supported: false +tcfeu_supported: false +sidebarType: 1 --- -### Note: +### Note * The Buzzoola Header Bidding adaptor requires setup and approval before beginning. Please reach out to for more details. * Please note that cookie support is required. diff --git a/dev-docs/bidders/bwx.md b/dev-docs/bidders/bwx.md new file mode 100644 index 0000000000..fd3b2e9cac --- /dev/null +++ b/dev-docs/bidders/bwx.md @@ -0,0 +1,26 @@ +--- +layout: bidder +title: BoldwinX +description: BoldwinX Bidder Adapter +biddercode: bwx +media_types: banner, video, native +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: false +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +safeframes_ok: true +--- + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-------------------------------|------------------------------------|-----------| +| `pid` | required | unique placement ID | `aa8210e2013wc095fe9dba67981040b0` | `string` | +| `env` | optional | Environment name | `bwx-stage` | `string` | diff --git a/dev-docs/bidders/byplay.md b/dev-docs/bidders/byplay.md deleted file mode 100644 index 0cd4a92035..0000000000 --- a/dev-docs/bidders/byplay.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: ByPlay -description: Prebid ByPlay Bidder Adaptor -pbjs: true -biddercode: byplay -media_types: video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|----------------|----------|----------| -| `sectionId` | required | The section ID | `'7986'` | `string` | diff --git a/dev-docs/bidders/c1x.md b/dev-docs/bidders/c1x.md index af3a99716e..93868aee3f 100644 --- a/dev-docs/bidders/c1x.md +++ b/dev-docs/bidders/c1x.md @@ -2,24 +2,26 @@ layout: bidder title: C1X description: Prebid C1X Bidder Adaptor +pbs: false pbjs: true biddercode: c1x -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x +media_types: banner +tcfeu_supported: false +pbs_app_supported: false +enable_download: true --- -### Note: +### Note The C1X Header Bidding adaptor requires approval from the C1X team. Please reach out to for more information. ### Bid params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|-----------------------------------------------------------------|-------------------------------------|----------| -| `siteId` | required | Site ID from which the request is originating | `'999'` | `string` | -| `pixelId` | optional | Publisher's pixel ID | `'12345'` | `string` | -| `floorPriceMap` | optional | Minimum floor prices needed from the DSP's to enter the auction | `{"300x250": 4.00,"300x600": 3.00}` | `object` | -| `dspid` | optional | DSP ID | `'4321'` | `string` | -| `pageurl` | optional | Url of the webpage where the request is originating from | `'4321'` | `string` | +| Name | Scope | Description | Example | Type | +|----------------|----------|-----------------------------------------------------------------|-------------------------------------|----------| +| `placementId` | required | Placement ID | `'12345'` | `string` | +| `siteId` | required | Site ID from which the request is originating | `'999'` | `string` | +| `dealId` | optional | Deal ID to get the specific deal from our DSP | `'123456'` | `string` | +| `floorPriceMap`| optional | Minimum floor prices needed from the DSP's to enter the auction | `{"300x250": 4.00,"300x600": 3.00}` | `object` | +| `pageurl` | optional | Url of the webpage where the request is originating from | `'www.example.com'` | `string` | diff --git a/dev-docs/bidders/cadent_aperture_mx.md b/dev-docs/bidders/cadent_aperture_mx.md new file mode 100644 index 0000000000..e1f4c0e950 --- /dev/null +++ b/dev-docs/bidders/cadent_aperture_mx.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Cadent Aperture MX +description: Prebid Cadent Aperture MX Bidder Adaptor +pbjs: true +pbs: true +biddercode: cadent_aperture_mx +filename: cadentApertureMXBidAdapter +media_types: banner, video +tcfeu_supported: true +gvl_id: 183 +gpp_supported: true +usp_supported: true +schain_supported: true +floors_supported: true +userIds: identityLink, uid2 +sidebarType: 1 +--- + +### Registration + +To use this bidder you will need an account and a valid tagid from our exchange. For further information, please contact your Account Manager or . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------|----------|----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|------------| +| `tagid` | required | The Tag ID from Cadent Aperture MX. | `test1` | `string` | +| `bidfloor` | optional | The CPM bid floor | `0.25` | `string` | diff --git a/dev-docs/bidders/caroda.md b/dev-docs/bidders/caroda.md new file mode 100644 index 0000000000..2b20b41273 --- /dev/null +++ b/dev-docs/bidders/caroda.md @@ -0,0 +1,48 @@ +--- +layout: bidder +title: Caroda +description: Prebid Caroda Bidder Adaptor +biddercode: caroda +media_types: banner, video +coppa_supported: true +tcfeu_supported: true +usp_supported: true +prebid_member: false +pbjs: true +pbs: false +schain_supported: true +userIds: all +gvl_id: 954 +floors_supported: true +multiformat_supported: will-bid-on-any, will-bid-on-one +fpd_supported: true +safeframes_ok: true +ortb_blocking_supported: false +deals_supported: false +sidebarType: 1 +--- + +### Bid params + +The Caroda Bidding adapter requires setup before beginning. Please contact us on + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------------------------|-----------------------------------------------------------------|-------------------|-----------| +| `ctok` | required | id unique to a customer | `"abcdef"` | `string` | +| `placementId` | optional | used when there are multiple placements configured per domain | `"opzabc123"` | `string` | +| `priceType` | optional | price type | `"gross"` | `string` | + +### OpenRTB request config + +OpenRTB bid request `app`, `site`, `device` properties configured using prebid config. + +``` javascript +pbjs.setConfig({ + ortb2: { + app: { + name: 'My APP' + } + } +}); +``` diff --git a/dev-docs/bidders/catapultx.md b/dev-docs/bidders/catapultx.md deleted file mode 100644 index abb551bf81..0000000000 --- a/dev-docs/bidders/catapultx.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: CatapultX -description: CatapultX Bidder Adaptor -pbjs: true -pbs: true -biddercode: catapultx -aliasCode : adkernel -media_types: banner, video -gdpr_supported: true -usp_supported: true -coppa_supported: true -pbs_app_supported: true -schain_supported: true ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-----------------------|---------------------------|----------| -| `host` | required | RTB host | `'cpm.catapultx.com'` | `string` | -| `zoneId` | required | Zone Id | 76156 | `integer`| diff --git a/dev-docs/bidders/ccx.md b/dev-docs/bidders/ccx.md index 895fc9036d..d769c89bff 100644 --- a/dev-docs/bidders/ccx.md +++ b/dev-docs/bidders/ccx.md @@ -1,11 +1,14 @@ --- layout: bidder title: Clickonometrics -description: Prebid Clickonometrics Bidder Adaptor +description: Prebid Clickonometrics Bidder Adapter pbjs: true +pbs: true biddercode: ccx -media_types: video -gdpr_supported: true +media_types: banner, video +gvl_id: 773 +tcfeu_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/cedato.md b/dev-docs/bidders/cedato.md deleted file mode 100644 index 2aa6857b46..0000000000 --- a/dev-docs/bidders/cedato.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: bidder -title: Cedato -description: Prebid Cedato Bidder Adapter -top_nav_section: dev_docs -media_types: banner, video -gdpr_supported: true -usp_supported: true -nav_section: reference -pbjs: true -biddercode: cedato -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -| ---- | ----- | ----------- | ------- | ---- | -| `player_id` | required | The player ID from Cedato | `1450133326` | `integer` | -| `bidfloor` | optional | Bid floor value | `0.01` | `integer` | - -### Note - -The Cedato adapter requires setup and approval from the Cedato team. -Please reach out to your account team or publishers@cedato.com for more information. diff --git a/dev-docs/bidders/chtnw.md b/dev-docs/bidders/chtnw.md new file mode 100644 index 0000000000..505d1ce140 --- /dev/null +++ b/dev-docs/bidders/chtnw.md @@ -0,0 +1,23 @@ +--- +layout: bidder +title: chtnw +description: Prebid CHTNW Bidder Adaptor +pbjs: true +biddercode: chtnw +media_types: banner, video, native +gvl_id: none +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +prebid_member: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------|----------------------|----------| +| `placementId` | required | The CHT placement ID | `'38EL412LO82XR9O6'` | `string` | diff --git a/dev-docs/bidders/cleanmedianet.md b/dev-docs/bidders/cleanmedianet.md new file mode 100644 index 0000000000..2035fd58e0 --- /dev/null +++ b/dev-docs/bidders/cleanmedianet.md @@ -0,0 +1,33 @@ +--- +layout: bidder +title: Clean Media Net +description: Clean Media Bidder Adapter +biddercode: cleanmedianet +pbjs: true +media_types: banner, video +tcfeu_supported: false +usp_supported: true +coppa_supported: false +schain_supported: true +floors_supported: true +userIds: +prebid_member: false +safeframes_ok: true +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +gvl_id: +multiformat_supported: will-bid-on-any +--- + +### Disclosure + +Note: This bidder appears to only consider gdprApplies if a consent string is available. This may result in some incorrect GDPR processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------+----------+--------------------------------------------------------+-------------------------+---------| +| `supplyPartnerId` | required | The supply account's ID in your Clean Media dashboard. | `"1253"`, `"1254"`, etc | string | diff --git a/dev-docs/bidders/clickforce.md b/dev-docs/bidders/clickforce.md index 2b961b28b7..0aae55bd0f 100644 --- a/dev-docs/bidders/clickforce.md +++ b/dev-docs/bidders/clickforce.md @@ -5,6 +5,7 @@ description: Prebid Clickforce Bidder Adaptor pbjs: true biddercode: clickforce media_types: native +sidebarType: 1 --- ### Bid Params (display ad) @@ -20,4 +21,3 @@ media_types: native | Name | Scope | Description | Example | Type | |--------|----------|------------------------|----------|----------| | `zone` | required | The CLICKFORCE zone ID | `'6878'` | `string` | - diff --git a/dev-docs/bidders/clicktripz.md b/dev-docs/bidders/clicktripz.md deleted file mode 100644 index a7a175df80..0000000000 --- a/dev-docs/bidders/clicktripz.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: Clicktripz -description: Prebid Clicktripz Bidder Adaptor -pbjs: true -biddercode: clicktripz -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `placementId` | required | The Placement ID from Clicktripz | `'4312c63f'` | `string` | -| `siteId` | required | The site ID from Clicktripz | `'prebid'` | `string` | diff --git a/dev-docs/bidders/codefuel.md b/dev-docs/bidders/codefuel.md index f2b9b20833..a32e6dee7a 100644 --- a/dev-docs/bidders/codefuel.md +++ b/dev-docs/bidders/codefuel.md @@ -6,9 +6,10 @@ pbjs: true pbs: true media_types: banner biddercode: CodeFuel -gdpr_supported: false +tcfeu_supported: false usp_supported: false floors_supported: false +sidebarType: 1 --- ### Description @@ -17,15 +18,14 @@ Module that connects to Codefuel bidder to fetch bids. Display format is supported but not native format. Using OpenRTB standard. ### Bid Params + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------------------------------|------------------------------------------|----------| | `placementId` | required | Placement-Id defined by the caller | `'0111f8ac-2d40-4613-8557-b47dbf622fff'` | `string` | - ### Configuration - ```javascript pbjs.setConfig({ codefuel: { diff --git a/dev-docs/bidders/cointraffic.md b/dev-docs/bidders/cointraffic.md index 03f3974f41..336d71f251 100644 --- a/dev-docs/bidders/cointraffic.md +++ b/dev-docs/bidders/cointraffic.md @@ -4,6 +4,7 @@ title: Cointraffic description: Prebid Cointraffic Bidder Adaptor pbjs: true biddercode: cointraffic +sidebarType: 1 --- diff --git a/dev-docs/bidders/coinzilla.md b/dev-docs/bidders/coinzilla.md index 7e77dee719..dd324b9273 100644 --- a/dev-docs/bidders/coinzilla.md +++ b/dev-docs/bidders/coinzilla.md @@ -5,6 +5,7 @@ description: Prebid Coinzilla Bidder Adaptor pbjs: true pbs: true biddercode: coinzilla +sidebarType: 1 --- diff --git a/dev-docs/bidders/collectcent.md b/dev-docs/bidders/collectcent.md index 78e42374aa..0fafa1587a 100644 --- a/dev-docs/bidders/collectcent.md +++ b/dev-docs/bidders/collectcent.md @@ -6,6 +6,7 @@ pbjs: true biddercode: collectcent enable_download: false pbjs_version_notes: not in 5.x +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/colombia.md b/dev-docs/bidders/colombia.md deleted file mode 100644 index 10ea4fe7ea..0000000000 --- a/dev-docs/bidders/colombia.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: COLOMBIA -description: Prebid COLOMBIA Bidder Adaptor -pbjs: true -biddercode: colombia -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|------------------|---------|----------| -| `placementId` | required | The placement ID(Adunit Id) | | `string` | diff --git a/dev-docs/bidders/colossus.md b/dev-docs/bidders/colossus.md index e7b322df75..a377f317eb 100644 --- a/dev-docs/bidders/colossus.md +++ b/dev-docs/bidders/colossus.md @@ -11,13 +11,21 @@ gdpr: true pbjs: false pbs: true pbs_app_supported: true +sidebarType: 1 --- +### Disclosure + +This adapter is known to use an HTTP 1 endpoint. Header bidding often generates multiple requests to the same host and bidders are encouraged to change to HTTP 2 or above to help improve publisher page performance via multiplexing. + ### Prebid.Server Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|----------|----------------------------------------------------------|------------|-----------| -| `TagID` | required | Placement Id will be generated on Colossus SSP Platform. | `'0'` | `string` | +| `TagID` | optional | Placement Id will be generated on Colossus SSP Platform. | `'0'` | `string` | +| `groupId` | optional | Group Id will be generated on Colossus SSP Platform. | `'0'` | `string` | + +You only need to use one parameter: either TagID or groupId *For prebidJS parametres, look into colossusssp.md* diff --git a/dev-docs/bidders/colossusssp.md b/dev-docs/bidders/colossusssp.md index 26d6da21c0..4edb102200 100644 --- a/dev-docs/bidders/colossusssp.md +++ b/dev-docs/bidders/colossusssp.md @@ -8,9 +8,9 @@ schain_supported: true media_types: banner, video, native userIds: britepoolid, identityLink, unifiedId, id5Id, uid2 gdpr: true -fpd_supported: true pbjs: true pbs: false +sidebarType: 1 --- ### Prebid.JS Bid Params diff --git a/dev-docs/bidders/compass.md b/dev-docs/bidders/compass.md index ac2506bc9a..49b7428af3 100644 --- a/dev-docs/bidders/compass.md +++ b/dev-docs/bidders/compass.md @@ -4,7 +4,7 @@ title: Compass description: Prebid Compass Bidder Adapter biddercode: compass usp_supported: true -gdpr_supported: true +tcfeu_supported: true coppa_supported: true schain_supported: true floors_supported: true @@ -13,6 +13,7 @@ pbjs: true pbs: true pbs_app_supported: true gvl_id: 883 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/conceptx.md b/dev-docs/bidders/conceptx.md new file mode 100644 index 0000000000..eb5520af43 --- /dev/null +++ b/dev-docs/bidders/conceptx.md @@ -0,0 +1,46 @@ +--- +layout: bidder +title: Conceptx +description: Conceptx bidder adapter +biddercode: conceptx +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +floors_supported: true +media_types: banner +userIds: all +pbjs: true +pbs: false +pbs_app_supported: false +sidebarType: 1 +safeframes_ok: true +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------------------------------------------------------|----------|----------| +| `site` | required | The site `'your-page-name'`. | `'your-page-name'` | `string` | +| `adunit` | required | The specific adunit | `'some-id-3'` | `string`| + +#### Banner example + +```js +var adUnits = [ + code: 'your-banner-container-id', + mediaTypes: { + banner: { + sizes: [[930, 180]] + } + }, + bids: [{ + bidder: 'conceptx', + params: { + site: "example", adunit: "some-id-3" + } + }] +]; +``` diff --git a/dev-docs/bidders/concert.md b/dev-docs/bidders/concert.md index 130ee510f9..40f627720a 100644 --- a/dev-docs/bidders/concert.md +++ b/dev-docs/bidders/concert.md @@ -6,8 +6,11 @@ hide: true pbjs: true biddercode: concert media_types: banner -gdpr_supported: true +tcfeu_supported: false usp_supported: true +gpp_supported: true +userIds: sharedId, unifiedId, uid2 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/connatix.md b/dev-docs/bidders/connatix.md new file mode 100644 index 0000000000..d961bb7cac --- /dev/null +++ b/dev-docs/bidders/connatix.md @@ -0,0 +1,80 @@ +--- +layout: bidder +title: Connatix +description: Connatix Bidder Adapter +biddercode: connatix +tcfeu_supported: true +gvl_id: 143 +usp_supported: true +coppa_supported: false +gpp_sids: tcfeu, usp +schain_supported: false +dchain_supported: false +userId: none +media_types: banner +safeframes_ok: true +deals_supported: true +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement id | `'ed8a9c16-88ea-4724-aa0d-013c3e595e49'` | `string` | +| `bidfloor` | optional | Floor price | `2.5` | `float` | + +#### Example + +```js +var adUnits = [ + { + code: '1', + mediaTypes: { + banner: { + sizes: [[640, 480], [320, 180]], + }, + }, + bids: [ + { + bidder: 'connatix', + params: { + placementId: 'e4984e88-9ff4-45a3-8b9d-33aabcad634e', // required + bidfloor: 2.5, // optional + }, + }, + // Add more bidders and their parameters as needed + ], + }, + // Define more ad units here if necessary +]; +``` + +### Configuration + +To maximize revenue efficiency, please enable ```iframe``` user syncing. + +Connatix strongly recommends enabling user syncing through iFrames. This functionality improves DSP user match rates and increases the bid rate and bid price. Make sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Connatix. + +#### Example configuration + +```js +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: ['connatix'], + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/connectad.md b/dev-docs/bidders/connectad.md index b5f67acab3..ec7418a887 100644 --- a/dev-docs/bidders/connectad.md +++ b/dev-docs/bidders/connectad.md @@ -4,7 +4,7 @@ title: ConnectAd description: ConnectAd Prebid Adaptor biddercode: connectad media_types: banner -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true @@ -15,9 +15,13 @@ floors_supported: true pbjs: true pbs: true gvl_id: 138 +sidebarType: 1 --- -### Prebid Server Note: +### Prebid Server Note + +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} + Please reach out to your ConnectAd Account Manager before configuring the S2S adapter for approval and setup. ### Bid Params diff --git a/dev-docs/bidders/consumable-server.md b/dev-docs/bidders/consumable-server.md new file mode 100644 index 0000000000..5f5119652f --- /dev/null +++ b/dev-docs/bidders/consumable-server.md @@ -0,0 +1,360 @@ +--- +layout: bidder +title: Consumable +description: Prebid Consumable Bidder adapter +userIds: all +pbjs: false +pbs: true +pbs_app_supported: true +schain_supported: true +coppa_supported: true +tcfeu_supported: true +floors_supported: true +usp_supported: true +gpp_supported: true +biddercode: consumable +media_types: banner, video, audio +gvl_id: 591 +deals_supported: true +fpd_supported: true +sidebarType: 1 +multiformat_supported: will-bid-on-one +safeframes_ok: true +--- + +### Note + +The Consumable adapter requires setup and approval from your Consumable account manager, even for existing Consumable publishers. Please reach out to your account manager to enable Prebid for your account. + +### Disclosure + +The Consumable bid adapter may cycle the ad initially shown with a new one at various intervals. This means the advertiser meta-data accompanying the bid response may be incomplete at the time of response. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------------|---------|-----------| +| `siteId` | required | The site ID from Consumable. | `12345` | `integer` | +| `networkId` | required | The network ID from Consumable. | `9969` | `integer` | +| `unitId` | required | The unit ID from Consumable. | `987654` | `integer` | +| `unitName` | required | The unit name from Consumable. | `cnsmbl-unit` | `string` | +| `placementId` | required | the placementid from Consumable. | `0421008445828ceb46f496700a5fa65e` | `string` | + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Supported media types](#supported-media-types) +* [Setup instructions to call Consumable through Prebid Server](#setup-instructions-to-call-consumable-through-prebid-server) + * [Call Consumable from a web browser](#call-consumable-from-a-web-browser) + * [Call Consumable from Prebid Mobile SDK](#call-consumable-from-prebid-mobile-sdk) + * [Call Consumable from CTV/long-form video environment](#call-consumable-from-ctvlong-form-video-environment) +* [Bid request parameters](#bid-request-parameters) + * [Site](#site-banner-video-audio) + * [App](#app-or-ctv-banner-video-audio) +* [Examples](#examples) + +## Introduction + +Publishers can use Prebid Server in any of the following ways with Consumable. Consumable's adapter supports all of the following methods: + +* If you want to call Consumable from a web environment, you can use Prebid.js to call Prebid Server, and then Prebid Server uses our server-side adapter to call Consumable. This reduces workload on the browser. For set up instructions, see [Call Consumable from a web browser](#call-consumable-from-a-web-browser) section on this page. +* In mobile apps, you can use the Prebid Mobile SDK to call Prebid Server and then Prebid Server uses our server-side adapter to call Consumable. For set up instructions, see [Call Consumable from Prebid Mobile SDK](#call-consumable-from-prebid-mobile-sdk) section on this page. +* In CTV apps and other long-form video environments, you (or the SSAI vendor) can make a call to Prebid Server using OpenRTB, and then Prebid Server uses our server-side adapter to call Consumable. For set up instructions, see [Call Consumable from CTV/long-form video environment](#call-consumable-from-ctvlong-form-video-environment) section on this page. + +## Supported media types + +The following table lists the media types that Consumable supports. For information about the the Time-To-Live (TTL) for each media type, see [How Consumable counts impressions](https://kb.Consumableexchange.com/publishers/billing/how_Consumable_counts_impressions.htm) in our Knowledge Base. + +{: .table .table-bordered .table-striped } +| Type | Prebid Server support | +| ----------- | ----------- | +| banner | Supported | +| video | Supported, including ad pods for OTT | +| audio | Supported | + +## Setup instructions to call Consumable through Prebid Server + +**Note:** If you are hosting your own Prebid Server instance, you must contact your Consumable Exchange Representative to get an endpoint and setup instructions. + +If you are using an existing Prebid Server instance that is already configured to call Consumable, depending on whether you want to call Consumable from the browser, mobile app, CTV, or long-form video, follow any of the below sections to complete the Consumable-specific configuration. + +### Call Consumable from a web browser + +To call Consumable from a web browser using Prebid Server, you must first configure Prebid.js to call Consumable directly from the browser using our client-side adapter. Follow the quick start instructions provided in Prebid's [Getting Started for Developers](/dev-docs/getting-started.html) documentation. Complete the following steps to complete the Consumable-specific configuration: + +1. Build the binary in one of the following ways: + [Download Prebid.js](/download.html) from the Prebid site to use the standard compiled binary that Prebid includes in the download process and select **Consumable Exchange** as an adapter. +2. Define the Consumable-specific parameters at the bidder level which include adding `consumable` as the bidder and the `siteId`. For Consumable's bidder-specific parameters, see the [Bid request parameters](#bid-request-parameters) section below. + + ```javascript + { + bidder: 'consumable', + params: { + "networkId": 11, + "siteId": 32, + "unitId": 42, + "unitName": "cnsmbl-audio-728x90-slider" + } + } + ``` + +3. Define your ad units in the `adUnit` object. This includes the details about the ad slots such as the media types, ad size, and ad code. For more information about this object, see Prebid's [Ad Unit Reference](/dev-docs/adunit-reference.html) documentation. +4. Enable user syncing by adding the following code in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function. Consumable strongly recommends enabling user syncing through iFrames, though we do also support image-based syncing. This functionality improves DSP user match rates and increases the Consumable bid rate and bid price. Make sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Consumable. + + ```javascript + pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: ['consumable'], + filter: 'include' + } + } + } + }); + ``` + +5. (Optional) Set up First Party Data (FPD). For more information about the data types we support and the instructions for each option, see the [Set up First Party Data (FPD)](/dev-docs/bidders/consumable.html#set-up-first-party-data-fpd) section in our Prebid.js documentation on the Prebid site. +6. (Optional) If you want to monetize instream video, you need to enable a cache endpoint in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function as follows:
      + + ```javascript + pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + ``` + +### Call Consumable from Prebid Mobile SDK + +**Before you begin:** Contact your Consumable Exchange representative to get your `placementId`. You must provide this placementID to your Prebid Server host company. + +**Note:** To implement Prebid Mobile SDK, follow Prebid's [Getting Started with Prebid Mobile](/prebid-mobile/prebid-mobile-getting-started.html) documentation. + +To add Consumable as a bidder to your mobile app: + +1. Inform your Prebid Server hosting company to add `consumable` as a bidder in the configuration and include the `placementId` that Consumable provides to you at the time of integration. +2. Define the Consumable-specific parameters at the bidder level. For information about these parameters, see the [Bid request parameters](#bid-request-parameters) section below. +3. Include any ad unit level required or optional parameters provided in Prebid's [Prebid Mobile API - iOS](/prebid-mobile/pbm-api/ios/ios-sdk-integration-gam-original-api.html) and [Prebid Mobile API - Android](/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html) documentation. + +### Call Consumable from CTV/long-form video environment + +**Before you begin:** Contact your Consumable Exchange Representative to get the `placementId`. You must provide this placement ID to your Prebid Server host company. + +**Note:** To implement CTV and long-form video using Prebid Server, follow Prebid's [Long Form Video](/prebid-server/use-cases/pbs-lfv.html) documentation. + +To add Consumable as a bidder: + +1. Inform your Prebid Server hosting company to add `consumable`as a bidder in the configuration and include the `placementId` that Consumable provides to you at the time of integration. +2. Define the Consumable-specific parameters at the bidder level. For information about these parameters, see the [Bid request parameters](#bid-request-parameters) section below. +3. Include any ad unit level required or optional parameters provided in Prebid's [/openrtb2/video](/prebid-server/endpoints/openrtb2/pbs-endpoint-video.html) documentation. + +## Bid request parameters + +For a list of the OpenRTB fields that Consumable supports in bid requests, see [List of supported OpenRTB bid request fields for sellers](https://kb.Consumableexchange.com/publishers/openrtb_integration/list_of_supported_openrtb_bid_request_fields_for_sellers.htm#List_of_supported_OpenRTB_bid_request_fields_for_sellers). The following are the required fields for the various supported media types. +### Site (Banner, Video, Audio) + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------------|---------|-----------| +| `siteId` | required | The site ID from Consumable. | `12345` | `integer` | +| `networkId` | required | The network ID from Consumable. | `9969` | `integer` | +| `unitId` | required | The unit ID from Consumable. | `987654` | `integer` | +| `unitName` | required | The unit name from Consumable. | `cnsmbl-unit` | `string` | + +### App or CTV (Banner, Video, Audio) + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Key | Scope | Type | Description | +|---|---|---|---| +| `placementId` | Required | String | An Consumable-specific identifier that is associated with this ad unit. It will be associated with the single size, if the size is provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'0421008445828ceb46f496700a5fa65e'`| + +## Examples + +**Banner** + +```json +{ + "id": "cons-banner-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "w": 300, + "h": 250, + "id": "1", + "pos": 0, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "instl": 0, + "tagid": "5602709", + "bidfloor": 0.02, + "bidfloorcur": "USD", + "secure": 1, + "ext": { + "consumable": { + "placementId": "0421008445828ceb46f496700a5fa65e" + } + } + } + ], + "app": { + "bundle": "555555555", + "storeurl": "https://apps.apple.com/us/app/test-app/id555555555", + "publisher": { + "id": "123456" + }, + "content": { + "title": "Entertainment", + "genre": "IAB9-30,IAB6,IAB9-7,IAB1" + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", + "ip": "10.20.30.40", + "ifa": "2E2E2E2E-3B3B-4141-8A8A-181818181818" + }, + "at": 1, + "tmax": 200 +} +``` + +**Video** + +```json +{ + "id": "cons-video-example", + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "video/mp4", + "video/3gpp", + "video/webm" + ], + "minduration": 15, + "maxduration": 60, + "startdelay": -1, + "protocols": [ + 2, + 3, + 5, + 6 + ], + "w": 320, + "h": 480, + "placement": 1, + "linearity": 1, + "minbitrate": 1000, + "api": [ + 1, + 2, + 3, + 5 + ] + }, + "secure": 1, + "ext": { + "consumable": { + "placementId": "0421008445828ceb46f496700a5fa65e" + } + } + } + ], + "app": { + "bundle": "555555555", + "storeurl": "https://apps.apple.com/us/app/test-app/id555555555", + "publisher": { + "id": "123456" + }, + "content": { + "title": "Entertainment", + "genre": "IAB9-30,IAB6,IAB9-7,IAB1" + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E18", + "ip": "10.20.30.40", + "ifa": "2E2E2E2E-3B3B-4141-8A8A-181818181818" + }, + "at": 1, + "tmax": 1000 +} +``` + +**Audio** + +```json +{ + "id": "cons-audio-example", + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "video/mp3" + ], + "minduration": 15, + "maxduration": 60, + "startdelay": -1, + "protocols": [ + 2, + 3, + 5, + 6 + ], + "placement": 1, + "linearity": 1, + "minbitrate": 1000, + "api": [ + 1, + 2, + 3, + 5 + ] + }, + "secure": 1, + "ext": { + "consumable": { + "placementId": "0421008445828ceb46f496700a5fa65e" + } + } + } + ], + "app": { + "bundle": "555555555", + "storeurl": "https://apps.apple.com/us/app/test-app/id555555555", + "publisher": { + "id": "123456" + }, + "content": { + "title": "Entertainment", + "genre": "IAB9-30,IAB6,IAB9-7,IAB1" + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E18", + "ip": "10.20.30.40", + "ifa": "2E2E2E2E-3B3B-4141-8A8A-181818181818" + }, + "at": 1, + "tmax": 1000 +} +``` diff --git a/dev-docs/bidders/consumable.md b/dev-docs/bidders/consumable.md index 9f56640166..52009f80cf 100644 --- a/dev-docs/bidders/consumable.md +++ b/dev-docs/bidders/consumable.md @@ -1,17 +1,34 @@ --- layout: bidder title: Consumable -description: Prebid Consumable Bidder Adaptor +description: Prebid Consumable Bidder adapter +userIds: all pbjs: true -pbs: true +pbs: false pbs_app_supported: true +schain_supported: true +coppa_supported: true +tcfeu_supported: true +floors_supported: true +usp_supported: true +gpp_supported: true biddercode: consumable -gdpr_supported: true +media_types: banner, video, audio gvl_id: 591 +deals_supported: true +fpd_supported: true +sidebarType: 1 +multiformat_supported: will-bid-on-one +safeframes_ok: true --- -### Note: -The Consumable adaptor requires setup and approval from your Consumable account manager, even for existing Consumable publishers. Please reach out to your account manager to enable Prebid.js for your account. +### Note + +The Consumable adapter requires setup and approval from your Consumable account manager, even for existing Consumable publishers. Please reach out to your account manager to enable Prebid.js for your account. + +### Disclosure + +The Consumable bid adapter may cycle the ad initially shown with a new one at various intervals. This means the advertiser meta-data accompanying the bid response may be incomplete at the time of response. ### Bid Params @@ -22,3 +39,236 @@ The Consumable adaptor requires setup and approval from your Consumable account | `networkId` | required | The network ID from Consumable. | `9969` | `integer` | | `unitId` | required | The unit ID from Consumable. | `987654` | `integer` | | `unitName` | required | The unit name from Consumable. | `cnsmbl-unit` | `string` | + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Supported media types](#supported-media-types) +* [Set up Prebid.js to call Consumable directly from the browser](#set-up-prebidjs-to-call-consumable-directly-from-the-browser-client-side-adapter) +* [Set up Prebid.js to call Consumable through Prebid Server](#set-up-prebidjs-to-call-consumable-through-prebid-server-server-side-adapter) +* [Set up First Party Data (FPD)](#set-up-first-party-data-fpd) + * [Global data](#set-up-first-party-data-fpd) + * [Consumable bidder-specific data](#consumable-bidder-specific-data) + * [AdUnit-specific data](#adunit-specific-data) +* [Bid request parameters](#bid-request-parameters) + * [Banner](#banner) + * [Video](#video) +* [Examples](#examples) + +## Introduction + +Publishers can use Prebid.js to call Consumable Exchange (Consumable) in any of the following ways: + +* **Call through our client-side adapter:** Prebid.js calls Consumable directly from the browser using our client-side adapter. This option tends to have a better cookie match rate. For configuration instructions, see the [Set up Prebid.js to call Consumable directly from the browser (client-side adapter)](#set-up-prebidjs-to-call-consumable-directly-from-the-browser-client-side-adapter) on this page. +* **Call through our server-side adapter**: Prebid.js makes a call to Prebid Server and then Prebid Server uses our server-side adapter to call Consumable. This reduces workload on the browser. For configuration instructions, see the [Set up Prebid.js to call Consumable through Prebid Server (server-side adapter)](#set-up-prebidjs-to-call-consumable-through-prebid-server-server-side-adapter) on this page. + +**Notes:** + +* **Recommended Global Bidder settings:** For our adapter, Consumable recommends enabling local storage. As of Prebid.js 7.x, local storage access must be explicitly specified. By leveraging local storage, Consumable is able to take advantage of the latest features our exchange has to offer. For instructions on enabling local storage, see Prebid’s [pbjs.bidderSettings](/dev-docs/publisher-api-reference/bidderSettings.html) documentation. + +### Example + +```javascript +pbjs.bidderSettings = { + consumable: { + storageAllowed: true + } +}; +``` + +## Supported media types + +The following table lists the media types that Consumable supports. + +{: .table .table-bordered .table-striped } + +| Type | Prebid Server support | +|--------| ----------- | +| banner | Supported | +| video | Supported | + +## Set up Prebid.js to call Consumable directly from the browser (client-side adapter) + +To call Consumable from a web browser environment using a Prebid Server integration, see the Consumable-specific configuration steps in [Setup instructions to call Consumable through Prebid Server](/dev-docs/bidders/consumable-server.html#setup-instructions-to-call-consumable-through-prebid-server) in our Prebid Server documentation on the Prebid site. + +## Set up Prebid.js to call Consumable through Prebid Server (server-side adapter) + +In this configuration, Prebid.js makes a call to Prebid Server and then Prebid Server uses our server-side adapter to call Consumable. Complete the following steps to configure Consumable as a demand source: + +1. If you are hosting your own Prebid Server instance, see [Setup instructions to call Consumable through Prebid Server](/dev-docs/pbs-bidders.html#setup-instructions-to-call-consumable-through-prebid-server). +2. In the `[pbjs.setConfig()]` function, within the `s2sConfig` property, add `consumable` to the `bidders` attribute. +3. Define the Consumable-specific parameters at the bidder level. For Consumable's bidder-specific parameters, see the [Bid request parameters](#bid-request-parameters) section below. +4. Define your ad units in the `adUnit` object. For more information about this object, see Prebid's [Ad Unit Reference](/dev-docs/adunit-reference.html) documentation. +5. Enable user syncing by adding the following code in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function. Consumable strongly recommends enabling user syncing through iFrames, though we do also support image-based syncing. This functionality improves DSP user match rates and increases the Consumable bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Consumable.
      + + ```javascript + pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: ['consumable'], + filter: 'include' + } + } + } + }); + ``` + +6. (Optional) Set up First Party Data (FPD). For more information about the data types we support and the instructions for each option, see the [Set up First Party Data (FPD)](#set-up-first-party-data-fpd) section below. +7. (Optional) If you want to monetize instream video, you need to enable a cache endpoint in the `[pbjs.setConfig()]` function as follows: + + ```javascript + pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + ``` + +## Set up First Party Data (FPD) + +You can set up the Prebid.js FPD module using Global data, Consumable bidder-specific site data, or ad unit-specific data. Consumable supports deal targeting in all the three FPD types. + +### Global data + +Use this data type to allow all bid adapters to have access to first party data that might be useful in ad targeting. This is available from Prebid.js version 4.30 and above. + +To supply data that is accessible to all bidders, use the `[pbjs.setConfig()]` object as illustrated below. Use the `[setBidderConfig()]` function to supply bidder-specific data. For more information about the standard or more detailed examples, see Prebid's [First Party Data Feature](/features/firstPartyData.html) documentation. + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + ... + }, + user: { + ... + } + } +}); +``` + +### Consumable bidder-specific data + +This data type is available from Prebid version 7.49.0 and above. You can use it to specify key-value pairs that will be included in your query string when targeting deals. For example, if a user visits a news page, you can pass that information by submitting a key-value pair for `category = news`. You can then create a deal in the Consumable UI and activate the deal only on pages that contain `category = news` as the key-value pair. + +To include the FPD in a bid request, in the `[pbjs.setConfig()]` object at the `consumable` bidder level, provide the key-values in the `firstPartyData` parameter. Make sure that you set it before the `pbjs.requestBids` configuration. If you want to change the values, you can update the `pbjs.setConfig` once again. The change will be reflected in all future bid requests. + +```javascript +pbjs.setConfig({ + consumable: { + firstPartyData: { + '': '', + '': '', + // ... + } + } +}); +``` + +### AdUnit-specific data + +Use this data type to specify key-value pairs at the ad unit level when targeting deals and apply it to all bidders. This will be available from Prebid.js version 7.46 and above. To include the adUnit-specific data in a bid request, see Prebid's [Supplying AdUnit-Specific Data](/features/firstPartyData.html#supplying-adunit-specific-data) documentation. + +```javascript +ortb2Imp: { + ext: { + data: { + pbadslot: "homepage-top-rect", + adUnitSpecificAttribute: "123" + } + } +} +``` + +## Bid request parameters + +### Banner + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------------|---------|-----------| +| `siteId` | required | The site ID from Consumable. | `12345` | `integer` | +| `networkId` | required | The network ID from Consumable. | `9969` | `integer` | +| `unitId` | required | The unit ID from Consumable. | `987654` | `integer` | +| `unitName` | required | The unit name from Consumable. | `cnsmbl-unit` | `string` | + +### Video + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------------|---------|-----------| +| `siteId` | required | The site ID from Consumable. | `12345` | `integer` | +| `networkId` | required | The network ID from Consumable. | `9969` | `integer` | +| `unitId` | required | The unit ID from Consumable. | `987654` | `integer` | +| `unitName` | required | The unit name from Consumable. | `cnsmbl-unit` | `string` | + +## Examples + +**Banner** + +```javascript +var adUnits = [{ + code: 'banner-div-a', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'consumable', + params: { + "networkId": 11, + "siteId": 32, + "unitId": 42, + "unitName": "the-answer" + } + } + ] +}]; + +``` + +**Video:**
      + +```javascript +var adUnits = [{ + code: 'video-div-a', + mediaTypes: { + video: { + // Preferred location as of version 4.43 + video obj + playerSize: [300, 250], + api: [2], + protocols: [2, 3, 5, 6], + minduration: 5, + maxduration: 30, + mimes: ['video/mp4', 'application/javascript'], + placement: 3 + } + }, + bids: [{ + bidder: 'consumable', + params: { + "networkId": 11, + "siteId": 32, + "unitId": 42, + "unitName": "the-answer" + video: { + // openrtb v2.5 compatible video obj + // If required, use this to override mediaTypes.video.XX properties + } + } + }] +}]; + +``` diff --git a/dev-docs/bidders/contentexchange.md b/dev-docs/bidders/contentexchange.md index 364ee93d6f..9930f09b62 100644 --- a/dev-docs/bidders/contentexchange.md +++ b/dev-docs/bidders/contentexchange.md @@ -6,10 +6,12 @@ biddercode: contentexchange usp_supported: true schain_supported: true media_types: banner, video, native -gdpr_supported: true +gvl_id: 864 +tcfeu_supported: true pbjs: true pbs: false pbs_app_supported: false +sidebarType: 1 --- ### Prebid.JS Bid Params diff --git a/dev-docs/bidders/contentignite.md b/dev-docs/bidders/contentignite.md index ef2461a98c..452956a9c7 100644 --- a/dev-docs/bidders/contentignite.md +++ b/dev-docs/bidders/contentignite.md @@ -4,6 +4,7 @@ title: Content Ignite description: Prebid Contnent Ignite Adaptor pbjs: true biddercode: contentignite +sidebarType: 1 --- diff --git a/dev-docs/bidders/converge.md b/dev-docs/bidders/converge.md index d4a010aad0..02c95c05f9 100644 --- a/dev-docs/bidders/converge.md +++ b/dev-docs/bidders/converge.md @@ -2,21 +2,28 @@ layout: bidder title: Converge-Digital description: Converge-Digital Bidder Adaptor -pbjs: true -pbs: true biddercode: converge -aliasCode : adkernel +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +tcfeu_supported: true +gpp_supported: true +gvl_id: 248 usp_supported: true coppa_supported: true pbs_app_supported: true -gvl_id: 248 schain_supported: true userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The Converge-Digital Bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/conversant.md b/dev-docs/bidders/conversant.md deleted file mode 100644 index 80f142c8f2..0000000000 --- a/dev-docs/bidders/conversant.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -layout: bidder -title: Conversant -description: Prebid Conversant Bidder Adaptor -pbjs: true -pbs: true -biddercode: conversant -media_types: video -gdpr_supported: true -userIds: criteo, id5Id, identityLink, liveIntentId, parrableId, pubCommonId, unifiedId, publinkId -prebid_member: true -gvl_id: 24 ---- - - - -### Bid Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|---------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------|------------------| -| `site_id` | optional | The site ID from Conversant. | `'87293'` | `string` | -| `secure` | required (for secure pages) | If impression requires secure HTTPS URL creative assets and markup. 0 for non-secure, 1 for secure. Default is non-secure | `1` | `integer` | -| `bidfloor` | optional | Bid floor | `0.50` | `float` | -| `tag_id` | optional | Identifies specific ad placement. | `'cnvr-test-tag'` | `string` | -| `white_label_url`| optional | Override the destination URL the request is sent to. | `'https://mydomain.com/hbendpoint'` | `string` | -| `pubcid_name` | optional | Name of the pub common id. Conversant adapter can read the id directly if the UserID module is absent. Default is _pubcid.| `'_pubcid'` | `string` | - -### Video Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|---------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------|------------------| -| `position` | optional | Ad position on screen. See details below. Only supported in bids.params. | `1` | `integer` | -| `mimes` | optional | Array of content MIME types supported. Required for video | `['video/mp4']` | `Array` | -| `maxduration` | optional | Maximum duration in seconds for this video as an integer. | `30` | `integer` | -| `api` | optional | Array of supported API frameworks. See details below. | `[2]` | `Array` | -| `protocols` | optional | Array of supported video protocols. See details below. | `[2]` | `Array` | - - -Video parameters can be included in either `mediaTypes.video` or `bids.params` except where noted. - -The following values are defined in the [ORTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). - -### position - -+ `0` : Unknown -+ `1` : Above the Fold -+ `3` : Below the Fold -+ `4` : Header -+ `5` : Footer -+ `6` : Sidebar -+ `7` : Full Screen - -### api - -+ `1` : VPAID 1.0 -+ `2` : VPAID 2.0 -+ `3` : MRAID 1.0 -+ `4` : ORMMA -+ `5` : MRAID 2.0 -+ `6` : MRAID 3.0 - -### protocols -+ `1` : VAST 1.0 -+ `2` : VAST 2.0 -+ `3` : VAST 3.0 -+ `4` : VAST 1.0 Wrapper -+ `5` : VAST 2.0 Wrapper -+ `6` : VAST 3.0 Wrapper -+ `7` : VAST 4.0 -+ `8` : VAST 4.0 Wrapper -+ `9` : DAAST 1.0 -+ `10` : DAAST 1.0 Wrapper - -### First Party Data -Publishers should use the `ortb2` method of setting for setting First Party Data. -Example first party data configuration that is available to all adUnits -``` -pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - ortb2: { - site: { - content: { - series: 'MySeries', - season: 'My Season', - episode: 3, - title: 'My Title' - } - } - } -}); -``` - -Example AdUnit specific data using the `ortb2Imp` object -``` - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - playerSize: [[640, 480]] - } - }, - ortb2Imp: { - instl: 1, - ext: { - data: { - adUnitSpecificAttribute: "123" - } - } - }, - bids: [{ - bidder: 'conversant', - params: { - site_id: '108060', - mimes: ['video/mp4', 'video/webm'] - } - }] - } - - pbjs.que.push(function(){ - pbjs.addAdUnits(videoAdUnits); - } -``` - diff --git a/dev-docs/bidders/copper6.md b/dev-docs/bidders/copper6.md new file mode 100644 index 0000000000..c51e695ae7 --- /dev/null +++ b/dev-docs/bidders/copper6.md @@ -0,0 +1,108 @@ +--- +layout: bidder +title: SSP Copper6 +description: SSP Copper6 Bidder Adapter +biddercode: copper6 +aliasCode: adtelligent +media_types: video,banner +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: false +pbjs: true +pbs: true +deals_supported: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from Copper6 Media. | `12412` | `integer` | + +### Description + +Copper6 Media header bidding adapter connects with Copper6 Media demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'copper6', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'copper6', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'copper6', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'copper6', + params: { + aid: 529814 + } + }] + } + ]; +``` diff --git a/dev-docs/bidders/cosmos.md b/dev-docs/bidders/cosmos.md deleted file mode 100644 index deb8130dbe..0000000000 --- a/dev-docs/bidders/cosmos.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: COSMOS -description: Prebid COSMOS Bidder Adapter -pbjs: true -biddercode: cosmos -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Integration Note: - -Cosmos bidder adapter requires setup and approval from the Cosmos team. Please reach out to your account manager for more information and to start using it. - -### Bid params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -| ------------------- | -------- | ------------------------------------- | ------------ | --------- | -| `publisherId` | required | The publisher ID from Cosmos | `1001` | `integer` | -| `tagId` | optional | Identifier for specific ad placement | `1001` | `integer` | -| `bidFloor` | optional | The minimum bid value | `1.07` | `float` | diff --git a/dev-docs/bidders/cox.md b/dev-docs/bidders/cox.md index 625dd157f4..bdc03f787c 100644 --- a/dev-docs/bidders/cox.md +++ b/dev-docs/bidders/cox.md @@ -4,6 +4,7 @@ title: Cox description: Prebid Cox Bidder Adaptor pbjs: true biddercode: cox +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/cpmstar.md b/dev-docs/bidders/cpmstar.md index 3b97562e91..0573d20d60 100644 --- a/dev-docs/bidders/cpmstar.md +++ b/dev-docs/bidders/cpmstar.md @@ -6,9 +6,10 @@ pbjs: true pbs: true biddercode: cpmstar media_types: banner, video -gdpr_supported: true +tcfeu_supported: false usp_supported: true coppa_supported: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/craft.md b/dev-docs/bidders/craft.md index 857213225b..5df97f5875 100644 --- a/dev-docs/bidders/craft.md +++ b/dev-docs/bidders/craft.md @@ -4,11 +4,12 @@ title: craft description: Prebid craft Bidder Adapter biddercode: craft media_types: banner -gdpr_supported: false +tcfeu_supported: false coppa_supported: false usp_supported: false schain_supported: false pbjs: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/criteo.md b/dev-docs/bidders/criteo.md index c1797cdd39..58901ad55e 100644 --- a/dev-docs/bidders/criteo.md +++ b/dev-docs/bidders/criteo.md @@ -5,28 +5,29 @@ description: Prebid Criteo Bidder Adaptor pbjs: true pbs: true biddercode: criteo -media_types: display, native, video -gdpr_supported: true +media_types: display, video, native (pbjs only) +tcfeu_supported: true +dsa_supported: true usp_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, pubProvidedId, sharedId, unifiedId prebid_member: true -floors_supported: false +floors_supported: true fpd_supported: true schain_supported: true gvl_id: 91 +coppa_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +gpp_supported: true --- -### Notes -{: .alert.alert-warning :} -*Criteo currently only supports getFloor if floors are in USD and if the publisher is enabling the Criteo Publisher Tag external js call. +### Notes {: .alert.alert-warning :} -Prebid-Server support is on alpha test and is currently a non-finished product. Activation requires setup and approval before beginning. Please reach out to your account manager or publishers@criteo.com for more details. +This bidder adapter automatically includes the Criteo User ID module and performs iFrame syncs. -### Disclosure - -This bidder sets `adId` on the bid response and hasn't responded to the Prebid.js team to confirm uniqueness -of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381). +{: .alert.alert-warning :} +Prebid-Server support is on alpha test and is currently a non-finished product. Activation requires setup and approval before beginning. Please reach out to your account manager or for more details. ### Bid Params @@ -35,8 +36,25 @@ of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381) |-------------------|----------|----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|------------| | `zoneId` | required | (deprecated) The zone ID from Criteo. Should be replaced by `networkId` when using zone matching. | `234234` | `integer` | | `networkId` | required | The network ID from Criteo. Please reach out your Criteo representative for more details. | `456456` | `integer` | +| `pubid` | required | publisher id | `'ABC123'` | `string` | | `nativeCallback` | optional | (Prebid.js only) Callback to perform render in native integrations. Please reach out your Criteo representative for more details. | `function(payload) { console.log(payload); }` | `function` | | `integrationMode` | optional | (Prebid.js only) Integration mode to use for ad render (none or 'AMP'). Please reach out your Criteo representative for more details. | `'AMP'` | `string` | +| `publisherSubId` | optional | Custom identifier for reporting. Please reach out your Criteo representative for more details. | `'adunit-1'` | `string` | + +### First Party Data + +Criteo supports both `ortb2` and `ortb2Imp` methods to set [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +The standard Open RTB properties supported from `ortb2` / `ortb2Imp` are described in the following table. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| `ortb2.user` | optional | Details via a Open RTB User object about the human user of the device; the advertising audience. | N/A | `object` | +| `ortb2.site` | optional | Details via a Open RTB Site object about the publisher’s website. | N/A | `object` | +| `ortb2Imp.rwdd` | optional | Indicates whether the user receives a reward for viewing the ad, where 0 = no, 1 = yes. | `1` | `integer` | + +Besides these standard properties, `ext` field can be used to send any publisher specific data which may have been discussed with a Criteo representative. ### Video Object @@ -57,12 +75,14 @@ In addition, Criteo adapter relies on parameters specified in the mediaTypes.vid | `context` | required | `outstream`, `instream` or `long-form` | `instream` | `string` | | `mimes` | required | List of the content MIME types supported by the player | `["video/mp4"]` | `Array` | | `playerSize` | required | Width and height of the player | `[640, 480]` | `Array` | -| `protocols` | required | Supported video bid response protocols. VAST 1.0: `1`; VAST 2.0: `2`; VAST 3.0: `3`; VAST 1.0 Wrapper: `4`; VAST 2.0 Wrapper: `5`; VAST 3.0 Wrapper: `6`; | `|5, 6]` | `Array` | -| `maxduration` | required | Maximum ad duration in seconds | `20` | `integer` | -| `api` | required | API frameworks supported. VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID-1: `3`; ORMMA: `4`; MRAID-2: `5`; | `[1, 2]` | `Array` | +| `protocols` | required | Supported video bid response protocols. VAST 1.0: `1`; VAST 2.0: `2`; VAST 3.0: `3`; VAST 1.0 Wrapper: `4`; VAST 2.0 Wrapper: `5`; VAST 3.0 Wrapper: `6`; | `[5, 6]` | `Array` | +| `maxduration` | required | Maximum ad duration in seconds | `20` | `integer` | +| `api` | required | API frameworks supported. VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; ORMMA: `4`; MRAID 2.0: `5`; MRAID 3.0: `6`; OMID 1.0: `7`; | `[1, 2]` | `Array` | +| `plcmt` | optional | 1=in-stream, 2=accompanying content, 3=interstitial, 4=no content/standalone. Highly recommended to comply with new IAB video specifications. | `1` | `integer` | #### Example of Video Ad-unit -``` + +```javascript var adUnits = [ { code: 'video1', @@ -75,8 +95,8 @@ var adUnits = [ api: [1, 2], playerSize: [640,480], protocols: [2, 3], - skip: 0, - playbackmethod: [1], + skip: 0, + playbackmethod: [1], placement: 1 } }, @@ -88,3 +108,21 @@ var adUnits = [ }] }]; ``` + +### Additional Config (Optional) + +If you don't want to use the FastBid adapter feature, you can disable it via this configuration: + +```javascript +pbjs.setConfig({ + 'criteo': { + fastBidVersion: 'none', + } +}); +``` + +Criteo teams are planning to completely remove this feature with Prebid 9.0 + +Criteo Bid Adapter supports the collection of the user's hashed email, if available. + +Please consider passing it to the adapter, following [these guidelines](https://publisherdocs.criteotilt.com/prebid/#hashed-emails). diff --git a/dev-docs/bidders/cwire.md b/dev-docs/bidders/cwire.md index 9137f50690..5447a41314 100644 --- a/dev-docs/bidders/cwire.md +++ b/dev-docs/bidders/cwire.md @@ -3,19 +3,35 @@ layout: bidder title: C-WIRE description: C-WIRE Prebid Bidder Adapter pbjs: true +pbs: true biddercode: cwire -gdpr_supported: false +tcfeu_supported: true +gvl_id: 1081 usp_supported: false schain_supported: false -userIds: flocId, uid2Id -media_types: banner, video +userIds: none +enable_download: true +media_types: banner +sidebarType: 1 +--- --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-----------------------|-----------|-----------| -| `pageId` | required | C-WIRE page id | `2453` | `integer` | -| `placementId` | required | C-WIRE placement id | `113244` | `integer` | -| `adUnitElementId` | optional | Target div to write to | `'other_div_id'` | `string` | +| Name | Scope | Description | Example | Type | +|---------------|:--------:|:-------------------:|:--------:|:---------:| +| `pageId` | required | C-WIRE page id | `2453` | `integer` | +| `placementId` | required | C-WIRE placement id | `113244` | `integer` | + +### URL parameters + +Additionally, the following parameters can be passed by URL parameters for testing. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|:--------:|:--------------------------------:|:-------------------------------:|:--------:| +| `cwcreative` | optional | C-WIRE creative id to force | `&cwcreative=1234` | `string` | +| `cwgroups` | optional | C-WIRE group name to force | `&cwgroups=test-group` | `string` | +| `cwfeatures` | optional | Comma separated list of features | `&cwfeatures=feature1,feature2` | `string` | +| `cwdebug` | optional | Debug flag | `&cwdebug=true` | `string` | diff --git a/dev-docs/bidders/dailyhunt.md b/dev-docs/bidders/dailyhunt.md deleted file mode 100644 index 8054d482d2..0000000000 --- a/dev-docs/bidders/dailyhunt.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -layout: bidder -title: Dailyhunt -description: Prebid Dailyhunt Bidder Adaptor -pbjs: true -biddercode: dailyhunt -media_types: display, native, video -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------|----------|-------------|---------|------| -| `placement_id` | required | Serving ads based on placement_id. Contact Dailyhunt for placement_id. | `1` | `int` | -| `publisher_id` | required | Serving ads based on publisher_id. Contact Dailyhunt for publisher_id. | `1` | `int` | -| `partner_name` | required | Serving ads based on partner_name. Contact Dailyhunt for partner_name. | `dailyhunt` | `string` | -| `test_mode` | optional | Serving test mode campaign only. | `true` | `bool` | -| `bidfloor` | optional | Minimum bid for this bid expressed in CPM. | `1.4` | `float` | -| `video` | optional | A Video object required if this bid is offered as a video ad opportunity. It is ortb video object. | `video: { w: 640, h: 480, mimes: ["video/mp4"] }` | `object` | -|`site` | optional | Details about the publisher’s website. It is ortb site object. | `site:{id:"102855",cat:["IAB3-1"],domain:"http://m.dailyhunt.in",page:"http://m.dailyhunt.in/1234.html "}` | `object` | -| `device` | optional | Details about the user’s device to which the impression will be delivered. It is ortb device object. | `device: { ip: "64.124.253.1", os: "OS X", ua: "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.16) }` | `object` | -| `user` | optional | Details about the human user of the device; the advertising audience. It is ortb user object. | `user: { id: "456789876567897654678987656789", gender: "M", gender: 1990, keywords: "marketing,traveling,reading" }` | `object` | -| `publisher` | optional | Details about the Publisher of the site. It is ortb publisher object. | `publisher: { id: "8953", name: "dailyhunt", "cat": [ "IAB3-1" ], "domain": "m.dailyhunt.in" }` | `object` | - -**Notes: The `video`, `site`, `device`, `user`, `publisher` objects are all ORTB objects. Please refer to the [ORTB documentation](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for additional details.** - -# Test Parameters -``` - var adUnits = [ - { - code: '/83414793/prebid_test_display', - sizes: [[300, 250], [320, 50]], - mediaTypes: { - banner : { - sizes: [[300, 250], [320, 50]], - } - }, - bids: [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt', - device: { - ip: "182.23.143.212" - } - } - } - ] - }, - { - code: '/83414793/prebid_test_native', - sizes: [[300, 250]], - mediaTypes: { - native: { - title: { - required: true - }, - body: { - required: true - }, - image: { - required: true - }, - cta: { - required: true - } - } - }, - bids: [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt', - device: { - ip: "182.23.143.212" - } - } - } - ] - }, - { - code: '/83414793/prebid_test_video', - mediaTypes: { - video: { - playerSize: [1280, 720], - context: 'instream' - } - }, - bids: [ - { - bidder: 'dailyhunt', - params: { - placement_id: 1, - publisher_id: 1, - partner_name: 'dailyhunt', - device: { - ip: "182.23.143.212" - }, - video: { - mimes: [ - 'video/mp4' - ] - } - } - } - ] - } - ]; -``` diff --git a/dev-docs/bidders/dailymotion.md b/dev-docs/bidders/dailymotion.md new file mode 100644 index 0000000000..5557b2befb --- /dev/null +++ b/dev-docs/bidders/dailymotion.md @@ -0,0 +1,176 @@ +--- +layout: bidder +title: Dailymotion +description: Dailymotion Prebid Bidder Adapter +pbjs: true +pbs: false +biddercode: dailymotion +media_types: video +gvl_id: 573 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +deals_supported: true +floors_supported: true +sidebarType: 1 +safeframes_ok: true +ortb_blocking_supported: false +--- + +### Registration + +To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through . + +This API key will ensure proper identification of your inventory and allow you to get real bids. + +# Configuration options + +Before calling this adapter, you need to at least set a video adUnit in an instream context and the API key in the bid parameters: + +```javascript +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'fake_api_key' + }, + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + }, + }, + } +]; +``` + +`apiKey` is your publisher API key. For testing purpose, you can use "dailymotion-testing". + +# Test Parameters + +By setting the following bid parameters, you'll get a constant response to any request, to validate your adapter integration: + +```javascript +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing', + }, + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + }, + }, + } +]; +``` + +Please note that failing to set these will result in the adapter not bidding at all. + +# Sample video AdUnit + +To allow better targeting, you should provide as much context about the video as possible. +There are three ways of doing this depending on if you're using Dailymotion player or a third party one. + +If you are using the Dailymotion player, you should only provide the video `xid` in your ad unit, example: + +```javascript +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing', + video: { + xid: 'x123456' // Dailymotion infrastructure unique video ID + }, + } + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + api: [2, 7], + context: 'instream', + startdelay: 0, + w: 1280, + h: 720, + }, + } + } +]; +``` + +This will automatically fetch the most up-to-date information about the video. +If you provide any other metadata in addition to the `xid`, they will be ignored. + +If you are using a third party video player, you should not provide any `xid` and instead fill the following members: + +```javascript +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing', + video: { + description: 'this is a video description', + duration: 556, + iabcat1: ['IAB-2'], + iabcat2: ['6', '17'], + id: '54321', + lang: 'FR', + livestream: 0, + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', + } + } + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + api: [2, 7], + context: 'instream', + startdelay: 0, + w: 1280, + h: 720, + }, + } + } +]; +``` + +Each of the following video metadata fields can be added in bids.params.video. + +* `description` - Video description +* `duration` - Video duration in seconds +* `iabcat1` - List of IAB category IDs from the [1.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%201.0.tsv) +* `iabcat2` - List of IAB category IDs from the [2.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.0.tsv) and above +* `id` - Video unique ID in host video infrastructure +* `lang` - ISO 639-1 code for main language used in the video +* `livestream` - 0 = not live, 1 = content is live +* `private` - True if video is not publicly available +* `tags` - Tags for the video, comma separated +* `title` - Video title +* `topics` - Main topics for the video, comma separated +* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player) + +If you already specify [First-Party data](https://docs.prebid.org/features/firstPartyData.html) through the `ortb2` object when calling [`pbjs.requestBids(requestObj)`](https://docs.prebid.org/dev-docs/publisher-api-reference/requestBids.html), we will fallback to those values when possible. See the mapping below. + +| From ortb2 | Metadata fields | +|---------------------------------------------------------------------------------|-----------------| +| `ortb2.site.content.cat` OR `ortb2.site.content.data` where `ext.segtax` is `4` | `iabcat1` | +| `ortb2.site.content.data` where `ext.segtax` is `5`, `6` or `7` | `iabcat2` | +| `ortb2.site.content.id` | `id` | +| `ortb2.site.content.language` | `lang` | +| `ortb2.site.content.livestream` | `livestream` | +| `ortb2.site.content.keywords` | `tags` | +| `ortb2.site.content.title` | `title` | diff --git a/dev-docs/bidders/danmarket.md b/dev-docs/bidders/danmarket.md index a410fc2f77..ecdad8b81f 100644 --- a/dev-docs/bidders/danmarket.md +++ b/dev-docs/bidders/danmarket.md @@ -4,7 +4,8 @@ title: DAN Marketplace description: Dentsu Aegis Network Marketplace Bidder Adapter pbjs: true biddercode: danmarket -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/datablocks.md b/dev-docs/bidders/datablocks.md index 58aea81085..7254c9c936 100644 --- a/dev-docs/bidders/datablocks.md +++ b/dev-docs/bidders/datablocks.md @@ -7,12 +7,12 @@ description: Prebid Datablocks Bidder Adaptor media_types: banner,native biddercode: datablocks prebid_member: true -gdpr_supported: true +tcfeu_supported: false pbs_app_supported: true schain_supported: true usp_supported: true userIds: criteo,unifiedId,netId,pubcid -fpd_supported: true +sidebarType: 1 --- ### Bid Params @@ -20,7 +20,7 @@ fpd_supported: true {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------|----------|------------------------|---------|----------| -| sourceId | required | Website Source Id | 111 | integer | -| host | optional | Network Host to request from | 'prebid.datablocks.bet' | string | +| source_id | required | Website Source Id | 111 | integer | +| host | optional | Network Host to request from | 'prebid.dblks.net' | string | | tagid | optional | Placement ID | 'leaderboard_1' | string | | vis_optout | optional | Opt out of visibility metric | true | boolean | diff --git a/dev-docs/bidders/datawrkz.md b/dev-docs/bidders/datawrkz.md new file mode 100644 index 0000000000..7c450f99d0 --- /dev/null +++ b/dev-docs/bidders/datawrkz.md @@ -0,0 +1,46 @@ +--- +layout: bidder +title: Datawrkz +description: Prebid Datawrkz Bidder Adaptor +biddercode: datawrkz +media_types: banner, video, native +tcfeu_supported: false +prebid_member: false +coppa_supported: true +usp_supported: true +floors_supported: true +pbjs: true +deals_supported: true +sidebarType: 1 +--- + +### Note + +The Datawrkz Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `site_id` | required | String | Site id | "test_site_id" +| `deals` | optional | Array | Array of deal objects | `[{id: "deal_1"},{id: "deal_2"}]` +| `bidfloor` | optional | Float | Minimum bid for this impression expressed in CPM | `0.5` +| `outstreamType` | optional | String | Type of outstream video to the played. Available options: inline, slider_top_left, slider_top_right, slider_bottom_left, slider_bottom_right, interstitial_close, and listicle | "inline" +| `outstreamConfig` | optional | Object | Configuration settings for outstream ad unit | `{ad_unit_audio: 1, show_player_close_button_after: 5, hide_player_control: 0}` + +### Deal Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `id` | required | String | Deal id | "test_deal_id" + +### Outstream Config Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `ad_unit_audio` | optional | Integer | Set default audio option for the player. 0 to play audio on hover and 2 to mute | `0` or `2` +| `show_player_close_button_after` | optional | Integer | Show player close button after specified seconds | `5` +| `hide_player_control` | optional | Integer | Show/hide player controls. 0 to show player controls and 1 to hide | `1` diff --git a/dev-docs/bidders/decenterads.md b/dev-docs/bidders/decenterads.md deleted file mode 100644 index 206d453ca3..0000000000 --- a/dev-docs/bidders/decenterads.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: bidder -title: DecenterAds -description: Prebid DecenterAds Bidder Adaptor -pbs: true -pbjs: true -biddercode: decenterads -media_types: banner, video, native -gdpr_supported: true -pbs_app_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: - -The Example Bidding adapter requires setup before beginning. Please contact us at support@decenterads.com - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------|-----------|----------| -| `placementId` | required | Placement ID | `'12345'` | `string` | diff --git a/dev-docs/bidders/deepintent.md b/dev-docs/bidders/deepintent.md index 762de6591f..edb31fd240 100644 --- a/dev-docs/bidders/deepintent.md +++ b/dev-docs/bidders/deepintent.md @@ -6,9 +6,12 @@ pbjs: true pbs: true biddercode: deepintent media_types: banner, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true +coppa_supported: true +gpp_sids: usp, usnat, usstate_all gvl_id: 541 +sidebarType: 1 --- ### Bid Params @@ -22,13 +25,10 @@ gvl_id: 541 | `user` | optional | user params according to IAB standards | `'{"gender":"F"}''`| `object` | | `pos` | optional | ad position as per IAB standards | `1` | `number` | - - ### Configuration Deepintent recommends the UserSync configuration below. Without it, the Deepintent adapter will not able to perform user syncs, which lowers match rate and reduces monetization. - ```javascript pbjs.setConfig({ userSync: { @@ -41,7 +41,9 @@ pbjs.setConfig({ } }); ``` + ### AdUnit Format for Banner + ```javascript var adUnits = [ { @@ -75,27 +77,30 @@ var adUnits = [ } ]; ``` + ### video parameters + Deepintent supports video as of Prebid v1.16.0 {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | +| Name | Scope | Description | Example | | :----------------------| :------- | :---------------------------------------------------------- | :------ | -| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | -| `video.skippable` | optional | If 'true', user can skip ad | `true` | -| `video.minduration` | optional | Minimum ad duration in seconds | `5` | -| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | -| `video.startdelay` | optional | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | -| `video.playbackmethod` | optional | Defines whether inventory is user-initiated or autoplay sound on/off
      Values:
      `1`: Auto-play, sound on
      `2`: Auto-play, sound off
      `3`: Click-to-play
      `4`: mouse-over | `1` | -| `video.api` | optional | API frameworks supported
      Values:
      `1`: VPAID 1.0
      `2`: VPAID 2.0
      `3`: MRAID-1
      `4`: ORMMA
      `5`: MRAID-2 | `[1, 2]` | -| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | -| `video.battr` | optional | Blocked creative attributes, See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.3 for values | `[3, 9]` | -| `video.linearity` | optional | Indicates if the impression is linear or nonlinear
      Values:
      `1`: Linear/In-Stream
      `2`: Non-Linear/Overlay. | `1` | -| `video.placement` | optional | Video placement type. See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.9 for Values | `1` | -| `video.minbitrate` | optional | Minumim bit rate in Kbps. | 50 | -| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | 70 | +| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | +| `video.skippable` | optional | If 'true', user can skip ad | `true` | +| `video.minduration` | optional | Minimum ad duration in seconds | `5` | +| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | +| `video.startdelay` | optional | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | +| `video.playbackmethod` | optional | Defines whether inventory is user-initiated or autoplay sound on/off
      Values:
      `1`: Auto-play, sound on
      `2`: Auto-play, sound off
      `3`: Click-to-play
      `4`: mouse-over | `1` | +| `video.api` | optional | API frameworks supported
      Values:
      `1`: VPAID 1.0
      `2`: VPAID 2.0
      `3`: MRAID-1
      `4`: ORMMA
      `5`: MRAID-2 | `[1, 2]` | +| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | +| `video.battr` | optional | Blocked creative attributes, See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.3 for values | `[3, 9]` | +| `video.linearity` | optional | Indicates if the impression is linear or nonlinear
      Values:
      `1`: Linear/In-Stream
      `2`: Non-Linear/Overlay. | `1` | +| `video.placement` | optional | Video placement type. See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.9 for Values | `1` | +| `video.minbitrate` | optional | Minumim bit rate in Kbps. | 50 | +| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | 70 | ### AdUnit Format for Video + ```javascript var videoAdUnits = [ { @@ -109,6 +114,7 @@ var videoAdUnits = [ bids: [{ bidder: 'deepintent', params: { + tagId: "1399", // required publisherId: '32572', // required adSlot: '38519891@300x250' // required video: { diff --git a/dev-docs/bidders/definemedia.md b/dev-docs/bidders/definemedia.md new file mode 100644 index 0000000000..ca38797ff8 --- /dev/null +++ b/dev-docs/bidders/definemedia.md @@ -0,0 +1,25 @@ +--- +layout: bidder +title: DEFINE MEDIA +description: Prebid DEFINE MEDIA Bidder Adapter +biddercode: definemedia +tcfeu_supported: true +gvl_id: 440 +media_types: banner, native +pbjs: false +pbs: true +pbs_app_supported: false +prebid_member: false +--- + +### Registration + +Please reach out to our account management team to get started. Contact information is available under [a link](https://definemedia.de). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `mandantId` | required | Mandant ID | `5` | `integer`| +| `adslotId` | optional | Adslot ID | `199` | `integer`| diff --git a/dev-docs/bidders/defymedia.md b/dev-docs/bidders/defymedia.md index beb21724e2..c20713b198 100644 --- a/dev-docs/bidders/defymedia.md +++ b/dev-docs/bidders/defymedia.md @@ -5,6 +5,7 @@ description: Prebid Defy Media Bidder Adaptor pbjs: true biddercode: defymedia aliasCode : appnexus +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/deltaprojects.md b/dev-docs/bidders/deltaprojects.md index cafcc93ef8..397b461908 100644 --- a/dev-docs/bidders/deltaprojects.md +++ b/dev-docs/bidders/deltaprojects.md @@ -3,16 +3,18 @@ layout: bidder title: Delta Projects description: Prebid Delta Projects Bidder Adapter biddercode: deltaprojects -gdpr_supported: true +tcfeu_supported: true gvl_id: 209 media_types: banner safeframes_ok: false floors_supported: true pbjs: true +sidebarType: 1 --- ### Note -Contact publishers@deltaprojects.com to get a publisher id and to agree on a currency. Delta Projects + +Contact to get a publisher id and to agree on a currency. Delta Projects will always bid and log values in the agreed upon currency, utilizing the currency module if necessary and available. ### Bid Params @@ -20,14 +22,16 @@ will always bid and log values in the agreed upon currency, utilizing the curren {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|----------|--------------------------------------------------------------------------|-----------------|----------| -| `publisherId` | required | Publisher ID from Delta Projects. Contact publishers@deltaprojects.com | `'4'` | `string` | +| `publisherId` | required | Publisher ID from Delta Projects. Contact | `'4'` | `string` | | `currency` | optional | The bid currency agreed with Delta Projects. | `'SEK'` | `string` | | `siteId` | optional | Site ID from Delta Projects. | `'example.com'` | `string` | | `tagId` | optional | Identifier for specific ad placement or ad tag. | `'1234'` | `string` | | `test` | optional | Indicate test model. Don't set anything if it is not in test mode. | `'true'` | `string` | ### Example + #### Banner + ``` var adUnits = [ { diff --git a/dev-docs/bidders/denakop.md b/dev-docs/bidders/denakop.md index 0b390e05e4..80a075e07f 100644 --- a/dev-docs/bidders/denakop.md +++ b/dev-docs/bidders/denakop.md @@ -2,19 +2,28 @@ layout: bidder title: Denakop description: Denakop Bidder Adaptor -pbjs: true -pbs: true biddercode: denakop +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The Denakop bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/dgads.md b/dev-docs/bidders/dgads.md deleted file mode 100644 index 4575da5bc6..0000000000 --- a/dev-docs/bidders/dgads.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: dgads -description: Prebid dgads Bidder Adapter -pbjs: true -biddercode: dgads -media_types: native -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------|---------|----------| -| `site_id` | required | Publisher ID | `'12'` | `string` | -| `location_id` | required | Placement ID | `'23'` | `string` | diff --git a/dev-docs/bidders/dianomi.md b/dev-docs/bidders/dianomi.md new file mode 100644 index 0000000000..6b9a9f8867 --- /dev/null +++ b/dev-docs/bidders/dianomi.md @@ -0,0 +1,116 @@ +--- +layout: bidder +title: Dianomi +description: Prebid Dianomi Bidder Adaptor +biddercode: dianomi +media_types: banner, native, video +coppa_supported: false +tcfeu_supported: true +usp_supported: true +prebid_member: true +pbjs: true +pbs: true +schain_supported: true +userIds: all +gvl_id: 885 +floors_supported: true +fpd_supported: true +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Note + +- Supports `display` and `banner` formats. +- Uses `OpenRTB` standard. + +### Registration + +The Dianomi Adapter requires setup before beginning. Please contact us at . + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------------------------|----------------------|--------------------|-----------| +| `smartadId` | required | Placement ID | `12345` | `integer` | +| `endpoint` | optional | for testing only | `www-prebid.dianomi.com` | `string` | + +Note: smartadId is a pre agreed ID between the publisher and Dianomi. + +#### Native example + +```js +var adUnits = [ + code: 'your-native-container-id', + mediaTypes: { + native: { + image: { + required: false, + sizes: [100, 50] + }, + title: { + required: false, + len: 140 + }, + sponsoredBy: { + required: false + }, + clickUrl: { + required: false + }, + body: { + required: false + }, + icon: { + required: false, + sizes: [50, 50] + } + } + }, + bids: [{ + bidder: 'dianomi', + params: { + smartadId: 9607 + } + }] +]; +``` + +#### Banner example + +```js +var adUnits = [ + code: 'your-banner-container-id', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'dianomi', + params: { + smartadId: 9607 + } + }] +]; +``` + +#### Video example + +```js +var adUnits = [ + code: 'your-video-container-id', + mediaTypes: { + video: { + playerSize: [[640, 480]] + } + }, + bids: [{ + bidder: 'dianomi', + params: { + smartadId: 9607 + } + }] +]; +``` diff --git a/dev-docs/bidders/didnadisplay.md b/dev-docs/bidders/didnadisplay.md new file mode 100644 index 0000000000..fe42c420cd --- /dev/null +++ b/dev-docs/bidders/didnadisplay.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: diDNA Display +description: diDNA Display Bidder Adaptor +biddercode: didnadisplay +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The diDNA Display bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.didna.io'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/didnavideo.md b/dev-docs/bidders/didnavideo.md index c73e778d06..51e51dbb86 100644 --- a/dev-docs/bidders/didnavideo.md +++ b/dev-docs/bidders/didnavideo.md @@ -6,13 +6,16 @@ pbjs: true biddercode: didnavideo aliasCode: aniview media_types: banner, video -gdpr_supported: true +gvl_id: 780 (aniview) +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true +sidebarType: 1 --- -### Note: +### Note + For more information about [diDNA](http://didna.io/). ### Bid Params @@ -24,7 +27,8 @@ For more information about [diDNA](http://didna.io/). | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` + +```javascript videoAdUnit = [ { code: 'video1', diff --git a/dev-docs/bidders/digiad.md b/dev-docs/bidders/digiad.md new file mode 100644 index 0000000000..83e0f0f629 --- /dev/null +++ b/dev-docs/bidders/digiad.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Digiad DMCC +description: Digiad DMCC Adaptor +biddercode: digiad +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Digiad DMCC bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.digidayin.com'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/discovery.md b/dev-docs/bidders/discovery.md new file mode 100644 index 0000000000..e094aea49c --- /dev/null +++ b/dev-docs/bidders/discovery.md @@ -0,0 +1,82 @@ +--- +layout: bidder +title: DiscoveryDsp +description: DiscoveryDsp Prebid Bidder Adapter +biddercode: discovery +media_types: banner,native +pbjs: true +enable_download: true +sidebarType: 1 +--- +### Note + +The DiscoveryDSP Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `token` | required | publisher token | `'1e100887dd614b7f69fdd1360437'` | `string` | +| `test` | recommend | 0(default): production env mode.
      1: dev env mode and no charge.we will bid Higher frequency to make debug easier. | `1/0` | `Number` | +| `tagid` | required | tagid | `'abcdefg'` | `string` | +| `publisher` | required | publisher id | `'abcdefg'` | `string` | + +#### Prebid Server Test Request + +banner + +``` +var adUnits = [ + { + code: "test-div-1", + mediaTypes: { + banner: { + sizes: [[300, 250]], + }, + }, + bids: [ + { + bidder: "discovery", + params: { + token: "a4e66b955e3b19b88a357b4ace01ac31", + tagid: 'test_tagid', + publisher: 'test_publisher' + }, + }, + ], + }, + ]; +``` + +native + +``` +var adUnits = [ + { + code: "test-div-2", + mediaTypes: { + native: { + title: { + required: true + }, + image: { + required: true + } + } + }, + bids: [ + { + bidder: "discovery", + params: { + token: "03d467db07075683b0c373b6b3d3113c", + tagid: 'test_tagid', + publisher: 'test_publisher' + }, + }, + ], + }, + ]; +``` + +`If the bid interface status code is 200, the bid is successful, if the status code is 204, there is no bid, please send the request parameters to media-support@popin.cc, we will be the first time to feedback` diff --git a/dev-docs/bidders/displayio.md b/dev-docs/bidders/displayio.md new file mode 100644 index 0000000000..9eb9d291c8 --- /dev/null +++ b/dev-docs/bidders/displayio.md @@ -0,0 +1,39 @@ +--- +layout: bidder +title: Displayio +description: Prebid Displayio Bidder Adapter +biddercode: displayio +media_types: banner, video +tcfeu_supported: true +usp_supported: true +safeframes_ok: true +pbjs: true +pbs: false +prebid_member: false +gvl_id: none +sidebarType: 1 +--- + +### Note + +Before configuring the display.io adapter you must reach out your account manager from display.io team (or send a request to ) for approval and setup steps. + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Type | Description | Example | +|----------------| ----- | ---- |----------------------------------------|--------------------------------------------------------------| +| `siteId` | required | Number | SiteId and PlacementID are your inventory IDs on the display.io platform (please ask your Account Manager for your site and placement IDs). | 7753 | +| `placementId` | required | Number | SiteId and PlacementID are your inventory IDs on the display.io platform (please ask your Account Manager for your site and placement IDs). | 5375 | +| `adsSrvDomain` | required | String | | "appsrv.display.io" | +| `cdnDomain` | required | String | | "cdn.display.io" | +| `renderURL` | optional | String | | "" | +| `pageCategory` | optional | String | Comma-separated list of IAB content categories that describe the current page or view of the site, list of available values. | "pageCategory1, pageCategory2" | +| `keywords` | optional | String | Comma-separated list of keywords describing the content. | "keyword1, keyword2, keyword3" | +| `custom` | optional | Object | User-defined targeting key-value pairs. custom applies to a specific unit. | `{headerTextColor: "red", fixedHeaderSelector: '.site-header'}` | +| `custom.headerText`| optional | String | Ad container header text. By default, text is "Scroll to continue with content". Limited to 50 characters. | "Our awesome advertisement" | +| `custom.headerTextColor`| optional | String | Ad container header text color, "white" by default | "#2196f3" | +| `custom.headerBackgroundColor`| optional | String | Ad container header background color, "black" by default | "#fff" | +| `custom.adContainerBackgroundColor`| optional | String | Ad container body background color, "transparent" by default | "#000" | +| `custom.fixedHeaderSelector`| optional | String | In case your webpage has a fixed header – the header Id attribute or header class attribute should be defined as a value for parameter fixedHeaderSelector. | ".site-header" | diff --git a/dev-docs/bidders/displayioads.md b/dev-docs/bidders/displayioads.md new file mode 100644 index 0000000000..ec81d2d8c5 --- /dev/null +++ b/dev-docs/bidders/displayioads.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: DisplayioAds +description: DisplayioAds Bidder Adaptor +biddercode: displayioads +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The DisplayioAds bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.displayio.cloud'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/districtm.md b/dev-docs/bidders/districtm.md index aa75acb5f7..8174d7ac17 100644 --- a/dev-docs/bidders/districtm.md +++ b/dev-docs/bidders/districtm.md @@ -6,10 +6,11 @@ top_nav_section: dev_docs nav_section: reference pbjs: true biddercode: districtm -aliasCode : appnexus -sidebarType: 1 isBidder: true gvl_id: 144 +pbjs_version_notes: not supported in 7.0+ +sidebarType: 1 +enable_download: false --- ### Bid Params diff --git a/dev-docs/bidders/districtmdmx.md b/dev-docs/bidders/districtmdmx.md index fef2443cc5..b0996aeba9 100644 --- a/dev-docs/bidders/districtmdmx.md +++ b/dev-docs/bidders/districtmdmx.md @@ -4,19 +4,20 @@ title: DistrictmDMX description: Prebid DistrictmDMX Bidder Adaptor pbjs: true biddercode: districtmDMX -gdpr_supported: true +tcfeu_supported: false schain_supported: true floors_supported: true usp_supported: true coppa_supported: true userIds: britepoolId, criteo, id5Id, identityLink, intentiq, liveIntentId, netId, parrableId, pubCommonId, unifiedId +pbjs_version_notes: not supported in 7.0+ +sidebarType: 1 --- - ### Bid Params -##### Prebid version 1.0 and above. +#### Prebid version 1.0 and above {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | @@ -24,7 +25,7 @@ userIds: britepoolId, criteo, id5Id, identityLink, intentiq, liveIntentId, netId | `dmxid` | required | Placement Id | `100001` | `integer` | | `memberid` | required | Account id | `100003` | `integer` | -##### Prebid 0.34~ legacy +#### Prebid 0.34~ legacy {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | diff --git a/dev-docs/bidders/distroscale.md b/dev-docs/bidders/distroscale.md new file mode 100644 index 0000000000..380916a4d6 --- /dev/null +++ b/dev-docs/bidders/distroscale.md @@ -0,0 +1,50 @@ +--- +layout: bidder +title: DistroScale +description: Prebid DistroScale Bidder Adaptor +biddercode: distroscale +media_types: banner +pbjs: true +pbs: false +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +fpd_supported: true +userIds: all +floors_supported: true +safeframes_ok: false +prebid_member: true +gvl_id: 754 +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------------|-----------------|----------| +| `pubid` | required | Publisher ID | `'12345'` | `string` | +| `zoneid` | optional | Zone ID | `'67890'` | `string` | + +### Prebid Test Request + +```javascript +var adUnits = [{ + code: 'banner-1', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [{ + bidder: 'distroscale', + params: { + pubid: '12345' // required, must be a string + ,zoneid: '67890' // optional, must be a string + } + }] +}]; +``` + +These test parameters can be used to verify that the DistroScale adapter is working properly. This example includes a DistroScale test publisher ID, an optional zone ID and sizes that would match with the test creative. diff --git a/dev-docs/bidders/divreach.md b/dev-docs/bidders/divreach.md index 463708821b..1dfb682416 100644 --- a/dev-docs/bidders/divreach.md +++ b/dev-docs/bidders/divreach.md @@ -6,6 +6,7 @@ pbjs: true biddercode: divreach aliasCode: adbutler media_types: banner +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/djax.md b/dev-docs/bidders/djax.md deleted file mode 100644 index 477d34f1ec..0000000000 --- a/dev-docs/bidders/djax.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: DJAX -description: Prebid djax Bidder Adapter -pbjs: true -biddercode: djax -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|----------------------------------------------------------------------------------------|-----------------------------|-----------| -| `publisherId` | required | Publisher id associated with DJAX | `1` | `integer` | diff --git a/dev-docs/bidders/dmx.md b/dev-docs/bidders/dmx.md index 7c34908359..c72bc52953 100644 --- a/dev-docs/bidders/dmx.md +++ b/dev-docs/bidders/dmx.md @@ -5,7 +5,9 @@ pbs: true media_types: banner, video biddercode: dmx gvl_id: 144 -gdpr_supported: true +tcfeu_supported: true +pbjs_version_notes: not supported in 7.0+ +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/doceree.md b/dev-docs/bidders/doceree.md index f40812868c..555fde4d4b 100644 --- a/dev-docs/bidders/doceree.md +++ b/dev-docs/bidders/doceree.md @@ -1,20 +1,22 @@ --- layout: bidder title: Doceree -description: Prebid DivReach Bidder Adapter +description: Prebid Doceree Bidder Adapter pbjs: true biddercode: doceree media_types: banner +gvl_id: 1063 tcf2_supported: true -gdpr_supported: true +tcfeu_supported: true +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |-------------------|----------|----------------|---------------------------|----------| -| `placementId` | required | Placement Id | `'DOC_7jm9j5eqkl0xvc5w'` | `string` | -| `publisherUrl` | optional | Current url | `https://doceree.com` | `string` | -| `gdpr` | optional | Flag to check if gdpr applies | `1` | `string` | -| `gdprConsent` | optional | URL-safe base64-encoded Transparency & Consent string | `CPQfU1jPQfU1jG0AAAENAwCAAAAAAAAAAAAAAAAAAAAA.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g` | `string` | +| `placementId` | required | Placement Id | `'DOC_7jm9j5eqkl0xvc5w'` | `string` | +| `publisherUrl` | optional | Current url | `https://doceree.com` | `string` | +| `gdpr` | optional | Flag to check if gdpr applies | `1` | `string` | +| `gdprConsent` | optional | URL-safe base64-encoded Transparency & Consent string | `CPQfU1jPQfU1jG0AAAENAwCAAAAAAAAAAAAAAAAAAAAA.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g` | `string` | diff --git a/dev-docs/bidders/docereeadmanager.md b/dev-docs/bidders/docereeadmanager.md new file mode 100644 index 0000000000..b70e45499b --- /dev/null +++ b/dev-docs/bidders/docereeadmanager.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: Doceree AdManager +description: Doceree AdManager Prebid Bidder Adapter +pbjs: true +biddercode: docereeAdManager +media_types: banner +gvl_id: 1063 +tcfeu_supported: true +userIds: all (with commercial activation) +sidebarType: 1 +schain_supported: true +safeframes_ok: true +deals_supported: true +floors_supported: true +fpd_supported: false +privacy_sandbox: no + +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------|----------|----------------|---------------------------|----------| +| `placementId` | required | Placement Id | `'DOC-19-1'` | `string` | +| `publisherUrl` | optional | Current url | `https://doceree.com` | `string` | +| `gdpr` | optional | Flag to check if gdpr applies | `1` | `string` | +| `gdprConsent` | optional | URL-safe base64-encoded Transparency & Consent string | `CPQfU1jPQfU1jG0AAAENAwCAAAAAAAAAAAAAAAAAAAAA.IGLtV_T9fb2vj-_Z99_tkeYwf95y3p-wzhheMs-8NyZeH_B4Wv2MyvBX4JiQKGRgksjLBAQdtHGlcTQgBwIlViTLMYk2MjzNKJrJEilsbO2dYGD9Pn8HT3ZCY70-vv__7v3ff_3g` | `string` | diff --git a/dev-docs/bidders/dsp_geniee.md b/dev-docs/bidders/dsp_geniee.md new file mode 100644 index 0000000000..ba35412f0b --- /dev/null +++ b/dev-docs/bidders/dsp_geniee.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: Geniee +description: Geniee Bidder Adapter +biddercode: dsp_geniee +userId: imuId +media_types: banner +safeframes_ok: false +floors_supported: true +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +sidebarType: 1 +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +gpp_sids: none +schain_supported: false +dchain_supported: false +deals_supported: false +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +--- +### Note + +This is [Geniee](https://geniee.co.jp) Bidder Adapter for Prebid.js. + +Please contact us before using the adapter. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|----------|-----------------------|-----------|-----------| +| `test` | optional | test mode flag | `0` | `integer` | diff --git a/dev-docs/bidders/dspx.md b/dev-docs/bidders/dspx.md index 9b9133e49d..44fa5b472c 100644 --- a/dev-docs/bidders/dspx.md +++ b/dev-docs/bidders/dspx.md @@ -5,12 +5,17 @@ description: Prebid DSPx Bidder Adapter pbjs: true biddercode: dspx media_types: banner, video -gdpr_supported: true -userIds: uid2, netId +tcfeu_supported: true +schain_supported: true +userIds: uid2, netId, id5Id, sharedId +multiformat_supported: will-bid-on-one +gvl_id: 602 +sidebarType: 1 --- -### Note: -The DSPx Bidder Adapter requires setup and approval from DSPx team. Please reach out to your account team or prebid@dspx.tv for more information. +### Note + +The DSPx bidder adapter requires setup and approval from the DSPx team. Please reach out to for more information and start using it. ### Bid Params @@ -19,13 +24,13 @@ The DSPx Bidder Adapter requires setup and approval from DSPx team. Please reach | Name | Scope | Description | Example | Type | |---------------|----------|----------------------------------------------------------------------------|------------------------|-----------------| | `placement` | required | Placement ID from dspx. | `'101'` | `string` | -| `pfilter` | optional | Selection filter. E.g. floorprice (min_cpm_micros) | `{"floorprice": 1000000}`| `object` | +| `pfilter` | optional | Custom filter parameters. | `{"customxy": 1000000}`| `object` | | `bcat` | optional | List of Blocked Categories (IAB) - comma separated. | `'IAB2,IAB4'` | `string` | - **Notice:** The creative type can be checked by the `type` property of `bidResponse` object. E.g.: + ```js bidsBackHandler: function(bids) { - var contentType = bids[0].type // JS InSkin|JS Interscroller Type A|...; + var contentType = bids[0].type } ``` diff --git a/dev-docs/bidders/duration.md b/dev-docs/bidders/duration.md index 2c2e61cb9a..e3f21964fa 100644 --- a/dev-docs/bidders/duration.md +++ b/dev-docs/bidders/duration.md @@ -7,13 +7,14 @@ aliasCode: nobid pbjs: true pbs: true media_types: banner, video -gdpr_supported: true +tcfeu_supported: true gvl_id: 816 usp_supported: true schain_supported: true coppa_supported: true userId: criteo, unifiedId, id5Id safeframes_ok: true +sidebarType: 1 --- ### Bid Params @@ -25,51 +26,51 @@ safeframes_ok: true | `placementId` | optional | placementId is provided by your Duration Media account manager(s). This parameter allows to report on a specific ad unit | | `integer` | | `video`| optional | Object containing video targeting parameters. Note that this parameter is not used in Prebid Server. See [Video Object](#duration-video-object) for details. | `video: { playback_method: ['auto_play_sound_off'] }` | `object`| - ### Note -If you are using Google Ad Manager (GAM), it is highly recommended to make sure the “Serve in Safeframe” box in creative settings is unchecked. + +If you are using Google Ad Manager (GAM), it is highly recommended to make sure the “Serve in Safeframe” box in creative settings is unchecked. If you absolutely want to run Duration Media in a Saferame creative, please contact your Duration Media repsentative to coordinate this setup. +### Test Parameters -# Test Parameters -``` - var adUnits = [ - { - code: 'test-div1', - mediaTypes: { - banner: { - sizes: [[300, 250]], // a display size +```javascript +var adUnits = [ + { + code: 'test-div1', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "duration", + params: { + siteId: 2, + placementId: 3 } - }, - bids: [ - { - bidder: "duration", - params: { - siteId: 2, - placementId: 3 - } + } + ] + },{ + code: 'test-div2', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "duration", + params: { + siteId: 2 } - ] - },{ - code: 'test-div2', - mediaTypes: { - banner: { - sizes: [[320, 50]], // a mobile size - } - }, - bids: [ - { - bidder: "duration", - params: { - siteId: 2 - } - } - ] - } - ]; + } + ] + } +]; ``` - + #### Video Object @@ -83,4 +84,3 @@ If you absolutely want to run Duration Media in a Saferame creative, please cont | `minduration` | Integer that defines the minimum video ad duration in seconds. | `integer` | | `maxduration` | Integer that defines the maximum video ad duration in seconds. | `integer` | | `frameworks` | Array of integers listing API frameworks supported by the publisher. Allowed values: None: `0`; VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; ORMMA: `4`; MRAID 2.0: `5`. | `Array` | - diff --git a/dev-docs/bidders/dxkulture.md b/dev-docs/bidders/dxkulture.md new file mode 100644 index 0000000000..2d29640cb4 --- /dev/null +++ b/dev-docs/bidders/dxkulture.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: DXKulture +description: Prebid DXKulture Bidder Adapter +pbjs: true +pbs: true +biddercode: dxkulture +media_types: banner, video +tcfeu_supported: false +gdpr_supported: true +usp_supported: true +schain_supported: true +sidebarType: 1 + +--- + +### Integration Note + +The DXKulture Header Bidding adapter requires approval from the DXKulture team. Please reach out to for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------|----------|--------------------|-------------|-----------| +| `placementId` | required | Placement Id | `'1234abcd'` | `string` | +| `publisherId` | required | Publisher Id | `'12345'` | `string` | +| `bidfloor` | optional | Bid Floor | `2.3` | `float` | +| `bidfloorcur` | optional | Bid Floor Currency | `'USD'` | `string` | diff --git a/dev-docs/bidders/e_volution.md b/dev-docs/bidders/e_volution.md index d5798caaad..5282e7589b 100644 --- a/dev-docs/bidders/e_volution.md +++ b/dev-docs/bidders/e_volution.md @@ -4,19 +4,20 @@ title: E-volution tech description: Prebid E-volution tech Bidder Adapter pbjs: true biddercode: e_volution -gdpr_supported: true +tcfeu_supported: true media_types: banner, video, native gvl_id: 957 pbs: true pbs_app_supported: true usp_supported: true schain_supported: true -pbjs_version_notes: in 6.8+ +userIds: id5Id +sidebarType: 1 --- -### Note: +### Note -The E-volution Bidding adapter requires setup before beginning. Please contact us at admin@e-volution.ai +The E-volution Bidding adapter requires setup before beginning. Please contact us at ### Prebid.JS Bid Params diff --git a/dev-docs/bidders/ebdr.md b/dev-docs/bidders/ebdr.md index 56036ed355..0fc6be4dd5 100644 --- a/dev-docs/bidders/ebdr.md +++ b/dev-docs/bidders/ebdr.md @@ -5,6 +5,7 @@ description: Prebid EngageBDR Bidder Adaptor biddercode: ebdr pbjs: true media_types: video +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/edge226.md b/dev-docs/bidders/edge226.md new file mode 100644 index 0000000000..9eccba455e --- /dev/null +++ b/dev-docs/bidders/edge226.md @@ -0,0 +1,31 @@ +--- +layout: bidder +title: Edge226 +description: Prebid Edge226 Bidder Adapter +biddercode: edge226 +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +pbjs: true +pbs: true +pbs_app_supported: true +gvl_id: 1202 +sidebarType: 1 +multiformat_supported: will-bid-on-one +safeframes_ok: true +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/edgequeryx.md b/dev-docs/bidders/edgequeryx.md deleted file mode 100644 index 11451f6332..0000000000 --- a/dev-docs/bidders/edgequeryx.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: bidder -title: Edge Query X -description: Prebid for Edge Query X Adaptor -pbjs: true -biddercode: edgequeryx -media_types: display -gdpr_supported: true -schain_supported: true -usp_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -The Edge Query bidder adaptor requires setup and approval from the Edge Query team. Please reach out to your account manager for more information and start using it. - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|-----------| -| `accountId`| required | The account ID | `test` | `string` | -| `widgetId` | required | The widget ID | `test` | `string` | -| `domain` | optional | The network domain (default see example) | `'https://deep.edgequery.io'` | `string` | -| `appName` | optional | Mobile application name | `'Edge Query Preview'` | `string` | - diff --git a/dev-docs/bidders/eightPod.md b/dev-docs/bidders/eightPod.md new file mode 100644 index 0000000000..58dc14f0d3 --- /dev/null +++ b/dev-docs/bidders/eightPod.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: 8pod +description: Prebid EightPod Bidder Adaptor +biddercode: eightPod +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +gpp_sids: none +schain_supported: false +dchain_supported: false +userId: none +media_types: banner +deals_supported: false +floors_supported: false +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +sidebarType: 1 +safeframes_ok: false +multiformat_supported: will-not-bid +privacy_sandbox: no +ortb_blocking_supported: false +--- + +### Registration + +The EightPod adapter requires setup before beginning. Please contact us at + +### Bid Params + +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------------------------------------------------------------------------------------------------------|----------------------------|----------| +| `placementId` | required | The unique identifier of the ad placement. Could be obtained from the 8pod UI or from your account manager. | "placementId-438753744289" | `string` | +| `publisherId` | optional | The unique identifier of the publisher. | "publisherId-438753744289" | `string` | diff --git a/dev-docs/bidders/embimedia.md b/dev-docs/bidders/embimedia.md new file mode 100644 index 0000000000..59ae7a0225 --- /dev/null +++ b/dev-docs/bidders/embimedia.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Embi Media +description: Prebid Embi Media Bidder Adaptor +biddercode: embimedia +pbjs: false +pbs: true +media_types: banner, video, audio, native +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Note + +The Embi Media Bidding adapter requires setup before beginning. + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:----------------------|:-----------------------|:----------| +| `host` | required | Ad network's RTB host | `'bidder-embi.media'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | diff --git a/dev-docs/bidders/emetriq.md b/dev-docs/bidders/emetriq.md new file mode 100644 index 0000000000..17b59ae32b --- /dev/null +++ b/dev-docs/bidders/emetriq.md @@ -0,0 +1,31 @@ +--- +layout: bidder +title: emetriq +description: emetriq Bidder Adapter +biddercode: emetriq +aliasCode: appnexus +tcfeu_supported: true +gvl_id: 213 +schain_supported: true +userId: all +media_types: banner, video, native +safeframes_ok: true +deals_supported: true +pbjs: true +pbs: true +prebid_member: false +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placement_id` (PBS+PBJS) or `placementId` (PBJS) | required | Placement id | `'32068254'` | `string` | + +emetriq is an aliased bidder for AppNexus. + +### Note + +For setup with emetriq, please reach out to [admins@emetriq.com](mailto:admins@emetriq.com) diff --git a/dev-docs/bidders/emoteev.md b/dev-docs/bidders/emoteev.md deleted file mode 100644 index d9731d89ba..0000000000 --- a/dev-docs/bidders/emoteev.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: Emoteev -description: Prebid Emoteev Bidder Adaptor -pbjs: true -biddercode: emoteev -gdpr_supported: true -userIds: pubCommonId -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------------|----------|--------------------------------------------------------------------------|----------------|---------| -| `adSpaceId` | required | Provided by Emoteev team | `5084` | Integer | -| `context` | required | One of `'in-content'`, `'footer'`, `'overlay'`, `'wallpaper'` | `'in-content'` | String | -| `externalId` | optional | Use it when you want to link your bids to some specific id on your side. | `12` | Integer | diff --git a/dev-docs/bidders/emtv.md b/dev-docs/bidders/emtv.md new file mode 100644 index 0000000000..b3fa16078b --- /dev/null +++ b/dev-docs/bidders/emtv.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: EMTV +description: Prebid EMTV Bidder Adapter +biddercode: emtv +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +multiformat_supported: will-not-bid +pbjs: true +pbs: true +pbs_app_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/emx_digital.md b/dev-docs/bidders/emx_digital.md deleted file mode 100644 index 00acc8c306..0000000000 --- a/dev-docs/bidders/emx_digital.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: bidder -title: EMX Digital -description: Prebid EMX Digital Bidder Adaptor -pbjs: true -pbs: true -biddercode: emx_digital -media_types: banner, video -gdpr_supported: true -gvl_id: 183 -usp_supported: true -schain_supported: true -userIds: identityLink, uid2 ---- - -### Registration - -To use this bidder you will need an account and a valid tagid from our exchange. For further information, please contact your Account Manager or adops@emxdigital.com. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------------|----------|----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|------------| -| `tagid` | required | The Tag ID from EMX Digital. | `test1` | `string` | -| `bidfloor` | optional | The CPM bid floor | `0.25` | `string` | diff --git a/dev-docs/bidders/engageadx.md b/dev-docs/bidders/engageadx.md index 9402d71593..d4a88fcd22 100644 --- a/dev-docs/bidders/engageadx.md +++ b/dev-docs/bidders/engageadx.md @@ -2,19 +2,28 @@ layout: bidder title: EngageADX description: EngageADX Bidder Adaptor -pbjs: true -pbs: true biddercode: engageadx +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true usp_supported: true coppa_supported: true +gpp_supported: true pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The EngageADX bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/engagebdr.md b/dev-docs/bidders/engagebdr.md index df1cb08c2c..78e6eb36cb 100644 --- a/dev-docs/bidders/engagebdr.md +++ b/dev-docs/bidders/engagebdr.md @@ -4,6 +4,7 @@ title: Engage BDR pbs: true media_types: banner biddercode: engagebdr +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/engageya.md b/dev-docs/bidders/engageya.md index a085c9bd45..7ff89a13f9 100644 --- a/dev-docs/bidders/engageya.md +++ b/dev-docs/bidders/engageya.md @@ -5,9 +5,14 @@ description: Prebid Engageya Bidder Adapter media_type: banner, native biddercode: engageya pbjs: true -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- +### Disclosure + +Note: This bidder appears to only consider gdprApplies if a consent string is available. This may result in some incorrect TCF2 processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + ### Bid params {: .table .table-bordered .table-striped } @@ -16,4 +21,3 @@ gdpr_supported: true | widgetId | required | Widget ID, provided by Engageya. | `85610` | integer | | websiteId | required | Website ID, provided by Engageya. | `91140` | integer | | pageUrl | optional | Pass current user URL. | `'https://engageya.com'` | String | - diff --git a/dev-docs/bidders/envivo.md b/dev-docs/bidders/envivo.md deleted file mode 100644 index b19dd59148..0000000000 --- a/dev-docs/bidders/envivo.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: envivo -description: Prebid envivo Bidder Adapter -pbjs: true -biddercode: envivo -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|----------------------------------------------------------------------------------------|-----------------------------|-----------| -| `publisherId` | required | Publisher id associated with envivo | `1` | `integer` | diff --git a/dev-docs/bidders/eplanning.md b/dev-docs/bidders/eplanning.md index b6b0466f71..3938737592 100644 --- a/dev-docs/bidders/eplanning.md +++ b/dev-docs/bidders/eplanning.md @@ -4,16 +4,21 @@ title: E-Planning description: Prebid E-Planning Bidder Adapter pbjs: true pbs: true +media_types: banner, video biddercode: eplanning usp_supported: true -gdpr_supported: true +tcfeu_supported: true pbs_app_supported: true +floors_supported: true +userIds: all gvl_id: 90 +sidebarType: 1 --- -### Note: +### Note + The E-Planning Header Bidding adaptor requires setup and approval from the E-Planning team. Please go to [E-Planning website](http://www.e-planning.net) for more details. ### Bid Params @@ -22,8 +27,8 @@ The E-Planning Header Bidding adaptor requires setup and approval from the E-Pla | Name | Scope | Description | Example | Type | |-------|----------|-----------------------------------------------|---------------------------|-----------| | `ci` | required | Your partner ID (provided by E-Planning) | `'18f66'` | `string` | -| `sv` | optional | Indicates a bidder URL different than default | `'ads.us.e-planning.net'` | `string` | -| `isv` | optional | Indicates a CDN URL different than default | `'us.img.e-planning.net'` | `string` | +| `sv` | optional | Indicates a bidder URL different than default | `'pbjs.e-planning.net'` | `string` | +| `isv` | optional | Indicates a CDN URL different than default | `'i.e-planning.net'` | `string` | | `t` | optional | Indicates bidding for testing purposes | `1` | `integer` | | `ml` | optional | Uses placement names as ad unit names instead of sizes | `1` | `integer` | | `sn` | optional | Uses space name instead of sizes | `adunitName` | `string` | diff --git a/dev-docs/bidders/epom.md b/dev-docs/bidders/epom.md index d1d5897a28..aa678395db 100644 --- a/dev-docs/bidders/epom.md +++ b/dev-docs/bidders/epom.md @@ -3,7 +3,7 @@ layout: bidder title: Epom description: Prebid Epom Bidder Adapter biddercode: epom -gdpr_supported: false +tcfeu_supported: false gvl_id: 849 usp_supported: false coppa_supported: true @@ -15,11 +15,12 @@ pbjs: false pbs: true pbs_app_supported: true prebid_member: false +sidebarType: 1 --- -### Note: +### Note -The Epom Bidding adapter requires setup before beginning. Please contact us at support@epom.com +The Epom Bidding adapter requires setup before beginning. Please contact us at ### Bid Params diff --git a/dev-docs/bidders/epsilon.md b/dev-docs/bidders/epsilon.md new file mode 100644 index 0000000000..1c6b3f4645 --- /dev/null +++ b/dev-docs/bidders/epsilon.md @@ -0,0 +1,136 @@ +--- +layout: bidder +title: Epsilon +description: Epsilon Prebid Bidder Adaptor (formerly Conversant) +pbjs: true +pbs: true +biddercode: conversant +media_types: video +tcfeu_supported: true +userIds: criteo, id5Id, identityLink, liveIntentId, parrableId, pubCommonId, unifiedId, publinkId +prebid_member: true +schain_supported: true +gvl_id: 24 +sidebarType: 1 +--- + + + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|---------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------|------------------| +| `site_id` | required | The site ID from Epsilon. | `'87293'` | `string` | +| `secure` | required (for secure pages) | If impression requires secure HTTPS URL creative assets and markup. 0 for non-secure, 1 for secure. Default is non-secure | `1` | `integer` | +| `bidfloor` | optional | Bid floor | `0.50` | `float` | +| `tag_id` | optional | Identifies specific ad placement. | `'cnvr-test-tag'` | `string` | +| `white_label_url`| optional | Override the destination URL the request is sent to. | `'https://mydomain.com/hbendpoint'` | `string` | +| `pubcid_name` | optional | Name of the pub common id. Epsilon adapter can read the id directly if the UserID module is absent. Default is _pubcid.| `'_pubcid'` | `string` | + +### Video Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|---------------|-----------------------------|---------------------------------------------------------------------------------------------------------------------------|-------------------|------------------| +| `position` | optional | Ad position on screen. See details below. Only supported in bids.params. | `1` | `integer` | +| `mimes` | optional | Array of content MIME types supported. Required for video | `['video/mp4']` | `Array` | +| `maxduration` | optional | Maximum duration in seconds for this video as an integer. | `30` | `integer` | +| `api` | optional | Array of supported API frameworks. See details below. | `[2]` | `Array` | +| `protocols` | optional | Array of supported video protocols. See details below. | `[2]` | `Array` | + +Video parameters can be included in either `mediaTypes.video` or `bids.params` except where noted. + +The following values are defined in the [ORTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). + +### position + ++ `0` : Unknown ++ `1` : Above the Fold ++ `3` : Below the Fold ++ `4` : Header ++ `5` : Footer ++ `6` : Sidebar ++ `7` : Full Screen + +### api + ++ `1` : VPAID 1.0 ++ `2` : VPAID 2.0 ++ `3` : MRAID 1.0 ++ `4` : ORMMA ++ `5` : MRAID 2.0 ++ `6` : MRAID 3.0 + + + +### protocols + ++ `1` : VAST 1.0 ++ `2` : VAST 2.0 ++ `3` : VAST 3.0 ++ `4` : VAST 1.0 Wrapper ++ `5` : VAST 2.0 Wrapper ++ `6` : VAST 3.0 Wrapper ++ `7` : VAST 4.0 ++ `8` : VAST 4.0 Wrapper ++ `9` : DAAST 1.0 ++ `10` : DAAST 1.0 Wrapper + +### First Party Data + +Publishers should use the `ortb2` method of setting for setting First Party Data. +Example first party data configuration that is available to all adUnits + +``` +pbjs.setConfig({ + debug: true, + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + }, + ortb2: { + site: { + content: { + series: 'MySeries', + season: 'My Season', + episode: 3, + title: 'My Title' + } + } + } +}); +``` + +Example AdUnit specific data using the `ortb2Imp` object + +``` + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [[640, 480]] + } + }, + ortb2Imp: { + instl: 1, + ext: { + data: { + adUnitSpecificAttribute: "123" + } + } + }, + bids: [{ + bidder: 'conversant', + params: { + site_id: '108060', + mimes: ['video/mp4', 'video/webm'] + } + }] + } + + pbjs.que.push(function(){ + pbjs.addAdUnits(videoAdUnits); + } +``` diff --git a/dev-docs/bidders/ergadx.md b/dev-docs/bidders/ergadx.md index 2aedf405a1..02803608c9 100644 --- a/dev-docs/bidders/ergadx.md +++ b/dev-docs/bidders/ergadx.md @@ -2,19 +2,28 @@ layout: bidder title: eRGADX description: eRGADX Bidder Adaptor +biddercode: ergadx pbjs: true pbs: true -biddercode: ergadx -aliasCode : adkernel media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The eRGADX bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/eskimi.md b/dev-docs/bidders/eskimi.md new file mode 100644 index 0000000000..9b5e9e9be3 --- /dev/null +++ b/dev-docs/bidders/eskimi.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Eskimi +description: Prebid Eskimi Bidder Adapter +pbjs: true +pbs: false +biddercode: eskimi +deals_supported: false +media_types: banner, video +gvl_id: 814 +schain_supported: true +floors_supported: true +safeframes_ok: false +multiformat_supported: will-bid-on-any +ortb_blocking_supported: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------|----------|---------------------------------|------------------------|-----------| +| `placementId` | required | The placement ID from Eskimi. | `612` | `integer` | +| `bcat` | optional | ORTB blocked categories | `['IAB-1-1']` | `string[]`| +| `badv` | optional | ORTB blocked advertiser domains | `['example.com']` | `string[]`| +| `bapp` | optional | ORTB blocked applications | `['com.example.game']` | `string[]`| + +Additionally `battr` ORTB blocking param may be set on `BANNER` and `VIDEO` media types to specify blocked creative +attributes. diff --git a/dev-docs/bidders/etarget.md b/dev-docs/bidders/etarget.md index d68eeb522f..4de459a50e 100644 --- a/dev-docs/bidders/etarget.md +++ b/dev-docs/bidders/etarget.md @@ -4,11 +4,12 @@ title: Etarget description: Prebid Etarget Bidder Adaptor biddercode: etarget media_types: banner, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true pbjs: true fpd_supported: true gvl_id: 29 +sidebarType: 1 --- ### Bid Params @@ -24,6 +25,7 @@ gvl_id: 29 #### First Party Data In release 5.0 and later, publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: + - ortb2.site.ext.data.* - ortb2.site.keywords - ortb2.site.content.data[] @@ -33,6 +35,7 @@ In release 5.0 and later, publishers should use the `ortb2` method of setting Fi The ETARGET exchange supports the IAB standard Audience Taxonomy v1.1 and Content Taxonomy v2.2. Example first party data that's available to all bidders and all adunits: + ``` pbjs.setConfig({ ortb2: { @@ -56,6 +59,7 @@ pbjs.setConfig({ ``` Example of first party data available only to the ETARGET bidder. Applies across all ad units. + ``` pbjs.setBidderConfig({ bidders: ["etarget"], diff --git a/dev-docs/bidders/evtech.md b/dev-docs/bidders/evtech.md new file mode 100644 index 0000000000..3565948b84 --- /dev/null +++ b/dev-docs/bidders/evtech.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Evolution Technologies +description: Evolution Technologies Bidder Adaptor +biddercode: evtech +pbjs: false +pbs: true +media_types: banner, video, audio, native +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:----------------------|:------------------|:----------| +| `host` | required | Ad network's RTB host | `'e-volution.ai'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | diff --git a/dev-docs/bidders/exads.md b/dev-docs/bidders/exads.md new file mode 100644 index 0000000000..6e877ffb1b --- /dev/null +++ b/dev-docs/bidders/exads.md @@ -0,0 +1,404 @@ +--- +layout: bidder +title: EXADS +description: EXADS Bidder Adapter +pbjs: true +multiformat_supported: will-not-bid +biddercode: exads +dsa_supported: true +gvl_id: 1084 +tcfeu_supported: true +media_types: banner, video, native +safeframes_ok: false +deals_supported: false +floors_supported: true +ortb_blocking_supported: true +--- + +### Example + +A very minimal RTB Banner example that shows how to use the EXADS adapter. +The most important attributes are: **endpoint**, **fid** and **zoneId**. You can get them after configuring the zones. +For more details about ad formats and parameters, read it in the next sections. + +```js + +adUnits = [ + { + code: 'postbid_iframe', // the frame where to render the creative + mediaTypes: { + banner: { + sizes: [300, 250], + }, + }, + bids: [ + { + bidder: 'exads', + params: { + zoneId: 12345, + fid: '829a896f011475d50da0d82cfdd1af8d9cdb07ff', + partner: 'ortb_2_4', + siteId: '123', + siteName: 'test.com', + country: 'IRL, + userIp: '0.0.0.0', + userId: '1234', + impressionId: impression_id.toString(), + mimes: ['image/jpg'], + endpoint: 'https://your-ad-network.com/rtb.php', + }, + }, + ], + }, +]; +``` + +### Configuration + +#### Video settings + +If you will work with video stream ad formats you could choose to use the prebidJS video module to render the video using already supported video players as videoJS. +Add the `video` config if you need to render videos using the video module. +For more info navigate to [instructions](/prebid-video/video-module.html). + +#### RTB Banner 2.4 + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `zoneID` | required | You can get it from the endpoint created after configuring the zones | `12345` | `integer` | +| `fid` | required | You can get it from the endpoint created after configuring the zones | `'829a896f011475d50da0d82cfdd1af8d9cdb07ff'` | `string` | +| `partner` | required | Currently we support rtb 2.4 (“ortb_2_4”) only | `'ortb_2_4'` | `string` | +| `siteId` | recommended | Unique Site ID | `'123'` | `string` | +| `siteName` | | Site name | `'test.com'` | `string` | +| `banner.sizes` | required | [width, height] | `[145,256]` | `integer array` | +| `userIp` | required | IP address of the user, ipv4 or ipv6 | `'0.0.0.0'` | `string` | +| `userId` | *required | Unique user ID (string). *If you cannot generate a user ID, you can leave it empty (""). The request will get a response as long as “user” object is included in the request | `''` | `string` | +| `country` | required | country ISO3 | `'IRL'` | `string` | +| `impressionId` | required | Unique impression ID within this bid request | `'abcde'` | `string` | +| `keywords` | optional | Keywords can be used to ensure ad zones get the right type of advertising. Keywords should be a string of comma-separated words | `'lifestyle, humour'` | `string` | +| `bidfloor` | optional | Minimum bid for this impression (CPM) / click (CPC) and account currency | `0.00000011` | `float` | +| `bidfloorcur` | optional | Currency for minimum bid value specified using ISO-4217 alpha codes | `'EUR'` | `string` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB25', 'IAB7-39','IAB8-18','IAB8-5','IAB9-9']` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `['first.com', 'second.com']` | `string array` | +| `mimes` | optional | List of supported mime types. We support: image/jpeg, image/jpg, image/png, image/png, image/gif, image/webp, video/mp4 | `['image/jpg']` | `string array` | +| `dsa` | optional | DSA transparency information. To see the specific paragraph for more details. | `{ dsarequired: 3, pubrender: 0, datatopub: 2 }` | `object` | +| `endpoint` | required | EXADS endpoint (URL) | `https://your-ad-network.com/rtb.php` | `string` | + +##### RTB Banner 2.4 (Image) + +```js +adUnits = [ + { + code: 'postbid_iframe', // the frame where to render the creative + mediaTypes: { + banner: { + sizes: [300, 250], + }, + }, + bids: [ + { + bidder: 'exads', + params: { + zoneId: 12345, + fid: '829a896f011475d50da0d82cfdd1af8d9cdb07ff', + partner: 'ortb_2_4', + siteId: '123', + siteName: 'test.com', + userIp: '0.0.0.0', + userId: '1234', + country: 'IRL', // optional + impressionId: impression_id.toString(), + keywords: 'lifestyle, humour', // optional + bidfloor: 0.00000011, // optional + bidfloorcur: 'EUR', // optional + bcat: ['IAB25', 'IAB7-39', 'IAB8-18', 'IAB8-5', 'IAB9-9'], // optional + badv: ['first.com', 'second.com'], // optional + mimes: ['image/jpg'], + dsa: { + // optional + dsarequired: 3, + pubrender: 0, + datatopub: 2, + }, + endpoint: 'https://your-ad-network.com/rtb.php', + }, + }, + ], + }, +]; +``` + +##### RTB Banner 2.4 (Video) + +```js +adUnits = [ + { + code: 'postbid_iframe', // the frame where to render the creative + mediaTypes: { + banner: { + sizes: [900, 250], + }, + }, + bids: [ + { + bidder: 'exads', + params: { + zoneId: 12345, + fid: '829a896f011475d50da0d82cfdd1af8d9cdb07ff', + partner: 'ortb_2_4', + siteId: '123', + siteName: 'test.com', + userIp: '0.0.0.0', + userId: '1234', + country: 'IRL', // optional + impressionId: '1234', // optional + keywords: 'lifestyle, humour', // optional + bidfloor: 0.00000011, // optional + bidfloorcur: 'EUR', // optional + bcat: ['IAB25', 'IAB7-39', 'IAB8-18', 'IAB8-5', 'IAB9-9'], // optional + badv: ['first.com', 'second.com'], // optional + mimes: ['image/jpg'], + dsa: { + // optional + dsarequired: 3, + pubrender: 0, + datatopub: 2, + }, + endpoint: 'https://your-ad-network.com/rtb.php', + }, + }, + ], + }, +]; +``` + +#### RTB 2.4 Video (Instream/OutStream/Video Slider) - VAST XML or VAST TAG (url) + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `zoneID` | required | You can get it from the endpoint created after configuring the zones | `12345` | `integer` | +| `fid` | required | You can get it from the endpoint created after configuring the zones | `'829a896f011475d50da0d82cfdd1af8d9cdb07ff'` | `string` | +| `partner` | required | Currently we support rtb 2.4 (“ortb_2_4”) only | `'ortb_2_4'` | `string` | +| `siteId` | recommended | Unique Site ID | `'123'` | `string` | +| `siteName` | | Site name | `'test.com'` | `string` | +| `userIp` | required | IP address of the user, ipv4 or ipv6 | `'0.0.0.0'` | `string` | +| `userId` | *required | Unique user ID (string). *If you cannot generate a user ID, you can leave it empty (""). The request will get a response as long as “user” object is included in the request | `''` | `string` | +| `country` | required | country ISO3 | `'IRL'` | `string` | +| `impressionId` | required | Unique impression ID within this bid request | `'abcde'` | `string` | +| `keywords` | optional | Keywords can be used to ensure ad zones get the right type of advertising. Keywords should be a string of comma-separated words | `'lifestyle, humour'` | `string` | +| `bidfloor` | optional | Minimum bid for this impression (CPM) / click (CPC) and account currency | `0.00000011` | `float` | +| `bidfloorcur` | optional | Currency for minimum bid value specified using ISO-4217 alpha codes | `'EUR'` | `string` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB25', 'IAB7-39','IAB8-18','IAB8-5','IAB9-9']` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `['first.com', 'second.com']` | `string array` | +| `mediaTypes` | required | To see the specific paragraph for details | `{ video: { mimes: ['video/mp4'], context: 'instream', protocols: [3, 6] }}` | `object` | +| `dsa` | optional | DSA transparency information. To see paragraph for more info | `{ dsarequired: 3, pubrender: 0, datatopub: 2 }` | `object` | +| `endpoint` | required | EXADS endpoint (URL) | `https://your-ad-network.com/rtb.php` | `string` | + +##### MediaTypes.video + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `mimes` | required | list of supported mime types | `['video/mp4']` | `string array` | +| `protocols` | required | list of supported video bid response protocols | `[3, 6]` | `integer array` | +| `context` | recommended | the video context, either ‘instream’, ‘outstream’. Defaults to ‘instream’ | `'instream'` | `string` | + +```js +adUnits = [ + { + code: 'postbid_iframe', + mediaTypes: { + video: { + mimes: ['video/mp4'], + context: 'instream', + protocols: [3, 6], + }, + }, + bids: [ + { + bidder: 'exads', + params: { + zoneId: 12345, + fid: '829a896f011475d50da0d82cfdd1af8d9cdb07ff', + partner: 'ortb_2_4', + siteId: '123', + siteName: 'test.com', + userIp: '0.0.0.0', + userId: '1234', + impressionId: '1234', + imp: { + ext: { + video_cta: 0, + }, + }, + dsa: { + // optional + dsarequired: 3, + pubrender: 0, + datatopub: 2, + }, + country: 'IRL', // optional + keywords: 'lifestyle, humour', // optional + bidfloor: 0.00000011, // optional + bidfloorcur: 'EUR', // optional + bcat: ['IAB25', 'IAB7-39', 'IAB8-18', 'IAB8-5', 'IAB9-9'], // optional + badv: ['first.com', 'second.com'], // optional + endpoint: 'https://your-ad-network.com/rtb.php', + }, + }, + ], + }, +]; +``` + +#### RTB 2.4 Native + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `zoneID` | required | You can get it from the endpoint created after configuring the zones | `12345` | `integer` | +| `fid` | required | You can get it from the endpoint created after configuring the zones | `'829a896f011475d50da0d82cfdd1af8d9cdb07ff'` | `string` | +| `partner` | required | Currently we support rtb 2.4 (“ortb_2_4”) only | `'ortb_2_4'` | `string` | +| `siteId` | recommended | Unique Site ID | `'123'` | `string` | +| `siteName` | | Site name | `'test.com'` | `string` | +| `userIp` | required | IP address of the user, ipv4 or ipv6 | `'0.0.0.0'` | `string` | +| `userId` | *required | Unique user ID (string). *If you cannot generate a user ID, you can leave it empty (""). The request will get a response as long as “user” object is included in the request | `''` | `string` | +| `country` | required | country ISO3 | `'IRL'` | `string` | +| `impressionId` | required | Unique impression ID within this bid request | `'abcde'` | `string` | +| `keywords` | optional | Keywords can be used to ensure ad zones get the right type of advertising. Keywords should be a string of comma-separated words | `'lifestyle, humour'` | `string` | +| `bidfloor` | optional | Minimum bid for this impression (CPM) / click (CPC) and account currency | `0.00000011` | `float` | +| `bidfloorcur` | optional | Currency for minimum bid value specified using ISO-4217 alpha codes | `'EUR'` | `string` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB25', 'IAB7-39','IAB8-18','IAB8-5','IAB9-9']` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `['first.com', 'second.com']` | `string array` | +| `native.plcmtcnt` | optional | the number of identical placements in this Layout | `4` | `integer` | +| `assets` | required | To see the specific paragraph for more info | `{}` | `object` | +| `dsa` | optional | DSA transparency information. To see paragraph for more info | `{ dsarequired: 3, pubrender: 0, datatopub: 2 }` | `object` | +| `endpoint` | required | EXADS endpoint (URL) | `https://your-ad-network.com/rtb.php` | `string` | + +##### Assets + +* **assets (title)** + * **id** - unique asset ID, assigned by exchange. Typically a counter for the array (integer): + *1 - image asset ID + * 2 - title asset ID + * 3 - description asset ID + * **required** - set to 1 if asset is required or 0 if asset is optional (integer) + * **title** + * len (required) - maximum length of the text in the title element (integer) +* **assets (data)** + * **id** - unique asset ID, assigned by exchange. Typically a counter for the array (integer): + *1 - image asset ID + * 2 - title asset ID + * 3 - description asset ID + * **data** + * **type** - type ID of the element supported by the publisher (integer). We support: + *1 - sponsored - sponsored By message where response should contain the brand name of the sponsor + * 2 - desc - descriptive text associated with the product or service being advertised + * **len** - maximum length of the text in the element’s response (integer) +* **assets (img)** + * **id** - unique asset ID, assigned by exchange. Typically a counter for the array (integer): + *1 - image asset ID + * 2 - title asset ID + * 3 - description asset ID + * **required** - set to 1 if asset is required or 0 if asset is optional (integer) + * **img** + * **type** - type ID of the image element supported by the publisher. We support: + *1 - icon image (integer) + * 3 - large image preview for the ad (integer) + * **w** - width of the image in pixels, optional (integer) + * **h** - height of the image in pixels, optional (integer) + +```js +adUnits = [ + { + code: 'postbid_iframe', + mediaTypes: { + native: { + ortb: { + assets: [ + { + id: 2, + required: 1, + title: { + len: 124, + }, + }, + { + id: 3, + data: { + type: 1, + len: 50, + }, + }, + { + id: 1, + required: 1, + img: { + type: 3, + w: 300, + h: 300, + }, + }, + ], + }, + }, + }, + bids: [ + { + bidder: 'exads', + params: { + zoneId: 12345, + fid: '829a896f011475d50da0d82cfdd1af8d9cdb07ff', + partner: 'ortb_2_4', + siteId: '123', + siteName: 'test.com', + userIp: '0.0.0.0', + userId: '1234', + impressionId: '1234', + native: { + // optional + plcmtcnt: 4, + }, + dsa: { + dsarequired: 3, + pubrender: 0, + datatopub: 2, + }, + country: 'IRL', // optional + keywords: 'lifestyle, humour', // optional + bidfloor: 0.00000011, // optional + bidfloorcur: 'EUR', // optional + bcat: ['IAB25', 'IAB7-39', 'IAB8-18', 'IAB8-5', 'IAB9-9'], // optional + badv: ['first.com', 'second.com'], // optional + endpoint: 'https://your-ad-network.com/rtb.php', + }, + }, + ], + }, +]; +``` + +### DSA Transparency + +All DSA information, returned by the ad server, can be found into the **meta** tag of the response. As: + +```js +"meta": { + "dsa": { + "behalf": "...", + "paid": "...", + "transparency": [ + { + "params": [ + ... + ] + } + ], + "adrender": ... + } +} +``` + +For more information navigate to the [page](/dev-docs/bidder-adaptor.html). diff --git a/dev-docs/bidders/eywamedia.md b/dev-docs/bidders/eywamedia.md index e069c77e8d..ee3727b399 100644 --- a/dev-docs/bidders/eywamedia.md +++ b/dev-docs/bidders/eywamedia.md @@ -5,7 +5,8 @@ description: Prebid Eywamedia Bidder Adaptor pbjs: true biddercode: eywamedia media_types: display -gdpr_supported: false +tcfeu_supported: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/fairtrade.md b/dev-docs/bidders/fairtrade.md index d26c7fefc2..cb262e40e9 100644 --- a/dev-docs/bidders/fairtrade.md +++ b/dev-docs/bidders/fairtrade.md @@ -4,6 +4,7 @@ title: FairTrade description: FairTrade Bidder Adapter pbjs: true biddercode: fairtrade +sidebarType: 1 --- diff --git a/dev-docs/bidders/featureforward.md b/dev-docs/bidders/featureforward.md index 9b6f924fd1..09c470b2fb 100644 --- a/dev-docs/bidders/featureforward.md +++ b/dev-docs/bidders/featureforward.md @@ -6,6 +6,7 @@ top_nav_section: dev_docs nav_section: reference pbjs: true biddercode: featureforward +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/feedad.md b/dev-docs/bidders/feedad.md index bfcf75ec66..64201463b9 100644 --- a/dev-docs/bidders/feedad.md +++ b/dev-docs/bidders/feedad.md @@ -4,9 +4,10 @@ title: FeedAd description: Prebid FeedAd Bidder Adaptor pbjs: true biddercode: feedad -gdpr_supported: true +tcfeu_supported: true media_types: banner gvl_id: 781 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/felixads.md b/dev-docs/bidders/felixads.md index 9bc6ed33c7..e633e47c44 100644 --- a/dev-docs/bidders/felixads.md +++ b/dev-docs/bidders/felixads.md @@ -2,20 +2,28 @@ layout: bidder title: felixads description: Prebid felixads Bidder Adaptor +biddercode: felixads pbjs: true pbs: false -biddercode: felixads -aliascode: adkernel media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The felixads Bidding adaptor requires setup and approval before beginning. Please reach out to for more details diff --git a/dev-docs/bidders/fidelity.md b/dev-docs/bidders/fidelity.md deleted file mode 100644 index f18a36bf0b..0000000000 --- a/dev-docs/bidders/fidelity.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: Fidelity Media -description: Prebid Fidelity Media Bidder Adapter -pbjs: true -schain_supported: true -biddercode: fidelity -media_types: banner -gdpr_supported: true -usp_supported: true -gvl_id: 408 -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------|----------|--------------------------------------------------|--------------------------|----------| -| zoneid | required | The ad zone or tag specific ID | `'27248'` | `string` | -| floor | optional | The floor CPM price for the request | `0.1234` | `float` | -| server | optional | Bidder domain (default `'x.fidelity-media.com'`) | `'x.fidelity-media.com'` | `string` | diff --git a/dev-docs/bidders/finative.md b/dev-docs/bidders/finative.md new file mode 100644 index 0000000000..0d7df0cde9 --- /dev/null +++ b/dev-docs/bidders/finative.md @@ -0,0 +1,18 @@ +--- +layout: bidder +title: Finative +description: Prebid Finative Bidder Adaptor +pbjs: true +biddercode: finative +media_types: native +tcfeu_supported: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------|--------------------|-----------| +| `adUnitId` | required | ID of the Ad Unit | `8ao` | `string` | +| `url` | optional | URL from the Page | `example.tld` | `string` | diff --git a/dev-docs/bidders/flipp.md b/dev-docs/bidders/flipp.md new file mode 100644 index 0000000000..343f7e388f --- /dev/null +++ b/dev-docs/bidders/flipp.md @@ -0,0 +1,43 @@ +--- +layout: bidder +title: flipp +description: Prebid Flipp Bidder Adapter +biddercode: flipp +media_types: banner +pbjs: true +pbs: true +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +floors_supported: false +userIds: none +prebid_member: false +safeframes_ok: true +deals_supported: false +pbs_app_supported: false +fpd_supported: false +multiformat_supported: will-not-bid +ortb_blocking_supported: false +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `publisherNameIdentifier` | required | Publisher name identifier | `test-publisher-name` | `string` | +| `creativeType` | required | Type of the creative | `NativeX` | `NativeX\|DTX` | +| `siteId` | required | ID associated with the site | `123456` | `integer` | +| `zoneIds` | optional | Zones to request from bidder | `[789, 123]` | `array[integer]` | +| `userKey` | optional | User Key to power experience optimization and frequency capping. Publishers: please confirm with legal counsel before using this feature. | `4188d8a3-22d1-49cb-8624-8838a22562bd` | `uuidv4` | +| `options` | optional | Additional integration specific context | `options: { "startCompact": true }` | `map[string]interface{}` | + +Current available integration options are as follows: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `startCompact` | optional | Height of the experience will be reduced | `true` | `boolean` | +| `dwellExpand` | optional | Auto expand the experience after a certain time passes | `true` | `boolean` | +| `contentCode` | optional | Force show a certain experience. Generally used for testing and debugging purposes. | `publisher-test` | `string` | diff --git a/dev-docs/bidders/fluct.md b/dev-docs/bidders/fluct.md index 5403970b0d..9ab9184f8d 100644 --- a/dev-docs/bidders/fluct.md +++ b/dev-docs/bidders/fluct.md @@ -4,11 +4,12 @@ title: fluct description: Prebid fluct Bidder Adapter biddercode: fluct media_types: banner -gdpr_supported: false +tcfeu_supported: false coppa_supported: false usp_supported: false schain_supported: true pbjs: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/freepass.md b/dev-docs/bidders/freepass.md new file mode 100644 index 0000000000..f86b5c1640 --- /dev/null +++ b/dev-docs/bidders/freepass.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: freepass +description: Prebid FreePass Bidder Adapter +biddercode: freepass +media_types: banner +pbjs: true +userIds: freepassId +sidebarType: 1 +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +floors_supported: false +prebid_member: false +safeframes_ok: false +deals_supported: false +fpd_supported: true +ortb_blocking_supported: false +gvl_id: none +multiformat_supported: will-not-bid +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| publisherId | required | publisherId | `'PUBLISHER_ID'` | `string` | +| publisherUrl | optional | url for publisher | `'PUBLISHER_URL'` | `string` | diff --git a/dev-docs/bidders/freewheel-ssp.md b/dev-docs/bidders/freewheel-ssp.md deleted file mode 100644 index f264e52b00..0000000000 --- a/dev-docs/bidders/freewheel-ssp.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: FreeWheel-ssp -description: Freewheel Bidder Adaptor -pbjs: true -biddercode: freewheel-ssp -gdpr_supported: true -usp_supported: true -media_types: video ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-------------|---------|----------| -| `zoneId` | required | | | `string` | diff --git a/dev-docs/bidders/freewheelssp.md b/dev-docs/bidders/freewheelssp.md new file mode 100644 index 0000000000..781c137295 --- /dev/null +++ b/dev-docs/bidders/freewheelssp.md @@ -0,0 +1,67 @@ +--- +layout: bidder +title: FreeWheelssp +description: Freewheel Bidder Adaptor +pbjs: true +pbs: true +biddercode: freewheelssp +aliasCode: freewheel-ssp +gvl_id: 285 +tcfeu_supported: true +usp_supported: true +gpp_supported: true +coppa_supported: true +schain_supported: true +media_types: video +ortb_blocking_supported: partial +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-------------------------|--------|----------| +| `zoneId` | required | The zone ID for the ad. | "2003" | `string` | +| `format` | optional | The format to use for displaying the ad. Can be one of the following:
      *screen-roll
      * intext-roll
      *sliderad
      * floorad
      *expand-banner
      * instream
      * inbanner
      Note: The screen-roll, intext-roll, sliderad and floorad formats are all FreeWheel outstream formats.
      Default value: "instream" | "screen-roll" | `string` | +| `bidfloor` | optional | Bid floor price. | 13.2118 | `float` | +| `bidfloorcur` | optional | Bid floor currency. | "USD" | `string` | +| `vastUrlParams` | optional | Add query parameters to the vast request. Should be a single item level JSON.
      Works with formats: instream, inbanner | { protocolVersion:'3.0' } | `object` | + +When the following params are used with instream or inbanner formats, they should be included in the `vastUrlParams` object. For other formats, they should be included directly in the `params` object: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-------------------------|--------|----------| +| `soundButton` | optional | If enabled, the sound will be off by default and the user will be able to turn it on/off by clicking on a button. (disabled on iOS devices)
      Default value: false | true | `boolean` | +| `defaultMute` | optional | If "soundButton=true" is set, controls if the video will start with the sound muted.
      Default value: true | false | `boolean` | +| `timeline` | optional | Display a progress bar to the bottom of the ad unit.
      Default value: false | true | `boolean` | +| `protocolVersion` | optional | Specify the VAST version that will be used for the vastVersion parameter value on AdsSetup request.
      Default Value: 4.2 | 3 .0 | `float` | +| `onOver` | optional | Allows to enable the sound only when the mouse is over the ad container.
      Works with formats: screen-roll, intext-roll, sliderad, floorad, expand-banner
      Default value: false | true | `boolean` | +| `closeTimeout` | optional | The duration in milliseconds before displaying the close button.
      Works with formats: screen-roll, intext-roll, sliderad, floorad
      Default value: 5000 | 2000 | `integer` | +| `animated` | optional | Enable an animation on opening and on closing of the video.
      Works with formats: intext-roll, sliderad
      Default value: true | false | `boolean` | +| `animationSpeed` | optional | If the animated parameter is set to true, allows to choose the animation speed in milliseconds.
      Works with formats: intext-roll, sliderad
      Default value: 700 | 500 | `integer` | +| `contentId` | optional | Displays the ad inside the content-id dom element (dom id). Requires an 'auto', 'p' or 'article' param.
      Works with format: intext-roll | "element-id" | `string` | +| `auto` | optional | If value is set to "v2", position the intext-roll automatically. If contentId is set, the auto positioning will find a position inside the 'contentId' dom element.
      If contentId is not set, the auto positionaing will search the best position to display the ad based on the page semantic. It will select several possible position and show the intext-roll at the time one of them is made visible.
      Works with format: intext-roll
      Default value: null | "v2" | `string` | +| `article` | optional | Set the location of the ad just after the given article tag in the page (0 is for the first article tag). If content-id is set, the article index is relative to articles inside the 'content-id' dom element | "element-id"
      Works with format: intext-roll | `string` | +| `p` | optional | Set the location of the ad just after the given paragraph tag in the page (0 is for the first p tag). If content-id is set, the p index is relative to paragraphs inside the 'content-id' dom element.
      Works with format: intext-roll | "element-id" | `string` | +| `iframeMode` | optional | Indicate to intext-roll that it is served in a friendly hidden iframe. Can be one of the following:
      *normal - place ad in friendly iframe
      * dfp - place ad in iframe on dfp platform
      Works with format: intext-roll | "normal" | `string` | +| `inRead` | optional | When true, will keep the ad slot window on the page when the ad is done.
      Works with format: intext-roll
      Default value: false | true | `boolean` | +| `lang` | optional | Text language. Can be one of: [fr,en,es,it,de,nl,pt]
      Works with format: intext-roll
      Default value: "fr" | "en" | `string` | +| `openingTime` | optional | The time in milliseconds to display the opening animation.
      Works with format: intext-roll
      Default value: 0 | 100 | `integer` | +| `pauseRatio` | optional | Specify the viewabilityratio where the ad is paused. This can be a float between 0 and 1, or "never" which means never paused. The default value will pause when the ad has less than 50% viewability.
      Works with formats: intext-roll, expand-banner
      Default value: 0.5 | 0.9 | `float` \| `string` | +| `closeAction` | optional | Define what to do for the banner after all ads complete. Can be one of:
      *collapse - will set the target css display property to "none".
      * hide - will leave the target element in place, empty.
      Works with formats: intext-roll, expand-banner
      Default value: “collapse” | "hide" | `string` | +| `domId` | optional | id of the dom element containing the text. If this targeted div is empty, be sure it has the needed width or a width of 0px will be used. Note that the script tag should be added in the page AFTER the targeted dom element so the target will be ready when the script runs.
      Works with formats: intext-roll, expand-banner | "element-id" | `string` | +| `errorAction` | optional | Define what to do for the banner after an ad error. Can be one of:
      *collapse - will set the target css display property to "none".
      * hide - will leave the target element in place, empty.
      Works with formats: intext-roll, expand-banner
      Default value: “collapse” | "hide" | `string` | +| `stickToTop` | optional | Controls if the ad will stick to the top of the browser window. Can be one of the following:
      *true - The ad will stick to the top of the browser window upon scroll.
      * "bottom" - The ad will stick to the top and will be hidden again when reaching the bottom of the page.
      * number - The ad will stick to the top for the given distance in pixels.
      Works with formats: intext-roll, expand-banner | 300 | `boolean \| string \| number` | +| `blurDisplay` | optional | Allow to choose between too blur effects for the sides of the banner. Can be one of:
      *big - will show the blured video only once in the background.
      * duplicate - will show the blured video twice: once for each side.
      Works with format: expand-banner
      Default value: "big" | "duplicate" | `string` | +| `expandDirection` | optional | Allows to force the expansion direction. Can be one of the following:
      *before - Expand to the left if the banner is vertical and to the top if the banner is horizontal.
      * after - Expand to the right if the banner is vertical and to the bottom if the banner is horizontal.
      *center - Expand to left and right if the banner is vertical. Expand to the top and bottom if the banner is horizontal.
      * auto - Expand based on the space available on the page. Expand to the left and/or right if the banner is vertical. and expand to the top and bottom if the banner is horizontal, depending on the space available.
      * none - Banner will not expand
      Works with format: expand-banner
      Default value: "auto" | "before" | `string` | +| `zIndex` | optional | Force the z-index value on the ad container. The default value is around 4100 (see IAB guidelines). Use this parameter if it doesn't fit your needs.
      Works with format: expand-banner
      Default value: ~4100 | 1000 | `integer` | +| `hAlign` | optional | Horizontal side where to display the video. Can be one of:
      *left - horizontal align to the left of the page.
      * middle - horizontal align to the middle of the page.
      * right - horizontal align to the right of the page.
      Works with format: sliderad
      Default value: "right" | "left" | `string` | +| `hSpacing` | optional | Set a horizontal spacing between the hAlign side and the video.
      Works with format: sliderad
      Default value: 10 | 20 | `integer` | +| `vAlign` | optional | Vertical side where to display the video. Can be one of:
      *top - vertical align to the top of the page.
      * middle - vertical align to the middle of the page.
      * bottom - vertical align to the bottom of the page.
      Works with format: sliderad
      Default value: "bottom" | "top" | `string` | +| `vSpacing` | optional | Set a vertical spacing between the vAlign side and the video.
      Works with format: sliderad
      Default value: 10 | 20 | `integer` | +| `mod` | optional | Ad trigger mode. Can be one of:
      *asap - play the ad asap
      * click - play the ad when the user clicks a link
      * scroll - play the ad when the user scrolls
      Works with format: screen-roll
      Default value: "asap" | "click" | `string` | +| `opacity` | optional | Define the opacity of the background. This is a number between 0 (completely transparent) and 1 (totally black).
      Works with format: screen-roll
      Default value: 0.4 | .5 | `float` | +| `smartPlay` | optional | Enable to use autoPlay on mobile devices.
      Works with format: screen-roll
      Default value: false | true | `boolean` | +| `bannerHeight` | optional | The height in pixel of the bottom banner. The video ad takes this height when its not expanded.
      Works with format: floorad
      Default value: 250 | 500 | `integer` | diff --git a/dev-docs/bidders/frvradn.md b/dev-docs/bidders/frvradn.md new file mode 100644 index 0000000000..e6dbf8073b --- /dev/null +++ b/dev-docs/bidders/frvradn.md @@ -0,0 +1,32 @@ +--- +layout: bidder +title: FRVR Ad Network +description: FRVR Ad Network Prebid Bidder Adapter +biddercode: frvradn +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +multiformat_supported: will-bid-on-one +safeframes_ok: true +userIds: all +pbjs: false +pbs: true +pbs_app_supported: true +gvl_id: 1107 +sidebarType: 1 +--- + +### Registration + +FRVR Ad Network Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `publisher_id` | required | Publisher ID | `'11111'` | `string` | +| `ad_unit_id` | required | Ad Unit ID | `'22222'` | `string` | diff --git a/dev-docs/bidders/futureads.md b/dev-docs/bidders/futureads.md index bae56ea0f5..6fe057af2f 100644 --- a/dev-docs/bidders/futureads.md +++ b/dev-docs/bidders/futureads.md @@ -7,13 +7,13 @@ pbs: true biddercode: futureads aliasCode: admixer media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true -fpd_supported: true gvl_id: 511 userIds: AdmixerID prebid_member: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/fyber.md b/dev-docs/bidders/fyber.md index fd28322e7e..002b6e8fad 100644 --- a/dev-docs/bidders/fyber.md +++ b/dev-docs/bidders/fyber.md @@ -5,8 +5,12 @@ description: Prebid Fyber Bidder Adaptor pbjs: true biddercode: fyber media_types: banner +sidebarType: 1 --- +{: .alert.alert-warning :} +Fyber is probably a defunct bidder, as the domain previously registered, inner-active.com, is no-longer-active. + ### Bid Params {: .table .table-bordered .table-striped } @@ -14,4 +18,4 @@ media_types: banner |----------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------| | `appId` | required | The app. ID provided by Inneractive | `'Company_App_OS'` | `string` | | `adSpotType` | required | The ad spot type (`'BANNER'`/`RECTANGLE`) | `'BANNER'` | `string` | -| `customParams` | optional | Allows passing custom parameters in the bid request. See more details at: https://confluence.inner-active.com/display/DevWiki/IA+Adapter+AdUnit+Bidder+Configuration | | `object` | +| `customParams` | optional | Allows passing custom parameters in the bid request. | | `object` | diff --git a/dev-docs/bidders/gambid.md b/dev-docs/bidders/gambid.md index 36dc5ebb3e..1e2eada831 100644 --- a/dev-docs/bidders/gambid.md +++ b/dev-docs/bidders/gambid.md @@ -11,6 +11,7 @@ media_types: banner, video biddercode: gambid aliasCode: gamoshi userIds: id5Id, unifiedId +sidebarType: 1 --- ### Bid params @@ -19,4 +20,3 @@ userIds: id5Id, unifiedId | Name | Scope | Description | Example | Type | |-------------------|----------|---------------------------------------------------------------|----------------------|----------| | `supplyPartnerId` | required | ID of the supply partner | `'12345'` | `string` | - diff --git a/dev-docs/bidders/gamma.md b/dev-docs/bidders/gamma.md index 3935c66e0e..726bf6792a 100644 --- a/dev-docs/bidders/gamma.md +++ b/dev-docs/bidders/gamma.md @@ -6,6 +6,7 @@ pbjs: true pbs: true biddercode: gamma media_types: video +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/gamoshi.md b/dev-docs/bidders/gamoshi.md index 00e23743f9..2b1a874644 100644 --- a/dev-docs/bidders/gamoshi.md +++ b/dev-docs/bidders/gamoshi.md @@ -6,12 +6,13 @@ biddercode: gamoshi pbjs: true pbs: true media_types: banner, video -gdpr_supported: true +tcfeu_supported: true tcf2_supported: true schain_supported: true usp_supported: true userIds: id5Id, unifiedId gvl_id: 644 +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/getintent.md b/dev-docs/bidders/getintent.md index 671ec6fe1f..ad9b2ad204 100644 --- a/dev-docs/bidders/getintent.md +++ b/dev-docs/bidders/getintent.md @@ -6,6 +6,7 @@ pbjs: true biddercode: getintent media_types: video, banner floors_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/giants.md b/dev-docs/bidders/giants.md index 11dbdad564..348e735963 100644 --- a/dev-docs/bidders/giants.md +++ b/dev-docs/bidders/giants.md @@ -5,6 +5,7 @@ description: Prebid IPAX Bidder Adaptor pbjs: true biddercode: giants media_types: video +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/gjirafa.md b/dev-docs/bidders/gjirafa.md index 75dbe78ba6..e0b0a9d7a9 100644 --- a/dev-docs/bidders/gjirafa.md +++ b/dev-docs/bidders/gjirafa.md @@ -5,6 +5,7 @@ description: Prebid Gjirafa Bidder Adaptor pbjs: true biddercode: gjirafa media_types: banner, video +sidebarType: 1 --- diff --git a/dev-docs/bidders/glimpse.md b/dev-docs/bidders/glimpse.md index 0c20c9be85..867ecbaafc 100644 --- a/dev-docs/bidders/glimpse.md +++ b/dev-docs/bidders/glimpse.md @@ -4,37 +4,42 @@ title: Glimpse Protocol description: Glimpse Protocol Bid Adapter biddercode: glimpse pbjs: true -gdpr_supported: true +tcfeu_supported: true +usp_supported: true deals_supported: true media_types: banner gvl_id: 1012 +sidebarType: 1 --- +{: .alert.alert-warning :} +glimpse is probably a defunct bidder, as the glimpseportal.io domain is no longer active. + ## Overview -``` +```text Module Name: Glimpse Protocol Bid Adapter Module Type: Bidder Adapter -Maintainer: publisher@glimpseprotocol.io +Maintainer: support@glimpseportal.io ``` ## Description -This module connects publishers to Glimpse Protocol's demand sources via Prebid.js. Our innovative marketplace protects consumer privacy while allowing precise targeting. +Glimpse protects consumer privacy while allowing precise targeting. This module connects publishers +to Glimpse Protocol's demand sources via Prebid.js. ## Supported Media Types -| Type | Sizes | +{: .table .table-bordered .table-striped } +| Type | Sizes | | -------- | ----------------------------------------- | | `Banner` | 300x250, 300x600, 320x50, 728x90, 970x250 | ## Setup -This section shows how to configure your Prebid.js integration to work with the Glimpse module. - ### Prerequisites -Before you start to configure Glimpse, you will need to build a `prebid.js` file with the Glimpse module included, and include both `gpt.js` and `prebid.js` in the `head` of each page with supply. An example of a typical pair of script tags might be: +Before you start, you will need to build a `prebid.js` file with the Glimpse module included, and include both `gpt.js` and `prebid.js` in the `head` of each page with supply. An example of a typical pair of script tags might be: ```html ``` -### Publisher Registration - -Coming soon. - -### Domain Registration - -Coming soon. - -### Ad Unit Registration - -Coming soon. - ## Configuration ### Bid Requests -Our adapter captures the following values in the `params` block of each bid request: +Our adapter expects the following values in the `params` block of each bid request: -| Name | Scope | Type | Description | Example | -| ------------- | -------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| `placementId` | Required | string | A unique identifier associated with a publisher and ad unit, provided by the Glimpse Publisher Portal when registering a unit | 'glimpse-placement-id' | -| `demand` | Optional | string | Target demand source (defaults to 'glimpse') | 'xandr' | -| `keywords` | Optional | Record | Audience targeting data (applies to the single ad unit) | { sticky: true } | +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example | +| ----- | -------- | ------ | --------------------------------------------------------------------------------------------------- | ---------------------- | +| `pid` | Required | string | A unique identifier representing an ad unit. It is provided by Glimpse when registering an ad unit. | 'glimpse-placement-id' | #### Example @@ -82,11 +74,7 @@ const units = [ { bidder: "glimpse", params: { - placementId: "glimpse-placement-id", - demand: "glimpse", - keywords: { - sticky: true, - }, + pid: "glimpse-placement-id", }, }, ], @@ -96,43 +84,47 @@ const units = [ ### First Party Data -Our adapter captures site and user level data that can be passed to all units using the `ortb2` block, as described [here](https://docs.prebid.org/features/firstPartyData.html). +Our adapter works with first party data providers as described [here](https://docs.prebid.org/features/firstPartyData.html). In this example we add Permutive data to our bidder request using [setBidderConfig](https://docs.prebid.org/features/firstPartyData.html#supplying-bidder-specific-data). #### Example ```javascript pbjs.que.push(() => { - pbjs.setConfig({ - ortb2: { - site: { - keywords: "sports, basketball", - ext: { - data: { - title: "The Premier League", + pbjs.setBidderConfig({ + bidders: ["glimpse"], + config: { + ortb2: { + site: { + keywords: "business,finance,crypto", + ext: { + data: { + permutive: { + pvc: JSON.parse(localStorage.getItem("permutive-pvc")) ?? {}, + }, + }, }, }, - }, - user: { - keywords: "food, takeaway", - ext: { - data: { - firstVisit: true, + user: { + ext: { + data: { + permutive: { + keywords: JSON.parse(localStorage.getItem("_psegs")) ?? [], + enrichers: + JSON.parse( + localStorage.getItem("permutive-data-enrichers") + ) ?? {}, + }, + }, }, }, }, - } + }, }) - - ... }) ``` ## FAQs -### Can I test my setup without a Publisher Portal Account? - -Yes, to test your setup, you can trigger Glimpse to respond with randomly-generated bids for your correctly-configured units by setting `demand: 'demo'` in the `params` of each unit. - ### Can you provide additional support? -Of course! You can check the Glimpse Prebid Adapter documentation, [here](https://docs.glimpseportal.io/en/latest/), or reach out to us at [publisher@glimpseprotocol.io](mailto:publisher@glimpseprotocol.io). +Of course! You can check the Glimpse Prebid Adapter documentation or reach out to us at . diff --git a/dev-docs/bidders/globalsun.md b/dev-docs/bidders/globalsun.md new file mode 100644 index 0000000000..6b3d5c2048 --- /dev/null +++ b/dev-docs/bidders/globalsun.md @@ -0,0 +1,25 @@ +--- +layout: bidder +title: Globalsun +description: Prebid Globalsun Bidder Adapter +biddercode: globalsun +media_types: banner, video, native +pbjs: true +pbs: true +safeframes_ok: true +fpd_supported: false +multiformat_supported: will-not-bid +ortb_blocking_supported: partial +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +--- + +### Prebid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | diff --git a/dev-docs/bidders/glomex.md b/dev-docs/bidders/glomex.md index ef5e580b90..582bb6c0e9 100644 --- a/dev-docs/bidders/glomex.md +++ b/dev-docs/bidders/glomex.md @@ -4,10 +4,12 @@ title: Glomex description: Prebid Glomex Bidder Adapter biddercode: glomex media_types: banner -gdpr_supported: true +gvl_id: 967 +tcfeu_supported: true schain_supported: false prebid_member: false pbjs: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/gmossp.md b/dev-docs/bidders/gmossp.md index 98b20a2ee2..17a15ce3f2 100644 --- a/dev-docs/bidders/gmossp.md +++ b/dev-docs/bidders/gmossp.md @@ -4,7 +4,9 @@ title: GMOSSP description: Prebid GMOSSP Bidder Adaptor pbjs: true biddercode: gmossp +userIds: imuid, sharedId, identityLink media_types: banner +sidebarType: 1 --- diff --git a/dev-docs/bidders/gnet.md b/dev-docs/bidders/gnet.md index 70af8f195d..2a43334992 100644 --- a/dev-docs/bidders/gnet.md +++ b/dev-docs/bidders/gnet.md @@ -4,6 +4,7 @@ title: Gnet description: Prebid Gnet Bidder Adaptor pbjs: true biddercode: gnet +sidebarType: 1 --- ### Bid Params @@ -13,4 +14,3 @@ biddercode: gnet |---------------|----------|--------------------------------------------|-------------------------------------|----------| | `websiteId` | required | The Gnet website ID | `'1'` | `string` | | `adunitId` | required | The Gnet adunit ID | `'1'` | `string` | - diff --git a/dev-docs/bidders/go2net.md b/dev-docs/bidders/go2net.md index f1ce1099d6..c401d7bf49 100644 --- a/dev-docs/bidders/go2net.md +++ b/dev-docs/bidders/go2net.md @@ -6,6 +6,7 @@ pbjs: true biddercode: go2net aliasCode: admixer media_types: video +sidebarType: 1 --- ### bid params diff --git a/dev-docs/bidders/goldbach.md b/dev-docs/bidders/goldbach.md index 6f9b4f7fc5..72ffa4a491 100644 --- a/dev-docs/bidders/goldbach.md +++ b/dev-docs/bidders/goldbach.md @@ -4,29 +4,33 @@ title: Goldbach description: Prebid Goldbach Bidder Adaptor biddercode: goldbach media_types: banner, video, native -gdpr_supported: true +gvl_id: 580 +tcfeu_supported: true prebid_member: true -userIds: criteo, unifiedId, netId, identityLink, flocId, uid2 +userIds: criteo, unifiedId, netId, identityLink, uid2 schain_supported: true coppa_supported: true usp_supported: true -getFloor: true +floors_supported: true pbjs: true -pbs: true +pbs: false +sidebarType: 1 --- ### Table of Contents -- [Bid Params](#godlbach-bid-params) -- [Video Object](#godlbach-video-object) -- [User Object](#godlbach-user-object) -- [App Object](#godlbach-app-object) -- [Custom Targeting keys](#custom-targeting-keys) -- [Passing Keys Without Values](#godlbach-no-value) -- [User Sync in AMP](#godlbach-amp) -- [Debug Auction](#godlbach-debug-auction) +- [Table of Contents](#table-of-contents) + - [Bid Params](#bid-params) + - [Video Object](#video-object) + - [User Object](#user-object) + - [App Object](#app-object) + - [Custom Targeting keys](#custom-targeting-keys) + - [Passing Keys Without Values](#passing-keys-without-values) + - [User Sync in AMP](#user-sync-in-amp) + - [Mobile App Display Manager Version](#mobile-app-display-manager-version) + - [Debug Auction](#debug-auction) - + {: .alert.alert-danger :} All Goldbach (Xandr) placements included in a single call to `requestBids` must belong to the same parent Publisher. If placements from two different publishers are included in the call, the Goldbach bidder will not return any demand for those placements.
      @@ -58,7 +62,7 @@ All Goldbach (Xandr) placements included in a single call to `requestBids` must | `externalImpId` | optional | Specifies the unique identifier of an externally generated auction. | `'bacbab02626452b097f6030b3c89ac05'` | `string` | | `generate_ad_pod_id`| optional | Signal to Goldbach to split impressions by ad pod and add unique ad pod id to each request. Specific to long form video endpoint only. Supported by Prebid Server, not Prebid JS. | `true` | `boolean` | - + #### Video Object @@ -73,8 +77,7 @@ All Goldbach (Xandr) placements included in a single call to `requestBids` must | `playback_method` | A string that sets the playback method supported by the publisher. Allowed values: `"auto_play_sound_on"`; `"auto_play_sound_off"`; `"click_to_play"`; `"mouse_over"`; `"auto_play_sound_unknown"`. | `string` | | `frameworks` | Array of integers listing API frameworks supported by the publisher. Allowed values: None: `0`; VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; MRAID 2.0: `4`; ORMMA: `5`; OMID 1.0 `6`. | `Array` | - - + #### User Object @@ -88,8 +91,7 @@ All Goldbach (Xandr) placements included in a single call to `requestBids` must | `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | | `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | - - + #### App Object @@ -102,13 +104,13 @@ Goldbach supports using prebid within a mobile app's webview. If you are interes | `device_id` | Object that contains the advertising identifiers of the user (`idfa`, `aaid`, `md5udid`, `sha1udid`, or `windowsadid`). | `{ aaid: "38400000-8cf0-11bd-b23e-10b96e40000d" }` | `object` | | `geo` | Object that contains the latitude (`lat`) and longitude (`lng`) of the user. | `{ lat: 40.0964439, lng: -75.3009142 }` | `object` | - + #### Custom Targeting keys Goldbach returns custom keys that can be sent to the adserver through bidderSettings: buyerMemberId, dealPriority, and dealCode. The following snippet demonstrates how to add these custom keys as key-value pairs. -``` +```javascript pbjs.bidderSettings = { godlbach: { adserverTargeting: [ @@ -134,14 +136,13 @@ pbjs.bidderSettings = { } ``` - + #### Passing Keys Without Values It's possible to use the `keywords` parameter to define keys that do not have any associated values. Keys with empty values can be created in Prebid.js and can also be sent through Prebid Server to Goldbach. The following are examples of sending keys with empty values: - -``` +```javascript keywords: { myKeyword: '', myOtherKeyword: [''] @@ -152,20 +153,20 @@ The preceding example passes the key `myKeyword` with an empty value. The key `m You can define keys with values and without values in the same `keywords` definition. In this next example, we've defined the key `color` with an array of values: `red`, `blue`, and `green`. We've followed that with the key `otherKeyword` with an empty value array. -``` +```javascript keywords: { color: ['red', 'blue', 'green'], otherKeyword: [''] } ``` - + #### User Sync in AMP If you are syncing user id's with Prebid Server and are using Goldbach's managed service, see [AMP Implementation Guide cookie-sync instructions](/dev-docs/show-prebid-ads-on-amp-pages.html#user-sync) for details. - + #### Mobile App Display Manager Version @@ -183,9 +184,9 @@ Enabling the Goldbach Debug Auction feature should only be done for diagnosing t To understand what is happening behind the scenes during an auction, you can enable a debug auction by adding an `apn_prebid_debug` cookie with a JSON string. For example: -{% highlight js %} +```javascript { "enabled": true, "dongle": "QWERTY", "debug_timeout": 1000, "member_id": 958 } -{% endhighlight %} +``` To view the results of the debug auction, add the `pbjs_debug=true` query string parameter and open your browser's developer console. @@ -196,4 +197,3 @@ To view the results of the debug auction, add the `pbjs_debug=true` query string | `dongle` | Your account's unique debug password. | `QWERTY` | `string` | | `member_id` | The ID of the member running the debug auction | `958` | `integer` | | `debug_timeout` | The timeout for the debug auction results to be returned | `3000` | `integer` | - diff --git a/dev-docs/bidders/gothamads.md b/dev-docs/bidders/gothamads.md index d41aa86cbd..a85e21c03c 100644 --- a/dev-docs/bidders/gothamads.md +++ b/dev-docs/bidders/gothamads.md @@ -3,7 +3,7 @@ layout: bidder title: gothamads description: Prebid gothamads Bidder Adaptor biddercode: gothamads -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true ccpa_supported: true @@ -12,16 +12,24 @@ media_types: banner, video, native safeframes_ok: true deals_supported: true pbjs: true +pbs: true +sidebarType: 1 +floors_supported: true +prebid_member: false +fpd_supported: false +gvl_id: none +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +userIds: all --- -### Note: - -The Example Bidding adapter requires setup before beginning. Please contact us at support@gothamads.com +### Note +Gothamads will bid only on first impresion in bid request. +The Example Bidding adapter requires setup before beginning. Please contact us at ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | placement id | `'qdasx'` | `string` | -| `accountId` | required | account id | `'asffw1'` | `string` | +| `accountId` | required | account id | `'hash'` | `string` | diff --git a/dev-docs/bidders/gourmetads.md b/dev-docs/bidders/gourmetads.md index e6909c8d34..cfe9df0ee2 100644 --- a/dev-docs/bidders/gourmetads.md +++ b/dev-docs/bidders/gourmetads.md @@ -5,6 +5,7 @@ description: Prebid Gourmet Ads Bidder Adaptor pbjs: true biddercode: gourmetads aliasCode : appnexus +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/greedygame.md b/dev-docs/bidders/greedygame.md new file mode 100644 index 0000000000..63f1167308 --- /dev/null +++ b/dev-docs/bidders/greedygame.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: GreedyGame +description: Prebid GreedyGame Bidder Adaptor +biddercode: greedygame +pbjs: false +pbs: true +media_types: banner, video, audio, native +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Note + +The GreedyGame Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:----------------------|:-----------------------|:----------| +| `host` | required | Ad network's RTB host | `'rtb-greedygame.com'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | diff --git a/dev-docs/bidders/grid.md b/dev-docs/bidders/grid.md index 1f6a3db4ff..c74e1876c6 100644 --- a/dev-docs/bidders/grid.md +++ b/dev-docs/bidders/grid.md @@ -5,17 +5,30 @@ description: Prebid TheMediaGrid Bidder Adaptor pbjs: true pbs: true biddercode: grid -media_types: banner, video -gdpr_supported: true +media_types: banner, video, native (s2s only) +multiformat_supported: will-bid-on-any +gvl_id: 686 +tcfeu_supported: true usp_supported: true +gpp_supported: true schain_supported: true floors_supported: true userIds: all tcf2_supported: true coppa_supported: true fpd_supported: true +sidebarType: 1 --- +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [Bidder Config](#bidder-config) +- [First Party Data](#first-party-data) +- [Native setup example (s2s only)](#native-setup-example-s2s-only) + + ### Bid Params @@ -23,14 +36,15 @@ fpd_supported: true | Name | Scope | Description | Example | Type | |----------------|----------|-------------------------------------------------------------------------------------------------------------|-------------------------------------------|-----------| | `uid` | required | Represents the MediaGrid bidder system Ad Slot ID associated with the respective div id from the site page. | `1` | `integer` | -| `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | | `bidFloor` | optional | Floor of the impression opportunity. If present in the request overrides XML info. | `0.8` | `float` | + -###Bidder Config +### Bidder Config You can allow writing in localStorage `pbjs.setBidderConfig` for the bidder `grid` -``` + +```javascript pbjs.setBidderConfig({ bidders: ["grid"], config: { @@ -38,4 +52,70 @@ pbjs.setBidderConfig({ } }) ``` + If it will be "true" this allow TheMediaGrid Bid Adapter to write userId in first party localStorage + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.ext.device`: Non standard arbitrary user device +- `ortb2.user.keywords`: Standard IAB OpenRTB 2.5 user.keywords field. It will be included in ext.keywords.user.ortb2 +- `ortb2.site.keywords`: Standard IAB OpenRTB 2.5 site.keywords field. It will be included in ext.keywords.site.ortb2 +- `ortb2.site.cat[]`: Standard IAB OpenRTB 2.5 site.cat field. It will be sent as part of site.cat array +- `ortb2.site.pagecat[]`: Standard IAB OpenRTB 2.5 site.pagecat field. It will be sent as part of site.cat array +- `ortb2.site.content.genre`: Standard IAB OpenRTB 2.5 site.content.genre field + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` +- `ortb2.imp[].instl` + + + +### Native setup example (s2s only) + +Setup native in adUnit mediaTypes, for example: + +```javascript +... +mediaTypes: { + native: { + ortb: { + ver: '1.2', + "assets": [ + { + "id": 1, + "img": { + "hmin": 180, + "wmin": 216, + "type": 3 + }, + "required": 1 + }, + { + "title": { + "len": 140 + }, + "id": 2, + "required": 1 + }, + { + "id": 3, + "data": { + "len": 25, + "type": 1 + }, + "required": 1 + } + ], + } + } +}, +... +``` diff --git a/dev-docs/bidders/gridNM.md b/dev-docs/bidders/gridNM.md index fc92e91a17..49224f42d2 100644 --- a/dev-docs/bidders/gridNM.md +++ b/dev-docs/bidders/gridNM.md @@ -5,9 +5,10 @@ description: Prebid TheMediaGridNM Bidder Adapter pbjs: true biddercode: gridNM media_types: video -gdpr_supported: true +tcfeu_supported: false usp_supported: true fpd_supported: true +sidebarType: 1 --- @@ -22,8 +23,8 @@ fpd_supported: true | `pubdata` | optional | publisher data, will be used by JW Player to pass their info | `{"jwpseg" : ["1111", "2222"]})` | `object` | | `floorcpm` | optional | floor cpm | `0.56` | `float` | | `video` | optional | video parameters which should be passed for no-mapping approach | | `object` | -| `video.mimes` | optional | Content MIME types supported | `['video/mp4', 'video/x-ms-wmv']` | `string array` | -| `video.mind` | optional | Minimum video ad duration in seconds. | `1` | `integer` | +| `video.mimes` | optional | Content MIME types supported | `['video/mp4', 'video/x-ms-wmv']` | `string array` | +| `video.mind` | optional | Minimum video ad duration in seconds. | `1` | `integer` | | `video.maxd` | optional | Maximum video ad duration in seconds | `60` | `int` | | `video.protocols` | optional | Array of supported video protocols | `[1,2,3,4,5,6]` | `integer array` | | `video.size` | optional | player size wxh | `'300x250'` | `string` | @@ -35,3 +36,9 @@ fpd_supported: true | `video.startdelay` | optional | Indicates the start delay in seconds | `0` | `int` | | `video.placement` | optional | Placement type for the impression. | `1` | `int` | | `video.playbackmethod` | optional | Playback methods that may be in use | `[1]` | `integer array` | + +### First Party Data + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` diff --git a/dev-docs/bidders/groupm.md b/dev-docs/bidders/groupm.md deleted file mode 100644 index dc9cd2df8e..0000000000 --- a/dev-docs/bidders/groupm.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -layout: bidder -title: GroupM -description: Prebid GroupM Bidder Adaptor -biddercode: groupm -aliasCode: pubmatic -media_types: banner, video, native -gdpr_supported: true -usp_supported: true -coppa_supported: true -schain_supported: true -floors_supported: true -userIds: all -prebid_member: true -safeframes_ok: true -pbjs: true -pbs: true -pbs_app_supported: true -fpd_supported: true -gvl_id: 98 ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------|------------------------------|----------| -| `publisherId` | required | Publisher ID | `'32572'` | `string` | -| `adSlot` | optional | Ad Slot Name (see below)| `'38519891'` | `string` | -| `pmzoneid` | optional | Zone ID | `'zone1,zone2'` | `string` | -| `lat` | optional | Latitude | `'40.712775'` | `string` | -| `lon` | optional | Longitude | `'-74.005973'` | `string` | -| `yob` | optional | Year of Birth | `'1982'` | `string` | -| `gender` | optional | Gender | `'M'` | `string` | -| `kadpageurl` | optional | Overrides Page URL | `'http://www.yahoo.com/'`| `string` | -| `kadfloor` | optional | Bid Floor | `'1.75'` | `string` | -| `currency` | optional | Bid currency | `'AUD'` (Value configured only in the 1st adunit will be passed on.
      Values if present in subsequent adunits, will be ignored.) | `string` | -| `dctr` | optional | Deal Custom Targeting
      (Value configured only in the 1st adunit will be passed on.
      Values if present in subsequent adunits, will be ignored.) | `'key1=123\|key2=345'` | `string` | -| `bcat` | optional | Blocked IAB Categories
      (Values from all slots will be combined and only unique values will be passed. An array of strings only. Each category should be a string of a length of more than 3 characters.) | `[ 'IAB1-5', 'IAB1-6', 'IAB1-7' ]` | `array of strings` | -| `deals` | optional | PMP deals
      (Values from each slot will be passed per slot. An array of strings only. Each deal-id should be a string of a length of more than 3 characters.) | `[ 'deal-id-5', 'deal-id-6', 'deal-id-7' ]` | `array of strings` | -| `outstreamAU` | optional | Oustream AdUnit described in Blue BillyWig UI. This field is mandatory if mimeType is described as video and context is outstream (i.e., for outstream videos) | `'renderer_test_groupm'` | `string` | - -GroupM is an aliased bidder of PubMatic - -### Prebid Server Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------|------------------------------|----------| -| `publisherId` | required | Publisher ID | `"32572"` | `string` | -| `adSlot` | optional | Ad Slot Name | `"38519891"` | `string` | -| `pmzoneid` | optional | Comma separated zone id. Used im deal targeting & site section targeting. e.g drama,sport| `"zone1,zone2"` | `string` | -| `dctr` | optional | Deal Custom Targeting, pipe separated key-value pairs| `"key1=123\|key2=345"` | `string` | -| `wrapper` | optional | Specifies GroupM openwrap configuration for a publisher | `"wrapper": { "profile": 123, "version": 1}` | `object` | -| `keywords` | optional | A set of key-value pairs; A key can have one or more values associated with it. They are used in buy-side segment targeting.| `"keywords": { "genre": ["rock", "pop"] }` | `object` | - - - -### Prebid Server Test Request - -The following test parameters can be used to verify that Prebid Server is working properly with the -GroupM adapter. This example includes an `imp` object with an GroupM test publisher ID, ad slot, -and sizes that would match with the test creative. - -``` -"imp":[ - { - "id":“"some-impression-id”, - "banner":{ - "format":[ - { - "w":300, - "h":250 - }, - { - "w":300, - "h":600 - } - ] - }, - "ext":{ - "groupm":{ - "publisherId":“156276”, - "adSlot":"groupm_test" - } - } - } - ] -``` diff --git a/dev-docs/bidders/growads.md b/dev-docs/bidders/growads.md index 8f7c295ad4..6c546e04d8 100644 --- a/dev-docs/bidders/growads.md +++ b/dev-docs/bidders/growads.md @@ -5,6 +5,7 @@ description: Prebid GrowAdvertising Bidder Adapter pbjs: true biddercode: growads media_types: banner, native +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/gumgum.md b/dev-docs/bidders/gumgum.md index c655f75fd9..11d1694e87 100644 --- a/dev-docs/bidders/gumgum.md +++ b/dev-docs/bidders/gumgum.md @@ -10,21 +10,22 @@ media_types: banner, video schain_supported: true floors_supported: true userIds: unifiedId, identityLink -gdpr_supported: true +gvl_id: 61 +tcfeu_supported: true usp_supported: true -fpd_supported: true +gpp_supported: true +sidebarType: 1 --- -### Note: +### Note The GumGum Header Bidding adaptor requires setup and approval from the GumGum team. Please reach out to your account manager or for more information. - Client side and server side parameters differ slightly. For Server side (Prebid S2S) implementation, - we currently accept the `zone` parameter. For Client side (Prebid.js) implementation, we accept `zone` and - a long list of other parameters which are listed below. + we currently accept the `zone` parameter. For Client side (Prebid.js) implementation, we accept `zone` and + a long list of other parameters which are listed below. ### Server Side Bid Params @@ -35,6 +36,7 @@ Client side and server side parameters differ slightly. For Server side (Prebid | `pubId` | required for all bid requests tracking multiple domains or sites | Publisher ID | `123` | `integer` | | `irisid` | optional | Iris.tv ID | `'iris_6f9285823a4'` | `string` | | `slot` | optional | Placement ID | `40` | `number` | +| `product` | required for new supported products like 'skins' | Product Type | `skins` | `string` | ### Client Side Bid Params @@ -44,6 +46,7 @@ Client side and server side parameters differ slightly. For Server side (Prebid | `zone` | required for all bid requests tracking a single domain or site | Tracking ID | `'ggumtest'` | `string` | | `pubId` | required for all bid requests tracking multiple domains or sites | Publisher ID | `123` | `integer` | | `slot` | required for slot placement only | Slot ID | `9` | `integer` | +| `product` | required for new supported products like 'skins' | Product Type | `skins` | `string` | | `iriscat` | optional | Iris.tv segments | `'segment1,segment2'` | `string` | | `irisid` | optional | Iris.tv ID | `'123'` | `string` | | `bidfloor` | optional | CPM bidfloor in USD | `0.03` | `float` | @@ -62,12 +65,13 @@ Client side and server side parameters differ slightly. For Server side (Prebid | `ICV` | required for ICV placement only | ICV ID | `19` | `integer` | | `bidfloor` | optional | CPM bidfloor in USD | `0.03` | `float` | -Please note that both video and in-video products require a mediaType of video while all other products +Please note that both video and in-video products require a mediaType of video while all other products require a mediaType of banner. ### Client Side Examples + Client side integration currently supports slot, in-screen, video, and in-video products. -The following examples are based on the 'Client Side Bid Params' table. +The following examples are based on the 'Client Side Bid Params' table. All bid requests require a zone or pubId parameter: { @@ -87,6 +91,7 @@ To enable ad requests at a publisher level, instead of `zone` use `pubId`: } #### In-Screen + To enable ad requests for in-screen, either `zone` or `pubId` must be present in the params object: { @@ -96,7 +101,20 @@ To enable ad requests for in-screen, either `zone` or `pubId` must be present in } } +#### Skins + +Skins ad requests require the `product` parameter with the value of `skins` in the params object: + + { + bidder: 'gumgum', + params: { + zone: 'zone_id', // provided by GumGum + product: 'skins' + } + } + #### Slot + Slot ad requests require the `slot` parameter in the params object: { @@ -108,6 +126,7 @@ Slot ad requests require the `slot` parameter in the params object: } #### Video and In-Video + For video and in-video products, please follow the configuration shown under the in-screen example. Additionally, you will need to define a 'video' field in the 'mediaTypes' object. For example: @@ -118,7 +137,7 @@ Additionally, you will need to define a 'video' field in the 'mediaTypes' object playerSize: [640, 480], minduration: 1, maxduration: 2, - linearity: 1, // ** Change this to 2 for in-video + linearity: 1, // ** Change this to 2 for in-video startdelay: 1, placement: 1, protocols: [1, 2] @@ -126,17 +145,17 @@ Additionally, you will need to define a 'video' field in the 'mediaTypes' object } } -Please note: +Please note: All fields under video (context, playerSize, minDuration etc) are the minimum requirements to make a video ad request. -You should replace playerSize, minduration, maxduration, startdelay, placement, and protocols values to your -specifications (see [OpenRTB spec 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for more information). +You should replace playerSize, minduration, maxduration, startdelay, placement, and protocols values to your +specifications (see [OpenRTB spec 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for more information). `linearity` should be set to 1 for video product, and 2 for in-video. - ### Server Side Examples + At the moment, the only products supported via Prebid S2S are slot, in-screen, and video. -The configuration is similar to client side configuration. +The configuration is similar to client side configuration. Add the following object in your `bids` array: { @@ -147,8 +166,9 @@ Add the following object in your `bids` array: } #### Slot -The mediaTypes field should have ‘banner’ with sizes using standard IAB display sizes (as seen in the example below). -The zone id is provided by GumGum. + +The mediaTypes field should have ‘banner’ with sizes using standard IAB display sizes (as seen in the example below). +The zone id is provided by GumGum. { mediaTypes: { @@ -167,9 +187,10 @@ The zone id is provided by GumGum. } #### In-Screen -The adUnits settings for both in-screen and slot have a similar structure. The only difference between slot -and in-screen ad unit configuration is the sizes. -In-screen products require a non-standard IAB display size (e.g. [1, 1] as seen in the example below or any + +The adUnits settings for both in-screen and slot have a similar structure. The only difference between slot +and in-screen ad unit configuration is the sizes. +In-screen products require a non-standard IAB display size (e.g. [1, 1] as seen in the example below or any other size you choose). { @@ -188,7 +209,24 @@ other size you choose). ] } +#### Skins + +The skins product requires a similar setup to its client side header bidding counterpart: + + { + bids: [ + { + bidder: 'gumgum', + params: { + zone: 'zone_id', // provided by GumGum + product: 'skins' + } + }, + ] + } + #### Video + The video product requires nearly the same setup as with Prebid client side header bidding: { @@ -217,7 +255,6 @@ The video product requires nearly the same setup as with Prebid client side head ] } -All fields under video (context, playerSize, minDuration etc) are the minimum requirements -to make a video ad request. Please replace playerSize, w, h, mimes, minduration, maxduration, +All fields under video (context, playerSize, minDuration etc) are the minimum requirements +to make a video ad request. Please replace playerSize, w, h, mimes, minduration, maxduration, startdelay, and protocols values to your specifications (see [OpenRTB spec 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for more information). - diff --git a/dev-docs/bidders/gxone.md b/dev-docs/bidders/gxone.md index dc7af55820..7257cbfcc4 100644 --- a/dev-docs/bidders/gxone.md +++ b/dev-docs/bidders/gxone.md @@ -4,6 +4,7 @@ title: GXOne description: GXOne Bidder Adapter pbjs: true biddercode: gxone +sidebarType: 1 --- diff --git a/dev-docs/bidders/h12media.md b/dev-docs/bidders/h12media.md index 46531323fd..ec95a4a3c0 100644 --- a/dev-docs/bidders/h12media.md +++ b/dev-docs/bidders/h12media.md @@ -5,9 +5,10 @@ description: Prebid H12 Media Bidder Adaptor pbjs: true biddercode: h12media media_types: banner -gdpr_supported: true +tcfeu_supported: false usp_supported: true userIds: all +sidebarType: 1 --- @@ -25,7 +26,7 @@ userIds: all Example: -``` bash +```javascript { bidder: "h12media", params: { diff --git a/dev-docs/bidders/haxmedia.md b/dev-docs/bidders/haxmedia.md deleted file mode 100644 index 096d358667..0000000000 --- a/dev-docs/bidders/haxmedia.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: bidder -title: Haxmedia -description: Prebid Haxmedia Bidder Adapter -biddercode: haxmedia -usp_supported: true -schain_supported: true -media_types: banner, video, native -gdpr: true -pbjs: true -pbs: false -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Prebid.JS Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|----------------------------------------------------------|------------|-----------| -| `placementId` | required | Placement Id will be generated on Haxmedia Platform. | `'0'` | `string` | diff --git a/dev-docs/bidders/headbidder.md b/dev-docs/bidders/headbidder.md new file mode 100644 index 0000000000..aa5c3bae00 --- /dev/null +++ b/dev-docs/bidders/headbidder.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Headbidder.net +description: Headbidder.net Bidder Adaptor +biddercode: headbidder +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Headbidder.net bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.fmlabsonline.com'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/headbidding.md b/dev-docs/bidders/headbidding.md index bcdab3d642..089558ca8d 100644 --- a/dev-docs/bidders/headbidding.md +++ b/dev-docs/bidders/headbidding.md @@ -7,12 +7,24 @@ top_nav_section: dev_docs nav_section: reference pbjs: true - +pbs: false biddercode: headbidding - +media_types: banner, native, video +gvl_id: 14 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true aliasCode : adkernel - - +sidebarType: 1 --- @@ -21,7 +33,7 @@ aliasCode : adkernel {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------|----------|-------------|---------|----------| -| `zoneId` | required | | | `string` | +| `zoneId` | required | | | `integer` | | `host` | required | | | `string` | Head Bidding is an aliased bidder for AdKernel diff --git a/dev-docs/bidders/holid.md b/dev-docs/bidders/holid.md new file mode 100644 index 0000000000..8edde7773d --- /dev/null +++ b/dev-docs/bidders/holid.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: Holid +description: Prebid Holid Bidder Adapter +biddercode: holid +pbjs: true +media_types: banner +gvl_id: 1177 +tcfeu_supported: true +usp_supported: true +prebid_member: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ---------- | -------- | ---------------------------- | --------- | -------- | +| `adUnitID` | required | Ad Unit ID provided by Holid | `'12345'` | `string` | + +### Configuration + +To increase the match rate and monetization, Holid recommends turning on iframe-based user sync. + +```javascript +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: '*', // '*' means all bidders + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/houseofpubs.md b/dev-docs/bidders/houseofpubs.md index fa8fd70c61..c90ce59021 100644 --- a/dev-docs/bidders/houseofpubs.md +++ b/dev-docs/bidders/houseofpubs.md @@ -2,19 +2,30 @@ layout: bidder title: HouseOfPubs description: House of Pubs Bid Adapter -pbjs: true biddercode: houseofpubs +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true schain_supported: true -aliasCode : adkernel +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: - -Please contact info@houseofpubs.com for any questions or for information about our Prebid program. +### Note +Please contact for any questions or for information about our Prebid program. ### Bid Params @@ -22,4 +33,4 @@ Please contact info@houseofpubs.com for any questions or for information about o | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Our Host | `'cpm.houseofpubs.com'` | `string` | -| `zoneId` | required | Example RTB zone id | `'12345'` | `string` | +| `zoneId` | required | Example RTB zone id | `12345` | `integer` | diff --git a/dev-docs/bidders/hpmdnetwork.md b/dev-docs/bidders/hpmdnetwork.md deleted file mode 100644 index b1557dc4fc..0000000000 --- a/dev-docs/bidders/hpmdnetwork.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: bidder -title: HPMD Network -description: Prebid HPMD Network Bidder Adaptor -pbjs: true -biddercode: hpmdnetwork -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -Note: -The HPMD Network adapter requires setup and approval beforehand. -For more information, visit [HPMD Network website](https://www.hpmdnetwork.ru/publishers). - -### Bid parameters - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|-----------|----------------------------------------------------------|--------------------|------------------| -| `placementId` | required | The slot ID from HPMD Network. | `'2362'` | `string` | diff --git a/dev-docs/bidders/huaweiads.md b/dev-docs/bidders/huaweiads.md index 1211990c2b..17c8cb7054 100644 --- a/dev-docs/bidders/huaweiads.md +++ b/dev-docs/bidders/huaweiads.md @@ -5,22 +5,20 @@ description: Prebid HuaweiAds Bidder Adapter biddercode: huaweiads gvl_id: 856 media_types: banner, video, native +tcfeu_supported: true +coppa_supported: true safeframes_ok: false deals_supported: true pbjs: false pbs: true pbs_app_supported: true prebid_member: false +sidebarType: 1 --- -### Note: +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at hwads@huawei.com. -1. The following parameters need to be registered on the HuaweiAds platform, and at the same time, the permission to access the server interface needs to be opened on the HuaweiAds platform. -2. You can find ( publisherid, signkey, keyid ) on the platform after registration. -3. You need to create your advertising creative on the platform and get the corresponding ( slotid, adtype ). -4. We need OAID, GAID, IMEI (One must not be empty, you can collect OAID first, or use GAID) in our request, so when using prebidmobile, please add something like "TargetingParams.addUserData("oaid", "oaid-test") TargetingParams.addUserData("gaid", "gaid-test") TargetingParams.addUserData("imei", "imei-test")". -5. You can also send the clientTime to the HuaweiAds Adx server, like "TargetingParams.addUserData("clientTime", "2018-11-02 16:34:07.981+0800")". if not, it will use the prebid server time and zone. +The Huawei Bidding adapter requires setup and approval before implementation. Please contact us at [developereu@huawei.com](mailto:developereu@huawei.com), also you can [submit a ticket online](https://developer.huawei.com/consumer/en/support/feedback/#/). ### Bid Params @@ -31,4 +29,32 @@ The Example Bidding adapter requires setup before beginning. Please contact us a | `signkey` | required | Sign Key | `'5d********82c38594f8b2bdfd9f********a398dca734932898e3********8d'` | `string` | | `keyid` | required | Key Id | `'2'` | `string` | | `slotid` | required | Slot Id | `'u42ohmaufh'` | `string` | -| `adtype` | required | Ad Type | `'native'` | `string` | +| `adtype` | required | Ad Type | `'banner','native','interstitial','rewarded'` | `string` | + +Notes: + +1. The following parameters need to be registered on the HuaweiAds platform, and at the same time, the permission to access the server interface needs to be opened on the HuaweiAds platform. +2. You can find publisherid, signkey, and keyid on the platform after registration. +3. You need to create your advertising creative on the platform and get the corresponding slotid and adtype. +4. We require OAID (Open Advertising ID) or GAID (Google Advertising ID) in the request. OAID and GAID are non-permanent device identifiers that allow personalized ads to be served to users while protecting user data privacy. In most cases, OAID is used for HMS phones and GAID is used for GMS phones. GAID is collected by default. For OAID on HMS phones, app developers should call the AdvertisingIdClient.getAdvertisingIdInfo(mContext) method to [obtain the OAID](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/identifier-service-obtaining-oaid-sdk-0000001050064988), then add the OAID to the request using the Prebid SDK as shown below. +5. The auction will use the Prebid Server time zone, but this can be by developers if they send the `clientTime` targeting parameter to the HuaweiAds Adx server using the Prebid SDK. For example: `TargetingParams.addUserData("clientTime", "2018-11-02 16:34:07.981+0800")`. + +### Obtain the OAID + +```java +// Add the OAID to user data in prebid initialization +if ( isHmsAvailable() ) { + TargetingParams.addUserData("oaid", AdvertisingIdClient.Info info = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext()).getId()); +} + +//Determine the HMS availability +public static boolean isHmsAvailable(Context context) { + boolean isAvailable = false; + if (null != context) { + int result = HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context); + isAvailable = (com.huawei.hms.api.ConnectionResult.SUCCESS == result); + } + Log.i(TAG, "isHmsAvailable: " + isAvailable); + return isAvailable; +} +``` diff --git a/dev-docs/bidders/huddledmasses.md b/dev-docs/bidders/huddledmasses.md index a316719916..93dabba956 100644 --- a/dev-docs/bidders/huddledmasses.md +++ b/dev-docs/bidders/huddledmasses.md @@ -4,6 +4,7 @@ title: Huddled Masses description: Prebid Huddled Masses Bidder Adaptor pbjs: true biddercode: huddledmasses +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/hybrid.md b/dev-docs/bidders/hybrid.md index 462fb58a13..0200561076 100644 --- a/dev-docs/bidders/hybrid.md +++ b/dev-docs/bidders/hybrid.md @@ -5,7 +5,8 @@ description: Prebid Hybrid.ai Bidder Adapter pbjs: true media_types: banner, video biddercode: hybrid -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Note @@ -14,16 +15,14 @@ You can use this adapter to get a bid from Hybrid.ai Please reach out to your Hybrid.ai account team before using this plugin to get placeId. The code below returns a demo ad. - ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------------|------------------------|-------------------------------------------------------------------|--------------------------------------|----------| -| `placeId` | required | The place id. | '5af45ad34d506ee7acad0c26' | `string` | -| `placement` | required | Adunit placement, possible values: banner, video, inImage | 'banner' | `string` | -| `imageUrl` | required for inImage | URL of the image on which the banner will be displayed | 'https://hybrid.ai/images/image.jpg' | `string` | - +| Name | Scope | Description | Example | Type | +|---------------------|------------------------|-------------------------------------------------------------------|----------------------------------------|----------| +| `placeId` | required | The place id. | '5af45ad34d506ee7acad0c26' | `string` | +| `placement` | required | Adunit placement, possible values: banner, video, inImage | 'banner' | `string` | +| `imageUrl` | required for inImage | URL of the image on which the banner will be displayed | `'https://hybrid.ai/images/image.jpg'` | `string` | ### Sample Banner Ad Unit @@ -93,10 +92,10 @@ var adUnits = [{ - - Prebid.js Banner Example - - - + + Prebid.js Banner Example + + + + -

      Prebid.js Banner Ad Unit Test

      -
      - - -
      +

      Prebid.js Banner Ad Unit Test

      +
      + + +
      ``` diff --git a/dev-docs/bidders/hypelab.md b/dev-docs/bidders/hypelab.md new file mode 100644 index 0000000000..c94f8f9d50 --- /dev/null +++ b/dev-docs/bidders/hypelab.md @@ -0,0 +1,53 @@ +--- +layout: bidder +title: HypeLab +description: Prebid HypeLab Bidder Adapter +pbjs: true +pbs: false +biddercode: hypelab +sidebarType: 1 +media_types: banner +userIds: all +safeframes_ok: false +floors_supported: false +fpd_supported: false +ortb_blocking_supported: false +--- + +### Registration + +The HypeLab adapter requires setup and approval from the HypeLab team. Please reach out to your account manager for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------|---------|----------| +| `property_slug` | required | The property slug | `prebid` | `string` | +| `placement_slug` | required | The placement slug | `test_placement` | `string` | + + +### Example Banner Configuration + +```js +var adUnits = [ + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[728, 90]], + }, + }, + bids: [ + { + bidder: 'hypelab', + params: { + property_slug: 'prebid', + placement_slug: 'test_placement' + } + } + ] + } +] +``` + diff --git a/dev-docs/bidders/ias.md b/dev-docs/bidders/ias.md index c9e88f4860..7827450b1c 100644 --- a/dev-docs/bidders/ias.md +++ b/dev-docs/bidders/ias.md @@ -4,12 +4,12 @@ title: Integral Ad Science (IAS) description: Prebid Integral Ad Science Bidder Adaptor pbjs: true biddercode: ias -pbjs_version_notes: for 5.x, use the module +sidebarType: 1 --- -### Note: +### Note -This module is an integration with prebid.js with an IAS product, pet.js. It is not a bidder per se but works in a similar way: retrieve data that publishers might be interested in setting keyword targeting, like predicted viewability and brand safety words. Please reach out to your account manager or check out [our publisher solutions](https://integralads.com/solutions/publishers/) for more +This module is an integration with prebid.js with an IAS product, pet.js. It is not a bidder per se but works in a similar way: retrieve data that publishers might be interested in setting keyword targeting, like predicted viewability and brand safety words. Please reach out to your account manager or check out [our publisher solutions](https://integralads.com/who-we-help/publishers/) for more information. ### Bid Params diff --git a/dev-docs/bidders/idx.md b/dev-docs/bidders/idx.md new file mode 100644 index 0000000000..99c238e2a1 --- /dev/null +++ b/dev-docs/bidders/idx.md @@ -0,0 +1,26 @@ +--- +layout: bidder +title: IDX bidder adapter +description: Prebid IDX Bidder Adapter +biddercode: idx +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +media_types: banner +safeframes_ok: true +deals_supported: false +floors_supported: false +fpd_supported: false +pbjs: false +pbs: false +prebid_member: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| diff --git a/dev-docs/bidders/iionads.md b/dev-docs/bidders/iionads.md new file mode 100644 index 0000000000..7f9b957c60 --- /dev/null +++ b/dev-docs/bidders/iionads.md @@ -0,0 +1,41 @@ +--- +layout: bidder +title: iion +description: iion Bidder Adaptor +biddercode: iionads +pbjs: true +pbs: true +media_types: video, banner +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:--------------------------------------------------|:----------------|:----------| +| `host` | required | Ad network's RTB host | `'iionads.com'` | `string` | +| `adUnitId` | required | Ad Unit Id will be generated on iionads Platform. | `42` | `integer` | +| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` | `string` | +| `publisherId` | required | Publisher ID | `'12345'` | `string` | +| `custom1` | optional | Custom targeting field 1 | `'custom1'` | `string` | +| `custom2` | optional | Custom targeting field 2 | `'custom2'` | `string` | +| `custom3` | optional | Custom targeting field 3 | `'custom3'` | `string` | +| `custom4` | optional | Custom targeting field 4 | `'custom4'` | `string` | +| `custom5` | optional | Custom targeting field 5 | `'custom5'` | `string` | + +iionads server-side Prebid Server adapter requires only `publisherId` and `host` parameters. But iionads client-side Prebid.js adapter requires only `host`, `adUnitId`, `adUnitType`. + +iionads server-side Prebid Server adapter supports only `banner`, `video`, `audio`, `native` media types. But iionads client-side Prebid.js adapter supports only `banner` and `video` media types, doesn't support `audio` and `native`. diff --git a/dev-docs/bidders/illumin.md b/dev-docs/bidders/illumin.md new file mode 100644 index 0000000000..9d67a10c8a --- /dev/null +++ b/dev-docs/bidders/illumin.md @@ -0,0 +1,70 @@ +--- +layout: bidder +title: Illumin +description: Prebid Illumin Bidder Adaptor +biddercode: illumin +filename: illuminBidAdapter +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +gpp_supported: true +floors_supported: true +media_types: banner, video +prebid_member: false +safeframes_ok: false +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|-------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from Illumin. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from Illumin. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | optional | The minimum bid value desired. Illumin will not respond with bids lower than this value. | `0.90` | `float` | + +## Example + + ```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'illumin', + params: { + cId: '562524b21b1c1f08117fc7f9', // Required - PROVIDED DURING SETUP... + pId: '59ac17c192832d0011283fe3', // Required - PROVIDED DURING SETUP... + bidFloor: 1.23 // Optional + } + }] + } +]; + +// configure pbjs to enable user syncing +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: 'illumin', + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/imds.md b/dev-docs/bidders/imds.md new file mode 100644 index 0000000000..f526d56702 --- /dev/null +++ b/dev-docs/bidders/imds.md @@ -0,0 +1,105 @@ +--- +layout: bidder +title: iMedia Digital Services (iMDS) +description: Prebid iMedia Digital Services Bidder (iMDS) Adapter +pbjs: true +pbs: true +biddercode: imds +tcfeu_supported: false +usp_supported: true +userIds: all +media_types: banner, video +coppa_supported: false +gpp_supported: true +schain_supported: true +dchain_supported: false +safeframes_ok: true +pbs_app_supported: true +deals_supported: false +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-any +prebid_member: false +gvl_id: none +sidebarType: 1 +--- + +### Note + +The iMedia Digital Services bidder adapter requires setup and approval from iMedia Digital Services. Please reach out to your account manager for more information and to start using it. + +### Configuration + +iMedia Digital Services requires that `iframe` is used for user syncing. + +Example configuration: + +```javascript +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: '*', // represents all bidders + filter: 'include' + } + } + } +}); +``` + +### DFP Video Creative +To use video, setup a `VAST redirect` creative within Google Ad Manager with the following VAST tag URL: + +If using the new `imds` adapter with x8.x or later: + +```text +https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_uuid_imds%%&AUCTION_PRICE=%%PATTERN:hb_pb_imds%% +``` + +If using the legacy `synacormedia` adapter with v7.x or earlier: + +```text +https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_uuid_synacormedia%%&AUCTION_PRICE=%%PATTERN:hb_pb_synacormedia%% +``` + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ---- | ----- | ----------- | ------- | ---- | +| `seatId` | required | The seat ID from iMedia Digital Services. This will be the same for all ad units. | `'prebid'` | `string` | +| `tagId` | required | The placement ID or tag ID from iMedia Digital Services. | `'demo1'` | `string` | +| `placementId` | optional | Legacy parameter replaced by `tagId` | `'demo1'` | `string` | +| `bidfloor` | optional | Legacy parameter for floor price for the request. Replaced by [Price Floors Module](/dev-docs/modules/floors.html) | `0.1` | `float` | + +### Example Ad Unit + +```javascript +var adUnits = [{ + "code": "test-div", + "mediaTypes": { + "video": { + "pos": 1, + "playerSize": [300, 250], + "context": "instream", + "mimes": ["video/mp4"], + "protocols": [2, 3, 5, 6, 7, 8], + "playbackmethod": [2], + "skip": 0, + "minduration": 15, + "maxduration": 30, + "startdelay": 0, + "linearity": 1 + } + }, + "bids": [{ + "bidder": "imds", + "params": { + "seatId": "prebid", + "tagId": "demo1", + "bidfloor": 0.20 + } + }] +}] +``` diff --git a/dev-docs/bidders/imonomy.md b/dev-docs/bidders/imonomy.md deleted file mode 100644 index d9fcb504b6..0000000000 --- a/dev-docs/bidders/imonomy.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Imonomy -description: Prebid Imonomy Bidder Adaptor -pbjs: true -biddercode: imonomy -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------------------|--------------------------------------|----------| -| `hbid` | required | header-bidding id from Imonomy | `'14567718624'` | `string` | -| `placementId` | required | placement id from Imonomy | `'e69148e0ba6c4c07977dc2daae5e1577'` | `string` | diff --git a/dev-docs/bidders/impactify.md b/dev-docs/bidders/impactify.md index 20c55f326b..2d93d26fc2 100644 --- a/dev-docs/bidders/impactify.md +++ b/dev-docs/bidders/impactify.md @@ -5,7 +5,7 @@ description: Prebid Impactify Bidder Adapter pbjs: true pbs: true biddercode: impactify -gdpr_supported: true +tcfeu_supported: true tcf2_supported: true usp_supported: true schain_supported: true @@ -13,11 +13,12 @@ coppa_supported: true media_types: video userIds: criteo, id5Id, pubCommonId, unifiedId, uid2, netId gvl_id: 606 +sidebarType: 1 --- -### Note: +### Note -The Impactify adaptator requires setup and validation from the Impactify team. Simply email us your contact details at support@impactify.io and we'll make sure we'll connect you within 48h. +The Impactify adaptator requires setup and validation from the Impactify team. Simply email us your contact details at and we'll make sure we'll connect you within 48h. ### Bid Params @@ -32,9 +33,17 @@ The Impactify adaptator requires setup and validation from the Impactify team. S Impactify recommends the UserSync configuration below. Without it, the Impactify adapter will not be able to perform user syncs, which lowers match rate and reduces monetization. +Note : Impactify adapter needs storage access to work properly (Do not forget to set storageAllowed to true). + For Prebid.js v1.15.0 and later: ```javascript +pbjs.bidderSettings = { + impactify: { + storageAllowed: true // Mandatory + } +}; + pbjs.setConfig({ userSync: { filterSettings: { @@ -50,6 +59,13 @@ pbjs.setConfig({ For Prebid.js v1.14.0 and before: ```javascript + +pbjs.bidderSettings = { + impactify: { + storageAllowed: true // Mandatory + } +}; + pbjs.setConfig({ userSync: { iframeEnabled: true, diff --git a/dev-docs/bidders/improvedigital.md b/dev-docs/bidders/improvedigital.md index 8cf220e975..0cc21342ff 100644 --- a/dev-docs/bidders/improvedigital.md +++ b/dev-docs/bidders/improvedigital.md @@ -6,36 +6,32 @@ biddercode: improvedigital pbjs: true pbs: true coppa_supported: true -gdpr_supported: true +gpp_supported: true +tcfeu_supported: true usp_supported: true userIds: all media_types: banner, native, video schain_supported: true gvl_id: 253 pbs_app_supported: true +floors_supported: true +sidebarType: 1 --- + + ### Bid params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|----------|----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|-----------| | `placementId` | required | The placement ID from Improve Digital. | `1234567` | `integer` | +| `publisherId` | required | The publisher ID from Improve Digital. | `4567` | `integer` | | `keyValues` | optional | Contains one or more key-value pairings for key-value targeting | `{ testKey1: ['testValueA'], testKey2: ['testValueB', 'testValueC'] }` | `object` | | `bidFloor` | optional | Bid floor price | `0.01` | `float` | | `bidFloorCur` | optional | Bid floor price currency. Supported values: USD (default), EUR, GBP, AUD, DKK, SEK, CZK, CHF, NOK | `'USD'` | `string` | -| `video` | optional | Object with video parameters. See the [Video params](#improvedigital-video) section below for details. | | `object` | - - - -### Video params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------------|----------|------------------------------------------------|-------------------------------------------|-----------------| -| `skip` | optional | Indicates if the player will allow the video to be skipped. | `1` | `integer` | -| `skipmin` | optional | Videos of total duration greater than this number of seconds can be skippable. | `15` | `integer` | -| `skipafter` | optional | Number of seconds a video must play before skipping is enabled. | `5` | `integer` | +| `extend` | optional | See the [Extend mode section](#improvedigital-extend) | `true` | `boolean` | +| `rendererConfig` | optional | Configuration object for JS renderer of the RAZR creatives. Provided by Improve Digital. | `{ key1: value1 }` | `object` | ### Configuration @@ -44,46 +40,87 @@ pbs_app_supported: true #### Sizes By default, the adapter doesn't send Prebid ad unit sizes to Improve Digital's ad server and the sizes defined for each placement in the Polaris platform will be used. If the ad server should only respond with creative sizes as defined in Prebid ad unit configuration, turn on `usePrebidSizes` adapter parameter like this: + +```javascript +pbjs.setConfig({ + improvedigital: { usePrebidSizes: true } +}); ``` + + + +#### Renderer Config + +Global configuration for the special creative format renderer. Please use [rendererConfig bid param](#improvedigital-params) for ad slot specific configuration. + +```javascript pbjs.setConfig({ - improvedigital: {usePrebidSizes: true} + improvedigital: { + rendererConfig: { + // Global config object provided by Improve Digital + } + } }); ``` - + + +#### Extend Mode + +Improve Digital Extend mode provides publishers with access to additional demand from other SSPs. Before enabling please contact our team for more information. +The Extend mode can be enabled: + +* per ad unit via the `extend` [bid param](#improvedigital-params) +* for all ad units via `setConfig()`: + +```javascript +pbjs.setConfig({ + improvedigital: { + extend: true + } +}); +``` + + ### Examples -#### Configuration With placementId +Examples of different ad unit formats can be found in [Prebid.js ad unit reference](https://docs.prebid.org/dev-docs/adunit-reference.html#adUnit-banner-example). Improve Digital bidder must be added in the ad unit's `bids` array. Example: - var adUnits = [{ - code: 'div-gpt-ad-1499748733608-0', - sizes: [[600, 290]], - bids: [ - { - bidder: 'improvedigital', - params: { - placementId:1053688 - } +```javascript +pbjs.addAdUnits({ + code: 'banner1', + sizes: [[728, 90], [970, 250]], + bids: [ + { + bidder: 'improvedigital', + params: { + placementId: 1111111, + publisherId: 1234 } - ] - }]; - -#### Configuration With PlacementId and Key-Values - - var adUnits = [{ - code: 'div-gpt-ad-1499748733608-0', - sizes: [[600, 290]], - bids: [ - { - bidder: 'improvedigital', - params: { - placementId:1053689, - keyValues: { - testKey1: ["testValueA"], - testKey2: ["testValueB", "testValueC"] - } + } + ] +}); +``` + +#### Example for Key-Values + +```javascript +pbjs.addAdUnits({ + code: 'banner1', + sizes: [[600, 290]], + bids: [ + { + bidder: 'improvedigital', + params: { + placementId: 1111111, + publisherId: 1234, + keyValues: { + testKey1: ["testValueA"], + testKey2: ["testValueB", "testValueC"] } } - ] - }]; + } + ] +}); +``` diff --git a/dev-docs/bidders/incrementx.md b/dev-docs/bidders/incrementx.md new file mode 100644 index 0000000000..2182b871ba --- /dev/null +++ b/dev-docs/bidders/incrementx.md @@ -0,0 +1,23 @@ +--- +layout: bidder +title: IncrementX +description: Prebid IncrementX Bidder Adaptor +pbjs: true +biddercode: incrementx +media_types: banner +tcfeu_supported: false +multiformat_supported: will-bid-on-one +filename: incrxBidAdapter +sidebarType: 1 +--- + +### Note + +The IncrementX adapter currently doesn't support multiple sizes per ad placement and will favour the first one if multiple sizes exists. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|--------------------------|-----------------|----------| +| placementId | required | incrementx placement id | `'IX-HB-123'` | `string` | diff --git a/dev-docs/bidders/indiecue.md b/dev-docs/bidders/indiecue.md new file mode 100644 index 0000000000..0285053b50 --- /dev/null +++ b/dev-docs/bidders/indiecue.md @@ -0,0 +1,107 @@ +--- +layout: bidder +title: Indicue +description: Indicue Bidder Adapter +biddercode: indicue +aliasCode: adtelligent +media_types: video,banner +tcfeu_supported: false +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: false +pbjs: true +pbs: true +deals_supported: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from Indicue Media. | `12412` | `integer` | + +### Description + +Indicue Media header bidding adapter connects with Indicue Media demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'indicue', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'indicue', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'indicue', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'indicue', + params: { + aid: 529814 + } + }] + } + ]; +``` diff --git a/dev-docs/bidders/infytv.md b/dev-docs/bidders/infytv.md new file mode 100644 index 0000000000..1981e978b4 --- /dev/null +++ b/dev-docs/bidders/infytv.md @@ -0,0 +1,27 @@ +--- +layout: bidder +title: InfyTV +description: Prebid InfyTV Bidder Adapter +pbjs: true +biddercode: infytv +tcfeu_supported: false +media_types: video +coppa_supported: true +pbs: true +pbs_app_supported: true +usp_supported: true +schain_supported: true +sidebarType: 1 +--- + +### Note + +The Example Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|-----------|----------| +| `publisherId` | required | Publisher ID | `'11111'` | `string` | +| `placementId` | optional | Placement ID | `'11111'` | `string` | diff --git a/dev-docs/bidders/inmar.md b/dev-docs/bidders/inmar.md index f00dc47243..b930a0fdeb 100644 --- a/dev-docs/bidders/inmar.md +++ b/dev-docs/bidders/inmar.md @@ -2,19 +2,19 @@ layout: bidder title: Inmar description: Prebid Inmar Bidder Adapter - biddercode: inmar usp_supported: true userIds: identityLink, liveIntentId, unifiedId, pubCommonId, pubProvidedId, sharedId media_types: banner, video safeframes_ok: false deals_supported: true -fpd_supported: true pbjs: true +enable_download: false +sidebarType: 1 --- -### Note: +### Note -The Inmar Bidding adapter requires setup before beginning. Please contact us at prebid@inmar.com +The Inmar bidder is no longer supported. Please be advised to stop use of this adapter in all Prebid.js versions. ### Bid Params diff --git a/dev-docs/bidders/inmobi.md b/dev-docs/bidders/inmobi.md index bafea45f6d..be796ccfc0 100644 --- a/dev-docs/bidders/inmobi.md +++ b/dev-docs/bidders/inmobi.md @@ -3,7 +3,7 @@ layout: bidder title: InMobi description: InMobi Bidder Adapter biddercode: inmobi -gdpr_supported: true +tcfeu_supported: true usp_supported: false gvl_id: 333 coppa_supported: true @@ -11,18 +11,19 @@ schain_supported: true media_types: banner, video, native pbs: true pbs_app_supported: true +sidebarType: 1 --- -### Note: +### Note -The InMobi Prebid adapter requires a setup to create placement IDs. Please contact your InMobi partner manager for setup assistance. -For queries, write to us at prebid-support@inmobi.com +The InMobi Prebid adapter requires a setup to create placement IDs. Please contact your InMobi partner manager for setup assistance. +For queries, write to us at -### User Sync Disclosure: +### User Sync Disclosure InMobi has partnered with a third party, ID5, to use their ID as our primary user identifier for mobile web supply. We will also rely on ID5 IDs to handle compliance flows related to Data Subject Right requests in our systems. Hence, we require the publisher to use ID5’s sync URL for user syncing and passing the corresponding ID5 ID to InMobi in the bid request. For this purpose, we provide ID5’s sync URL in our Prebid adapter for User ID sync. Note that, InMobi has a direct contract with ID5 for consuming ID5 ID and the user sync via Prebid does not require the publisher to get into a contractual relationship with ID5. -To opt out of InMobi ads on mobile web inventory or for any other requests, the user needs to visit the Opt-out page on InMobi website (https://www.inmobi.com/page/opt-out/). For opting out of ID5 ID entirely, the user needs to visit ID5’s opt out page: https://id5.io/platform-privacy-policy/. +To opt out of InMobi ads on mobile web inventory or for any other requests, the user needs to visit the Opt-out page on InMobi website (). For opting out of ID5 ID entirely, the user needs to visit ID5’s opt out page: . ### Bid Params diff --git a/dev-docs/bidders/innity.md b/dev-docs/bidders/innity.md index 228490a590..d10cfbc2c5 100644 --- a/dev-docs/bidders/innity.md +++ b/dev-docs/bidders/innity.md @@ -4,9 +4,11 @@ title: Innity description: Prebid Innity Bidder Adapter pbjs: true biddercode: innity +sidebarType: 1 --- -### Note: +### Note + The Innity bidder adapter requires setup and approval from the Innity Media team, even for existing Innity Network publishers. Please reach out to your account manager for more information and to enable using this adapter. ### Bid Params diff --git a/dev-docs/bidders/inskin.md b/dev-docs/bidders/inskin.md index bca6d592bd..efc8b4cefe 100644 --- a/dev-docs/bidders/inskin.md +++ b/dev-docs/bidders/inskin.md @@ -4,10 +4,13 @@ title: Inskin description: Inskin Media Bidder Adaptor pbjs: true biddercode: inskin -gdpr_supported: true +gvl_id: 150 +tcfeu_supported: true +sidebarType: 1 --- -### Note: +### Note + The Inskin bidder adapter requires additional setup and approval from the Inskin Media Integrations team. Please reach out to your account manager for more information and to start using it. ### Bid Params diff --git a/dev-docs/bidders/insticator.md b/dev-docs/bidders/insticator.md index 794279bd07..ec3b8565f7 100644 --- a/dev-docs/bidders/insticator.md +++ b/dev-docs/bidders/insticator.md @@ -3,15 +3,173 @@ layout: bidder title: Insticator description: Prebid Insticator Bidder Adapter biddercode: insticator +tcfeu_supported: true +dsa_supported: true +gpp_sids: tcfeu, usnat, usstate_all, usp +usp_supported: true +coppa_supported: true gdpr_supported: true -media_types: banner +schain_supported: true +media_types: banner, video +multiformat_supported: will-bid-on-any pbjs: true gvl_id: 910 +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------|----------|-----------------|----------------------|-----------| -| `adUnitId` | Required | The ad unit ID provided by Insticator | `'test'` | `string` | +| Name | Scope | Description | Example | Type | +|-----------------------------|----------|-----------------------------------------------------------------------------------------|------------------------------------|----------| +| `adUnitId` | Required | The ad unit ID provided by Insticator | `'test'` | `string` | +| `yob` | optional | Year of Birth | `'1982'` | `string` | +| `gender` | optional | Gender | `'M'` | `string` | +| `instl` | optional | 1 = the ad is interstitial or full screen, 0 = not interstitial. | `1` | `number` | +| `pos` | optional | ad position as per IAB standards | `1` | `number` | +| `bid_endpoint_request_url` | optional | Url string representing the endpoint Insticator adaptor should make the request bids to. | `https://ex.ingage.com/v1/openrtb` | `string` | + +### Banner Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------------|----------------------|----------| +| `pos` | optional | ad position as per IAB standards | `1` | `number` | + +### Example + +```javascript +var adUnitsBannerOnly = [ + { + code: 'insticator-banner-ad-1', + mediaTypes: { + banner: { + sizes: [ + [336, 280], + [300, 250], + [320, 100], + ], + }, + }, + bids: [ + { + bidder: 'insticator', + params: { + adUnitId: 'example_adunit_id', + }, + }, + ], + }, +]; +``` + +#### First Party Data + +In release 8.45 and later, Insticator has added support for first party data which are optional and partners can send us. The following fields are supported: + +* ortb2.site.keywords +* ortb2.site.content.* +* ortb2.site.search +* ortb2.site.cat +* ortb2.site.pagecat +* ortb2.site.sectioncat +* ortb2.user.ext.* +* ortb2.user.data.* + +Here is an example first party data that insticator support. + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + keywords: "kw1,kw2", + content: { + title: 'title', + genre: 'rock', + }, + cat: ['IAB1-1'], + pagecat: ['IAB1-1'], + sectioncat: ['IAB1-1'], + ext: { + data: { + prodtype: ["a","b"] + } + } + }, + user: { + ext: { + data: { + ucat:["anything"] + } + } + } + } +}; +``` + +### Media Types +#### Video parameters + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | +|------------------------|-------------|-----------------------------------------------------------------|-------------------------------| +| `video.mimes` | required | Video MIME types | `['application/javascript',`
      `'video/mp4',`
      `'video/ogg',`
      `'video/webm',`
      `'video/mpeg']` | +| `video.w` | recommended | Width of the video player in device independent pixels (DIPS). | `640` | +| `video.h` | recommended | Height of the video player in device independent pixels (DIPS). | `480` | +| `video.placement` | recommended | Video placement type. (see OpenRTB v2.5 section 5.9 for options) | `3` | +| `video.plcmt` | recommended | Placement type for the impression. (See [OpenRTB v2.6](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/develop/AdCOM%20v1.0%20FINAL.md) Plcmt Subtypes - Video) | `5` | +| `video.playerSize` | optional | Array of supported sizes of the player. | `[[300, 250], [300, 600]]` | +| `video.playbackmethod` | optional | Playback methods that may be in use.(see OpenRTB v2.5 section 5.10 for options) | `[1, 2, 3, 4]` | +| `video.protocols` | optional | Supported video bid response protocol values are 2, 3, 5, 6, 7, 8. (see OpenRTB v2.5 section 5.8 for options) | `[2, 3, 5, 6, 7, 8]` | +| `video.maxduration` | optional | Maximum video ad duration in seconds | `30` | +| `video.minduration` | optional | Minimum video ad duration in seconds | `1` | +| `video.skip` | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes | `0` | +| `video.skipafter` | optional | Number of seconds a video must play before skipping is enabled | `5` | +| `video.startdelay` | optional | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. (see OpenRTB v2.5 section 5.12 for options) | `0` | +| `video.linearity` | optional | Indicates if the impression must be linear, nonlinear, etc. (see OpenRTB v2.5 section 5.7 for options) | `1` | +| `video.skipmin` | optional | Only if the ad is skippable. Videos of total duration greater than this number of seconds can be skippable | `5` | +| `video.sequence` | optional | For multiple ad in the same bid request. This value allow will for the coordinated delivery of multiple ad | `1` | +| `video.battr` | optional | Blocked creative attributes. (see OpenRTB v2.5 section 5.3 for options) | `[1]` | +| `video.maxextended` | optional | Max extended ad duration beyond the maxduration if extension is allowed. Blank or 0 - blocked. -1 - allowed without time limit | `30` | +| `video.minbitrate` | optional | Minimum bit rate in Kbps | `5` | +| `video.maxbitrate` | optional | Maximum bit rate in Kbps | `10000` | +| `video.playbackend` | optional | The event that causes playback to end. (see OpenRTB v2.5 section 5.11 for options) | `1` | +| `video.delivery` | optional | Supported delivery methods (1 = streaming, 2 = progressive, 3 = download). If none specified, assume all are supported. | `[1, 2]` | +| `video.pos` | optional | Ad position on screen. (see OpenRTB v2.5 section 5.4 for options) | `1` | +| `video.api` | optional | List of supported API frameworks for this impression. Supported API frameworks are between 1-7 (See [OpenRTB v2.6](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/develop/AdCOM%20v1.0%20FINAL.md) List API Frameworks) | `[2, 7]` | + +### Example + +```javascript +var adUnits = [ + { + code: 'insticator-video-ad-2', + mediaTypes: { + video: { + playerSize: [640, 480], + w: 640, + h: 480, + mimes: ['video/mp4', 'video/x-flv'], + protocols: [2, 3, 5, 6, 7, 8], + placement: 3, + startdelay: 0, + api: [2, 7], + skip: 0, + minduration: 1, + maxduration: 30, + playbackmethod: [1, 3], + battr: [13, 14], + linearity: 1, + minbitrate: 10, + maxbitrate: 10000 + } + }, + bids: [{ + bidder: 'insticator', + params: { + adUnitId: 'example_adunit_id' + } + }], + ... + }]; +``` diff --git a/dev-docs/bidders/integr8.md b/dev-docs/bidders/integr8.md index 27662ef942..e812cd99dd 100644 --- a/dev-docs/bidders/integr8.md +++ b/dev-docs/bidders/integr8.md @@ -5,6 +5,7 @@ description: Prebid Integr8 Bidder Adapter pbjs: true biddercode: integr8 media_types: banner, video +sidebarType: 1 --- @@ -14,4 +15,5 @@ media_types: banner, video |---------------|----------|------------------------------------------------------------------------|--------------------|-----------| | `propertyId` | required |Property id | `"12345"` | `string` | | `placementId` | required |Placement id | `"54321"` | `string` | +| `deliveryUrl` | optional |Custom endpoint url for the bid request | `"https://central.sea.integr8.digital/bid"` | `string` | | `data` | optional |Catalog data (contents) and/or inventory data (custom key/value pairs) | `{catalogs: [{ catalogId: "699229", items: ["193", "4", "1"] }], inventory: { category: ["tech"], query: ["iphone 12"] }}` | `object` | diff --git a/dev-docs/bidders/interactiveOffers.md b/dev-docs/bidders/interactiveOffers.md index daadab5e9d..9aa7e915d9 100644 --- a/dev-docs/bidders/interactiveOffers.md +++ b/dev-docs/bidders/interactiveOffers.md @@ -5,11 +5,13 @@ description: Prebid InteractiveOffers.com Bidder Adapter pbs: true pbjs: true biddercode: interactiveOffers -gdpr_supported: false +tcfeu_supported: false media_types: banner +sidebarType: 1 --- -### Note: +### Note + Module that connects to interactiveOffers demand sources. Param partnerId is required. ### Bid Params diff --git a/dev-docs/bidders/intertech.md b/dev-docs/bidders/intertech.md new file mode 100644 index 0000000000..29512af65b --- /dev/null +++ b/dev-docs/bidders/intertech.md @@ -0,0 +1,20 @@ +--- +layout: bidder +title: intertech +description: Prebid Intertech Bidder Adapter +pbs: true +biddercode: intertech +media_types: banner, native +--- + +### Registration + +The Intertech Bidding adapter requires setup before beginning. Please contact us at [prebid@intertechsrvcs.com](mailto:prebid@intertechsrvcs.com). + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------------------|-----------|-----------| +| `pageId` | required | Page ID | `123456` | `Integer` | +| `impId` | required | Block ID | `12` | `Integer` | diff --git a/dev-docs/bidders/invamia.md b/dev-docs/bidders/invamia.md index ec5dc91a79..072522f340 100644 --- a/dev-docs/bidders/invamia.md +++ b/dev-docs/bidders/invamia.md @@ -5,16 +5,17 @@ description: Prebid Invamia Bidder Adapter pbjs: true biddercode: invamia safeframes_ok: false +sidebarType: 1 --- ### Note Here is what you need for Prebid integration with Invamia: + 1. Register with Invamia. 2. Once registered and approved, you will receive a Zone ID. 3. Use the Zone ID as parameters in params. - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/invibes.md b/dev-docs/bidders/invibes.md index 9c1a368d8d..2847bf7778 100644 --- a/dev-docs/bidders/invibes.md +++ b/dev-docs/bidders/invibes.md @@ -2,14 +2,38 @@ layout: bidder title: Invibes description: Prebid Invibes Bidder Adaptor -pbjs: true biddercode: invibes -gdpr_supported: true -tcf2_supported: true -userIds: pubCommonId, pubProvidedId, uid2, zeotapIdPlus, id5id +tcfeu_supported: true +gvl_id: 436 +usp_supported: false +coppa_supported: false +gpp_sids: tcfeu +schain_supported: false +dchain_supported: false +userId: pubCommonId, pubProvidedId, uid2, zeotapIdPlus, id5id +media_types: banner, native +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: false +pbjs: true pbs: true +pbs_app_supported: false +prebid_member: false +multiformat_supported: will-bid-on-any +ortb_blocking_supported: false +privacy_sandbox: no +sidebarType: 1 --- +### Disclosure + +The bidder will use the Local Storage if allowed by the publisher and user gives consent on page with the following purposes: + - set an internal Invibes ID + - get the internal Invibes ID if it was set priorly for the user + +The bidder will NOT set any cookies. The bidder will also try to read from Cookies if publisher gibes the internal ID if this wasn't found in LocalStorage. + ### Bid Params {: .table .table-bordered .table-striped } @@ -19,4 +43,3 @@ pbs: true | `domainId` | optional | Id of domain | `1001` | `integer`| | `customEndpoint`| optional | Custom test domain | `https://bid.videostep.com/Bid/VideoAdContent` | `integer`| | `debug` | optional | Debug paramentes (only prebid server)| `{ "testBvid": "1234", "testLog": true }` | `object` | - diff --git a/dev-docs/bidders/iprom.md b/dev-docs/bidders/iprom.md index 243a1a0717..5689594c25 100644 --- a/dev-docs/bidders/iprom.md +++ b/dev-docs/bidders/iprom.md @@ -5,12 +5,13 @@ description: iPROM Prebid Adaptor biddercode: iprom media_types: banner pbjs: true -enable_download: false -pbjs_version_notes: not in 5.x, in 6.2+ +enable_download: true +sidebarType: 1 --- -### Prebid Server Note: -For registration with our bidder please see our website at [www.iprom.eu](https://www.iprom.eu) or contact us at support@iprom.si. +### Prebid Server Note + +For registration with our bidder please see our website at [www.iprom.eu](https://www.iprom.eu) or contact us at . ### Bid Params diff --git a/dev-docs/bidders/iqm.md b/dev-docs/bidders/iqm.md index a3251a5a72..31b546afcb 100644 --- a/dev-docs/bidders/iqm.md +++ b/dev-docs/bidders/iqm.md @@ -4,9 +4,10 @@ title: iQM description: Prebid iQM Bidder Adaptor pbjs: true biddercode: iqm +sidebarType: 1 --- -# Parameters +## Parameters {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | @@ -16,11 +17,12 @@ biddercode: iqm | `placementId` | required | The Placement ID from iQM | 23451 | | `bidfloor` | optional | Bid Floor | 0.50 | -# Description +## Description Module that connects to iQM demand sources -# Test Parameters +## Test Parameters + ``` var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', @@ -47,7 +49,7 @@ var adUnits = [{ ``` -# adUnit Video +## adUnit Video ``` var videoAdUnit = { diff --git a/dev-docs/bidders/iqx.md b/dev-docs/bidders/iqx.md new file mode 100644 index 0000000000..d3d3cd7a6a --- /dev/null +++ b/dev-docs/bidders/iqx.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: IQX +description: IQX Bidder Adapter +biddercode: iqx +media_types: banner, video, native +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: true +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +safeframes_ok: true +--- + +### Prebid.js Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------|---------------|-----------| +| `pid` | required | Placement ID | `test-banner` | `string` | +| `env` | required | Environment name | `iqx` | `string` | +| `ext` | optional | Specific integration config | `{}` | `object` | + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-------------------------------|------------------------------------|-----------| +| `env` | required | Environment name | `iqx-stage` | `string` | +| `pid` | required | unique placement ID | `aa8217e20131c095fe9dba67981040b0` | `string` | diff --git a/dev-docs/bidders/ironsource.md b/dev-docs/bidders/ironsource.md deleted file mode 100644 index a4ee00012e..0000000000 --- a/dev-docs/bidders/ironsource.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -layout: bidder -title: IronSource -description: Prebid IronSource Bidder Adaptor -pbjs: true -biddercode: ironsource -media_types: no-display, video -schain_supported: true -gdpr_supported: true -usp_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note - -The IronSource adapter requires setup and approval. Please reach out to prebid-digital-brands@ironsrc.com to setup an IronSource account. - -### Bid Parameters - -#### Video - -{: .table .table-bordered .table-striped } -| Name | Scope | Type | Description | Example -| ---- | ----- | ---- | ----------- | ------- -| `isOrg` | required | String | IronSource publisher Id provided by your IronSource representative | "56f91cd4d3e3660002000033" -| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 -| `ifa` | optional | String | The ID for advertisers (also referred to as "IDFA") | "XXX-XXX" -| `testMode` | optional | Boolean | This activates the test mode | false - -## Example -```javascript -var adUnits = [ - { - code: 'dfp-video-div', - sizes: [[640, 480]], - mediaTypes: { - video: { - playerSize: [[640, 480]], - context: 'instream' - } - }, - bids: [{ - bidder: 'ironsource', - params: { - isOrg: '56f91cd4d3e3660002000033', // Required - floorPrice: 5.00, // Optional - ifa: 'XXX-XXX', // Optional - testMode: false // Optional - } - }] - } - ]; -``` - -### Configuration -IronSource recommends setting UserSync by iframe for monetization. - -For Prebid.js v1.15.0 and later: - -pbjs.setConfig({ - userSync: { - filterSettings: { - iframe: { - bidders: '*', // '*' represents all bidders - filter: 'include' - } - } - } -}); - -For Prebid.js v1.14.0 and before: - -pbjs.setConfig({ - userSync: { - iframeEnabled: true, - enabledBidders: ['ironsource'] - } -}); diff --git a/dev-docs/bidders/ivs.md b/dev-docs/bidders/ivs.md new file mode 100644 index 0000000000..088d29cb3c --- /dev/null +++ b/dev-docs/bidders/ivs.md @@ -0,0 +1,21 @@ +--- +layout: bidder +title: IVS Bidder Adapter +description: Prebid IVS Bidder Adapter +biddercode: ivs +media_types: video +floors_supported: true +pbjs: true +sidebarType: 1 +--- + +### Note + +The IVS Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|----------|----------------------------|-------------|-----------| +| `publisherId` | required | Unique id of the publisher | `'3001234'` | `string` | diff --git a/dev-docs/bidders/ix-server.md b/dev-docs/bidders/ix-server.md new file mode 100644 index 0000000000..94ce0053f5 --- /dev/null +++ b/dev-docs/bidders/ix-server.md @@ -0,0 +1,401 @@ +--- +layout: bidder +title: Index Exchange (Prebid Server) +description: Prebid Index Exchange Bidder Adapter +biddercode: ix +pbjs: false +pbs: true +userIds: idl, netId, fabrickId, zeotapIdPlus, uid2, TDID, id5Id, lotamePanoramaId, publinkId, hadronId, pubcid, utiq, criteoID, euid, imuid, 33acrossId, nonID, pairid +pbs_app_supported: true +schain_supported: true +coppa_supported: true +tcfeu_supported: true +floors_supported: true +usp_supported: true +media_types: banner, video, native +safeframes_ok: true +fpd_supported: true +gvl_id: 10 +dchain_supported: false +deals_supported: true +prebid_member: yes +multiformat_supported: yes +sidebarType: 1 +privacy_sandbox: paapi +--- + + + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Supported media types](#supported-media-types) +* [Configure the Index adapter in your Prebid Server instance](#hosting-instance) +* [Publisher instructions to call Index through Prebid Server](#call-index) + * [Call Index from a web browser](#call-index-from-a-web-browser) + * [Call Index from Prebid Mobile SDK](#call-index-from-prebid-mobile-sdk) + * [Call Index from CTV/long-form video environment](#call-index-from-ctvlong-form-video-environment) + * [Call Index from any other server-to-server OpenRTB environment](#call-index-from-any-other-server-to-server-openrtb-environment) +* [Bid request parameters](#bid-request-parameters) + * [Banner](#banner) + * [Video](#video) +* [Examples](#examples) + + + +## Introduction + +Publishers can use Prebid Server in any of the following ways with Index Exchange (Index). Index's adapter supports all of the following methods: + +* If you want to call Index from a web environment, you can use Prebid.js to call Prebid Server, and then Prebid Server uses our server-side adapter to call Index. This reduces workload on the browser. For set up instructions, see [Call Index from a web browser](#call-index-from-a-web-browser) section on this page. +* In mobile apps, you can use the Prebid Mobile SDK to call Prebid Server and then Prebid Server uses our server-side adapter to call Index. For set up instructions, see [Call Index from Prebid Mobile SDK](#call-index-from-prebid-mobile-sdk) section on this page. +* In CTV apps and other long-form video environments, you (or the SSAI vendor) can make a call to Prebid Server using OpenRTB, and then Prebid Server uses our server-side adapter to call Index. For set up instructions, see [Call Index from CTV/long-form video environment](#call-index-from-ctvlong-form-video-environment) section on this page. +* In any other server-to-server OpenRTB environment, you can send OpenRTB bid requests to the Prebid Server host of your choice. For set up instructions, see [Call Index from any other server-to-server OpenRTB environment](#call-index-from-ortb) section on this page. + +**Note about sending multiple ad slots in a single bid request:** Index accepts up to 100 valid ad slots in a single bid request. If a single bid request contains more than 100 ad slots (including invalid ad slots), only the first 100 valid ad slots are accepted and the rest are ignored. For example, streaming TV media owners can signal multiple ad pods for long-form programming in a single request. + + + +## Supported media types + +The following table lists the media types that Index supports. For information about the the Time-To-Live (TTL) for each media type, see [How Index counts impressions](https://kb.indexexchange.com/publishers/billing/how_Index_counts_impressions.htm) in our Knowledge Base. + +{: .table .table-bordered .table-striped } +| Type | Prebid Server support | +| ----------- | ----------- | +| banner | Supported | +| video | Supported, including ad pods for OTT | +| native | Supported | + + + +## Configure the Index adapter in your Prebid Server instance + +**Before you begin:** Contact your Index Exchange Representative to get an endpoint and setup instructions. + +If you are hosting your own Prebid Server instance, depending on whether you are using Prebid Server Go or Prebid Server Java version, complete one of the following steps: + +* If you are using the Prebid Server Go version, in the `static/bidder-info/ix.yaml` file, complete the following: + + * Enable the adapter by deleting the `disabled: true` entry. + * Add the following new entry and include the regional endpoint provided to you by Index: + + ```javascript + endpoint: "https://" + ``` + + * Edit the below existing entry and include your publisher ID in the `s` parameter: + + ```javascript + userSync: + redirect: + url: "https://ssum.casalemedia.com/usermatchredir?s=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}" + ``` + + * Edit the below existing entry and include your publisher ID in the `s` parameter: + + ```javascript + userSync: + redirect: + iframe: "https://ssum.casalemedia.com/usermatch?s=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}" + ``` + +* If you are using [Prebid Server Java](https://github.com/prebid/prebid-server-java) version, edit the `prebid-server-java` entry in the `src/main/resources/bidder-config/ix.yaml` file as follows: + + * Edit the below existing entry and include the endpoint URL provided to you by Index. + + ```javascript + adapters: + ix: + endpoint: "https://" + ``` + + * Edit the below existing entry and include your publisher ID in the `s` parameter: + + ```javascript + adapters: + ix: + usersync: + redirect: + url: "https://ssum.casalemedia.com/usermatchredir?s=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}" + ``` + + * Add the below entry and include your publisher ID in the `s` parameter: + + ```javascript + adapters: + ix: + usersync: + iframe: + url: "https://ssum.casalemedia.com/usermatch?s=&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}" + ``` + + + +## Publisher instructions to call Index through Prebid Server + +If you are using an existing Prebid Server instance that is already configured to call Index, depending on whether you want to call Index from the browser, mobile app, CTV, or long-form video, follow any of the below sections to complete the Index-specific configuration. + + + +### Call Index from a web browser + +To call Index from a web browser using Prebid Server, you must first configure Prebid.js to call Index directly from the browser using our client-side adapter. Follow the quick start instructions provided in Prebid's [Getting Started for Developers](/dev-docs/getting-started.html) documentation. Complete the following steps to complete the Index-specific configuration: + +1. Build the binary in one of the following ways: + * [Download Prebid.js](/download.html) from the Prebid site to use the standard compiled binary that Prebid includes in the download process and select **Index Exchange** as an adapter. + * Build it on your own from the source code by following the instructions in [Prebid.js project README](https://github.com/prebid/Prebid.js/blob/master/README.md#build-optimization). If you use this method, you will need to include several modules in your build process. See the [Index modules to include in your build process](/dev-docs/bidders/ix.html#modules-to-include-in-your-build-process) section in our Prebid.js documentation on the Prebid site. +2. Define the Index-specific parameters at the bidder level which include adding `ix` as the bidder and the `siteId`. For Index's bidder-specific parameters, see the [Bid request parameters](#bid-request-parameters) section below. + + ```javascript + { + bidder: 'ix', + params: { + siteId: '9999990' + } + } + ``` + +3. Define your ad units in the `adUnit` object. This includes the details about the ad slots such as the media types, ad size, and ad code. For more information about this object, see Prebid's [Ad Unit Reference](/dev-docs/adunit-reference.html) documentation. +4. Enable user syncing by adding the following code in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function. Index strongly recommends enabling user syncing through iFrames, though we do also support image-based syncing. This functionality improves DSP user match rates and increases the Index bid rate and bid price. Make sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Index. + + ```javascript + pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: ['ix'], + filter: 'include' + } + } + } + }); + ``` + +5. (Optional) Set up First Party Data (FPD). For more information about the data types we support and the instructions for each option, see the [Set up First Party Data (FPD)](/dev-docs/bidders/ix.html#set-up-first-party-data-fpd) section in our Prebid.js documentation on the Prebid site. +6. (Optional) If you want to monetize instream video, you need to enable a cache endpoint in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function as follows:
      + + ```javascript + pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + ``` + +7. (Optional) If you want to monetize outstream video, you can choose among the following options: + * Use Index's outstream video player. For more information, see the [Index's outstream video player](/dev-docs/bidders/ix.html#index-outstream-video-player) section in our Prebid.js documentation on the Prebid site. + * Use your own outstream video player. For more information, see [Prebid's documentation on how to show video ads.](/dev-docs/show-outstream-video-ads.html) +8. (Optional) Configure Prebid Native with Index. For more information, see the [Prebid Native](/dev-docs/bidders/ix.html#prebid-native-configuration) section in our Prebid.js documentation on the Prebid site. Prebid Native is available from Prebid.js version 7.4.0 or higher. + + + +### Call Index from Prebid Mobile SDK + +**Before you begin:** Contact your Index Exchange representative to get your `siteId`. You must provide this site ID to your Prebid Server host company. + +**Note:** To implement Prebid Mobile SDK, follow Prebid's [Getting Started with Prebid Mobile](/prebid-mobile/prebid-mobile-getting-started.html) documentation. + +To add Index as a bidder to your mobile app: + +1. Inform your Prebid Server hosting company to add `ix`as a bidder in the configuration and include the `siteId` that Index provides to you at the time of integration. +2. Define the Index-specific parameters at the bidder level. For information about these parameters, see the [Bid request parameters](#bid-request-parameters) section below. +3. Include any ad unit level required or optional parameters provided in Prebid's [Prebid Mobile API - iOS](/prebid-mobile/pbm-api/ios/ios-sdk-integration-gam-original-api.html) and [Prebid Mobile API - Android](/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html) documentation. + + + +### Call Index from CTV/long-form video environment + +**Before you begin:** Contact your Index Exchange Representative to get the `siteId`. You must provide this site ID to your Prebid Server host company. + +**Note:** To implement CTV and long-form video using Prebid Server, follow Prebid's [Long Form Video](/prebid-server/use-cases/pbs-lfv.html) documentation. + +To add Index as a bidder: + +1. Inform your Prebid Server hosting company to add `ix`as a bidder in the configuration and include the `siteId` that Index provides to you at the time of integration. +2. Define the Index-specific parameters at the bidder level. For information about these parameters, see the [Bid request parameters](#bid-request-parameters) section below. +3. Include any ad unit level required or optional parameters provided in Prebid's [/openrtb2/video](/prebid-server/endpoints/openrtb2/pbs-endpoint-video.html) documentation. + + + +### Call Index from any other server-to-server OpenRTB environment + +To request bids from Index: + +* In requests that you make to your Prebid Server host, add `imp.ext.ix` and include the `siteId` that Index provides to you at the time of integration.
      + +**Example:** + +```javascript + "imp": [{ + "ext": { + "ix": { + "siteId": "9999990" + } + } + }], +``` + + + +## Bid request parameters + +For a list of the OpenRTB fields that Index supports in bid requests, see [List of supported OpenRTB bid request fields for sellers](https://kb.indexexchange.com/publishers/openrtb_integration/list_of_supported_openrtb_bid_request_fields_for_sellers.htm#List_of_supported_OpenRTB_bid_request_fields_for_sellers). The following are the required fields for the various supported media types. + +### Banner + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Key | Scope | Type | Description | +|---|---|---|---| +| `siteId` | Required | String | An Index-specific identifier that is associated with this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'9999990'`, `'9999991'`, `'9999992'`| + +### Video + +You must include these parameters at the bidder level. + +{: .table .table-bordered .table-striped } +| Key | Scope | Type | Description | +|---|---|---|---| +| `siteId` | Required | String | An Index-specific identifier that is associated with this ad unit. It will be associated with the single size, if the size is provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'9999990'`, `'9999991'`, `'9999992'`
      **Note:** You can re-use the existing `siteId` within the same flex position or video size, if the video adapts to the containing `
      ` element.| + +If you are using Index's outstream ad unit and have placed the video object at the bidder level, you must include the Index required parameters at the bidder level. You can include the optional parameters to specify the outstream ad unit configurations. + +{: .table .table-bordered .table-striped } +| Key | Scope | Type | Description | +|---|---|---|---| +| `video.w` | Required | Integer | The width of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. We strongly recommend video sizes to be `256 x 256` or greater, `300 x 250`, or `320 x 180`. | +| `video.h` | Required | Integer | The height of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. We strongly recommend video sizes to be `256 x 256` or greater, `300 x 250`, or `320 x 180`. | +| `video.playerSize` | Required | Integer[] | The video player size that will be passed to demand partners. | +| `video.playerConfig` | Optional | Hash | The Index-specific outstream ad unit configurations. | +| `video.playerConfig.floatOnScroll` | Optional | Boolean | A boolean specifying whether you want to use the player's floating capabilities, where:
      - `true`: Use the Index player's float capabilities.
      **Note:** If you set `floatOnScroll` to `true`, Index updates the placement value to `5`.
      **Note:** We do not recommend using the player's default float capabilities if you have more than one outstream ad unit per page.
      -`false`: Do not use the Index player's float capabilities (default). | +| `video.playerConfig.floatSize` | Optional | Integer[] | The height and width of the floating player in pixels. If you do not specify a float size, the player adjusts to the aspect ratio of the player size that is defined when it is not floating. Index recommends that you review and test the float size to your user experience preference. | +| `video.plcmt` | Required | Integer[] | The video's placement type, where:
      - `1` = Instream
      - `2` = Accompanying Content
      - `3` = Interstitial
      - `4` = No Content/Standalone | + + + +## Examples + +**Banner** + +```json +{ + "id": "ix-banner-id", + "imp": [ + { + "id": "imp-id", + "banner": { + "w": 300, + "h": 250, + "id": "1", + "pos": 0, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "instl": 0, + "tagid": "5602709", + "bidfloor": 0.02, + "bidfloorcur": "USD", + "secure": 1, + "ext": { + "ix": { + "siteId": "9999990" + } + } + } + ], + "app": { + "bundle": "555555555", + "storeurl": "https://apps.apple.com/us/app/test-app/id555555555", + "publisher": { + "id": "123456" + }, + "content": { + "title": "Entertainment", + "genre": "IAB9-30,IAB6,IAB9-7,IAB1" + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", + "ip": "10.20.30.40", + "ifa": "2E2E2E2E-3B3B-4141-8A8A-181818181818" + }, + "at": 1, + "tmax": 200 +} +``` + +**Video** + +```json +{ + "id": "ix-video-example", + "imp": [ + { + "id": "imp-id", + "video": { + "mimes": [ + "video/mp4", + "video/3gpp", + "video/webm" + ], + "minduration": 15, + "maxduration": 60, + "startdelay": -1, + "protocols": [ + 2, + 3, + 5, + 6 + ], + "w": 320, + "h": 480, + "placement": 1, + "linearity": 1, + "minbitrate": 1000, + "api": [ + 1, + 2, + 3, + 5 + ] + }, + "secure": 1, + "ext": { + "ix": { + "siteId": "9999990" + } + } + } + ], + "app": { + "bundle": "555555555", + "storeurl": "https://apps.apple.com/us/app/test-app/id555555555", + "publisher": { + "id": "123456" + }, + "content": { + "title": "Entertainment", + "genre": "IAB9-30,IAB6,IAB9-7,IAB1" + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E18", + "ip": "10.20.30.40", + "ifa": "2E2E2E2E-3B3B-4141-8A8A-181818181818" + }, + "at": 1, + "tmax": 1000 +} +``` diff --git a/dev-docs/bidders/ix.md b/dev-docs/bidders/ix.md index e7453c7e16..0edc681474 100644 --- a/dev-docs/bidders/ix.md +++ b/dev-docs/bidders/ix.md @@ -4,164 +4,553 @@ title: Index Exchange description: Prebid Index Exchange Bidder Adapter biddercode: ix pbjs: true -pbs: true -userIds: identityLink, netId, fabrickId, zeotapIdPlus, uid2, unifiedId, id5Id, lotamePanoramaId, publinkId, hadronId, pubcid +pbs: false +userIds: idl, netId, fabrickId, zeotapIdPlus, uid2, TDID, id5Id, lotamePanoramaId, publinkId, hadronId, pubcid, utiq, criteoID, euid, imuid, 33acrossId, nonID, pairid, MRKL pbs_app_supported: true schain_supported: true coppa_supported: true -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true floors_supported: true usp_supported: true -media_types: banner, video +gpp_supported: true +media_types: banner, video, native +safeframes_ok: true fpd_supported: true gvl_id: 10 +dchain_supported: false +deals_supported: true prebid_member: yes +multiformat_supported: yes +sidebarType: 1 +privacy_sandbox: paapi, topics --- -## Overview +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Supported media types](#supported-media-types) +* [Set up Prebid.js to call Index directly from the browser](#set-up-prebidjs-to-call-index-directly-from-the-browser-client-side-adapter) +* [Set up Prebid.js to call Index through Prebid Server](#set-up-prebidjs-to-call-index-through-prebid-server-server-side-adapter) +* [Modules to include in your build process](#modules-to-include-in-your-build-process) +* [Set up First Party Data (FPD)](#set-up-first-party-data-fpd) + * [Global data](#prebid-fpd-module) + * [Index bidder-specific data](#index-bidder-specific-fpd-module) + * [AdUnit-specific data](#adunit-specific-data) +* [Monetize instream video](#monetize-instream-video) +* [Index's outstream ad unit](#indexs-outstream-ad-unit) +* [Prebid Native configuration](#prebid-native-configuration) +* [Protected Audience API support](#protected-audience-api-support) +* [Signal inventory using external IDs](#signal-inventory-using-external-ids) +* [Bid request parameters](#bid-request-parameters) + * [Banner](#banner) + * [Video](#video) + * [Native](#native) +* [Multi-format ad units](#multi-format-ad-units) +* [Examples](#examples) + + + +## Introduction + +Publishers can use Prebid.js to call Index Exchange (Index) in any of the following ways: + +* **Call through our client-side adapter:** Prebid.js calls Index directly from the browser using our client-side adapter. This option tends to have a better cookie match rate. For configuration instructions, see the [Set up Prebid.js to call Index directly from the browser (client-side adapter)](#client-side-adapter) on this page. +* **Call through our server-side adapter**: Prebid.js makes a call to Prebid Server and then Prebid Server uses our server-side adapter to call Index. This reduces workload on the browser. For configuration instructions, see the [Set up Prebid.js to call Index through Prebid Server (server-side adapter)](#server-side-adapter) on this page. + +**Notes:** + +* **Send multiple ad slots in a single bid request**: Index accepts up to 100 valid ad slots in a single bid request. If a single bid request contains more than 100 ad slots (including invalid ad slots), only the first 100 valid ad slots are accepted and the rest are ignored. For example streaming TV media owners can signal multiple ad pods for long-form programming in a single request. +* **How to view bid requests sent to Index:** + * In your browser, open a new tab. + * Open the **Developer tools**. + * In **Developer tools**, click the **Network** tab. + * In the **Network** tab, search for requests sent to `casalemedia.com/cygnus` (from version 6.28.0 and earlier) or `casalemedia.com/openrtb/pbjs` (from version 6.29.0 and later). These are the bid requests sent to Index. +* **Recommended Global Bidder settings:** For our adapter, Index recommends enabling local storage. As of Prebid.js 7.x, local storage access must be explicitly specified. By leveraging local storage, Index is able to take advantage of the latest features our exchange has to offer. For instructions on enabling local storage, see Prebid’s [pbjs.bidderSettings](/dev-docs/publisher-api-reference/bidderSettings.html) documentation. + +### Example +```javascript +pbjs.bidderSettings = { + ix: { + storageAllowed: true + } +}; ``` -Module Name: Index Exchange Adapter -Module Type: Bidder Adapter -Maintainer: prebid.support@indexexchange.com + + + +## Supported media types + +The following table lists the media types that Index supports. For information about the the Time-To-Live (TTL) for each media type, see [How Index counts impressions](https://kb.indexexchange.com/publishers/billing/how_Index_counts_impressions.htm) in our Knowledge Base. + +{: .table .table-bordered .table-striped } + +| Type | Prebid Server support | +| ----------- | ----------- | +| banner | Supported | +| video | Supported | +| native | Supported | + + + +## Set up Prebid.js to call Index directly from the browser (client-side adapter) + +To call Index from a web browser environment using a Prebid Server integration, see the Index-specific configuration steps in [Setup instructions to call Index through Prebid Server](/dev-docs/bidders/ix-server.html#setup-instructions-to-call-index-through-prebid-server) in our Prebid Server documentation on the Prebid site. + + + +## Set up Prebid.js to call Index through Prebid Server (server-side adapter) + +In this configuration, Prebid.js makes a call to Prebid Server and then Prebid Server uses our server-side adapter to call Index. Complete the following steps to configure Index as a demand source: + +1. If you are hosting your own Prebid Server instance, see [Setup instructions to call Index through Prebid Server](/dev-docs/pbs-bidders.html#setup-instructions-to-call-index-through-prebid-server). +2. In the `[pbjs.setConfig()]` function, within the `s2sConfig` property, add `ix` to the `bidders` attribute. +3. Define the Index-specific parameters at the bidder level. For Index's bidder-specific parameters, see the [Bid request parameters](#bid-request-parameters) section below. +4. Define your ad units in the `adUnit` object. For more information about this object, see Prebid's [Ad Unit Reference](/dev-docs/adunit-reference.html) documentation. +5. Enable user syncing by adding the following code in the [pbjs.setConfig()](/dev-docs/publisher-api-reference/setConfig.html) function. Index strongly recommends enabling user syncing through iFrames, though we do also support image-based syncing. This functionality improves DSP user match rates and increases the Index bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. This configuration is optional in Prebid, but required by Index.
      + + ```javascript + pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: ['ix'], + filter: 'include' + } + } + } + }); + ``` + +6. (Optional) Set up First Party Data (FPD). For more information about the data types we support and the instructions for each option, see the [Set up First Party Data (FPD)](#set-up-first-party-data-fpd) section below. +7. (Optional) If you want to monetize instream video, see the [Monetize instream video](#monetize-instream-video) section below. +8. (Optional) If you want to monetize outstream video, you can choose among the following options: + * Use Index's outstream video player. For more information, see the [Index's outstream ad unit](#indexs-outstream-ad-unit) section below. + * Use your own outstream video player. For more information, see [Prebid’s documentation on how to show video ads.](/dev-docs/show-outstream-video-ads.html) +9. (Optional) Configure Prebid Native with Index. For more information, see the [Prebid Native](#prebid-native-configuration) section below. Prebid Native is available from Prebid.js version 7.4.0 or higher. + + + +## Modules to include in your build process + +If you are building the JS binary on your own from source code, follow the instructions in [Prebid.js project README](https://github.com/prebid/Prebid.js/blob/master/README.md#build-optimization). You will need to include the `ixBidAdapter`. If you want to show video ads with Google Ad Manager, also include the `dfpAdServerVideo` module. We highly recommend adding the `gptPreAuction` module as well, which improves a DSP's ability to bid accurately on your supply. The following is an example build command that include these modules:
      +`gulp build --modules=ixBidAdapter,dfpAdServerVideo,gptPreAuction,fooBidAdapter,bazBidAdapter` + +If you are using a JSON file to specify modules, add `ixBidAdapter` and `dfpAdServerVideo` to the modules array as follows: + +```javascript +[ + "ixBidAdapter", + "dfpAdServerVideo", + "gptPreAuction", + "fooBidAdapter", + "bazBidAdapter" +] ``` -## Description + + +## Set up First Party Data (FPD) -Publishers may access Index Exchange's (IX) network of demand sources through our Prebid.js and Prebid Server adapters. Both of these modules are GDPR and CCPA compliant. +You can set up the Prebid.js FPD module using Global data, Index bidder-specific site data, or ad unit-specific data. Index supports deal targeting in all the three FPD types. -### IX Prebid.js Adapter + -This module connects publishers to Index Exchange's (IX) network of demand sources through Prebid.js. This module is GDPR and CCPA compliant. +### Global data -It is compatible with the new Prebid.js 5.0 ad unit format where banner and video properties, including the size parameter, are stored in the `adUnits[].mediaTypes` object. IX still supports both size as an optional parameter and the Missing Sizes feature, but we recommend upgrading to the Prebid.js 5.0 format. +Use this data type to allow all bid adapters to have access to first party data that might be useful in ad targeting. This is available from Prebid.js version 4.30 and above. -For more information about how the `adUnits[].mediaTypes` object is formatted in Prebid.js 5.0, refer to the following example. +To supply data that is accessible to all bidders, use the `[pbjs.setConfig()]` object as illustrated below. Use the `[setBidderConfig()]` function to supply bidder-specific data. For more information about the standard or more detailed examples, see Prebid's [First Party Data Feature](/features/firstPartyData.html) documentation. ```javascript -var adUnits = [{ - // ... +pbjs.setConfig({ + ortb2: { + site: { + ... + }, + user: { + ... + } + } +}); +``` + + + +### Index bidder-specific data + +This data type is available from Prebid version 7.49.0 and above. You can use it to specify key-value pairs that will be included in your query string when targeting deals. For example, if a user visits a news page, you can pass that information by submitting a key-value pair for `category = news`. You can then create a deal in the Index UI and activate the deal only on pages that contain `category = news` as the key-value pair. + +To include the FPD in a bid request, in the `[pbjs.setConfig()]` object at the `ix` bidder level, provide the key-values in the `firstPartyData` parameter. Make sure that you set it before the `pbjs.requestBids` configuration. If you want to change the values, you can update the `pbjs.setConfig` once again. The change will be reflected in all future bid requests. + +```javascript +pbjs.setConfig({ + ix: { + firstPartyData: { + '': '', + '': '', + // ... + } + } +}); +``` + + + +### AdUnit-specific data + +Use this data type to specify key-value pairs at the ad unit level when targeting deals and apply it to all bidders. This will be available from Prebid.js version 7.46 and above. To include the adUnit-specific data in a bid request, see Prebid's [Supplying AdUnit-Specific Data](/features/firstPartyData.html#supplying-adunit-specific-data) documentation. + +```javascript +ortb2Imp: { + ext: { + data: { + pbadslot: "homepage-top-rect", + adUnitSpecificAttribute: "123" + } + } +} +``` + +## Monetize instream video + +Unlike Outstream Video, instream video does not use the Prebid Universal Creative. Instead, video bids provide VAST that Prebid caches to obtain a cache ID that can be retrieved with a URL. The cache ID is passed as a key value to the ad server. + +To monetize instream video, complete the following steps: + +1. Enable a cache endpoint in the `[pbjs.setConfig()]` function as follows: + + ```javascript + pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + ``` + +2. Set up your line items in Google Ad manger by following the instructions in Prebid's [Setting Up Video In GAM](/adops/setting-up-prebid-video-in-dfp.html) documentation. + +## Index's outstream ad unit + +Publishers who are using Index as a bidding adapter in Prebid.js can show outstream video ads on their site using Index's outstream ad unit. This allows a video ad to be placed anywhere on a publisher’s site, such as in-article, in-feed, and more. To use Index's outstream ad unit, you must be on Prebid.js version 5.13 or higher. However, if you are using your own outstream video player, Index's adapter can accept video signals from version 2.41.0 or higher.
      +**Note:** When you use the Index ad unit for outstream video, all impressions are considered viewable, which is similar to how Google's ActiveView counts impressions for outstream. This is because Index plays the outstream video as soon as it is in view and concurrently fires any impression pixels in the VAST. + +To use Index’s outstream ad unit, in your Prebid.js configuration:
      + +1. Perform the following steps in your Prebid.js configuration to create a new section for Index's outstream ad unit: + * Add a new code property under `adUnits`. The code could be the `divID` or the Google Ad Manager adUnit code. + * Within the `adUnits`, add `ix` as a `bidder`. + * At the `adUnit` level, under `mediaTypes`, you must add a `video` object that supports our required video parameters. For more information about which parameters to add, see the [Bid request parameters](#video) section below. This is useful for publishers who want to apply the same settings across all SSPs. + * Optionally, you can add the `video` object at the bidder level under `bids.params`. This is useful for publishers who may want to set up different configurations for different SSPs.
      +**Note:** The `bidder` level video configurations override the `adUnit` level configurations. The `playerConfig` is only a bidder level configuration. +2. (Recommended) To force the Index ad unit as the default player for Index, set `backupOnly` to true (see below example). This configuration allows you to use your own player only when an adapter does not provide their own player. This also forces any adapter that has a player to use their player by default. If no player is provided, by default, we will use our own ad unit script. +3. Configure the ad unit according to the options in the [Bid request parameters](#bid-request-parameters) section below. +4. Depending on your existing Prebid setup, complete one of the following: + * If you have an existing Prebid.js integration for banner, you can use the corresponding line items in your Google Ad Manager (GAM) account to retrieve outstream video demand. For more information, see Prebid's documentation on [How to set up line items](/adops/step-by-step.html). + * If you do not have an existing Prebid.js integration for banner, create a line item in your GAM account that is capable of serving an outstream video ad. For more information about how to do this, see Prebid's documentation on Setting up [Prebid Video in Google Ad Manager](/adops/setting-up-prebid-video-in-dfp.html). +5. Notify your Index Representative and provide your test page URL for validation. They will work with you to test the video ad unit and confirm that outstream video ads are being retrieved.
      + +For more information on how to structure the video object, refer to the following code example:
      + +```javascript +pbjs.addAdUnit({ + code: 'video1', + // This video player would apply to all prebid creatives... + renderer: { + url: 'example.com/publishersCustomRenderer.js', + backupOnly: true, + render: function (bid) { renderAdUnit(...) } + }, mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600] - ] - }, + // Publisher video player video settings... video: { - context: 'instream', - playerSize: [300, 250] + context: 'outstream', + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + placement: 3, + playbackmethod: [6], + skip: 1, + plcmt: 4 + } }, - // ... -}]; + bids: [{ + bidder: 'ix', + params: { + siteId: '9999990', + // Index ad unit video settings... + video: { + //minimum size for Video Player size is 144x144 in pixel + //maxduration can be any. + context: 'outstream', + playerSize: [640, 480], + mimes: ['video/mp4', 'video/webm', 'applications/javascript'], + protocols: [2, 3, 5, 6], + api: [2, 7], + playbackmethod: [6], + skip: 1, + w: 640, + h: 480, + minduration: 5, + maxduration: 60, + delivery: [2], + linearity: 1 + } + } + }] +}); ``` -### Supported Media Types (Prebid.js) -{: .table .table-bordered .table-striped } -| Type | Support | -|---|---| -| `banner` | Fully supported for all IX approved sizes | -| `video` | Fully supported for all IX approved sizes | -| `native` | Not supported | +*Please note that your use of the outstream video player will be governed by and subject to the terms and conditions of i) any master services or license agreement entered into by you and Index Exchange; ii) the information provided on our knowledge base linked [here](https://kb.indexexchange.com/publishers/prebid_integration/outstream_video_prebidjs.htm) and [here](https://kb.indexexchange.com/publishers/guidelines/standard_contractual_clauses.htm), and iii) our [Privacy Policy](https://www.indexexchange.com/privacy/). Your use of Index's outstream video player constitutes your acknowledgement and acceptance of the foregoing.* -### Supported Media Types (Prebid Server) + -{: .table .table-bordered .table-striped } -| Type | Support | -|------|-------| -| `banner` | Fully supported | -| `video` | Fully supported, including ad pods for OTT | -| `native` | Not supported | +## Prebid Native configuration + +Prebid Native is available from Prebid.js version 7.4.0 or higher. We support the three native template rendering options that are provided in [Setting up Prebid Native in Google Ad Manager](/adops/gam-native.html). The following code is an example of a Prebid native setup using Google Ad Manager, but the concept and implementation should be similar for other ad servers.
      + +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + native: { + image: { + required: true, + sizes: [150, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + }, + privacyLink: { + required: false + }, + body: { + required: true + len: 90 + }, + icon: { + required: true, + sizes: [50, 50] + } + } + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '9999990' + } + }] +}); +``` -# Ad Unit or Bidder Parameters + + +## Protected Audience API support + +**Before you begin:** + +* You must have Google Ad Manager and the [fledgeForGpt](/dev-docs/modules/fledgeForGpt.html) module. +* In your Google Ad Manager configuration, make sure that you have not opted out from using the Protected Audience API. For more information about the configuration, see Google's documentation on [Protected Audience API and Ad Manager after Chrome GA](https://support.google.com/admanager/answer/13627134?hl=en&ref_topic=12264880&sjid=10591375417866092080-NA). + +Follow these steps to configure your Prebid.js to specify that your ad slots are enabled for [Protected Audience](https://github.com/WICG/turtledove/blob/main/FLEDGE.md) auctions: + +1. Index recommends that you update your Prebid.js version to 8.37.0 or later.
      +**Note:** Prebid.js version 8.18.0 or later is supported. However, Prebid's `fledgeForGpt` module has been improved in version 8.37.0, which fixes some issues from the earlier version. +2. Build the `fledgeForGpt` module in your Prebid.js configuration by adding `fledgeForGpt` to the list of modules that you are already using. For more information about the module, see Prebid's [Fledge (Protected Audience) for GPT Module](/dev-docs/modules/fledgeForGpt.html) documentation. +3. If you are using a Prebid.js version that is between 8.18.0 and 8.36.0, you must configure your ad units to make them eligible for Protected Audience API demand. You can do this in the global-level configuration, bidder level, or ad-unit level. For more information about the configurations, see Prebid's [Fledge (Protected Audience) for GPT Module](/dev-docs/modules/fledgeForGpt.html) documentation. Index recommends that you do this in the global-level configuration by using the `defaultForSlots` parameter with a value of `1`. The following code is an example of the configuration done at the global level: + + ```javascript + pbjs.que.push(function() { + pbjs.setConfig({ + fledgeForGpt: { + enabled: true, + defaultForSlots: 1 + } + }); + }); + ``` + + **Note:** If you are using the `fledgeForGpt.bidders[]`, make sure that you include `ix` to the list of bidders as follows: + + ```javascript + pbjs.que.push(function() { + pbjs.setConfig({ + fledgeForGpt: { + enabled: true, + bidders: ['ix', /* any other bidders */], + defaultForSlots: 1 + } + }); + }); + ``` + +4. If you are using Prebid.js version 8.37.0 or later, you must complete the following steps to make your ad units eligible for Protected Audience API demand:
      +**Note:** If you continue to use the `fledgeForGpt` property, you will receive a warning message in the console logs stating that the `fledgeForGpt` configuration options will soon be renamed to `paapi`. Therefore, Index recommends that you use the `paapi` property, which is available in Prebid.js version 8.37.0 or later. + * In the `pbjs.setConfig().paapi` field, set the `defaultForSlots` parameter to `1`: + + ```javascript + pbjs.que.push(function() { + pbjs.setConfig({ + paapi: { + enabled: true, + defaultForSlots: 1 + bidders: ['ix', /* any other bidders */], + }); + }); + ``` + + * In the `paapi.gpt.autoconfig` field, set `autoconfig` to `false`. This step is important because, by default, the `fledgeForGpt` module expects the Google Publisher Tag (GPT) ad units to be loaded before the Protected Audience configuration is added to the ad unit. Setting `autoconfig` to `false` will avoid any race conditions resulting from asynchronous libraries being loaded out of order, which would prevent the ad unit from being properly configured for Protected Audience API.
      +**Note:** The `fledgeForGpt.autoconfig` property is also backward compatible and can be used in place of the `paapi.gpt.autoconfig` property. However, Index recommends that you use the `paapi.gpt.autoconfig` property.
      + + ```javascript + pbjs.que.push(function() { + pbjs.setConfig({ + paapi: { + enabled: true, + defaultForSlots: 1 + gpt: { + autoconfig: false + }, + bidders: ['ix', /* any other bidders */], + }); + }); + ``` + + * In the `pbjs.requestBids.bidsBackHandler` function, call the `pbjs.setPAAPIConfigForGPT()` function as follows:
      +**Note:** When calling the `pbjs.setPAAPIConfigForGPT();` function, make sure that you check the following: + * The function must be called in the `bidsBackHandler` each time new bids are requested (for example when refreshing `adSlots`). This is important because, when `autoconfig` is disabled, the `auctionConfig` needs to be associated with a GPT ad unit manually by calling `pbjs.setPAAPIConfigForGPT()`. + * The function must be called before the `pbjs.setTargetingForGPTAsync()` function. This is important because the Protected Audience configuration needs to be associated with a GPT ad unit before the Google Ad Manager call is executed. + + ```javascript + pbjs.requestBids({, , + // ... + bidsBackHandler: function(bids, timedOut, auctionId) { + pbjs.setPAAPIConfigForGPT(); + pbjs.setTargetingForGPTAsync(); + // ... + } + }) + ``` + + + +## Signal inventory using external IDs + +1. In the `pbjs.setBidderConfig` object at the `ix` bidder level, you must configure an `exchangeId` that applies to all your placements as follows. Note that the `exchangeId` is provided by Index. + + ```javascript + pbjs.setBidderConfig({ + bidders: ['ix'], + config: { + exchangeId: 123456 // Exchange-specific seller ID + } + }); + + ``` + +2. Configure `externalId` at the bidder ad unit level under `bids.params`. The following shows an example of a banner ad that includes the `externalId` at the bidder level: + + ```javascript + // Banner + var adUnits = [{ + code: 'banner-div-a', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 600] + ] + } + }, + bids: [{ + bidder: 'ix', + params: { + externalId: "example_value" // External placement ID, which could include an integer or string + } + } + ] + }]; -These params can be specified in the ad unit level, which will be the preferred way going forward with PBJS 5.0 + ``` -Each of the IX-specific parameters provided under the object are detailed here. + -The following parameters are specified in the ad unit `adUnits[].mediaTypes`. This includes each of the IX-specific parameters provided under `adUnits[].bids[].params`. +## Bid request parameters -In Prebid.js versions 5.0 and above, mediaType and sizes are not required to be defined at the ad unit level. +For a list of the OpenRTB fields that Index supports in bid requests, see [List of supported OpenRTB bid request fields for sellers](https://kb.indexexchange.com/publishers/openrtb_integration/list_of_supported_openrtb_bid_request_fields_for_sellers.htm#List_of_supported_OpenRTB_bid_request_fields_for_sellers). The following are the required fields for the various supported media types. ### Banner +You must include these parameters at the bidder level. + {: .table .table-bordered .table-striped } -| Key | Scope | Type | Description | + +| Name | Scope | Type | Description | |---|---|---|---| -| `siteId` | Required | String | An IX-specific identifier that is associated with this ad unit. It will be associated to the single size, if the size provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'3723'`, `'6482'`, `'3639'`| -| `sizes` | Optional | Number[Number[]] | The size/sizes associated with the site ID, as listed in the ad unit under `adUnits[].mediaTypes.banner.sizes`. For example, `[300, 250], [300, 600], [728, 90]`| +| `siteId` | Required | String | An Index-specific identifier that is associated with this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'9999990'`, `'9999991'`, `'9999992'`| ### Video +You must include these parameters at the bidder level. + {: .table .table-bordered .table-striped } -| Key | Scope | Type | Description | + +| Name | Scope | Type | Description | |---|---|---|---| -| `siteId` | Required | String | An IX-specific identifier that is associated with this ad unit. It will be associated to the single size, if the size is provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'3723'`, `'6482'`, `'3639'`| -| `size` | Optional | Number[] | The single size that is associated with the site ID, as listed in the ad unit under `adUnits[].sizes` or `adUnits[].mediaTypes.video.playerSize`. For example, [300, 250], [300, 600].

      This parameter is optional in Prebid.js versions 5.0 and above. Versions prior to 5.0 will still require a size parameter.| -| `video` | Optional | Hash | The video object will serve as the properties of the video ad. You can create any field under the video object that is mentioned in the `OpenRTB Spec v2.5`. Some fields like `mimes, protocols, minduration, maxduration` are required. Properties not defined at this level, will be pulled from the Adunit level.| -| `video.w` | Required | Integer | The video player size width in pixels that will be passed to demand partners.| -| `video.h` | Required | Integer | The video player size height in pixels that will be passed to demand partners.| -| `video.playerSize` | Optional* | Integer | The video player size that will be passed to demand partners. * In the absence of `video.w` and `video.h`, this field is required.| -| `video.mimes` | Required | String[] | Array list of content MIME types supported. Popular MIME types include, but are not limited to, `"video/x-ms- wmv"` for Windows Media and `"video/x-flv"` for Flash Video.| -| `video.minduration` | Required | Integer | Minimum video ad duration in seconds.| -| `video.maxduration` | Required | Integer | Maximum video ad duration in seconds.| -| `video.protocol` / `video.protocols` | Required | Integer / Integer[] | Either a single protocol provided as an integer, or protocols provided as a list of integers. `2` - VAST 2.0, `3` - VAST 3.0, `5` - VAST 2.0 Wrapper, `6` - VAST 3.0 Wrapper| +| `siteId` | Required | String | An Index-specific identifier that is associated with this ad unit. It will be associated with the single size, if the size is provided. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'9999990'`, `'9999991'`, `'9999992'`
      **Note:** You can re-use the existing `siteId` within the same flex position or video size, if the video adapts to the containing `
      ` element.| -## Setup Guide +If you are using Index's outstream ad unit and have placed the video object at the bidder level, you must include the Index required parameters at the bidder level. You can include the optional parameters to specify the outstream player configurations. -Follow these steps to configure and add the IX module to your Prebid.js -integration. +{: .table .table-bordered .table-striped } -The examples in this guide assume the following starting configuration (you may remove banner or video, if either does not apply). +| Name | Scope | Type | Description | +|---|---|---|---| +| `video.w` | Required | Integer | The width of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. We strongly recommend video sizes to be `256 x 256` or greater, `300 x 250`, or `320 x 180`. | +| `video.h` | Required | Integer | The height of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. We strongly recommend video sizes to be `256 x 256` or greater, `300 x 250`, or `320 x 180`. | +| `video.playerSize` | Required | Integer[] | The video player size that will be passed to demand partners. | +| `video.playerConfig` | Optional | Hash | The Index-specific outstream player configurations. | +| `video.playerConfig.floatOnScroll` | Optional | Boolean | A boolean specifying whether you want to use the player's floating capabilities, where:
      - `true`: Use the Index player's float capabilities.
      **Note:** If you set `floatOnScroll` to `true`, Index updates the placement value to `5`.
      **Note:** We do not recommend using the player's default float capabilities if you have more than one outstream ad unit per page.
      - `false`: Do not use the Index player's float capabilities (default). | +| `video.playerConfig.floatSize` | Optional | Integer[] | The height and width of the floating player in pixels. If you do not specify a float size, the player adjusts to the aspect ratio of the player size that is defined when it is not floating. Index recommends that you review and test the float size to your user experience preference. | +| `video.plcmt` | Required | Integer[] | The video's placement type, where:
      - `1` = Instream
      - `2` = Accompanying Content
      - `3` = Interstitial
      - `4` = No Content/Standalone | -In regards to video, `context` can either be `'instream'` or `'outstream'`. Note that `outstream` requires additional configuration on the adUnit. +### Native -```javascript -var adUnits = [{ - code: 'banner-div-a', - mediaTypes: { - banner: { - sizes: [ - [300, 250], - [300, 600] - ] - } - }, - bids: [] -}, -{ - code: 'video-div-a', - mediaTypes: { - video: { - context: 'instream', - playerSize: [1280, 720] - } - }, - bids: [] -}]; -``` +Index supports the same set of native assets that Prebid.js recognizes. For the list of native assets, see [Prebid.js Native Implementation Guide on the Prebid site.](https://docs.prebid.org/prebid/native-implementation.html#3-prebidjs-native-adunit-overview) -### 1. Add IX to the appropriate ad units + -For each size in an ad unit that IX will be bidding on, add one of the following -bid objects under `adUnits[].bids`: +## Multi-format ad units -```javascript -{ - bidder: 'ix', - params: { - siteId: '123456' - } -} -``` +Index supports multi-format ad units, see [Show Multi-Format Ads with Prebid.js](https://docs.prebid.org/dev-docs/show-multi-format-ads.html). For multi-format ad units, you can optionally specify a different siteId for each multi-format type at the bidder level. This is useful if you have deals set up with Index at the siteId level. See multi-format examples [here](#examples). + +The following are the parameters that you can specify for each multi-format type at the bidder level. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Type | Description | +|---|---|---|---| +| `siteId` | Required | String | An Index-specific identifier that is associated with this ad unit. This is similar to a placement ID or an ad unit ID that some other modules have. For example, `'9999990'`, `'9999991'`, `'9999992'`.

      Note: This will also act as the default siteID for multi-format adunits if a format specific siteId is not provided.| +| `banner.siteId` | Optional | String | An Index-specific identifier that is associated with this ad unit. This siteId will be prioritized over the default siteID for `banner` format in the multi-format ad unit.| +| `video.siteId` | Optional | String | An Index-specific identifier that is associated with this ad unit. This siteId will be prioritized over the default siteID for `video` format in the multi-format ad unit.| +| `native.siteId` | Optional | String | An Index-specific identifier that is associated with this ad unit. This siteId will be prioritized over the default siteID for `native` format in the multi-format ad unit.| + + -Set `params.siteId` in the bid object to the values provided -by your IX representative. +## Examples -**Examples** +**Banner** -**Banner:** ```javascript var adUnits = [{ code: 'banner-div-a', @@ -176,43 +565,38 @@ var adUnits = [{ bids: [{ bidder: 'ix', params: { - siteId: '123456' - } - }, { - bidder: 'ix', - params: { - siteId: '123456' + siteId: '9999990' } - }] + } + ] }]; + ``` -**Video (Instream):** + +**Video (instream):**
      +**Note**: `context` can either be `'instream'` or `'outstream'`. + ```javascript var adUnits = [{ code: 'video-div-a', mediaTypes: { video: { - // Preferred location for openrtb v2.5 compatible video obj + // Preferred location as of version 4.43 + video obj context: 'instream', playerSize: [300, 250], - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] + api: [2], + protocols: [2, 3, 5, 6], + minduration: 5, + maxduration: 30, + mimes: ['video/mp4', 'application/javascript'], + placement: 3 } }, bids: [{ bidder: 'ix', params: { - siteId: '12345' - } - }, { - bidder: 'ix', - params: { - siteId: '12345', + siteId: '9999990', video: { // openrtb v2.5 compatible video obj // If required, use this to override mediaTypes.video.XX properties @@ -220,262 +604,140 @@ var adUnits = [{ } }] }]; + ``` -Please note that you can re-use the existing `siteId` within the same flex -position. -**Video (Outstream):** -Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See http://prebid.org/dev-docs/show-outstream-video-ads.html for more information. +**Video (outstream)** ```javascript var adUnits = [{ - code: 'video-div-a', + code: 'div-gpt-ad-1571167646410-1', mediaTypes: { video: { + playerSize: [640, 360], context: 'outstream', - playerSize: [300, 250], - mimes: [ - 'video/mp4', - 'video/webm' - ], - minduration: 0, - maxduration: 60, - protocols: [6] - } - }, - renderer: { - url: 'https://test.com/my-video-player.js', - render: function (bid) { - ... + api: [2], + protocols: [2, 3, 5, 6], + minduration: 5, + maxduration: 30, + mimes: ['video/mp4', 'application/javascript'], + placement: 3, + plcmt: 4, + playbackmethod: 6 } }, bids: [{ bidder: 'ix', params: { - siteId: '12345', + siteId: '9999990' video: { - // If required, use this to override mediaTypes.video.XX properties + playerConfig: { + floatOnScroll: true, + floatSize: [300,250] + } } } }] }]; -``` - -#### Video Caching -Note that the IX adapter expects a client-side Prebid Cache to be enabled for video bidding. - -``` -pbjs.setConfig({ - usePrebidCache: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } -}); ``` -#### User Sync -Add the following code to enable user sync. IX strongly recommends enabling user syncing through iFrames. This functionality improves DSP user match rates and increases the IX bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. +**Prebid Native** -``` -pbjs.setConfig({ - userSync: { - iframeEnabled: true, - filterSettings: { - iframe: { - bidders: ['ix'], - filter: 'include' +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + native: { + image: { + required: true, + sizes: [150, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + }, + privacyLink: { + required: false + }, + body: { + required: true + len: 90 + }, + icon: { + required: true, + sizes: [50, 50] } } - } -}); -``` - -#### The **detectMissingSizes** feature -By default, the IX bidding adapter bids on all banner sizes available in the ad unit when configured to at least one banner size. If you want the IX bidding adapter to only bid on the banner size it’s configured to, switch off this feature using `detectMissingSizes`. -``` -pbjs.setConfig({ - ix: { - detectMissingSizes: false - } -}); -``` -OR -``` -pbjs.setBidderConfig({ - bidders: ["ix"], - config: { - ix: { - detectMissingSizes: false + }, + bids: [{ + bidder: 'ix', + params: { + siteId: '9999990' } - } + }] }); -``` - -### 2. Include `ixBidAdapter` in your build process - -When running the build command, include `ixBidAdapter` as a module, as well as `dfpAdServerVideo` if you require video support. - -``` -gulp build --modules=ixBidAdapter,dfpAdServerVideo,fooBidAdapter,bazBidAdapter -``` - -If a JSON file is being used to specify the bidder modules, add `"ixBidAdapter"` -to the top-level array in that file. - -```json -[ - "ixBidAdapter", - "dfpAdServerVideo", - "fooBidAdapter", - "bazBidAdapter" -] -``` -And then build. - -``` -gulp build --modules=bidderModules.json ``` -## Setting First Party Data (FPD) - -As a part of 4.30, IX will start to pick up FPD in the global FPD module, as well as continue to pick up IX bidder-specific FPD. Previous versions of IX Bid Adapter will only support the IX bidder-specific FPD. - -### Global FPD - -As of Prebid.js 4.30, use the more generic `ortb2` interface, which can be used for more than just First Party Data. +**Multi-format SiteId Overrides** -The First Party Data feature allows publishers to specify key/value data in one place where each compatible bid adapter can read it. - -To supply global data, use the [`setConfig()`](/dev-docs/publisher-api-reference/setConfig.html) function as illustrated below: - -``` -pbjs.setConfig({ - ortb2: { - site: { - ... +```javascript +var adUnits = [{ + code: slot.code, + mediaTypes: { + + banner: { + sizes: [300,250] + }, + native: { + title: { + required: false + }, + image: { + required: true + }, + sponsoredBy: { + required: false + }, + body: { + required: false + } }, - user: { - ... + + video: { + playerSize: sizes, + context: 'outstream', + api:[2], + protocols: [2, 3, 5, 6], + minduration: 5, + maxduration: 30, + mimes: ['video/mp4','application/javascript'] } - } -}); -``` - -Use the [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html) function to supply bidder-specific data. - -For more information about the standard or more detailed examples, refer to [First Party Data Feature](/features/firstPartyData.html). - -### IX bidder-specific FPD - -FPD allows you to specify key-value pairs that are passed as part of the -query string to IX for use in Private Marketplace Deals which rely on query -string targeting for activation. For example, if a user is viewing a -news-related page, you can pass on that information by sending `category=news`. -Then in the IX Private Marketplace setup screens, you can create Deals which -activate only on pages that contain `category=news`. Please reach out to your -IX representative if you have any questions or need help setting this up. - -To include FPD in a bid request, it must be set before `pbjs.requestBids` is -called. To set it, call `pbjs.setConfig` and provide it with a map of FPD keys -to values as such: - -```javascript -pbjs.setConfig({ - ix: { - firstPartyData: { - '': '', - '': '', - // ... - } - } -}); -``` - -The values can be updated at any time by calling `pbjs.setConfig` again. The -changes will be reflected in any proceeding bid requests. - -{: .alert.alert-warning :} -Continue to use IX bidder-specific First Party Data for IX deals. Global First Party Data is not yet supported in IX deals. Consult your IX representative with any questions. - -## Setting a Server Side Timeout - -Setting a server-side timeout allows you to control the max length of time taken to connect to the server. The default value when unspecified is 50ms. - -This is distinctly different from the global bidder timeout that can be set in -Prebid.js in the browser. - -To add a server-side timeout, it must be set before `pbjs.requestBids` is -called. To set it, call `pbjs.setConfig` and provide it with a timeout value as -such: - -```javascript -pbjs.setConfig({ - ix: { - timeout: 50 - } -}); -``` - -The timeout value must be a positive whole number in milliseconds. - -## IX Prebid Server Adapter - -Publishers who would like to retrieve IX demand via a Prebid Server instance can do so by adding IX to the list of bidders for a Prebid Server bid request, with a valid site ID. For example: - -```javascript -"imp": [ - { - "id": "test2", - "banner": { - "format": [ - { - "w": 300, - "h": 600 - } - ] - }, - "ext": { - "ix": { - "siteId": "12345" - } - } - } + }, + bids: [ + { + bidder: 'ix', + params: { + siteId: '9999990', + video: { + siteId: '9999991' + }, + native: { + siteId: '9999992' + }, + banner: { + siteId: '9999993' + } + } + }, ] -``` - -### Important Prebid Server Note -Any party operating their own hosted Prebid Server instances must reach out to IX (prebid.support@indexexchange.com) to receive approval and customized setup instructions. Please do not send Prebid Server requests without first contacting us -- you will not receive bid responses. - -## Additional Information - -### Bid Request Limit - -If a single bid request to IX contains more than 20 impression requests (i.e. -more than 20 objects in `bidRequest.imp`), only the first 20 will be accepted, -the rest will be ignored. - -To avoid this situation, ensure that when `pbjs.requestBid` is invoked, that the -number of bid objects (i.e. `adUnits[].bids`) with `adUnits[].bids[].bidder` set -to `'ix'` across all ad units that bids are being requested for does not exceed 20. - -### Time-To-Live (TTL) - -Banner bids from IX have a TTL of 300 seconds while video bids have a TTL of 1 hour, after which time they become invalid. - -If an invalid bid wins, and its associated ad is rendered, it will not count -towards total impressions on IX's side. - -## FAQs - -#### Why do I have to input size in `adUnits[].bids[].params` for IX when the size is already in the ad unit? - -If you are using Prebid.js version 5.0 and above, the `size` parameter is not a required field. Only the `siteID` is required, and it is stored with the sizes in the ad unit. - -#### How can I view the bid request sent to IX by Prebid.js? +}]; -In your browser of choice, create a new tab and open the developer tools. In -developer tools, select the network tab. Then, navigate to a page where IX is -set up to bid. Now, in the network tab, search for requests to -`casalemedia.com/cygnus`. These are the bid requests. +``` diff --git a/dev-docs/bidders/janet.md b/dev-docs/bidders/janet.md new file mode 100644 index 0000000000..b2ba8ba8b6 --- /dev/null +++ b/dev-docs/bidders/janet.md @@ -0,0 +1,122 @@ +--- +layout: bidder +title: JANet +description: Prebid JANet Bidder Adapter +biddercode: janet +aliasCode: adtelligent +media_types: video,banner +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: true +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from janet. | `529814` | `integer` | + +### Description + +JANet header bidding adapter connects with JANet demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'janet', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'janet', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'janet', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'janet', + params: { + aid: 529814 + } + }] + } + ]; +``` + +### Additional Configuration + +It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request +(default value is 10). + +``` javascript + pbjs.setBidderConfig({ + config: { + janet: { + chunkSize: 1 // makes 1 http request per 1 adunit configured + } + } + }); +``` diff --git a/dev-docs/bidders/jcm.md b/dev-docs/bidders/jcm.md deleted file mode 100644 index bb54e79087..0000000000 --- a/dev-docs/bidders/jcm.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: J Carter Marketing -description: Prebid J Carter Marketing Bidder Adaptor -pbjs: true -biddercode: jcm -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `id` | required | | | `string` | -| `siteId` | required | | | `string` | -| `tier2SiteID` | optional | | | `string` | -| `tier3SiteID` | optional | | | `string` | diff --git a/dev-docs/bidders/jixie.md b/dev-docs/bidders/jixie.md index e2945d6bc5..2caf7f9efd 100644 --- a/dev-docs/bidders/jixie.md +++ b/dev-docs/bidders/jixie.md @@ -7,12 +7,14 @@ pbs: true biddercode: jixie deals_supported: false media_types: banner, video -gdpr_supported: false +userIds: uid2, unifiedId +tcfeu_supported: false +sidebarType: 1 --- ### Registration -To use this bidder you will need an account and a valid unit from us. For further information, please contact contact@jixie.io +To use this bidder you will need an account and a valid unit from us. For further information, please contact ### Bid Params @@ -23,4 +25,3 @@ To use this bidder you will need an account and a valid unit from us. For furthe | `accountid` | optional | The accountid from jixie | `'12345678901234567890'` | `string` | | `jxprop1` | optional | special property #1 | `'somethingspecial1'` | `string` | | `jxprop2` | optional | special property #2 | `'somethingspecial2'` | `string` | - diff --git a/dev-docs/bidders/justpremium.md b/dev-docs/bidders/justpremium.md index f5eebddc3c..f2bcfd7e3e 100644 --- a/dev-docs/bidders/justpremium.md +++ b/dev-docs/bidders/justpremium.md @@ -4,10 +4,12 @@ title: Justpremium description: Prebid Justpremium Bidder Adaptor pbjs: true biddercode: justpremium -gdpr_supported: true +gvl_id: 62 +tcfeu_supported: true usp_supported: true schain_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +sidebarType: 1 --- diff --git a/dev-docs/bidders/jwplayer.md b/dev-docs/bidders/jwplayer.md new file mode 100644 index 0000000000..ca47edf0b2 --- /dev/null +++ b/dev-docs/bidders/jwplayer.md @@ -0,0 +1,303 @@ +--- +layout: bidder +title: JW Player +description: Prebid JW Player Bidder Adapter +biddercode: jwplayer +gvl_id: 1046 +pbjs: true +pbs: false +media_types: no-display, video +userIds: all (with commercial activation) +tcfeu_supported: true +dsa_supported: true +prebid_member: true +schain_supported: true +coppa_supported: true +usp_supported: true +floors_supported: true +fpd_supported: true +deals_supported: true +prebid_member: yes +sidebarType: 1 +--- + + + +## Table of contents + +* [Table of contents](#table-of-contents) +* [Introduction](#introduction) +* [Modules to include in your build process](#modules-to-include-in-your-build-process) +* [Bid Params](#bid-request-parameters) + * [Required Bidder Params](#required-bidder-params) + * [mediaTypes.video](#mediatypes-video) + * [First Party Data (FPD)](#set-up-first-party-data-fpd) +* [Examples](#examples) + + + +## Introduction + +The JW Player Bid Adapter allows publishers to tap into JW Player's Video Advertising Demand. +Publishers are not required to use JW Player as a video player. +Instream and outstream video ads are supported. + + + +## Modules to include in your build process + +You will need to include the `jwplayerBidAdapter` in your build. If you are building the JS binary on your own from source code, follow the instructions in [Prebid.js project README](https://github.com/prebid/Prebid.js/blob/master/README.md#build-optimization). +We recommend including the [jwplayerVideoProvider](dev-docs/modules/jwplayerVideoProvider.md) to connect Prebid.js to your JW Player instance via the [Prebid Video Module](prebid-video/video-module.md). +If you are not using the JW Player Video Provider, we suggest including the JW Player Real Time Data Provider [jwplayerRtdProvider](dev-docs/modules/jwplayerRtdProvider.md) in order to include JW Player's contextual ad targeting segments in your bid requests. + +The following is an example build command that include these modules:
      +`gulp build --modules=jwplayerBidAdapter,jwplayerVideoProvider`
      +or
      +`gulp build --modules=jwplayerBidAdapter,jwplayerRtdProvider` + +If you are using a JSON file to specify modules, add `jwplayerBidAdapter`, `jwplayerVideoProvider` and `jwplayerRtdProvider` to the modules array as follows: + +```javascript +[ + "jwplayerBidAdapter", + "jwplayerVideoProvider" +] +``` + +or + +```javascript +[ + "jwplayerBidAdapter", + "jwplayerRtdProvider" +] +``` + + + +## Bid Params + +We support all oRTB params and encourage populating as many as possible. + + + +### Required Bidder params + +You must include the following parameters at the bidder level, in `adUnit.bids[index].params`. + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | +|---|---|---|------------------------------------------------------| +| `siteId` | Required | String | Site-specific id that is provided by JW Player. | +| `publisherId` | Required | String | Publisher-specific id that is provided by JW Player. | +| `placementId` | Required | String | Placement-specific id that is provided by JW Player. | + + + +### mediaTypes.video + +We recommend populating as many params as possible in `adUnit.mediaTypes.video`. When using the [jwplayerVideoProvider](dev-docs/modules/jwplayerVideoProvider.md), these fields are populated automatically. + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | +|--------------------|-------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `video.w` | Recommended | Integer | Populated automatically when using the `jwplayerVideoProvider`. The width of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. | +| `video.h` | Recommended | Integer | Populated automatically when using the `jwplayerVideoProvider`. The height of the video player in pixels that will be passed to demand partners. You must define the size of the video player using the `video.w` and `video.h` parameters. | +| `video.plcmt` | Recommended | Integer | The video's placement type, where:
      - `1` = Instream
      - `2` = Accompanying Content
      - `3` = Interstitial
      - `4` = No Content/Standalone | + + + +### First Party Data (FPD) + +In release 4.30 and later, publishers who are not using the [jwplayerVideoProvider](dev-docs/modules/jwplayerVideoProvider.md) or [jwplayerRtdProvider](dev-docs/modules/jwplayerRtdProvider.md) can use the ortb2 method of setting First Party Data. +The following fields are required: + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | +|--------------------|-------------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `site.content.url` | Required | string | Populated automatically when the `jwplayerVideoProvider` or `jwplayerRtdProvider` are included. This is the URL of the media being rendered in the video player, for buy-side contextualization or review. This needs to be accessible (w/o DRM, Geo-blocking etc.) and without parameters (Such as size, quality etc.) | +| `site.page` | Required | string | URL of the page where the impression will be shown. | + +To supply data that is accessible to all bidders, use the `[pbjs.setConfig()]` object as illustrated below. Use the `[setBidderConfig()]` function to supply bidder-specific data. For more information about the standard or more detailed examples, see Prebid's [First Party Data Feature](/features/firstPartyData.html) documentation. + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + ... + }, + user: { + ... + } + } +}); +``` + + + +## Examples + +### With the JW Player Video Provider + +```javascript +const adUnit = { + code: 'test-ad-unit', + mediaTypes: { + video: {} // automatically populated by the Video Provider + }, + video: { + divId: 'player', // required to indicate which player is being used to render this ad unit. + }, + + bids: [{ + bidder: 'jwplayer', + params: { + publisherId: 'test-publisher-id', + siteId: 'test-site-id', + placementId: 'test-placement-id' + } + }] +}; + +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function () { + pbjs.setConfig({ + video: { + providers: [{ + divId: 'player', // must match the divId in the adUnit + vendorCode: 1, // JW Player vendorCode + playerConfig: { + licenseKey: 'LICENSE_KEY_HERE', + params: { + vendorConfig: { + mediaid: 'XYXYXYXY', + file: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/SubaruOutbackOnStreetAndDirt.mp4', + title: 'Subaru Outback On Street And Dirt', + description: 'Smoking Tire takes the all-new Subaru Outback to the highest point we can find in hopes our customer-appreciation Balloon Launch will get some free T-shirts into the hands of our viewers.', + advertising: {client: 'googima'} + } + } + } + }], + } + }); +}); + +pbjs.addAdUnits([adUnit]); +``` + +### With the JW Player RTD Provider + +```javascript +const adUnit = { + code: 'test-ad-unit', + mediaTypes: { + video: { + pos: 0, + w: 640, + h: 480, + mimes : ['application/vnd.apple.mpegurl', 'video/mp4'], + minduration : 0, + maxduration: 60, + protocols : [2,3,7,5,6,8], + startdelay: 0, + placement: 1, + plcmt: 1, + skip: 1, + skipafter: 10, + playbackmethod: [3], + api: [2], + linearity: 1 + } + }, + bids: [{ + bidder: 'jwplayer', + params: { + publisherId: 'test-publisher-id', + siteId: 'test-site-id', + placementId: 'test-placement-id' + } + }] +}; + +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function() { + pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: "jwplayer", + waitForIt: true, + params: { + mediaIDs: ['test-media-id'], + overrideContentUrl: 'always', + overrideContentId: 'always', + overrideContentTitle: 'always', + overrideContentDescription: 'always' + } + }] + }, + ortb2: { + site: { + content: { + url: 'test.mp4' // Necessary only when bidding before the JW Player instance is instantiated. + } + } + } + }); +}); +``` + +### Without the JW Player additional modules + +```javascript +const adUnit = { + code: 'test-ad-unit', + mediaTypes: { + video: { + pos: 0, + w: 640, + h: 480, + mimes : ['application/vnd.apple.mpegurl', 'video/mp4'], + minduration : 0, + maxduration: 60, + protocols : [2,3,7,5,6,8], + startdelay: 0, + placement: 1, + plcmt: 1, + skip: 1, + skipafter: 10, + playbackmethod: [3], + api: [2], + linearity: 1 + } + }, + bids: [{ + bidder: 'jwplayer', + params: { + publisherId: 'test-publisher-id', + siteId: 'test-site-id', + placementId: 'test-placement-id' + } + }] +}; + +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function() { + pbjs.setConfig({ + ortb2: { + site: { + content: { + url: 'test.mp4' + }, + page: 'your-page-url' + } + } + }); +}); +``` diff --git a/dev-docs/bidders/kargo.md b/dev-docs/bidders/kargo.md index 562d797b4d..9a3d684579 100644 --- a/dev-docs/bidders/kargo.md +++ b/dev-docs/bidders/kargo.md @@ -2,21 +2,87 @@ layout: bidder title: Kargo description: Prebid Kargo Bidder Adaptor +gvl_id: 972 pbjs: true biddercode: kargo -media_types: banner, video -gdpr_supported: true +media_types: banner, video, native +tcfeu_supported: true userIds: unifiedId usp_supported: true -gvl_id: 972 +coppa_supported: false +schain_supported: true +dchain_supported: true +safeframes_ok: false +deals_supported: true +floors_supported: true +fpd_supported: false +pbs: true +pbs_app_supported: false +prebid_member: true +gpp_supported: true +multiformat_supported: will-bid-on-any +pbjs_version_notes: if you require schains, avoid versions 7.46 to 7.53 +sidebarType: 1 --- -### Note: +### Disclosure + +This adapter is known to use an HTTP 1 endpoint. Header bidding often generates multiple requests to the same host and bidders are encouraged to change to HTTP 2 or above to help improve publisher page performance via multiplexing. + +### Note + Kargo is an invitation-only marketplace. Please reach out to your Kargo account manager to get setup. Also, you *must* test on a mobile device, or emulate a mobile device by manipulating the user agent string sent to the server. +### Bidder Settings + +The Kargo bid adapter uses browser local storage. Since Prebid.js 7.x, the access to it must be explicitly set. + +```js +// https://docs.prebid.org/dev-docs/publisher-api-reference/bidderSettings.html +pbjs.bidderSettings = { + kargo: { + storageAllowed: true + } +} +``` + ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------|---------|----------| -| `placementId` | required | | | `string` | +| `placementId` | required | The placementId of the ad slot. |`'_jWuc8Hks'`| `string` | + +### ORTB Blocking + +Kargo supports blocking advertisers in `badv` and categories in `bcat` parameters. +The blocked advertisers/categories list has no length limitation, but response timeout is more likely to occur as the number of entries grow. +Blocked advertisers list (`badv`) is an array of domains as strings. +Blocked categories list (`bcat`) is an array of IAB categories as strings. + +For example: + +#### Globally defined ORTB Blocking + +```javascript +pbjs.setConfig({ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } +)}; +``` + +#### ORTB Blocking specific only to the Kargo bidder + +```javascript +pbjs.setBidderConfig({ + bidders: ['kargo'], + config:{ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } + } +}); +``` diff --git a/dev-docs/bidders/kidoz.md b/dev-docs/bidders/kidoz.md index 49b4712ca6..003339a257 100644 --- a/dev-docs/bidders/kidoz.md +++ b/dev-docs/bidders/kidoz.md @@ -4,9 +4,10 @@ title: Kidoz pbs: true media_types: banner biddercode: kidoz -gdpr_supported: true +tcfeu_supported: false coppa_supported: true pbs_app_supported: true +sidebarType: 1 --- ### Registration @@ -14,7 +15,7 @@ pbs_app_supported: true Kidoz is exclusively for Mobile app COPPA compatible ads, 100% kid relevant and appropriate. In order for a company to receive bids from Kidoz, they must first open a publisher account at Kidoz.net -(https://accounts.kidoz.net/publishers/register) and accept the Kidoz Terms and Conditions and Privacy Policy. +() and accept the Kidoz Terms and Conditions and Privacy Policy. Kidoz publishers must confirm that all of their content properties are COPPA and GDPR compliant and perform no monitoring or tracking of U13 users in their operations. New publishers are provided a Publisher ID and AccessToken, this can also be used to login to their dashboard at the Kidoz.net portal to monitor their account activity. diff --git a/dev-docs/bidders/kimberlite.md b/dev-docs/bidders/kimberlite.md new file mode 100644 index 0000000000..350f1192a5 --- /dev/null +++ b/dev-docs/bidders/kimberlite.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Kimberlite +description: Prebid Kimberlite Bidder Adapter +biddercode: kimberlite +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +gpp_supported: false +schain_supported: false +dchain_supported: false +media_types: banner +safeframes_ok: false +deals_supported: true +floors_supported: true +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-not-bid +ortb_blocking_supported: partial +sidebarType: 1 +--- + +### Note + +The Kimberlite Bidding adapter requires setup. Please contact us at . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement ID | `'123'` | `string` | diff --git a/dev-docs/bidders/kiviads.md b/dev-docs/bidders/kiviads.md new file mode 100644 index 0000000000..bd4c4c0550 --- /dev/null +++ b/dev-docs/bidders/kiviads.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Kivi +description: Prebid Kivi Bidder Adapter +biddercode: kiviads +media_types: banner, video, native +pbjs: true +pbs: true +safeframes_ok: true +floors_supported: true +fpd_supported: false +multiformat_supported: will-not-bid +ortb_blocking_supported: partial +pbs_app_supported: true +tcfeu_supported: false +usp_supported: true +coppa_supported: true +deals_supported: false +schain_supported: true +dchain_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/kobler.md b/dev-docs/bidders/kobler.md index 9711b385c4..626aa435cb 100644 --- a/dev-docs/bidders/kobler.md +++ b/dev-docs/bidders/kobler.md @@ -7,9 +7,10 @@ pbjs: true media_types: banner floors_supported: true deals_supported: true +sidebarType: 1 --- -### Note: +### Note The Kobler Bidder Adapter requires setup and approval from Kobler AS. Please reach out to for more information. @@ -19,14 +20,16 @@ Please reach out to for more information. {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|--------------------| -| `placementId` | required | The identifier of the placement, it has to be issued by Kobler. | `'xjer0ch8'` | `string` | -| `zip` | optional | Zip code of the user or the medium. When multiple ad units are submitted together, it is enough to set this parameter on the first one. | `'102 22'` | `string` | -| `test` | optional | Whether the request is for testing only. When multiple ad units are submitted together, it is enough to set this parameter on the first one. Defaults to false. | `true` | `boolean` | +| `test` | optional | Whether the request is for testing only. When multiple ad units are submitted together, it is enough to set this parameter on the first one. Enables providing a custom URL through config.pageUrl. Defaults to false. | `true` | `boolean` | | `floorPrice` | optional | Floor price in CPM and in USD. Can be used as an alternative to the [Floors module](https://docs.prebid.org/dev-docs/modules/floors.html), which is also supported by this adapter. Defaults to 0. | `5.0` | `float` | -| `position` | optional | The position of the ad unit. Can be used to differentiate between ad units if the same placement ID is used across multiple ad units. The first ad unit should have a position of 0, the second one should have a position of 1 and so on. Defaults to 0. | `1` | `string` | | `dealIds` | optional | Array of deal IDs. | `['abc328745', 'mxw243253']` | `array of strings` | +### Implicit parameters + +Kobler identifies the placement using the combination of the page URL and the allowed sizes. As a result, it's important that the correct sizes are provided in `banner.sizes` in order for Kobler to correctly identify the placement. The main, desired format should be the first element of this array. + ### Example + ```javascript const adUnits = [{ code: 'div-gpt-ad-1460505748561-1', @@ -36,19 +39,18 @@ Please reach out to for more information. } }, bids: [{ - bidder: 'kobler', - params: { - placementId: 'k5H7et3R0' - } + bidder: 'kobler' }] }]; ``` In order to see a sample bid from Kobler (without a proper setup), you have to also do the following: -- Change the [`refererInfo` function](https://github.com/prebid/Prebid.js/blob/master/src/refererDetection.js) to return `'https://www.tv2.no/a/11734615'` as a [`referer`](https://github.com/prebid/Prebid.js/blob/caead3ccccc448e4cd09d074fd9f8833f56fe9b3/src/refererDetection.js#L169). This is necessary because Kobler only bids on recognized articles. -- Change the adapter's [`BIDDER_ENDPOINT`](https://github.com/prebid/Prebid.js/blob/master/modules/koblerBidAdapter.js#L8) to `'https://bid-service.dev.essrtb.com/bid/prebid_rtb_call'`. This endpoint belongs to the development server that is set up to always return a bid for the correct `placementId` and page URL combination. + +- Set the `test` parameter to `true`. +- Set `config.pageUrl` to `'https://www.tv2.no/mening-og-analyse/14555348/'`. This is necessary because Kobler only bids on recognized articles. Kobler runs its own test campaign to make sure there is always a bid for this specific page URL. ### Example With Optional Parameters + ```javascript const adUnits = [{ code: 'div-gpt-ad-1460505748561-1', @@ -60,11 +62,8 @@ In order to see a sample bid from Kobler (without a proper setup), you have to a bids: [{ bidder: 'kobler', params: { - placementId: 'k5H7et3R0', - zip: '102 22', test: true, floorPrice: 5.0, - position: 1, dealIds: ['abc328745', 'mxw243253'] } }] diff --git a/dev-docs/bidders/komoona.md b/dev-docs/bidders/komoona.md deleted file mode 100644 index bf5d0c0331..0000000000 --- a/dev-docs/bidders/komoona.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Komoona -description: Prebid Komoona Bidder Adaptor -pbjs: true -biddercode: komoona -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------------------|--------------------------------------|----------| -| `hbid` | required | header-bidding id from Komoona | `'1f5b2c10e66e419580bd943b9af692ab'` | `string` | -| `placementId` | required | placement id from Komoona | `'e69148e0ba6c4c07977dc2daae5e1577'` | `string` | diff --git a/dev-docs/bidders/krushmedia.md b/dev-docs/bidders/krushmedia.md index 90b4734ed9..2704296d11 100644 --- a/dev-docs/bidders/krushmedia.md +++ b/dev-docs/bidders/krushmedia.md @@ -9,6 +9,7 @@ media_types: banner, video, native gdpr: true pbjs: true pbs: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/kubient.md b/dev-docs/bidders/kubient.md index f8f124fa63..27d232d3a2 100644 --- a/dev-docs/bidders/kubient.md +++ b/dev-docs/bidders/kubient.md @@ -7,15 +7,15 @@ pbs: true schain_supported: true biddercode: kubient media_types: banner, video -gdpr_supported: true +tcfeu_supported: true usp_supported: true +coppa_supported: true tcf2_supported: true -pbjs: true -pbs: true gvl_id: 794 +sidebarType: 1 --- -### Note: +### Note The Kubient Bidder Adapter requires setup and approval before beginning. Please reach out to for more details. @@ -76,4 +76,3 @@ var adUnits = [ | Name | Scope | Description | Example | Type | |--------|----------|--------------------------------------------------|--------------------------|----------| | zoneid | required | The AdUnit or Tag specific ID | `'5fbb948f1e22b'` | `string` | - diff --git a/dev-docs/bidders/kueez.md b/dev-docs/bidders/kueez.md new file mode 100644 index 0000000000..075560da12 --- /dev/null +++ b/dev-docs/bidders/kueez.md @@ -0,0 +1,25 @@ +--- +layout: bidder +title: Kueez +description: Prebid Kueez Bidder Adapter +multiformat_supported: will-bid-on-any +pbjs: true +biddercode: kueez +media_types: banner, video +schain_supported: true +gvl_id: 1165 +tcfeu_supported: true +usp_supported: true +floors_supported: true +userIds: all +fpd_supported: true +sidebarType: 1 +--- + +### IMPORTANT NOTICE + +**TL;DR** +The `kueez` adapter is currently "on hold" in favor of the [KueezRTB bidder](/dev-docs/bidders/kueezrtb.html). +Please contact your Account Manager/Executive for details. + +Go To KueezRTB diff --git a/dev-docs/bidders/kueezrtb.md b/dev-docs/bidders/kueezrtb.md new file mode 100644 index 0000000000..c8bc315898 --- /dev/null +++ b/dev-docs/bidders/kueezrtb.md @@ -0,0 +1,71 @@ +--- +layout: bidder +title: KueezRTB +description: Prebid KueezRTB Bidder Adaptor +biddercode: kueezrtb +filename: kueezRtbBidAdapter +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +gpp_supported: true +floors_supported: true +media_types: banner, video +prebid_member: false +safeframes_ok: false +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +gvl_id: 1165 +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|-------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from KueezRTB. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from KueezRTB. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | optional | The minimum bid value desired. KueezRTB will not respond with bids lower than this value. | `0.90` | `float` | + +## Example + + ```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'kueezrtb', + params: { + cId: '562524b21b1c1f08117fc7f9', // Required - PROVIDED DURING SETUP... + pId: '59ac17c192832d0011283fe3', // Required - PROVIDED DURING SETUP... + bidFloor: 1.23 // Optional + } + }] + } +]; + +// configure pbjs to enable user syncing +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: 'kueezrtb', + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/kumma.md b/dev-docs/bidders/kumma.md index 841702782a..56340aa4d6 100644 --- a/dev-docs/bidders/kumma.md +++ b/dev-docs/bidders/kumma.md @@ -5,7 +5,8 @@ description: Prebid Kumma Bidder Adapter pbjs: true biddercode: kumma media_types: banner, native, video -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid Params @@ -23,73 +24,73 @@ gdpr_supported: true ### test params -``` - var adUnits = [{ - code: 'dfp-native-div', - mediaType: 'native', - mediaTypes: { - native: { - title: { - required: true, - len: 75 - }, - image: { - required: true - }, - body: { - len: 200 - }, - icon: { - required: false - } - } - }, - bids: [{ - bidder: 'kumma', - params: { - pubId: '29521', - siteId: '26048', - placementId: '123', - } - }] - }, - { - code: 'dfp-banner-div', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ], - } - }, - bids: [{ - bidder: 'kumma', - params: { - pubId: '29521', - siteId: '26049', - placementId: '123', - } - }] - }, - { - code: 'dfp-video-div', - sizes: [640, 480], - mediaTypes: { - video: { - context: "instream" - } - }, - bids: [{ - bidder: 'kumma', - params: { - pubId: '29521', - siteId: '26049', - placementId: '123', - video: { - skippable: true, - } - } - }] - } - ]; +```javascript +var adUnits = [{ + code: 'dfp-native-div', + mediaType: 'native', + mediaTypes: { + native: { + title: { + required: true, + len: 75 + }, + image: { + required: true + }, + body: { + len: 200 + }, + icon: { + required: false + } + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26048', + placementId: '123', + } + }] + }, + { + code: 'dfp-banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250] + ], + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26049', + placementId: '123', + } + }] + }, + { + code: 'dfp-video-div', + sizes: [640, 480], + mediaTypes: { + video: { + context: "instream" + } + }, + bids: [{ + bidder: 'kumma', + params: { + pubId: '29521', + siteId: '26049', + placementId: '123', + video: { + skippable: true, + } + } + }] + } +]; ``` diff --git a/dev-docs/bidders/lasso.md b/dev-docs/bidders/lasso.md new file mode 100644 index 0000000000..3c296a5d90 --- /dev/null +++ b/dev-docs/bidders/lasso.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Lasso +description: Prebid Lasso Bidder Adaptor +biddercode: lasso +pbjs: true +pbs: false +media_types: banner +tcfeu_supported: false +gvl_id: none +coppa_supported: true +usp_supported: true +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: false +multiformat_supported: will-not-bid +sidebarType: 1 +--- + +### Note + +The Lasso Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------------------|--------------------------------------|----------| +| `adUnitId` | required | Unique adUnitId from Lasso | `'12345'` | `string` | diff --git a/dev-docs/bidders/lemma.md b/dev-docs/bidders/lemma.md deleted file mode 100644 index fd3d712113..0000000000 --- a/dev-docs/bidders/lemma.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: bidder -title: LEMMA -description: Prebid Lemma Bidder Adapter -pbjs: true -biddercode: lemma -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Integration Note: - -Lemma bidder adapter requires setup and approval from the Lemma team. Please reach out to your account manager for more information and to start using it. - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -| ------------------- | -------- | ------------------------------------- | ------------ | --------- | -| `pubId` | required | The publisher ID from Lemma | `1001` | `integer` | -| `adunitId` | required | Identifier for specific ad adunit | `1001` | `integer` | -| `bidFloor` | optional | The minimum bid value | `1.07` | `float` | diff --git a/dev-docs/bidders/lemmadigital.md b/dev-docs/bidders/lemmadigital.md new file mode 100644 index 0000000000..9fb79336dc --- /dev/null +++ b/dev-docs/bidders/lemmadigital.md @@ -0,0 +1,150 @@ +--- +layout: bidder +title: LemmaDigital +description: Prebid Lemmadigital Bidder Adapter +biddercode: lemmadigital +media_types: video,banner +pbjs: true +pbs: true +schain_supported: true +floors_supported: true +pbs_app_supported: true +multiformat_supported: will-bid-on-one +safeframes_ok: true +ortb_blocking_supported: partial +userIds: all +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `pid` | required (for prebid-server) | Lemmadigital publisher Id provided by your Lemma representative | `1` | `integer` | +| `aid` | required (for prebid-server) | Lemmadigital ad unit Id provided by your Lemma representative | `3768` | `integer` | +| `pubId` | required (for prebid.js) | Lemmadigital publisher Id provided by your Lemma representative | `1` | `integer` | +| `adunitId` | required (for prebid.js) | Lemmadigital ad unit Id provided by your Lemma representative | `3768` | `string` | +| `device_type` | optional (for prebid.js) | Device Type | `'2'` | `integer` | +| `latitude` | optional (for prebid.js) | Latitude | `'40.712775'` | `string` | +| `longitude` | optional (for prebid.js) | Longitude | `'-74.005973'` | `string` | +| `currency` | optional (for prebid.js) | Currency | `'USD'` | `string` | +| `bidFloor` | optional (for prebid.js) | Bid Floor | `1.00` | `integer` | +| `category` | optional (for prebid.js) | Allowed categories | `[ 'IAB1-5', 'IAB1-6' ]` | `array of strings` | +| `page_category` | optional (for prebid.js) | Allowed page categories | `[ 'IAB1-5', 'IAB1-6' ]` | `array of strings` | + +### Description + +Get access to multiple demand partners across lemmadigital AdExchange and maximize your yield with lemmadigital header bidding adapter. + +lemmadigital header bidding adapter connects with lemmadigital demand sources in order to fetch bids. This adapter provides a solution for accessing Video demand and display demand. + +### video parameters + +The Lemmadigital adapter supports video + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | +| :----------------------| :------- | :---------------------------------------------------------- | :------ | +| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | +| `video.skippable` | optional | If 'true', user can skip ad | `true` | +| `video.minduration` | optional | Minimum ad duration in seconds | `5` | +| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | +| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | + +### AdUnit Format for Video + +```javascript +var videoAdUnits = [ +{ + code: 'test-div-video', + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream' + } + }, + bids: [{ + bidder: 'lemmadigital', + params: { + pubId: 1, // required + adunitId: '3769' // required + latitude: 37.3230, // optional + longitude: -122.0322, // optional + device_type: 4, // optional + video: { + mimes: ['video/mp4','video/x-flv'], // required + skip: 1, // optional + minduration: 5, // optional + maxduration: 30, // optional + protocols: [ 2, 3 ], // optional + } + }, + }] +}] +``` + +### AdUnit Format for Banner + +```javascript +var bannerAdUnits = [ +{ + code: 'test-div-banner', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]], // required + } + }, + bids: [{ + bidder: 'lemmadigital', + params: { + pubId: 1, // required + adunitId: '3769' // required + latitude: 37.3230, // optional + longitude: -122.0322, // optional + device_type: 2, // optional + }, + }] +}] +``` + +### Additional Configuration + +Lemmadigital recommends setting UserSync by iframe for monetization. + +### Prebid Server Test Request + +The following test request can be used to verify that Prebid Server is working properly with the lemmadigital adapter. This example includes an `imp` object with a Lemma test publisher id, and ad id. + +```json +{ + "id": "test-request-id", + "imp": [{ + "id": "test-imp-id", + "banner": { + "format": [{ + "w": 1920, + "h": 1080 + }], + "w": 1920, + "h": 1080 + }, + "ext": { + "lemmadigital": { + "aid": 3768, + "pid": 1 + } + }, + "bidfloor": 0.1 + }], + "device": { + "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" + }, + "site": { + "id": "siteID", + "publisher": { + "id": "1" + } + } +} +``` diff --git a/dev-docs/bidders/lifestreet.md b/dev-docs/bidders/lifestreet.md index dc867e2600..4b2e9109a3 100644 --- a/dev-docs/bidders/lifestreet.md +++ b/dev-docs/bidders/lifestreet.md @@ -6,11 +6,12 @@ pbjs: true pbs: true biddercode: lifestreet media_types: video -gdpr_supported: true +tcfeu_supported: true usp_supported: true gvl_id: 67 enable_download: false -pbjs_version_notes: not ported to 5.x +pbjs_version_notes: not ported to 5.x, added back 7.13 +sidebarType: 1 --- diff --git a/dev-docs/bidders/liftoff.md b/dev-docs/bidders/liftoff.md new file mode 100644 index 0000000000..c55d6febc9 --- /dev/null +++ b/dev-docs/bidders/liftoff.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: liftoff +description: Prebid liftoff Bidder Adapter +biddercode: liftoff +tcfeu_supported: false +usp_supported: true +gpp_supported: false +coppa_supported: true +schain_supported: true +dchain_supported: false +media_types: video +safeframes_ok: false +pbjs: false +pbs: true +pbs_app_supported: true +deals_supported: true +floors_supported: true +fpd_supported: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: partial +prebid_member: false +sidebarType: 1 +--- + +### Note + +The Liftoff Bidding adapter requires setup before beginning. Please contact us at . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------------------|----------|-------------------------|-------------|----------| +| bid_token | required | super token | 'aaaa123' | string | +| app_store_id | optional | pub appstore id | '5123400' | string | +| placement_reference_id | optional | placement reference id | '912340000' | string | diff --git a/dev-docs/bidders/limelightDigital.md b/dev-docs/bidders/limelightDigital.md index 9714e224f2..36590aec21 100644 --- a/dev-docs/bidders/limelightDigital.md +++ b/dev-docs/bidders/limelightDigital.md @@ -2,17 +2,39 @@ layout: bidder title: Limelight Digital description: Prebid Limelight Digital Bidder Adaptor -pbjs: true biddercode: limelightDigital -media_types: video +pbjs: true +pbs: true +media_types: video, banner +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example |type| -| :----------- | :--------- | :------------ | :----------------- |:---| -| `host` | required | Ad network's RTB host | `'exchange.ortb.net'` | `string` | -| `adUnitId` | required | Ad Unit Id will be generated on Limelight Digital Platform. | 0 | `integer` | -| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` | `string` | -| `publisherId` | optional | Publisher ID | `'12345'` | `string` | + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:------------------------------------------------------------|:----------------------|:----------| +| `host` | required | Ad network's RTB host | `'exchange.ortb.net'` | `string` | +| `adUnitId` | required | Ad Unit Id will be generated on Limelight Digital Platform. | `42` | `integer` | +| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` | `string` | +| `publisherId` | required | Publisher ID | `'12345'` | `string` | +| `custom1` | optional | Custom targeting field 1 | `'custom1'` | `string` | +| `custom2` | optional | Custom targeting field 2 | `'custom2'` | `string` | +| `custom3` | optional | Custom targeting field 3 | `'custom3'` | `string` | +| `custom4` | optional | Custom targeting field 4 | `'custom4'` | `string` | +| `custom5` | optional | Custom targeting field 5 | `'custom5'` | `string` | + +Limelight Digital server-side Prebid Server adapter requires only `publisherId` and `host` parameters. But Limelight Digital client-side Prebid.js adapter requires only `host`, `adUnitId`, `adUnitType`. + +Limelight Digital server-side Prebid Server adapter supports only `banner`, `video`, `audio`, `native` media types. But Limelight Digital client-side Prebid.js adapter supports only `banner` and `video` media types, doesn't support `audio` and `native`. diff --git a/dev-docs/bidders/livewrapped.md b/dev-docs/bidders/livewrapped.md index 2c5976efc3..f6c9c2c7c9 100644 --- a/dev-docs/bidders/livewrapped.md +++ b/dev-docs/bidders/livewrapped.md @@ -5,17 +5,19 @@ description: Prebid Livewrapped Bidder Adaptor biddercode: livewrapped pbjs: true media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true +prebid_member: true userIds: all schain_supported: true gvl_id: 919 usp_supported: true coppa_supported: true safeframes_ok: true -fpd_supported: true +floors_supported: true +sidebarType: 1 --- -### Note: +### Note The Livewrapped Bidder Adapter requires setup and approval from Livewrapped AB. Please reach out to for more information. diff --git a/dev-docs/bidders/lkqd.md b/dev-docs/bidders/lkqd.md index 4a53c0757c..1a5979f2d0 100644 --- a/dev-docs/bidders/lkqd.md +++ b/dev-docs/bidders/lkqd.md @@ -3,18 +3,45 @@ layout: bidder title: LKQD description: Prebid LKQD Bidder Adaptor pbjs: true -biddercode: lkqd -enable_download: false -pbjs_version_notes: not ported to 5.x +biddercode: lkqd +media_types: video +tcfeu_supported: false +schain_supported: true +enable_download : false +sidebarType: 1 --- -### Note: -For more information about [LKQD Ad Serving and Management](https://www.nexstardigital.com/), please contact info@lkqd.com. +### Note + +For more information about [LKQD Ad Serving and Management](https://www.nexstardigital.com/), please contact . ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------------|----------|------------------|----------------|------| -| `placementId` | required | | `'263'` | `string` | | `siteId` | required | | `'662921'` | `string` | +| `placementId` | required | | `'263'` | `string` | + +### Ad Unit Setup for Instream Video + +```javascript +const adUnits = [{ + code: 'video1', // ad slot HTML element ID + mediaTypes: { + video: { // We recommend setting the following video params + // in Ad Unit rather than bidder params as per Prebid 4.0 recommendation. + playerSize: [640, 480], // required + context: 'instream' // required + } + }, + bids: [{ + bidder: 'lkqd', + params: { + siteId: '662921', // required + placementId: '263' // required + } + }], + // ... +}]; +``` diff --git a/dev-docs/bidders/lm_kiviads.md b/dev-docs/bidders/lm_kiviads.md new file mode 100644 index 0000000000..b5068bfebe --- /dev/null +++ b/dev-docs/bidders/lm_kiviads.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: LM KiviAds +description: LM Kiviads Bidder Adapter +biddercode: lm_kiviads +media_types: banner, video +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: true +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Prebid.js Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------|---------------|-----------| +| `pid` | required | Placement ID | `test-banner` | `string` | +| `env` | required | Environment name | `lm_kiviads` | `string` | +| `ext` | optional | Specific integration config | `{}` | `object` | + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------|------------------------------------|-----------| +| `env` | required | Environment name | `lm_kiviads-stage` | `string` | +| `pid` | required | Unique placement ID | `cs230510321b516f0eb9a10e5913d3b1` | `string` | diff --git a/dev-docs/bidders/lockerdome.md b/dev-docs/bidders/lockerdome.md index fbbaf1a056..fcb5b14689 100644 --- a/dev-docs/bidders/lockerdome.md +++ b/dev-docs/bidders/lockerdome.md @@ -5,9 +5,10 @@ description: Prebid LockerDome Bidder Adapter biddercode: lockerdome pbjs: true pbs: true -gdpr_supported: true +tcfeu_supported: false usp_supported: true schain_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/logan.md b/dev-docs/bidders/logan.md index 01fb0f3af2..0330cdcb11 100644 --- a/dev-docs/bidders/logan.md +++ b/dev-docs/bidders/logan.md @@ -6,10 +6,16 @@ biddercode: logan usp_supported: true schain_supported: true media_types: banner, video, native -gdpr: true +tcfeu_supported: false pbjs: true +pbs: true +sidebarType: 1 --- +### Disclosure + +Note: This bidder appears to only consider gdprApplies if a consent string is available. This may result in some incorrect GDPR processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/logicad.md b/dev-docs/bidders/logicad.md index f0c28c3825..1c8dfe434d 100644 --- a/dev-docs/bidders/logicad.md +++ b/dev-docs/bidders/logicad.md @@ -9,8 +9,9 @@ biddercode: logicad deals_supported: false media_types: banner, native userIds: all -gdpr_supported: false +tcfeu_supported: false prebid_member: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/loglylift.md b/dev-docs/bidders/loglylift.md index b00bfc0ead..f15ce42f93 100644 --- a/dev-docs/bidders/loglylift.md +++ b/dev-docs/bidders/loglylift.md @@ -3,12 +3,12 @@ layout: bidder title: LOGLY lift description: Prebid LOGLY lift Bidder Adaptor biddercode: loglylift -gdpr_supported: false +tcfeu_supported: false usp_supported: false coppa_supported: false schain_supported: false dchain_supported: false -media_types: no-display, native +media_types: banner, native safeframes_ok: false deals_supported: false floors_supported: false @@ -16,6 +16,7 @@ fpd_supported: false pbjs: true pbs: false prebid_member: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/loopme.md b/dev-docs/bidders/loopme.md deleted file mode 100644 index bc261b6922..0000000000 --- a/dev-docs/bidders/loopme.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: LoopMe -description: Prebid LoopMe Bidder Adaptor -pbjs: true -biddercode: loopme -gdpr_supported: true -media_types: banner, video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------------|--------------|----------| -| `ak` | required | LoopMe Application Key | `'cc885e3acc'` | `string` | - -Test LoopMe application keys: banner - cc885e3acc, video - 223051e07f diff --git a/dev-docs/bidders/loyal.md b/dev-docs/bidders/loyal.md new file mode 100644 index 0000000000..cad6c831a5 --- /dev/null +++ b/dev-docs/bidders/loyal.md @@ -0,0 +1,33 @@ +--- +layout: bidder +title: Loyal +description: Prebid Loyal Bidder Adapter +biddercode: loyal +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +multiformat_supported: will-not-bid +pbjs: true +pbs: true +pbs_app_supported: true +safeframes_ok: true +deals_supported: false +ortb_blocking_supported: false +fpd_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|---------------------------------|------------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/lucead.md b/dev-docs/bidders/lucead.md new file mode 100644 index 0000000000..5d6aa90cbd --- /dev/null +++ b/dev-docs/bidders/lucead.md @@ -0,0 +1,52 @@ +--- +layout: bidder +title: Lucead +description: Prebid Lucead Bidder Adapter +biddercode: lucead +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +media_types: banner +safeframes_ok: true +deals_supported: true +floors_supported: true +fpd_supported: true +pbjs: true +pbs: false +prebid_member: true/false +ortb_blocking_supported: false +privacy_sandbox: paapi +sidebarType: 1 +--- +### Note + +The Lucead Bidding adapter requires setup before beginning. Please contact us at [prebid@lucead.com](mailto:prebid@lucead.com). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement id | `'11111'` | `string` | + +### Test Parameters + +```javascript +const adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: 'lucead', + params: { + placementId: '1', + } + } + ] + } + ]; +``` diff --git a/dev-docs/bidders/lunamedia.md b/dev-docs/bidders/lunamedia.md index 00f9dc31c3..c3a9dad11f 100644 --- a/dev-docs/bidders/lunamedia.md +++ b/dev-docs/bidders/lunamedia.md @@ -1,25 +1,25 @@ --- layout: bidder -title: Luna Media -description: Prebid Luna Media Bidder Adapter -pbjs: true -pbs: true +title: Lunamedia +description: Lunamedia Bidder Adapter biddercode: lunamedia -enable_download: false -pbjs_version_notes: not ported to 5.x +media_types: banner, video +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: false +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 --- -### Note: -For more information about Luna Media, please contact info@lunamedia.io - -### Bid Params +### Prebid Server Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------------|----------|------------------|------------------------------------------|-------------------| -| `placement ` | required | | `'263'` | `string` | -| `pubid` | required | | `'0cf8d6d643e13d86a5b6374148a4afac'` | `string` | -| `mimes` | optional | video only | `['video/mp4', 'application/javascript']`| `array of strings`| -| `playbackmethod` | optional | video only | `[2,6]` | `array of numbers`| -| `maxduration` | optional | video only | `30` | `number` | -| `skip` | optional | video only | `0 or 1` | `number` | +| Name | Scope | Description | Example | Type | +|-------------|----------|---------------------------------------------|------------------------------------|-----------| +| `pubid` | required | An id used to identify LunaMedia publisher. | `'d2b5502f83b65719d29ed4fa86e411ea'` | `string` | +| `placement` | optional | A placement created on adserver. | `'cs230510321b516f0eb9a10e5913d3b1'` | `string` | diff --git a/dev-docs/bidders/lunamediahb.md b/dev-docs/bidders/lunamediahb.md index 4fd4d09d09..ef6e95dd71 100644 --- a/dev-docs/bidders/lunamediahb.md +++ b/dev-docs/bidders/lunamediahb.md @@ -5,11 +5,13 @@ description: Prebid Lunamedia Bidder Adapter biddercode: lunamediahb usp_supported: true schain_supported: true -gdpr_supported: true +gvl_id: 998 +tcfeu_supported: true coppa_supported: true media_types: banner, video, native pbjs: true pbs: false +sidebarType: 1 --- ### Prebid.Server Bid Params diff --git a/dev-docs/bidders/luponmedia.md b/dev-docs/bidders/luponmedia.md index 598bc5d82e..a9821d6e76 100644 --- a/dev-docs/bidders/luponmedia.md +++ b/dev-docs/bidders/luponmedia.md @@ -4,15 +4,17 @@ title: LuponMedia description: LuponMedia Bidder Adapter pbjs: true biddercode: luponmedia -gdpr_supported: true +gvl_id: 1132 +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true userIds: digitrust, identityLink, liveIntentId, pubCommonId -pbjs_version_notes: not in 5.x, in 6.2+ +sidebarType: 1 --- -### Note: +### Note + The LuponMedia bidder adapter requires setup and approval from the LuponMedia support team, even for existing LuponMedia publishers. Please contact us for more information. ### Bid Params diff --git a/dev-docs/bidders/mabidder.md b/dev-docs/bidders/mabidder.md new file mode 100644 index 0000000000..cad1645a45 --- /dev/null +++ b/dev-docs/bidders/mabidder.md @@ -0,0 +1,18 @@ +--- +layout: bidder +title: mabidder +description: Media Aisle Prebid Bidder Adaptor +biddercode: mabidder +pbjs: true +pbs: true +media_types: banner +tcfeu_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------------------|------------|----------| +| `ppid` | required | Mabidder publisher placement ID | "1234" | `string` | diff --git a/dev-docs/bidders/madvertise.md b/dev-docs/bidders/madvertise.md index 3f58b6578b..1a01bf3d91 100644 --- a/dev-docs/bidders/madvertise.md +++ b/dev-docs/bidders/madvertise.md @@ -4,12 +4,13 @@ title: Madvertise description: Prebid Madvertise Bidder Adapter pbjs: true biddercode: madvertise -gdpr_supported: true +tcfeu_supported: true gvl_id: 153 media_types: banner, video safeframes_ok: true pbs: true pbs_app_supported: true +sidebarType: 1 --- ### Prebid.js Bid Params @@ -37,6 +38,7 @@ pbs_app_supported: true } } ``` + ### Prebid Server Bid Params {: .table .table-bordered .table-striped } @@ -44,7 +46,6 @@ pbs_app_supported: true |--------------|----------|---------------------------------------------------------------------------------------------------------|-----------------------------------------|-----------| |`zoneId` | required | The zone ID provided by Madvertise. | `'/1111111/banner'` | `string` | - #### Example ``` @@ -79,4 +80,3 @@ pbs_app_supported: true "tmax": 1000 } ``` - diff --git a/dev-docs/bidders/malltv.md b/dev-docs/bidders/malltv.md index 94298cb08a..1ac0097d51 100644 --- a/dev-docs/bidders/malltv.md +++ b/dev-docs/bidders/malltv.md @@ -5,6 +5,7 @@ description: Prebid MallTv Bidder Adaptor pbjs: true biddercode: malltv media_types: banner, video +sidebarType: 1 --- diff --git a/dev-docs/bidders/mantis.md b/dev-docs/bidders/mantis.md index ba004f27b6..f8b52850b4 100644 --- a/dev-docs/bidders/mantis.md +++ b/dev-docs/bidders/mantis.md @@ -6,7 +6,8 @@ pbjs: true biddercode: mantis media_types: native, video usp_supported: true -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/marsmedia.md b/dev-docs/bidders/marsmedia.md index 8281cb732f..0326fb435f 100644 --- a/dev-docs/bidders/marsmedia.md +++ b/dev-docs/bidders/marsmedia.md @@ -6,12 +6,13 @@ pbjs: true pbs: true biddercode: marsmedia media_types: video, banner -gdpr_supported: true +tcfeu_supported: true floors_supported: true schain_supported: true usp_supported: true coppa_supported: true gvl_id: 776 +sidebarType: 1 --- ### Bid Params @@ -21,8 +22,8 @@ gvl_id: 776 |---------------|----------|-------------|---------|----------| | zoneId | required | The zone ID from Mars Media Group. | 9999 | integer | - ### Banner - Ad Unit Setup + ```javascript var adUnits = [ { @@ -41,9 +42,10 @@ var adUnits = [ } }] } -``` +``` ### Instream Video - Ad Unit Setup + ```javascript var adUnits = [ { diff --git a/dev-docs/bidders/mathildeads.md b/dev-docs/bidders/mathildeads.md index c7dbe99b03..07ae040f96 100644 --- a/dev-docs/bidders/mathildeads.md +++ b/dev-docs/bidders/mathildeads.md @@ -6,12 +6,17 @@ biddercode: mathildeads usp_supported: true schain_supported: true media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: false pbjs: true pbs: false pbs_app_supported: false +sidebarType: 1 --- +### Disclosure + +Note: This bidder appears to only consider gdprApplies if a consent string is available. This may result in some incorrect TCF2 processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + ### Prebid.JS Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/matomy.md b/dev-docs/bidders/matomy.md index 33cd2b8da7..bf160281c7 100644 --- a/dev-docs/bidders/matomy.md +++ b/dev-docs/bidders/matomy.md @@ -5,6 +5,7 @@ description: Prebid Matomy Bidder Adaptor pbjs: true biddercode: matomy aliasCode : appnexus +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/meazy.md b/dev-docs/bidders/meazy.md deleted file mode 100644 index 380816144d..0000000000 --- a/dev-docs/bidders/meazy.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Meazy -description: Prebid Meazy Bidder Adaptor -pbjs: true -biddercode: meazy -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid params - -### Note -To enable Meazy bid adaptor we kindly ask you to sign up as a Publisher: team@meazy.co - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------|----------|---------------------|------------------------------------------|----------| -| pid | required | Meazy Publisher ID | `'6910b7344ae566a1'` | `string` | diff --git a/dev-docs/bidders/mediabrama.md b/dev-docs/bidders/mediabrama.md new file mode 100644 index 0000000000..5bc734ef79 --- /dev/null +++ b/dev-docs/bidders/mediabrama.md @@ -0,0 +1,56 @@ +--- +layout: bidder +title: MediaBrama +description: Prebid MediaBrama Bidder Adapter. +pbjs: true +pbs: false +gvl_id: none +biddercode: mediabrama +media_types: banner +gdpr_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +safeframes_ok: false +dchain_supported: false +deals_supported: false +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +prebid_member: false +--- + +### Description + +MediaBrama header bidding adapter connects with mediabrama demand sources to fetch bids for display placements. Please reach out to your account manager or for more information. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|----------|------------------------------------|------------|----------| +| `placementId`| optional | The placement ID from MediaBrama | `'24428'` | `string` | +| `bidFloor` | optional | Lowest value of expected bid price | `1.1` | `float` | + +### Test Parameters + +300x250 banner test + +```javascript +var adUnits = [{ + code: 'prebid-place', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'mediabrama', + params : { + placementId : "24428" //test, please replace after test + } + }] +}]; +``` diff --git a/dev-docs/bidders/mediaforce.md b/dev-docs/bidders/mediaforce.md index 7632e66665..3d1c154804 100644 --- a/dev-docs/bidders/mediaforce.md +++ b/dev-docs/bidders/mediaforce.md @@ -5,7 +5,8 @@ description: MediaForce Prebid Bidder Adapter media_types: banner, native biddercode: mediaforce pbjs: true -gdpr_supported: false +tcfeu_supported: false +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/mediafuse.md b/dev-docs/bidders/mediafuse.md new file mode 100644 index 0000000000..5669a23564 --- /dev/null +++ b/dev-docs/bidders/mediafuse.md @@ -0,0 +1,161 @@ +--- +layout: bidder +title: MediaFuse +description: Prebid MediaFuse Bidder Adapter +biddercode: mediafuse +media_types: video,banner +tcfeu_supported: false +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: true +sidebarType: 1 +--- + +### Prebid Server Note + +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} + +#### Prebid Server Test Request + +The following test parameters can be used to verify that Prebid Server is working properly with the server-side Mediafuse adapter. This example includes an Mediafuse test placement ID and sizes that would match with the test creative. + +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'mediafuse', + params: { + placementId: 13144370 + } + }] + }, + // Native adUnit + { + code: 'native-div', + sizes: [[1, 1]], + mediaTypes: { + native: { + title: { + required: true + }, + body: { + required: true + }, + image: { + required: true + }, + sponsoredBy: { + required: true + }, + icon: { + required: false + } + } + }, + bids: [{ + bidder: 'mediafuse', + params: { + placementId: 13232354, + allowSmallerSizes: true + } + }] + }, + // Video instream adUnit + { + code: 'video-instream', + sizes: [[640, 480]], + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'instream' + }, + }, + bids: [{ + bidder: 'mediafuse', + params: { + placementId: 13232361, + video: { + skippable: true, + playback_methods: ['auto_play_sound_off'] + } + } + }] + }, + // Video outstream adUnit + { + code: 'video-outstream', + sizes: [[300, 250]], + mediaTypes: { + video: { + playerSize: [[300, 250]], + context: 'outstream', + // Certain ORTB 2.5 video values can be read from the mediatypes object; below are examples of supported params. + // To note - mediafuse supports additional values for our system that are not part of the ORTB spec. If you want + // to use these values, they will have to be declared in the bids[].params.video object instead using the mediafuse syntax. + // Between the corresponding values of the mediaTypes.video and params.video objects, the properties in params.video will + // take precedence if declared; eg in the example below, the `skippable: true` setting will be used instead of the `skip: 0`. + minduration: 1, + maxduration: 60, + skip: 0, // 1 - true, 0 - false + skipafter: 5, + playbackmethod: [2], // note - we only support options 1-4 at this time + api: [1,2,3] // note - option 6 is not supported at this time + } + }, + bids: [ + { + bidder: 'mediafuse', + params: { + placementId: 13232385, + video: { + skippable: true, + playback_method: 'auto_play_sound_off' + } + } + } + ] + }, + // Banner adUnit in a App Webview + // Only use this for situations where prebid.js is in a webview of an App + // See Prebid Mobile for displaying ads via an SDK + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + } + bids: [{ + bidder: 'mediafuse', + params: { + placementId: 13144370, + app: { + id: "B1O2W3M4AN.com.prebid.webview", + geo: { + lat: 40.0964439, + lng: -75.3009142 + }, + device_id: { + idfa: "4D12078D-3246-4DA4-AD5E-7610481E7AE", // Apple advertising identifier + aaid: "38400000-8cf0-11bd-b23e-10b96e40000d", // Android advertising identifier + md5udid: "5756ae9022b2ea1e47d84fead75220c8", // MD5 hash of the ANDROID_ID + sha1udid: "4DFAA92388699AC6539885AEF1719293879985BF", // SHA1 hash of the ANDROID_ID + windowsadid: "750c6be243f1c4b5c9912b95a5742fc5" // Windows advertising identifier + } + } + } + }] + } +]; +``` diff --git a/dev-docs/bidders/mediago.md b/dev-docs/bidders/mediago.md index 670231f398..4b5f4fcd94 100644 --- a/dev-docs/bidders/mediago.md +++ b/dev-docs/bidders/mediago.md @@ -4,11 +4,20 @@ title: MediaGo description: MediaGo Prebid Bidder Adapter biddercode: mediago media_types: banner +tcfeu_supported: true +coppa_supported: true +usp_supported: true pbjs: true -enable_download: false -pbjs_version_notes: not ported to 5.x +floors_supported: true +gvl_id: 1020 +pbjs_version_notes: not ported to 5.x, added back 7.13 +sidebarType: 1 --- -### Note: +### Modules + +SharedID: We need you to include SharedID module,which is used to get prebid user commonid.It can better differentiating users to bid on ads. + +### Note The MediaGo Bidding adapter requires setup before beginning. Please contact us at @@ -18,3 +27,6 @@ The MediaGo Bidding adapter requires setup before beginning. Please contact us a | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| | `token` | required | publisher token | `'1e100887dd614b7f69fdd1360437'` | `string` | +| `test` | recommend | 0(default): production env mode.
      1: dev env mode and no charge.we will bid Higher frequency to make debug easier. | `1/0` | `Number` | +| `bidfloor` | recommend | Sets a floor price for the bid | `0.05` | `float` | +| `placementId` | recommend | The AD placement ID | `12341234` | `string` | diff --git a/dev-docs/bidders/mediaimpact.md b/dev-docs/bidders/mediaimpact.md new file mode 100644 index 0000000000..9893b22311 --- /dev/null +++ b/dev-docs/bidders/mediaimpact.md @@ -0,0 +1,39 @@ +--- +layout: bidder +title: MEDIAIMPACT +description: Prebid MEDIAIMPACT Bidder Adapter +pbjs: true +biddercode: mediaimpact +media_types: banner +sidebarType: 1 +tcfeu_supported: false +dsa_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +gpp_sids: None +schain_supported: false +dchain_supported: false +userId: () +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: false +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: false +privacy_sandbox: no +--- + +### Note + +The MEDIAIMPACT Bidding adapter requires setup before beginning. Please contact us at [info@mediaimpact.com.ua](mailto:info@mediaimpact.com.ua). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-------------|----------------------|-----------| +| `partnerId` | required | Partner ID. | `6698` | `integer` | +| `sizes` | optional | Custom size | `[[300,600]]` | `array` | diff --git a/dev-docs/bidders/mediakeys.md b/dev-docs/bidders/mediakeys.md index 0a58f06277..45efb078da 100644 --- a/dev-docs/bidders/mediakeys.md +++ b/dev-docs/bidders/mediakeys.md @@ -7,13 +7,14 @@ media_types: banner, video, native gvl_id: 498 pbjs: true floors_supported: true -gdpr_supported: true +tcfeu_supported: true schain_supported: true coppa_supported: true usp_supported: true safeframes_ok: true userIds: all fpd_supported: true +sidebarType: 1 --- @@ -22,6 +23,8 @@ fpd_supported: true - [Table of Contents](#table-of-contents) - [Important Notice](#important-notice) - [Bid Params](#bid-params) + - [First Party Data](#first-party-data) + - [Required and Recommended Modules](#required-and-recommended-modules) - [MediaType Banner](#mediatype-banner) - [MediaType Video](#mediatype-video) - [Instream video](#instream-video) @@ -34,7 +37,7 @@ fpd_supported: true The Mediakeys Bidding adapter requires setup before beginning and will respond with bids for whitelisted domains only. -Please contact us at prebidjs@mediakeys.com. +Please contact us at . @@ -45,7 +48,134 @@ Please contact us at prebidjs@mediakeys.com. |-------------|---------------------|------------------------------|-----------|-----------| | `context` | required for native | Native context | `1` | `integer` | | `plcmttype` | required for native | Native placement type | `2` | `integer` | -| | | | | | + + + +#### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.site.*`: Standard IAB OpenRTB 2.5 site fields +- `ortb2.site.content.data[]`: Standard IAB segment taxonomy site data +- `ortb2.site.ext.data.*`: Non standard arbitrary site data +- `ortb2.user.*`: Standard IAB OpenRTB 2.5 user fields +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.ext.data.*`: Non standard arbitrary user data + +Please note that field `ortb2.app.*`, in a webview context, is **not supported**. + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` + +Example first party data that's available to all bidders and all adunits: + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + // standard IAB OpenRTB 2.5 site fields are passed in `ortb2.site.*` + name: "example", + cat: ["IAB2"], + domain: "page.example.com", + + // standard IAB segment taxonomy site data is passed in `ortb2.site.content.data[]` + content: { + userrating: "4", + data: [{ name: "www.sitedataprovider1.com" }] + }, + + // any non standard arbitrary site data is passed in `ortb2.site.ext.data.*` + ext: { data: { arbitrarySiteKey: "arbitrary" } } + }, + user: { + // standard IAB OpenRTB 2.5 user fields are passed in `ortb2.user.*` + keywords: "a,b", + geo: { country: "FRA", lat: 48.9, lon: 2.2 }, + + // standard IAB segment taxonomy user data are passed in `ortb2.user.data[]` + data: [{ name: "www.userdataprovider1.com" }], + + // any non standard arbitrary user data is passed in `ortb2.user.ext.data.*` + ext: { data: { arbitraryUserKey: "arbitrary" } } + } + } +}); +``` + +Example of first party data available only to the Mediakeys bidder and applies across all ad units: + +```javascript +pbjs.setBidderConfig({ + bidders: ['mediakeys'], + config: { + ortb2: { + site: { + ext: { + data: { + pageType: "article", + category: "tools" + } + } + }, + user: { + ext: { + data: { + registered: true, + interests: ["cars"] + } + } + } + } + } +}); +``` + +Example of an adunit-specific with first party data: + +```javascript +var adUnit = { + // applies to all bidders + ortb2Imp: { + instl:1 + }, + bids: [{ + bidder: 'mediakeys', + params: {}, + // applies to mediakeys bidder only + ortb2Imp: { + ext: { + data: { + pbadslot: "homepage-top-rect", + adUnitSpecificAttribute: "123" + } + } + } + }] +}; +``` + + + +#### Required and Recommended Modules + +Mediakeys fully supports the following [Prebid.js Modules](https://docs.prebid.org/dev-docs/modules/): + +{: .table .table-bordered .table-striped } +| Module | Scope | +|-------------------------------------------------------------------------------------------------------|-----------------------------| +| [Consent Management - GDPR](https://docs.prebid.org/dev-docs/modules/consentManagement.html) | Required in Europe | +| [Consent Management - US Privacy](https://docs.prebid.org/dev-docs/modules/consentManagementUsp.html) | Required in US - California | +| [Supply Chain Object](https://docs.prebid.org/dev-docs/modules/schain.html) | Required for all traffic | +| [Instream Tracking](https://docs.prebid.org/dev-docs/modules/instreamTracking.html) | Required for Instream Video | +| [First Party Data Enrichment](https://docs.prebid.org/dev-docs/modules/enrichmentFpdModule.html) | Recommended for all traffic | + +Publishers must utilize the required modules in described scope to be able to receive bid responses. + +Before using [Supply Chain Object](https://docs.prebid.org/dev-docs/modules/schain.html) Module, please confirm with the Mediakeys team +the proper `asi` and `sid` field values that you should pass. @@ -89,7 +219,6 @@ Please refer to the following table to find acceptable values for mediakeys bidd | protocols | recommended | Array of supported video protocols:
      2: VAST 2.0
      3: VAST 3.0 | [2,3]
      default: [3] | array<integers>| | maxduration | recommended | Maximum video ad duration in seconds. | 30
      default: not set | integer | | skip | recommended | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes. | 1
      default: 0 | integer | -| | | | | | (*) Mediakeys bidder will adapt the bid response to send the video format closest to the `playerSize` (from an aspect ratio point of view). To maximize the responses, please consider requesting formats like: @@ -97,7 +226,7 @@ Please refer to the following table to find acceptable values for mediakeys bidd - medium video: `640x360` (low bandwidth, medium quality) - standard video: `640×480` (medium bandwidth, good quality) - full wide video: `854×480` (high bandwidth, superior quality) -- HD video: `1280x720` (miximum bandwidth, best quality) +- HD video: `1280x720` (maximum bandwidth, best quality) @@ -180,7 +309,7 @@ const adUnits = [{ Required Prebid configuration: -You must set up your preferred outstream renderer in the ad unit and use the following example code to fetch the +You must set up your preferred outstream renderer in the ad unit and use the following example code to fetch the `vast xml` document from mediakeys ad-server. Example Ad Unit: diff --git a/dev-docs/bidders/medianet.md b/dev-docs/bidders/medianet.md index e11e1867c5..81b317b744 100644 --- a/dev-docs/bidders/medianet.md +++ b/dev-docs/bidders/medianet.md @@ -3,17 +3,19 @@ layout: bidder title: Media.net description: Prebid Media.net Bidder Adaptor biddercode: medianet -gdpr_supported: true +tcfeu_supported: true media_types: banner,native,video usp_supported: true +coppa_supported: true +gpp_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId prebid_member: true pbjs: true gvl_id: 142 schain_supported: true floors_supported: true -fpd_supported: true pbs: true +sidebarType: 1 --- ### Bid Params @@ -26,7 +28,7 @@ pbs: true | `bidfloor` | optional | Bidfloor for the impression | `1.0` | `float` | | `video` | required for video Ad units | Object containing video targeting parameters. See [Video Object](#media.net-video-object) for details.|`video: { maxduration: 60 }` | `object` | - + #### Video Object @@ -37,20 +39,21 @@ pbs: true |minduration|integer|(Recommended) Specifies the minimum video ad duration, in seconds.|10| |maxduration|integer|(Recommended) Specifies the maximum video ad duration, in seconds.|60| |w|integer|(Recommended) Specifies the width of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|640| -|h|integer|(Recommended) Specifies the height of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|480| -|startdelay |integer | (Recommended) Specifies the start delay of the video ad|0| -|battr| array of integers|Specifies the video creative attributes to block. Refer to section 5.3 of the IAB specification for a list of attributes.| [ 13, 14 ]| -playbackmethod| array of integers| Specifies the allowed playback methods. If not specified, all are assumed to be allowed. Currently supported values are: `1: Autoplay, sound on`; `2: Autoplay, sound off`; `3: Click to play`; `4: Mouse over to play`|[1, 3]| -|api| array of integers| Specifies the supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. Currently supported values are: `1: VPAID 1.0`; `2: VPAID 2.0`; `3: MRAID-1`; `4: ORMMA`; `5: MRAID-2`|[1, 2]| -|protocols |array of integers| Array of supported video protocols. Currently supported values are: `1: VAST 1.0`; `2: VAST 2.0`; `3: VAST 3.0`; `4: VAST 1.0 Wrapper`; `5: VAST 2.0 Wrapper`; `6: VAST 3.0 Wrapper`; `7: VAST 4.0`|[1, 2]| -|placement |integer|Placement type for the impression. Possible options: `1: In-Stream`; `2: In-banner`; `3: Outstream/In-article`; `4: In-feed`; `5: Interstitial/Slider/Floating`; `6: Long-Form`;|1| +|h|integer|(Recommended) Specifies the height of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|480| +|startdelay|integer |(Recommended) Specifies the start delay of the video ad|0| +|battr|array of integers|Specifies the video creative attributes to block. Refer to section 5.3 of the IAB specification for a list of attributes.| [ 13, 14 ]| +playbackmethod|array of integers|Specifies the allowed playback methods. If not specified, all are assumed to be allowed. Currently supported values are: `1: Autoplay, sound on`; `2: Autoplay, sound off`; `3: Click to play`; `4: Mouse over to play`|[1, 3]| +|api| array of integers|Specifies the supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. Currently supported values are: `1: VPAID 1.0`; `2: VPAID 2.0`; `3: MRAID-1`; `4: ORMMA`; `5: MRAID-2`|[1, 2]| +|protocols|array of integers|Array of supported video protocols. Currently supported values are: `1: VAST 1.0`; `2: VAST 2.0`; `3: VAST 3.0`; `4: VAST 1.0 Wrapper`; `5: VAST 2.0 Wrapper`; `6: VAST 3.0 Wrapper`; `7: VAST 4.0`|[1, 2]| +|placement|integer|Placement type for the impression. Possible options: `1: In-Stream`; `2: In-banner`; `3: Outstream/In-article`; `4: In-feed`; `5: Interstitial/Slider/Floating`; `6: Long-Form`;|1| Besides the above-mentioned parameters, we support all other OpenRTB 2.x video objects as optional parameters. In addition to `bids[].params.video`, Media.net adapter consumes parameters specified in the `mediaTypes.video`. #### Example of Instream Video Ad-unit -``` + +```javascript var videoAdUnit = { code: 'video1', mediaTypes: { @@ -78,7 +81,8 @@ var videoAdUnit = { ``` #### Example of Native Ad-unit -``` + +```javascript var adUnits = [{ code: 'div-gpt-ad-1544091247692-0', mediaTypes: { @@ -111,7 +115,8 @@ var adUnits = [{ ``` #### Example of Banner Ad-unit -``` + +```javascript var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', mediaTypes: { @@ -138,4 +143,3 @@ var adUnits = [{ }] }]; ``` - diff --git a/dev-docs/bidders/mediasniper.md b/dev-docs/bidders/mediasniper.md new file mode 100644 index 0000000000..4a666dd317 --- /dev/null +++ b/dev-docs/bidders/mediasniper.md @@ -0,0 +1,22 @@ +--- +layout: bidder +title: Mediasniper +description: Mediasniper Prebid Bidder Adapter +biddercode: mediasniper +media_types: banner +pbjs: true +floors_supported: true +safeframes_ok: true +sidebarType: 1 +--- +### Note + +The Mediasniper Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement id | `'11111'` | `string` | +| `siteid` | optional | Site id | `'11111'` | `string` | diff --git a/dev-docs/bidders/mediasquare.md b/dev-docs/bidders/mediasquare.md index 4777ebf6ec..068d6d0462 100644 --- a/dev-docs/bidders/mediasquare.md +++ b/dev-docs/bidders/mediasquare.md @@ -4,12 +4,14 @@ title: MediaSquare description: Prebid MediaSquare Bidder Adapter pbjs: true biddercode: mediasquare -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true userIds: id5Id media_types: banner, video, native -glv_id: 791 +floors_supported: true +gvl_id: 791 +sidebarType: 1 --- @@ -18,5 +20,5 @@ glv_id: 791 {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|--------------------------------------|-----------| -| `owner ` | required | Mediasquare owner ID | `'test'` | `string` | +| `owner` | required | Mediasquare owner ID | `'test'` | `string` | | `code` | required | Mediasquare code ID | `'publishername_atf_desktop_rg_pave'` | `string` | diff --git a/dev-docs/bidders/mgid.md b/dev-docs/bidders/mgid.md index f363ab5d96..f832b549a0 100644 --- a/dev-docs/bidders/mgid.md +++ b/dev-docs/bidders/mgid.md @@ -6,17 +6,24 @@ pbjs: true pbs: true biddercode: mgid media_types: banner,native -gdpr_supported: true +tcfeu_supported: true +usp_supported: true gvl_id: 358 +floors_supported: true +ortb_blocking_supported: partial +multiformat_supported: will-bid-on-any +sidebarType: 1 --- ### Table of Contents -- [Description](#mgid-bid-desc) -- [Bid Params](#mgid-bid-params) -- [Test Params](#mgid-test-params) +- [Table of Contents](#table-of-contents) +- [Description](#description) +- [Bid params](#bid-params) +- [Test Parameters](#test-parameters) +- [User Sync](#user-sync) - + ### Description @@ -24,7 +31,7 @@ One of the easiest way to gain access to MGID demand sources - MGID header bidd MGID header bidding adapter connects with MGID demand sources to fetch bids for display placements. Please reach out to your account manager or for more information. - + ### Bid params @@ -36,13 +43,13 @@ MGID header bidding adapter connects with MGID demand sources to fetch bids for | `bidFloor` | optional | Lowest value of expected bid price | `1.1` | `float` | | `currency` | optional | Currency of request and response | `'GBP'` | `string` | - - + ### Test Parameters 300x600 banner test -``` + +```javascript var adUnits = [{ code: 'div-prebid', mediaTypes: { @@ -61,7 +68,8 @@ var adUnits = [{ ``` 300x250 banner test -``` + +```javascript var adUnits = [{ code: 'div-prebid', mediaTypes: { @@ -80,7 +88,8 @@ var adUnits = [{ ``` native test -``` + +```javascript var adUnits = [{ code: 'div-prebid', mediaTypes: { @@ -112,3 +121,36 @@ var adUnits = [{ }] }]; ``` + + + +### User Sync + +Mgid recommends UserSync configuration to be enabled. Without it, Mgid adapter will not be able to perform user syncs, which lowers match rate and reduces monetization. + +For Prebid.js v1.15.0 and later: + +```javascript +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: '*', // '*' represents all bidders + filter: 'include' + } + } + } +}); +``` + +For Prebid.js v1.14.0 and before: + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['mgid'] + }}); +``` + +Note: Combine the above configuration with any other UserSync configuration. Multiple setConfig() calls overwrite each other and only the last call for a given attribute will take effect. diff --git a/dev-docs/bidders/mgidX.md b/dev-docs/bidders/mgidX.md new file mode 100644 index 0000000000..93bbca96db --- /dev/null +++ b/dev-docs/bidders/mgidX.md @@ -0,0 +1,33 @@ +--- +layout: bidder +title: MgidX +description: Prebid MgidX Bidder Adapter +biddercode: mgidX +usp_supported: true +gdpr_supported: true +tcfeu_supported: true +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +multiformat_supported: will-not-bid +pbjs: true +pbs: true +pbs_app_supported: true +safeframes_ok: true +gvl_id: 358 +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|---------------------------------|------------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | +| `region` | optional | Region (for Prebid.js) | `'us-east'` (default) or `'eu'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/microad.md b/dev-docs/bidders/microad.md index 09f710565b..0fc734fb9c 100644 --- a/dev-docs/bidders/microad.md +++ b/dev-docs/bidders/microad.md @@ -5,6 +5,8 @@ description: Prebid MicroAd SSP Bidder Adaptor pbjs: true biddercode: microad media_types: banner +userIds: imuid, id5Id, tdid, novatiq, parrableId, dacId, identityLink, criteo, pubcid, uid2 +sidebarType: 1 --- Note: @@ -14,11 +16,12 @@ For more information, visit [MicroAd website](https://www.microad.co.jp/contact/ ### Bid parameters {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|---------------------------------------------------------------|--------------------------------------|----------| -| `spot` | required | Ad placement ID provided by MicroAd. | `'209e56872ae8b0442a60477ae0c58be9'` | `string` | -| `url` | optional | URL parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_URL}'` | `string` | -| `referrer` | optional | Referrer parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_REF}'` | `string` | -| `ifa` | optional | IFA parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_IFA}'` | `string` | -| `appid` | optional | App ID parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_APPID}'` | `string` | -| `geo` | optional | Geo parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_GEO}'` | `string` | +| Name | Scope | Description | Example | Type | +|------------|----------|-------------------------------------------------------------------|--------------------------------------|-----------------| +| `spot` | required | Ad placement ID provided by MicroAd. | `'209e56872ae8b0442a60477ae0c58be9'` | `string` | +| `url` | optional | URL parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_URL}'` | `string` | +| `referrer` | optional | Referrer parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_REF}'` | `string` | +| `ifa` | optional | IFA parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_IFA}'` | `string` | +| `appid` | optional | App ID parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_APPID}'` | `string` | +| `geo` | optional | Geo parameter. Effective only when provided by MicroAd. | `'${COMPASS_EXT_GEO}'` | `string` | +| `aids` | optional | User IDs parameter. `type` indicates User IDs type. | `[{type: 6, id: '*******'}]` | `Array` | diff --git a/dev-docs/bidders/minutemedia.md b/dev-docs/bidders/minutemedia.md new file mode 100644 index 0000000000..55c69cf49f --- /dev/null +++ b/dev-docs/bidders/minutemedia.md @@ -0,0 +1,89 @@ +--- +layout: bidder +title: MinuteMedia +description: Prebid MinuteMedia Bidder Adapter +pbjs: true +biddercode: minutemedia +media_types: banner, video +multiformat_supported: will-bid-on-any +schain_supported: true +tcfeu_supported: true +gpp_supported: true +gpp_sids: tcfeu, usstate_all, usp +usp_supported: true +pbs: true +floors_supported: true +userIds: all +fpd_supported: true +gvl_id: 918 +sidebarType: 1 +--- + +### Note + +The MinuteMedia adapter requires setup and approval. Please reach out to to setup an MinuteMedia account. + +### Bid Parameters + +#### Banner ,Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | MinuteMedia publisher Id provided by your MinuteMedia representative | "1234567890abcdef12345678" +| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false + +## Example + +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'minutemedia', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false // Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'minutemedia', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false // Optional + } + }] + } +]; +``` + +### Configuration + +MinuteMedia recommends setting UserSync by iframe for monetization. diff --git a/dev-docs/bidders/minutemediaplus.md b/dev-docs/bidders/minutemediaplus.md new file mode 100644 index 0000000000..68f867d9de --- /dev/null +++ b/dev-docs/bidders/minutemediaplus.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: MinuteMediaPlus +description: Prebid Minute Media Plus Bidder Adaptor +biddercode: mmplus +filename: minutemediaplusBidAdapter +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +floors_supported: true +gpp_supported: true +media_types: banner, video +prebid_member: false +safeframes_ok: false +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +gvl_id: 918 +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|--------------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from MinuteMediaPlus. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from MinuteMediaPlus. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | required | The minimum bid value desired. MinuteMediaPlus will not respond with bids lower than this value. | `0.90` | `float` | +| `subDomain`| optional | Sets the server subdomain, default: 'exchange'. | `'exchange'` | `string` | diff --git a/dev-docs/bidders/missena.md b/dev-docs/bidders/missena.md index 895cfe8c43..480761f0a0 100644 --- a/dev-docs/bidders/missena.md +++ b/dev-docs/bidders/missena.md @@ -6,12 +6,12 @@ biddercode: missena gvl_id: 867 pbjs: true safeframes_ok: false -pbjs_version_notes: not in 5.x, in 6.2+ +sidebarType: 1 --- ### Note -The Missena Bidding adapter requires setup before beginning. Please contact us at jney@missena.com +The Missena Bidding adapter requires setup before beginning. Please contact us at ### Bid params diff --git a/dev-docs/bidders/mobfox.md b/dev-docs/bidders/mobfox.md deleted file mode 100644 index 46c5ee5ca3..0000000000 --- a/dev-docs/bidders/mobfox.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: MobFox -description: Prebid MobFox Bidder Adaptor -pbjs: true -biddercode: mobfox -media_types: video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|------------------------------------------------------------------------|--------------------------------------|-----------| -| `s` | required | The hash of your inventory to identify which app is making the request | `'267d72ac3f77a3f447b32cf7ebf20673'` | `string` | -| `imp_instl` | optional | set to 1 if using interstitial otherwise delete or set to 0 | `1` | `integer` | diff --git a/dev-docs/bidders/mobfoxpb.md b/dev-docs/bidders/mobfoxpb.md index 429c1f02ca..425901a4f7 100644 --- a/dev-docs/bidders/mobfoxpb.md +++ b/dev-docs/bidders/mobfoxpb.md @@ -6,13 +6,14 @@ biddercode: mobfoxpb usp_supported: true schain_supported: true media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true pbjs: true pbs: true pbs_app_supported: true +gpp_supported: true gvl_id: 311 -enable_download: false -pbjs_version_notes: not ported to 5.x +enable_download: true +sidebarType: 1 --- ### Prebid.JS Bid Params @@ -22,12 +23,16 @@ pbjs_version_notes: not ported to 5.x |----------------|----------|----------------------------------------------------------|------------|-----------| | `placementId` | required | Placement Id will be generated on Mobfox Platform. | `'0'` | `string` | - ### Prebid Server Bid Params + Currently adapter doesn't support multiimpression, so only the first impression will be delivered {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|----------|----------------------------------------------------------|------------|-----------| -| `TagID` | required | Placement Id will be generated on Mobfox Platform. For direct integration | `'0'` | `string` | -| `key` | required | Endpoint id will be generated on Mobfox Platform. For s2s integration | `'0'` | `string` | +| `TagID` | optional | Placement Id will be generated on Mobfox Platform. For direct integration | `'0'` | `string` | +| `key` | optional | Endpoint id will be generated on Mobfox Platform. For s2s integration | `'0'` | `string` | + +### Note + +For the prebid server you only need to use one parameter: either TagID or key diff --git a/dev-docs/bidders/mobilefuse.md b/dev-docs/bidders/mobilefuse.md index 34b45f2850..fb72ad0ade 100644 --- a/dev-docs/bidders/mobilefuse.md +++ b/dev-docs/bidders/mobilefuse.md @@ -3,7 +3,9 @@ layout: bidder title: MobileFuse pbs: true pbjs: false -media_types: banner, video +media_types: banner, video, native +tcfeu_supported: true +gpp_supported: true schain_supported: true usp_supported: true coppa_supported: true @@ -11,13 +13,16 @@ biddercode: mobilefuse ccpa_supported: true prebid_member: true pbs_app_supported: true +floors_supported: true +gvl_id: 909 +ortb_blocking_supported: true +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|------------------------|---------|----------| -| placement_id | required | An ID which identifies this specific inventory placement | 1111 | integer | -| pub_id | required | An ID which identifies the publisher selling the inventory| 2222 | integer | -| tagid_src | optional | ext if passing publisher's ids, empty if passing MobileFuse IDs in placement_id field. Defaults to empty | '' | string | +| Name | Scope | Description | Example | Type | +| ------------ | -------- | ---------------------------------------------------------- | ------- | ------- | +| placement_id | required | An ID which identifies this specific inventory placement | 1111 | integer | +| pub_id | required | An ID which identifies the publisher selling the inventory | 2222 | integer | diff --git a/dev-docs/bidders/mobsmart.md b/dev-docs/bidders/mobsmart.md deleted file mode 100644 index 19f2b516c7..0000000000 --- a/dev-docs/bidders/mobsmart.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: Mobsmart -description: Prebid Mobsmart SSP Bidder Adaptor -pbjs: true -biddercode: mobsmart -media_types: banner -userIds: pubCommonId -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -The Mobsmart Bidding adapter requires setup and approval beforehand. -For more information, visit [Mobsmart website](https://kpis.jp/en/product_mobsmart). - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------------|----------|-----------------------------------------|----------|-----------| -| `floorPrice` | optional | Floor price | `10` | `Integer` | -| `currency` | optional | Currency of request and response | `'JPY'` | `string` | diff --git a/dev-docs/bidders/monetix.md b/dev-docs/bidders/monetix.md new file mode 100644 index 0000000000..f03d0e3546 --- /dev/null +++ b/dev-docs/bidders/monetix.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Monetix +description: Monetix Adaptor +biddercode: monetix +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_sids: tcfeu, usp +usp_supported: true +coppa_supported: true +pbs_app_supported: false +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Monetix bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.monetixads.com'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/motionspots.md b/dev-docs/bidders/motionspots.md new file mode 100644 index 0000000000..73169217a3 --- /dev/null +++ b/dev-docs/bidders/motionspots.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Motionspots +description: Motionspots Bidder Adaptor +biddercode: motionspots +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Motionspots bidding adapter requires setup and approval before implementation. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.motionspots.com'` | `string` | +| `zoneId` | required | Zone Id | 30164 | `integer` | diff --git a/dev-docs/bidders/motorik.md b/dev-docs/bidders/motorik.md new file mode 100644 index 0000000000..4489c7f846 --- /dev/null +++ b/dev-docs/bidders/motorik.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Motorik +description: Prebid Motorik Bidder Adaptor +biddercode: motorik +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +media_types: banner, video, native +safeframes_ok: true +deals_supported: true +pbjs: true +pbs: true +sidebarType: 1 +floors_supported: true +prebid_member: false +fpd_supported: false +gvl_id: none +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +userIds: all +--- + +### Note + +The Example Bidding adapter requires setup before beginning. Please contact us at . +Motorik will only respond to the first impression. Multiple ad formats in single request are not supported. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | placement id | `'a7402708185f6a0c00700fd21c4260d2'` | `string` | +| `accountId` | required | account id | `'motorikTest'` | `string` | diff --git a/dev-docs/bidders/my6sense.md b/dev-docs/bidders/my6sense.md index 0999af6682..dc65b12072 100644 --- a/dev-docs/bidders/my6sense.md +++ b/dev-docs/bidders/my6sense.md @@ -5,7 +5,8 @@ description: My6Sense Prebid Bidder Adapter media_type: native biddercode: my6sense pbjs: true -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/mytarget.md b/dev-docs/bidders/mytarget.md index d53cbca13a..a10bf209fe 100644 --- a/dev-docs/bidders/mytarget.md +++ b/dev-docs/bidders/mytarget.md @@ -4,6 +4,7 @@ title: myTarget description: Prebid myTarget Bidder Adapter pbjs: true biddercode: mytarget +sidebarType: 1 --- @@ -17,7 +18,6 @@ biddercode: mytarget | `position` | optional | Ad position on screen. See details below. | `1` | `number` | | `response` | optional | Bid response type. 0 - ad url (default), 1 - ad markup. | `1` | `number` | - ### Position The following values are defined in the [ORTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). diff --git a/dev-docs/bidders/nafdigital.md b/dev-docs/bidders/nafdigital.md deleted file mode 100644 index 5ea7fb30d5..0000000000 --- a/dev-docs/bidders/nafdigital.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: bidder -title: NAF Digital -description: Prebid NAF Digital Bidder Adaptor -top_nav_section: dev_docs -nav_section: reference -pbjs: true -biddercode: nafdigital -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: - -The NAF Digital bidder adapter requires setup and approval from the NAF Digital team. Please reach out to your account manager for more information and to start using it. - -### Bid Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -| ---- | ----- | ----------- | ------- | ---- | -| `publisherId` | required | The publisher ID from NAF Digital | `2141020` | `integer` | -| `bidFloor` | optional | The minimum bid value desired | `1.23` | `float` | diff --git a/dev-docs/bidders/nanointeractive.md b/dev-docs/bidders/nanointeractive.md deleted file mode 100644 index 0154d901e0..0000000000 --- a/dev-docs/bidders/nanointeractive.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -layout: bidder -title: Nano Interactive -description: Prebid Nano Interactive Bidder Adapter -pbjs: true -pbs: true -biddercode: nanointeractive -media_types: banner -gdpr_supported: true -gvl_id: 72 -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Requirements: -To be able to get identification key (`pid`), please contact us at
      -`https://www.nanointeractive.com/publishers`
      - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|--------------------------------------------------|------------------------------|----------| -| `pid` | required | Identification key, provided by Nano Interactive | `'5afaa0280ae8996eb578de53'` | `string` | -| `category` | optional | Contextual taxonomy | `'automotive'` | `string` | -| `categoryName` | optional | Contextual taxonomy (from URL query param) | `'cat_name'` | `string` | -| `nq` | optional | User search query | `'automobile search query'` | `string` | -| `name` | optional | User search query (from URL query param) | `'search_param'` | `string` | -| `subId` | optional | Channel - used to separate traffic sources | `'123'` | `string` | - -#### Configuration -The `category` and `categoryName` are mutually exclusive. If you pass both, `categoryName` takes precedence. -
      -The `nq` and `name` are mutually exclusive. If you pass both, `name` takes precedence. - -#### Example with only required field `pid` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53' - } - }] - }]; - -#### Example with `category` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - category: 'automotive', - subId: '123' - } - }] - }]; - -#### Example with `categoryName` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - // Category "automotive" is in the URL like: - // https://www....?cat_name=automotive&... - categoryName: 'cat_name', - subId: '123' - } - }] - }]; - -#### Example with `nq` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - // User searched "automobile search query" (extracted from search text field) - nq: 'automobile search query', - subId: '123' - } - }] - }]; - -#### Example with `name` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - // User searched "automobile search query" and it is in the URL like: - // https://www....?search_param=automobile%20search%20query&... - name: 'search_param', - subId: '123' - } - }] - }]; - -#### Example with `category` and `nq` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - category: 'automotive', - nq: 'automobile search query', - subId: '123' - } - }] - }]; - -#### Example with `categoryName` and `name` - var adUnits = [{ - code: 'nano-div', - sizes: [[300, 250], [300,600]], - bids: [{ - bidder: 'nanointeractive', - params: { - pid: '5afaa0280ae8996eb578de53', - categoryName: 'cat_name', - name: 'search_param', - subId: '123' - } - }] - }]; diff --git a/dev-docs/bidders/nasmediaAdmixer.md b/dev-docs/bidders/nasmediaAdmixer.md deleted file mode 100644 index a9910a1a0a..0000000000 --- a/dev-docs/bidders/nasmediaAdmixer.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: Nasmedia Admixer -description: Prebid Nasmedia Admixer Bidder Adapter -pbjs: true -biddercode: nasmediaAdmixer -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Note: - -The Nasmedia Admixer Bidder Adapter requires setup and approval from the Nasmedia Admixer team. -Please reach out to for more information. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|--------------------------------------------|--------------|----------| -| `media_key` | required | Publisher Key provided by Nasmedia Admixer | `'19038695'` | `string` | -| `adunit_id` | required | Adunit Id provided by Nasmedia Admixer | `'24190632'` | `string` | diff --git a/dev-docs/bidders/nativo.md b/dev-docs/bidders/nativo.md index 9c72c55f07..c330ead57a 100644 --- a/dev-docs/bidders/nativo.md +++ b/dev-docs/bidders/nativo.md @@ -3,15 +3,18 @@ layout: bidder title: Nativo description: Prebid Nativo Bidder Adapter pbjs: true +pbs: true gvl_id: 263 -gdpr_supported: true +tcfeu_supported: true usp_supported: true +userIds: all biddercode: nativo +sidebarType: 1 --- -### Note: +### Note -The Nativo Bidder adapter requires setup before beginning. Please contact us at prebiddev@nativo.com beforehand. +The Nativo Bidder adapter requires setup before beginning. Please contact us at beforehand. ### Bid Params diff --git a/dev-docs/bidders/navelix.md b/dev-docs/bidders/navelix.md deleted file mode 100644 index cc6ad3fb6c..0000000000 --- a/dev-docs/bidders/navelix.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -layout: bidder -title: Navelix -description: Prebid Navelix Bidder Adapter -biddercode: navelix -aliasCode: adtelligent -media_types: video,banner -gdpr_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId -schain_supported: true -coppa_supported: true -usp_supported: true -safeframes_ok: true -prebid_member: true -pbjs: true -pbs: false ---- - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|---------------------------------|----------|-----------| -| `aid` | required | The source ID from navelix. | `529814` | `integer` | - -### Description -Get access to multiple demand partners across Navelix AdExchange and maximize your yield with Navelix header bidding adapter. - -Navelix header bidding adapter connects with Navelix demand sources in order to fetch bids. -This adapter provides a solution for accessing Video demand and display demand. - -Navelix now supports adpod. - -### Test Parameters -``` - var adUnits = [ - - // Video instream adUnit - { - code: 'test-div', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'navelix', - params: { - aid: 472386 - } - }] - }, - - // Video outstream adUnit - { - code: 'test-div', - mediaTypes: { - video: { - context: 'outstream', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'navelix', - params: { - aid: 472386 - } - }] - }, - - // Video ADPOD adUnit - { - code: 'test-div', - sizes: [[640, 480]], - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'navelix', - params: { - aid: 472386 - } - }] - }, - - // Banner adUnit - { - code: 'test-div', - mediaTypes:{ - banner:{ - sizes: [[300, 250]] - } - } - bids: [{ - bidder: 'navelix', - params: { - aid: 529814 - } - }] - } - ]; -``` - -### Additional Configuration - -It is possible to configure requests to be split into chunks so as to have fewer bid requests in a single http request -(default value is 10). - -``` - pbjs.setBidderConfig({ - config: { - navelix: { - chunkSize: 1 // makes 1 http request per 1 adunit configured - } - } - }); -``` diff --git a/dev-docs/bidders/newborntownWeb.md b/dev-docs/bidders/newborntownWeb.md deleted file mode 100644 index f95a9b1968..0000000000 --- a/dev-docs/bidders/newborntownWeb.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: newborntownWeb -description: Prebid newborntownWeb Bidder Adaptor -pbjs: true -biddercode: newborntownWeb -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `publisher_id` | required | Publisher ID which is obtained from sfp.solomath.com | `'1238122'` | `string` | -| `slot_id` | required | Ad Slot ID which is obtained from sfp.solomath.com | `'123123'` | `string` | -| `bidfloor` | required | As a min CPM of this inventory sold | `0.2` | `float` | diff --git a/dev-docs/bidders/newspassid.md b/dev-docs/bidders/newspassid.md new file mode 100644 index 0000000000..1cddd2f8a3 --- /dev/null +++ b/dev-docs/bidders/newspassid.md @@ -0,0 +1,74 @@ +--- +Module Name: NewspassId Bidder Adapter +Module Type: Bidder Adapter +Maintainer: techsupport@newspassid.com +layout: bidder +title: Newspass ID +description: LMC Newspass ID Prebid JS Bidder Adapter +biddercode: newspassid +tcfeu_supported: false +gvl_id: none +usp_supported: true +coppa_supported: false +schain_supported: true +dchain_supported: false +userIds: criteo, id5Id, tdid, identityLink, liveIntentId, parrableId, pubCommonId, lotamePanoramaId, sharedId, fabrickId +media_types: banner +safeframes_ok: true +deals_supported: true +floors_supported: false +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Description + +LMC Newspass ID Prebid JS Bidder Adapter that connects to the NewspassId demand source(s). + +The Newspass bid adapter supports Banner mediaTypes ONLY. +This is intended for USA audiences only, and does not support GDPR + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|-----------|----------|---------------------------|------------|----------| +| `siteId` | required | The site ID. | `"NPID0000001"` | `string` | +| `publisherId` | required | The publisher ID. | `"4204204201"` | `string` | +| `placementId` | required | The placement ID. | `"0420420421"` | `string` | +| `customData` | optional | publisher key-values used for targeting | `[{"settings":{},"targeting":{"key1": "value1", "key2": "value2"}}],` | `array` | + +### Test Parameters + +A test ad unit that will consistently return test creatives: + +```javascript +//Banner adUnit + +const adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'newspassid', + params: { + publisherId: 'NEWSPASS0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '8000000015', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ + } + }] + }]; +``` + +### Note + +Please contact us at for any assistance testing your implementation before going live into production. diff --git a/dev-docs/bidders/nextMillennium.md b/dev-docs/bidders/nextMillennium.md index 6b863fd025..afc72fa9c5 100644 --- a/dev-docs/bidders/nextMillennium.md +++ b/dev-docs/bidders/nextMillennium.md @@ -1,7 +1,9 @@ --- layout: bidder title: NextMillennium -gdpr_supported: true +description: NextMillennium bid adapter +gvl_id: dev-docs/bidders/nextMillennium.md +tcfeu_supported: true usp_supported: true coppa_supported: false schain_supported: false @@ -14,16 +16,99 @@ pbs_app_supported: false pbjs: true pbs: true biddercode: nextMillennium -media_types: banner -description: NextMillennium bid adapter +media_types: banner, video +prebid_member: true +sidebarType: 1 --- -### bid params +### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------+----------+------------------------------------------+-----------|---------| +| Name | Scope | Description | Example | Type | +|----------------+-------+-----------------------------------+-----------+---------| | `placement_id` | required | Placement ID, provided by nextMillennium | `'12345'` | String | +| `group_id` | optional | Group ID, provided by nextMillennium | `'12345'` | String | + +Required one of the two parameters placement_id or group_id. -As input parameters, it accepts only `placement_id`, which is issued when registering in NextMillennium. Further information for the auction on NextMillennium side is generated automatically. + +For video ad requests, we recommend that you configure the `mediaTypes.video` parameters in your Ad Units ([https://docs.prebid.org/dev-docs/adunit-reference.html#video](https://docs.prebid.org/dev-docs/adunit-reference.html#video)). + +### Additional options + +#### disabledSendingStatisticData + +The `disabledSendingStatisticData` parameter disables sending statistics data to the nextMillennium server, such as bidRequested, bidResponse, noBid and bidTimeout events. +An example of enabling this option: + +```javascript +pbjs.setBidderConfig({ + bidders: ['nextMillennium'], + config: { + disabledSendingStatisticData: true, + }, +}) +``` + +#### Currency + +By default, the currency used for requires is `USD`. But you can use any other currency in the request. To do this, you must set this currency through the Prebid.js configuration and all responses will be returned in this currency. + +```javascript +pbjs.setConfig({ + // ... + "currency": { + "adServerCurrency": "JPY", + } + // ... +}); +``` + +#### OpenRTB 2.5 supported parameters + +The adapter for Prebid.js supports the following options: + +* `site.pagecat` +* `site.content.cat` +* `site.content.language` +* `device.sua'` +* `site.keywords'` +* `site.content.keywords'` +* `user.keywords'` + +You can set these parameters through the Prebid.js configuration setup functions: [pbjs.setConfig](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html) or [pbjs.setBidderConfig](https://docs.prebid.org/dev-docs/publisher-api-reference/setBidderConfig.html). +An example of setting openrtb parameters for the entire prebid.js script. + +```javascript +pbjs.setConfig({ + ortb2: { + site: { + pagecat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], + content: { + cat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], + language: 'EN' + }, + } + } +}); +``` + +An example of setting openrtb parameters only for the NextMillennium adapter. + +```javascript +pbjs.setBidderConfig({ + bidders: ['bidderB'], + config: { + ortb2: { + site: { + pagecat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], + content: { + cat: ['IAB2-11', 'IAB2-12', 'IAB2-14'], + language: 'EN' + }, + } + } + } +}); +``` diff --git a/dev-docs/bidders/nextroll.md b/dev-docs/bidders/nextroll.md index c99e92a4b3..e6908f1cf4 100644 --- a/dev-docs/bidders/nextroll.md +++ b/dev-docs/bidders/nextroll.md @@ -5,9 +5,11 @@ description: Prebid NextRoll Bidder Adapter pbjs: true biddercode: nextroll media_types: display, native -gdpr_supported: false +tcfeu_supported: false +floors_supported: true usp_supported: true prebid_member: true +sidebarType: 1 --- ### Bid Params @@ -21,6 +23,7 @@ prebid_member: true | `bidfloor` | optional | Per ad-unit bid floor, used if the floor module is not available | `2.3` | `number` | #### Example of Banner Ad-unit + ``` var adUnits = [ { @@ -70,6 +73,7 @@ var adUnits = [ ``` #### Example of Native Ad-unit + ``` var adUnits = [ { diff --git a/dev-docs/bidders/nexx360.md b/dev-docs/bidders/nexx360.md new file mode 100644 index 0000000000..089eeedd47 --- /dev/null +++ b/dev-docs/bidders/nexx360.md @@ -0,0 +1,132 @@ +--- +layout: bidder +title: Nexx360 +description: Prebid Nexx360 Bidder Adapter +pbjs: true +biddercode: nexx360 +tcfeu_supported: true +usp_supported: true +schain_supported: true +floors_supported: true +userIds: all +tcf2_supported: true +media_types: banner, video, native +gvl_id: 965 +pbs: false +sidebarType: 1 + +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------------|-------------------------------------- |-----------| +| `tagId` | required | Nexx360 tag ID | `"luvxjvgn"` | `string` | +| `videoTagId` | optional | Nexx360 Video tag ID | `"luvxjvgn"` | `string` | +| `nativeTagId` | optional | Nexx360 Native tag ID | `"luvxjvgn"` | `string` | +| `allBids` | optional | Return all bids | `true` | `boolean` | +| `divId` | optional | divId linked to adUnit | `"div-1"` | `string` | +| `adUnitName` | optional | A code to identify adUnit | `"header-ad"` | `string` | +| `adUnitPath` | optional | A reference to adUnit Path | `"/12345/nexx360/Homepage/HP/Header-Ad"` | `string` | + +### Bidder Config + +You can allow writing in localStorage `pbjs.bidderSettings` for the bidder `nexx360` + +```javascript +pbjs.bidderSettings = { + nexx360: { + storageAllowed : true + } +} +``` + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +### Test Parameters + +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'nexx360', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Video adUnit + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'nexx360', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Native adUnit + { + code: 'native1', + mediaTypes: { + native: { + title: { + required: true + }, + image: { + required: true + }, + sponsoredBy: { + required: true + } + } + }, + bids: [{ + bidder: 'nexx360', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Multiformat Ad + { + code: 'multi1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + }, + banner: { + sizes: [[300, 250], [300,600]] + }, + native: { + + } + }, + bids: [{ + bidder: 'nexx360', + params: { + tagId: 'luvxjvgn', + videoTagId: 'luvxjvgn' + } + }] + }; +]; +``` diff --git a/dev-docs/bidders/ninthdecimal.md b/dev-docs/bidders/ninthdecimal.md index 468e00ecfe..af53ba3f91 100644 --- a/dev-docs/bidders/ninthdecimal.md +++ b/dev-docs/bidders/ninthdecimal.md @@ -4,6 +4,7 @@ title: NinthDecimal pbs: true media_types: banner biddercode: ninthdecimal +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/nobid.md b/dev-docs/bidders/nobid.md index 02d54e53c0..5e3499a6c0 100644 --- a/dev-docs/bidders/nobid.md +++ b/dev-docs/bidders/nobid.md @@ -1,19 +1,22 @@ --- layout: bidder title: Nobid -description: Prebid Nobid Bidder Adaptor +description: Prebid NoBid Bidder Adaptor biddercode: nobid pbjs: true pbs: true media_types: banner, video -gdpr_supported: true +tcfeu_supported: true gvl_id: 816 usp_supported: true +gpp_supported: true schain_supported: true coppa_supported: true -userId: criteo, unifiedId, id5Id +userId: criteo, unifiedId, id5Id, intentIqId safeframes_ok: true -fpd_supported: true +prebid_member: false +floors_supported: true +sidebarType: 1 --- ### Bid Params @@ -25,14 +28,14 @@ fpd_supported: true | `placementId` | optional | placementId is provided by your NoBid account manager(s). This parameter allows to report on a specific ad unit | | `integer` | | `video`| optional | Object containing video targeting parameters. Note that this parameter is not used in Prebid Server. See [Video Object](#nobid-video-object) for details. | `video: { playback_method: ['auto_play_sound_off'] }` | `object`| - ### Note -If you are using Google Ad Manager (GAM), it is highly recommended to make sure the “Serve in Safeframe” box in creative settings is unchecked. + +If you are using Google Ad Manager (GAM), it is highly recommended to make sure the “Serve in Safeframe” box in creative settings is unchecked. If you absolutely want to run NoBid in a Saferame creative, please contact your Nobid repsentative to coordinate this setup. +### Test Parameters -# Test Parameters -``` +```javascript var adUnits = [ { code: 'test-div1', @@ -83,4 +86,3 @@ If you absolutely want to run NoBid in a Saferame creative, please contact your | `minduration` | Integer that defines the minimum video ad duration in seconds. | `integer` | | `maxduration` | Integer that defines the maximum video ad duration in seconds. | `integer` | | `frameworks` | Array of integers listing API frameworks supported by the publisher. Allowed values: None: `0`; VPAID 1.0: `1`; VPAID 2.0: `2`; MRAID 1.0: `3`; ORMMA: `4`; MRAID 2.0: `5`. | `Array` | - diff --git a/dev-docs/bidders/ocm.md b/dev-docs/bidders/ocm.md new file mode 100644 index 0000000000..120d96c19b --- /dev/null +++ b/dev-docs/bidders/ocm.md @@ -0,0 +1,108 @@ +--- +layout: bidder +title: Orangeclickmedia +description: Prebid OCM Bidder Adapter +biddercode: ocm +aliasCode: adtelligent +media_types: video,banner +tcfeu_supported: true +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: false +deals_supported: false +gvl_id: 1148 +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from OCM. | `529814` | `integer` | + +### Description + +OCM header bidding adapter connects with OCM demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'ocm', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'ocm', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'ocm', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'ocm', + params: { + aid: 529814 + } + }] + } + ]; +``` diff --git a/dev-docs/bidders/oftmedia.md b/dev-docs/bidders/oftmedia.md index dcb7302602..6d7b381972 100644 --- a/dev-docs/bidders/oftmedia.md +++ b/dev-docs/bidders/oftmedia.md @@ -5,11 +5,18 @@ description: Prebid One Fifty Two Media Bidder Adaptor pbjs: true biddercode: oftmedia aliasCode : appnexus -gdpr_supported: true +tcfeu_supported: true coppa_supported: true usp_supported: true -pbs: true +pbs: false schain_supported: true +media_types: banner, video, native +prebid_member: true +userIds: criteo, identityLink, netId, pubProvidedId, uid2, unifiedId, +floors_supported: true +fpd_supported: true +gvl_id: 32 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/oftmediahb.md b/dev-docs/bidders/oftmediahb.md deleted file mode 100644 index 6c90055382..0000000000 --- a/dev-docs/bidders/oftmediahb.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: 152MediaHB -description: Prebid 152MediaHB Bidder Adaptor -pbjs: true -media_types: video -gdpr_supported: true -biddercode: oftmediahb -aliasCode : adkernel ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-----------------------|---------------------------|----------| -| `host` | required | Ad network's RTB host | `'cpm.152media.com'` | `string` | -| `zoneId` | required | RTB zone id | `'30164'` | `string` | - -oftmediahb is an aliased bidder for AdKernel diff --git a/dev-docs/bidders/ogury.md b/dev-docs/bidders/ogury.md index a1ae8c5f42..e80db70e7e 100644 --- a/dev-docs/bidders/ogury.md +++ b/dev-docs/bidders/ogury.md @@ -3,7 +3,7 @@ layout: bidder title: ogury description: Ogury Bidder Adapter biddercode: ogury -gdpr_supported: true +tcfeu_supported: true gvl_id: 31 usp_supported: false coppa_supported: false @@ -16,15 +16,30 @@ deals_supported: false pbjs: true pbs: false prebid_member: false +sidebarType: 1 --- -### Note: +### Registration -The Ogury Bidding adapter requires setup before start of usage: some configuration & account creation needs to be done. Please contact us at web.inventory@ogury.co + Before Ogury's adapter integration, you have to register an account in the Ogury Platform. Please contact if you're interested in a partnership. +If you already have an account you'll need to register your websites (= assets) and the placements (= ad units) within the Platform. Alternatively reach out to your POC within Ogury to assist you with the placement creation. +A detailed overview about the integration process can be found in [this documentation](https://ogury-ltd.gitbook.io/mobile-web/header-bidding/ogury-prebid.js-adapter-integration). -### Bid Params + After this registration, you will receive the Asset IDs and Ad Unit IDs to start the integration. + +### Mandatory bid Params + +The minimal list of bid params is: {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| | `assetKey` | required | The asset key provided by Ogury | `'OGY-CA41D116484F'` | `string` | | `adUnitId` | required | Your ad unit id configured with Ogury | `'2c4d61d0-90aa-0139-0cda-0242ac120004'` | `string` | + +### Optional bid Params + +Depending on your advertising format needs, other optional parameters can be used. Supported parameters are detailed [here](https://ogury-ltd.gitbook.io/mobile-web/header-bidding/ogury-prebid.js-adapter-integration#optional-configuration). + +## How to contact us + +If you have any technical concerns or questions about the adapter, please contact . diff --git a/dev-docs/bidders/oms.md b/dev-docs/bidders/oms.md new file mode 100644 index 0000000000..5990e56780 --- /dev/null +++ b/dev-docs/bidders/oms.md @@ -0,0 +1,43 @@ +--- +layout: bidder +title: Online Media Solutions +description: Prebid Online Media Solutions(OMS) Bidder Adapter +tcfeu_supported: true +coppa_supported: true +usp_supported: true +pbjs: true +pbs: true +biddercode: oms +prebid_member: false +floors_supported: true +safeframes_ok: true +media_types: banner +schain_supported: true +userIds: id5Id, identityLink, pubProvidedId +pbs_app_supported: true +sidebarType: 1 +gvl_id: 883 +fpd_supported: true +gpp_sids: tcfeu, usnat +ortb_blocking_supported: true +--- +### Note + +The bidder requires setup before usage. Please get in touch with our team at to get started. + +### Prebid.JS Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +| ---- | ----- | ----------- | ------- | ---- | +| `publisherId` | required | Unique publisher ID | `12345` | `integer` | +| `bidFloor` | optional | The minimum bid value desired | `1.23` | `float` | + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------|---------------|----------| +| `pid` | required | Unique publisher ID | `'12345'` | `string` | diff --git a/dev-docs/bidders/oneVideo.md b/dev-docs/bidders/oneVideo.md deleted file mode 100644 index 4b50d23c55..0000000000 --- a/dev-docs/bidders/oneVideo.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: bidder -title: OneVideo -description: Prebid One Video Bidder Adaptor -pbjs: true -biddercode: oneVideo -media_types: video -gdpr_supported: true -usp_supported: true ---- - -### IMPORTANT NOTICE! -**TL;DR** -1. The `oneVideo` adapter is scheduled to be depreciated. -2. Our New `yahoossp` is available for early adoption. -3. Please contact your Account Manager/Executive for migration details. - -Dear Publishers & Partners, -As part of our platform consolidation process to simplify your integrations moving forward -We invite you to switch from the `oneVideo` Adapter to our NEW `yahoossp` bid adapter for both Display & Video inventory. -FYI - The oneVideo adapter is scheduled for depreciation in the upcoming months. - -Thanks in advance, -Yahoo SSP - -### Note: - -One Video adapter only supports video ads. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------|----------|--------------|----------|----------| -| `pubId` | required | Publisher ID | `'brxd'` | `string` | diff --git a/dev-docs/bidders/onedisplay.md b/dev-docs/bidders/onedisplay.md index e0749df141..b69aa968e9 100644 --- a/dev-docs/bidders/onedisplay.md +++ b/dev-docs/bidders/onedisplay.md @@ -5,9 +5,12 @@ description: Prebid AOL Bidder Adaptor pbjs: true biddercode: onedisplay aliasCode : aol +sidebarType: 1 --- -### IMPORTANT NOTICE! +### IMPORTANT NOTICE + **TL;DR** + 1. The `onedisplay` adapter is scheduled to be depreciated. 2. Our New `yahoossp` is available for early adoption. 3. Please contact your Account Manager/Executive for migration details. @@ -20,7 +23,6 @@ FYI - The oneVideo adapter is scheduled for depreciation in the upcoming months. Thanks in advance, Yahoo SSP - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/onefiftytwomedia.md b/dev-docs/bidders/onefiftytwomedia.md deleted file mode 100644 index d7b157bcdb..0000000000 --- a/dev-docs/bidders/onefiftytwomedia.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -layout: bidder -title: 152 Media 3.0 -description: Prebid 152 Media RTB Bidder Adapter -pbjs: true -biddercode: onefiftytwomedia -aliasCode: adtelligent -media_types: banner, video ---- - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|---------------------------------|----------|-----------| -| `aid` | required | The source ID | `350975` | `integer` | - - -### Test Parameters -``` - var adUnits = [ - - // Video instream adUnit - { - code: 'div-test-div', - sizes: [[640, 480]], - mediaTypes: { - video: { - context: 'instream' - } - }, - bids: [{ - bidder: 'onefiftytwomedia', - params: { - aid: 331133 - } - }] - }, - - // Video outstream adUnit - { - code: 'outstream-test-div', - sizes: [[640, 480]], - mediaTypes: { - video: { - context: 'outstream' - } - }, - bids: [{ - bidder: 'onefiftytwomedia', - params: { - aid: 331133 - } - }] - }, - - // Banner adUnit - { - code: 'div-test-div', - sizes: [[300, 250]], - bids: [{ - bidder: 'onefiftytwomedia', - params: { - aid: 350975 - } - }] - } - ]; -``` diff --git a/dev-docs/bidders/onemobile.md b/dev-docs/bidders/onemobile.md index aabc65de76..c6a264b321 100644 --- a/dev-docs/bidders/onemobile.md +++ b/dev-docs/bidders/onemobile.md @@ -5,10 +5,13 @@ description: Prebid AOL Bidder Adaptor aliase pbjs: true biddercode: onemobile aliasCode : aol +sidebarType: 1 --- -### IMPORTANT NOTICE! +### IMPORTANT NOTICE + **TL;DR** + 1. The `onemobile` adapter is scheduled to be depreciated. 2. Our New `yahoossp` is available for early adoption. 3. Please contact your Account Manager/Executive for migration details. diff --git a/dev-docs/bidders/oneplanetonly.md b/dev-docs/bidders/oneplanetonly.md index 4eba8521e5..56f336f612 100644 --- a/dev-docs/bidders/oneplanetonly.md +++ b/dev-docs/bidders/oneplanetonly.md @@ -4,6 +4,7 @@ title: Oneplanetonly description: Prebid Oneplanetonly Bidder Adaptor pbjs: true biddercode: oneplanetonly +sidebarType: 1 --- diff --git a/dev-docs/bidders/onetag.md b/dev-docs/bidders/onetag.md index 861137a841..e3f144a02e 100644 --- a/dev-docs/bidders/onetag.md +++ b/dev-docs/bidders/onetag.md @@ -6,10 +6,17 @@ pbjs: true pbs: true biddercode: onetag media_types: banner, video -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true +gpp_supported: true gvl_id: 241 usp_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +floors_supported: true +sidebarType: 1 +coppa_supported: true +privacy_sandbox: topics --- diff --git a/dev-docs/bidders/onomagic.md b/dev-docs/bidders/onomagic.md index abbcc8371a..1ec8b5c1dc 100644 --- a/dev-docs/bidders/onomagic.md +++ b/dev-docs/bidders/onomagic.md @@ -6,15 +6,16 @@ top_nav_section: dev_docs nav_section: reference pbjs: true biddercode: onomagic +sidebarType: 1 --- -### Note: +### Note The Onomagic bidder adapter requires setup and approval from the Onomagic team. Please reach out to your account manager for more information and to start using it. ### Bid Params -{: .table .table-bordered .table-striped } +{: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | | ---- | ----- | ----------- | ------- | ---- | diff --git a/dev-docs/bidders/open8.md b/dev-docs/bidders/open8.md index 5bb65f9531..4a7ed810d0 100644 --- a/dev-docs/bidders/open8.md +++ b/dev-docs/bidders/open8.md @@ -5,8 +5,8 @@ description: Prebid OPEN8 Bidder Adaptor pbjs: true biddercode: open8 media_types: video, banner -enable_download: false -pbjs_version_notes: not ported to 5.x +enable_download: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/openweb.md b/dev-docs/bidders/openweb.md index 162df57a03..fd07aeb675 100644 --- a/dev-docs/bidders/openweb.md +++ b/dev-docs/bidders/openweb.md @@ -2,63 +2,90 @@ layout: bidder title: OpenWeb description: Prebid OpenWeb Bidder Adapter +pbjs: true biddercode: openweb -media_types: banner -gdpr_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +media_types: banner, video +multiformat_supported: will-bid-on-any schain_supported: true coppa_supported: true +tcfeu_supported: true +gpp_supported: true +gpp_sids: tcfeu, usstate_all, usp usp_supported: true -safeframes_ok: true -prebid_member: true -pbjs: true -pbs: true +safeframes_ok: false +pbs: false +floors_supported: true +userIds: all +fpd_supported: true gvl_id: 280 +sidebarType: 1 --- -### Bid params +### Note + +The OpenWeb adapter requires setup and approval. Please reach out to to setup an OpenWeb account. + +### Bid Parameters + +#### Banner, Video {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|---------------------------------|----------|-----------| -| `aid` | required | The source ID from OpenWeb. | `650342` | `integer` | +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | OpenWeb publisher Id provided by your OpenWeb representative | "1234567890abcdef12345678" +| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false -### Description -OpenWeb.com official prebid adapter. Available in both client and server side versions. -OpenWeb header bidding adapter provides solution for accessing banner demand. +## Example -### Test Parameters -``` -var adUnits = [ - // Banner adUnit - { - mediaTypes: { +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { banner: { - sizes: [[300, 250]] + sizes: [ + [300, 250], + [728, 90] + ] } - }, - code: 'div-test-div', - bids: [{ - bidder: 'openweb', - params: { - aid: 650342 - } - }] - }, - // Prebid server - { - mediaTypes: { - banner: { - sizes: [[300, 250]] + }, + bids: [{ + bidder: 'openweb', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false // Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'openweb', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false // Optional } - }, - code: 'div-test-div', - bids: [{ - bidder: 'openweb', - params: { - aid: 650346 - } - }] - } + }] + } ]; ``` + +### Configuration + +OpenWeb recommends setting UserSync by iframe for monetization. diff --git a/dev-docs/bidders/openwebvideo.md b/dev-docs/bidders/openwebvideo.md index bc6a663c50..8dcb9f1fee 100644 --- a/dev-docs/bidders/openwebvideo.md +++ b/dev-docs/bidders/openwebvideo.md @@ -6,13 +6,16 @@ pbjs: true biddercode: openwebvideo aliasCode: aniview media_types: banner, video -gdpr_supported: true +gvl_id: 780 (aniview) +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true +sidebarType: 1 --- -### Note: +### Note + For more information about [OpenWeb](https://www.openweb.com/). ### Bid Params @@ -24,7 +27,8 @@ For more information about [OpenWeb](https://www.openweb.com/). | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` + +```javascript videoAdUnit = [ { code: 'video1', diff --git a/dev-docs/bidders/openwebxchange.md b/dev-docs/bidders/openwebxchange.md new file mode 100644 index 0000000000..eb7da48e83 --- /dev/null +++ b/dev-docs/bidders/openwebxchange.md @@ -0,0 +1,97 @@ +--- +layout: bidder +title: OpenWebXChange +description: Prebid OpenWebXChange Bidder Adapter +multiformat_supported: will-bid-on-any +pbjs: true +biddercode: openwebxchange +media_types: banner, video +schain_supported: true +coppa_supported: true +pbs: false +tcfeu_supported: true +usp_supported: true +floors_supported: true +userIds: all +gvl_id: 280 +sidebarType: 1 +--- + +### Note + +The OpenWebXChange adapter requires setup and approval. + +### Bid Parameters + +#### Banner, Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | OpenWebXChange publisher Id | "1234567890abcdef12345678" +| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false +| `rtbDomain` | optional | String | Sets the seller end point | "www.test.com" +| `is_wrapper` | private | Boolean | Please don't use unless your account manager asked you to | false +| `currency` | optional | String | 3 letters currency | "EUR" + +## Example + +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'openwebxchange', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'openwebxchange', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } + }] + } +]; +``` + +### Configuration + +We recommend setting UserSync by iframe for monetization. + +### Versions + +Prebid versions 5.0-5.3 are not supported +Banner >= 6.14.0 diff --git a/dev-docs/bidders/openx.md b/dev-docs/bidders/openx.md index 9bc0dab52e..db7088974f 100644 --- a/dev-docs/bidders/openx.md +++ b/dev-docs/bidders/openx.md @@ -7,44 +7,152 @@ pbs: true biddercode: openx media_types: banner, video schain_supported: true -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true +gpp_supported: true floors_supported: true -userIds: admixerId, adtelligentId, amxId, britepoolId, criteo, dapId, deepintentId, dmdId, fabrickId, flocId, hadronId, id5Id, identityLink, idxId, imuId, intentIqId, kinessoId, liveIntentId, lotamePanoramaId, merkleId, mwOpenLinkId, naveggId, netId, nextrollId, novatiq, parrableId, pubCommonId, publinkId, quantcastId, sharedId, tapadId, uid2, unifiedId, verizonMediaId, zeotapIdPlus +userIds: admixerId, adtelligentId, amxId, britepoolId, criteo, dapId, deepintentId, dmdId, fabrickId, hadronId, id5Id, identityLink, idxId, imuId, intentIqId, kinessoId, liveIntentId, lotamePanoramaId, merkleId, mwOpenLinkId, naveggId, netId, novatiq, parrableId, pubCommonId, publinkId, quantcastId, sharedId, tapadId, uid2, unifiedId, verizonMediaId, zeotapIdPlus prebid_member: true fpd_supported: true gvl_id: 69 +sidebarType: 1 --- ### Registration -If you have any questions regarding set up, please reach out to your account manager or support@openx.com. +If you have any questions regarding set up, please reach out to your account manager or . + +Please note that OpenX is transitioning its serving architecture and currently has 2 bid adapters as of Prebid 7. The legacy adapter is named openxBidAdapter. +The newer of the two is openxOrtbBidAdapter. Publishers are welcome to test with openxOrtbBidAdapter and give feedback. +After the transition openxOrtbBidAdapter will replace openxBidAdapter. + +IMPORTANT: only include either openxBidAdapter or openxOrtbBidAdapter in your build. + +### Prebid Server Note + +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} ### Bid Parameters + #### Banner {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | | ---- | ----- | ----------- | ------- | ---- | -| `delDomain` or `platform` | required | OpenX delivery domain or platform id provided by your OpenX representative. Both may be present. `platform` is preferred | "PUBLISHER-d.openx.net" or "555not5a-real-plat-form-id0123456789" | String | +| `delDomain` ~~or `platform`~~** | required | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" | String | | `unit` | required | OpenX ad unit ID provided by your OpenX representative. | "1611023122" | String | | `customParams` | optional | User-defined targeting key-value pairs. customParams applies to a specific unit. | `{key1: "v1", key2: ["v2","v3"]}` | Object | -| `customFloor` | optional | Minimum price in USD. customFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50

      **WARNING:**
      Misuse of this parameter can impact revenue | 1.50 | Number | +| `customFloor` | optional | Minimum price in USD. customFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50

      **WARNING:**
      Misuse of this parameter can impact revenue.

      Note:
      OpenX suggests using the [Price Floor Module](/dev-docs/modules/floors.html) instead of customFloor. The Price Floor Module is prioritized over customFloor if both are present. | 1.50 | Number | | `doNotTrack` | optional | Prevents advertiser from using data for this user.

      **WARNING:**
      Impacts all bids in the request. May impact revenue. | true | Boolean | | `coppa` | optional | Enables Child's Online Privacy Protection Act (COPPA) regulations. **WARNING:**
      Impacts all bids in the request. May impact revenue. | true | Boolean | +** platform is deprecated. Please use delDomain instead. If you have any questions please contact your representative. + +### AdUnit Format for Banner + +```javascript +var adUnits = [ + { + code: 'test-div', + sizes: [[728, 90]], // a display size + mediaTypes: {'banner': {}}, + bids: [ + { + bidder: 'openx', + params: { + unit: '539439964', + delDomain: 'se-demo-d.openx.net', + customParams: { + key1: 'v1', + key2: ['v2', 'v3'] + }, + } + }, { + bidder: 'openx', + params: { + unit: '539439964', + delDomain: 'se-demo-d.openx.net', + customParams: { + key1: 'v1', + key2: ['v2', 'v3'] + }, + } + } + ] + } +]; +``` + #### Video {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | | ---- | ----- | ----------- | ------- | ---- | | `unit` | required | OpenX ad unit ID provided by your OpenX representative. | "1611023122" | String | -| `delDomain` or `platform` | required | OpenX delivery domain or platform id provided by your OpenX representative. Both may be present. `platform` is preferred | "PUBLISHER-d.openx.net" or "555not5a-real-plat-form-id0123456789" | String | -| `openrtb` | optional | An OpenRtb Impression with Video subtype properties | `{ imp: [{ video: {mimes: ['video/x-ms-wmv, video/mp4']} }] }` | Object | +| `delDomain` ~~or `platform`~~** | required | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" | String | + +** platform is deprecated. Please use delDomain instead. If you have any questions please contact your representative. + +#### mediaTypes.video + +The following video parameters are supported here so publishers may fully declare their video inventory: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| context | required | instream or outstream |"outstream" | string | +| playerSize| required | width, height of the player in pixels | [640,360] - will be translated to w and h in bid request | array | +| mimes | required | List of content MIME types supported by the player (see openRTB v2.5 for options) | ["video/mp4"]| array| +| protocols | recommended | Supported video bid response protocol values
      1: VAST 1.0
      2: VAST 2.0
      3: VAST 3.0
      4: VAST 1.0 Wrapper
      5: VAST 2.0 Wrapper
      6: VAST 3.0 Wrapper
      7: VAST 4.0
      8: VAST 4.0 Wrapper | [2,3,5,6] | array| +| api | recommended | Supported API framework values:
      1: VPAID 1.0
      2: VPAID 2.0
      3: MRAID-1
      4: ORMMA
      5: MRAID-2 | [2] | array | +| linearity | recommended | OpenRTB2 linearity. 1: linear (in-stream ad), 2: non-linear (overlay ad) | 1 | integer | +| maxduration | recommended | Maximum video ad duration in seconds. | 30 | integer | +| minduration | recommended | Minimum video ad duration in seconds | 6 | integer | +| playbackmethod | recommended | Playback methods that may be in use. Only one method is typically used in practice. (see openRTB v2.5 section 5.10 for options)| [2]| array | +| minbitrate | optional | Minimum bit rate in Kbps. | 300 | integer | +| maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | integer | +| battr | optional | Blocked creative attributes | [13,14] | array| +| startdelay | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements.
      >0: Mid-Roll (value indicates start delay in second)
      0: Pre-Roll
      -1: Generic Mid-Roll
      -2: Generic Post-Roll | 0 | integer | +| placement | recommended | Placement type for the impression. (see openRTB v2.5 section 5.9 for options) | 1 | integer | +| | | | | | +### AdUnit Format for Video + +```javascript +var videoAdUnits = [ +{ + code: 'test-div-video', + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream', + mimes: ['video/mp4','video/x-flv'], // required + minduration: 5, // optional + maxduration: 30, // optional + startdelay: 5, // optional + playbackmethod: [1,3], // optional + api: [ 1, 2 ], // optional + protocols: [ 2, 3 ], // optional + battr: [ 13, 14 ], // optional + linearity: 1, // optional + placement: 2, // optional + minbitrate: 10, // optional + maxbitrate: 10 // optional + } + }, + bids: [{ + bidder: 'openx', + params: { + unit: '1611023124', + delDomain: 'PUBLISHER-d.openx.net' + } + }] +}] +``` ## Example + ```javascript var adUnits = [ { @@ -66,7 +174,7 @@ var adUnits = [ bidder: 'openx', params: { unit: '539439964', - platform: 'a3aece0c-9e80-4316-8deb-faf804779bd1', + delDomain: 'se-demo-d.openx.net', customParams: { key1: 'v1', key2: ['v2', 'v3'] @@ -95,7 +203,45 @@ var adUnits = [ ]; ``` +### First Party Data + +OpenX supports FPD configured under `ortb2.user`and `ortb2.site.content` as described [here](/features/firstPartyData.html). +Ad unit specific FPD is not supported, and segment taxonomies (`segtax`) are simply passed through. If you have any questions, please reach out to us at [prebid@openx.com] + +Example: + +```javascript +pbjs.setConfig({ + ... + ortb2: { + site: { + content: { + data: [{ + name: "www.dataprovider1.com", + ext: { segtax: 4 }, + segment: [ + { id: "687" }, + { id: "123" } + ] + }] + }, + }, + user: { + data: [{ + name: "dataprovider.com", + ext: { segtax: 4 }, + segment: [ + { id: "1" } + ] + }], + } + } + ... +}); +``` + ### Configuration + Add the following code to enable user syncing. By default, Prebid.js version 0.34.0+ turns off user syncing through iframes. OpenX strongly recommends enabling user syncing through iframes. This functionality improves DSP user match rates and increases the OpenX bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. @@ -109,6 +255,6 @@ pbjs.setConfig({ ``` ## Additional Details -[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) -[Video Ads](https://docs.openx.com/Content/developers/containers/prebid-video-adapter.html) +* [Banner Ads](https://docs.openx.com/publishers/prebid-adapter-web/) (Customer login required.) +* [Video Ads](https://docs.openx.com/publishers/prebid-adapter-video/) (Customer login required.) diff --git a/dev-docs/bidders/openxoutstream.md b/dev-docs/bidders/openxoutstream.md index 9f818829bc..3756cc47fb 100644 --- a/dev-docs/bidders/openxoutstream.md +++ b/dev-docs/bidders/openxoutstream.md @@ -8,12 +8,16 @@ media_types: native prebid_member: true coppa_supported: true gvl_id: 69 +sidebarType: 1 +enable_download : false --- +{: .alert.alert-warning :} +Deprecated adapter ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|----------------------|---------------------------|----------| -| `delDomain` | required | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" | String | +| `delDomain` | required | OpenX delivery domain provided by your OpenX representative. | "PUBLISHER-d.openx.net" | String | diff --git a/dev-docs/bidders/operaads.md b/dev-docs/bidders/operaads.md index 49393966e3..ec7f6fea7a 100644 --- a/dev-docs/bidders/operaads.md +++ b/dev-docs/bidders/operaads.md @@ -3,8 +3,8 @@ layout: bidder title: OperaAds description: Prebid OperaAds Bidder Adapter biddercode: operaads -gdpr_supported: false -gvl_id: none +tcfeu_supported: true +gvl_id: 1135 usp_supported: false coppa_supported: true schain_supported: true @@ -15,11 +15,12 @@ deals_supported: false pbjs: true pbs: true prebid_member: false +sidebarType: 1 --- ### Registration -If you have any questions regarding set up, please reach out to your account manager or adtech-prebid-group@opera.com. +If you have any questions regarding set up, please reach out to your account manager or . ### Bid Parameters diff --git a/dev-docs/bidders/opsco.md b/dev-docs/bidders/opsco.md new file mode 100644 index 0000000000..85dc552e93 --- /dev/null +++ b/dev-docs/bidders/opsco.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: OpsCo +description: Prebid OpsCo Bid Adapter +pbjs: true +biddercode: opsco +media_types: banner +tcfeu_supported: false +gvl_id: none +prebid_member: false +deals_supported: false +floors_supported: false +coppa_supported: false +fpd_supported: false +ortb_blocking_supported: false +gpp_sids: check with bidder +safeframes_ok: true +usp_supported: true +schain_supported: true +sidebarType: 1 + +--- + +### Integration Note + +OpsCo header bidding adapter connects with OpsCo demand sources. Please reach out to for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|------------------------|---------|----------| +| `placementId` | required | The Placement ID | `'123'` | `string` | +| `publisherId` | required | The Publisher ID | `'123'` | `string` | +| `siteId` | optional | The Site ID | `'123'` | `string` | +| `test` | optional | Whether the request is for testing only. | `true` | `boolean` | + diff --git a/dev-docs/bidders/optable.md b/dev-docs/bidders/optable.md new file mode 100644 index 0000000000..b937d20eb1 --- /dev/null +++ b/dev-docs/bidders/optable.md @@ -0,0 +1,43 @@ +--- +layout: bidder +title: Optable +description: Prebid Optable Bidder Adapter +biddercode: optable +pbjs: true +privacy_sandbox: paapi +prebid_member: true +sidebarType: 1 +--- + +### Registration + +If you have any questions regarding set up, please reach out to your account manager or . + +### Bid Parameters + +#### Banner + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ---- | ----- | ----------- | ------- | ---- | +| `site` | required | Optable site ID provided by your Optable representative. | "aaaaaaaa" | String | + +### AdUnit Format for Banner + +```javascript +var adUnits = [ + { + code: 'test-div', + sizes: [[728, 90]], // a display size + mediaTypes: {'banner': {}}, + bids: [ + { + bidder: 'optable', + params: { + site: 'aaaaaaaa', + } + } + ] + } +]; +``` diff --git a/dev-docs/bidders/optidigital.md b/dev-docs/bidders/optidigital.md new file mode 100644 index 0000000000..f9616fc97f --- /dev/null +++ b/dev-docs/bidders/optidigital.md @@ -0,0 +1,82 @@ +--- +layout: bidder +title: Optidigital +description: Prebid Optidigital Bidder Adapter +biddercode: optidigital +pbjs: true +floors_supported: true +tcfeu_supported: true +tcf2_supported: true +usp_supported: true +gpp_sids: tcfeu, usnat, usp +schain_supported: true +ortb_blocking_supported: true +safeframes_ok: true +media_types: banner +userIds: all +gvl_id: 915 +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|----------|------------------------------------------------|--------------------------|--------------------| +| `publisherId` | required | Unique id of the publisher | `'p1234'` | `string` | +| `placementId` | required | Identifier for specific ad placement or ad tag | `'Billboard_Top'` | `string` | +| `divId` | optional | Id of the div containing the ad slot | `'Billboard_Top_3c5425'` | `string` | +| `pageTemplate` | optional | Page template name of the current page | `'home'` | `string` | +| `badv` | optional | Blocked advertiser domains | `['example.com']` | `array of strings` | +| `bcat` | optional | Blocked advertiser categories | `['IAB1-1', 'IAB1-2']` | `array of strings` | +| `bapp` | optional | Blocked advertiser mobile app bundles | `['com.blocked']` | `array of strings` | +| `battr` | optional | Blocked creative attributes | `[1, 2]` | `array of integers`| + +### Note + +The Optidigital Bidding adapter requires setup before beginning. Please contact us at . +The following test parameters can be used to verify that the Optidigital adapter is working properly. This example includes an test publisherId and placementId that would return the test creative. + +### AdUnits configuration example + +```js + var adUnits = [{ + code: 'your-slot_1-div', // use exactly the same code as your slot div id. + mediaTypes: { + banner: { + sizes: [[300,600]] + } + }, + bids: [{ + bidder: 'optidigital', + params: { + publisherId: 'test', + placementId: 'Billboard_Top', + divId: 'Billboard_Top_3c5425', // optional parameter + pageTemplate: 'home', // optional parameter + badv: ['example.com'], // optional parameter + bcat: ['IAB1-1', 'IAB1-2'], // optional parameter + bapp: ['com.blocked'], // optional parameter + battr: [1, 2] // optional parameter + } + }] + }]; +``` + +### UserSync example +To optimize UserSync functionality and ensure optimal match rates and monetization with the Optidigital adapter, we strongly advise implementing the UserSync configuration through iFrame as provided below. Failure to do so may result in reduced match rates and monetization capabilities. + +```js +pbjs.setConfig({ +  userSync: { +    filterSettings: { +      iframe: { +        bidders: '*', // '*' represents all bidders +        filter: 'include' +      } +    } +  } +}); +``` + +Note: be aware that when using this configuration, you can combine it with other UserSync configurations as needed. Keep in mind that if you make multiple `setConfig()` calls, the last one for a specific attribute will take precedence and overwrite any previous configurations. diff --git a/dev-docs/bidders/optimatic.md b/dev-docs/bidders/optimatic.md index 6740cf99dd..fde1410d68 100644 --- a/dev-docs/bidders/optimatic.md +++ b/dev-docs/bidders/optimatic.md @@ -5,9 +5,10 @@ description: Prebid Optimatic Bidder Adaptor pbjs: true biddercode: optimatic media_types: video +sidebarType: 1 --- -### Note: +### Note Optimatic adapter only supports video ads. diff --git a/dev-docs/bidders/optimera.md b/dev-docs/bidders/optimera.md index 2aaf77483a..b31f54cbb9 100644 --- a/dev-docs/bidders/optimera.md +++ b/dev-docs/bidders/optimera.md @@ -4,7 +4,7 @@ title: Optimera description: Optimera Bidder Adaptor pbjs: true biddercode: optimera -pbjs_version_notes: for 5.x, use the module +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/optout.md b/dev-docs/bidders/optout.md index a4a0ebb62c..68c2262dd8 100644 --- a/dev-docs/bidders/optout.md +++ b/dev-docs/bidders/optout.md @@ -5,9 +5,9 @@ description: Prebid Opt Out Advertising Bidder Adaptor pbjs: true pbs: true biddercode: optout -gdpr_supported: true -fpd_supported: true +tcfeu_supported: true gvl_id: 227 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/orbidder.md b/dev-docs/bidders/orbidder.md index 089386a7b5..86b797753f 100644 --- a/dev-docs/bidders/orbidder.md +++ b/dev-docs/bidders/orbidder.md @@ -6,7 +6,10 @@ biddercode: orbidder pbjs: true pbs: true media_types: banner -gdpr_supported: true +gvl_id: 559 +tcfeu_supported: true +floors_supported: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/orbitsoft.md b/dev-docs/bidders/orbitsoft.md index 3996b98c96..258e828b1d 100644 --- a/dev-docs/bidders/orbitsoft.md +++ b/dev-docs/bidders/orbitsoft.md @@ -4,6 +4,7 @@ title: Orbitsoft description: Prebid Orbitsoft Bidder Adaptor pbjs: true biddercode: orbitsoft +sidebarType: 1 --- diff --git a/dev-docs/bidders/otm.md b/dev-docs/bidders/otm.md index e900908c94..f11c7b331a 100644 --- a/dev-docs/bidders/otm.md +++ b/dev-docs/bidders/otm.md @@ -6,6 +6,7 @@ pbjs: true biddercode: otm floors_supported: true media_types: banner +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/ottadvisors.md b/dev-docs/bidders/ottadvisors.md new file mode 100644 index 0000000000..a4131f0883 --- /dev/null +++ b/dev-docs/bidders/ottadvisors.md @@ -0,0 +1,49 @@ +--- +layout: bidder +title: ottadvisors Video +description: Prebid Video Bidder Adapter +pbjs: true +biddercode: ottadvisors +aliasCode: aniview +media_types: banner, video +gvl_id: 780 (aniview) +tcfeu_supported: true +usp_supported: true +schain_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Note + +For more information about [ottadvisors](http://ottadvisors.com/). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|------------------|------------------------------|----------| +| `AV_PUBLISHERID` | required | Publisher/Netid | `'55b88d4a181f465b3e8b4567'` | `string` | +| `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | + +### Test Parameters + +```javascript +const videoAdUnit = [ +{ + code: 'video1', + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'outstream' + }, + }, + bids: [{ + bidder: 'ottadvisors', + params: { + AV_PUBLISHERID: '55b78633181f4603178b4568', + AV_CHANNELID: '5d19dfca4b6236688c0a2fc4' + } + }] +}]; +``` diff --git a/dev-docs/bidders/outbrain.md b/dev-docs/bidders/outbrain.md index cbb5bc78a0..bd278c0e50 100644 --- a/dev-docs/bidders/outbrain.md +++ b/dev-docs/bidders/outbrain.md @@ -3,23 +3,26 @@ layout: bidder title: Outbrain description: Outbrain Prebid Bidder Adapter biddercode: outbrain -gdpr_supported: true +tcfeu_supported: true gvl_id: 164 usp_supported: true coppa_supported: true -media_types: banner, native +media_types: banner, native, video safeframes_ok: true pbjs: true pbs: true pbs_app_supported: true prebid_member: true userIds: id5Id, identityLink -pbjs_version_notes: v4.35 and later +floors_supported: true +multiformat_supported: will-bid-on-one +ortb_blocking_supported: partial +sidebarType: 1 --- ### Registration -The Outbrain Adapter requires setup before beginning. Please contact us at prebid.org@outbrain.com. +The Outbrain Adapter requires setup before beginning. Please contact us at . ### Configuration @@ -27,6 +30,7 @@ The Outbrain Adapter requires setup before beginning. Please contact us at prebi The Outbrain adapter does not work without setting the correct bidder and usersync URLs. You will receive the URLs when contacting us. + ``` pbjs.setConfig({ outbrain: { @@ -39,9 +43,10 @@ pbjs.setConfig({ #### Prebid server Similar to the Prebid.js configuration described above, our prebid server adapter requires you to configure the bidder and usersync URLs. -You will receive the URLs when contacting us. +You will receive the URLs when contacting us. Please note that you need to replace the `` part with the actual external URL of the prebid server host. + ``` adapters: outbrain: @@ -50,18 +55,48 @@ adapters: ``` +### First Party Data + +Publishers can use the `ortb2` configuration parameter to provide First Party Data. + +#### OpenRTB Parameters + +The following table contains currently supported parameters. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|--------------------|----------|-----------------------------------------------------------------------------------------------------------|--------------------|----------------| +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1']` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `['example.com']` | `string array` | +| `wlang` | optional | Allow list of languages for creatives using ISO-639-1-alpha-2. Omission implies no specific restrictions. | `['en', 'de']` | `string array` | + +Example configuration: + +``` +pbjs.setConfig({ + ortb2: { + bcat: ['IAB1-1'], + badv: ['example.com'], + wlang: ['en', 'de'] + } +}); +``` + ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------------------|----------|----------------------------------------------------------------|--------------------|----------------| -| `publisher.id` | required | The publisher account ID | `'2706'` | `string` | -| `publisher.name` | optional | The publisher name | `'Publisher Name'` | `string` | -| `publisher.domain` | optional | The publisher domain | `'publisher.com'` | `string` | -| `tagid` | optional | Identifier for specific ad placement or ad tag | `'tag-id'` | `string` | -| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1']` | `string array` | -| `badv` | optional | Block list of advertisers by their domains | `['example.com']` | `string array` | +| Name | Scope | Description | Example | Type | +|--------------------|----------|------------------------------------------------|--------------------|----------------| +| `publisher.id` | required | The publisher account ID | `'2706'` | `string` | +| `publisher.name` | optional | The publisher name | `'Publisher Name'` | `string` | +| `publisher.domain` | optional | The publisher domain | `'publisher.com'` | `string` | +| `tagid` | optional | Identifier for specific ad placement or ad tag | `'tag-id'` | `string` | +| `bcat` | optional | (Deprecated) | `['IAB1-1']` | `string array` | +| `badv` | optional | (Deprecated) | `['example.com']` | `string array` | + +Note: Providing `bcat` and `badv` via Bid Params is deprecated, the First Party Data method should be preferred (see above). When both methods are provided, first party data values will be used and bid param values will be ignored. #### Native example @@ -110,6 +145,7 @@ var adUnits = [ ``` #### Banner example + ``` var adUnits = [ code: '/19968336/prebid_display_example_1', @@ -133,3 +169,42 @@ var adUnits = [ }] ]; ``` + +#### Video example + +``` +var adUnits = [ + code: '/19968336/prebid_video_example_1', + mediaTypes: { + video: { + context: "outstream", + playerSize: [[640, 480]], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [1], + skip: 1, + api: [2], + minbitrate: 1000, + maxbitrate: 3000, + minduration: 3, + maxduration: 10, + startdelay: 2, + placement: 4, + linearity: 1 + }, + }, + bids: [{ + bidder: 'outbrain', + params: { + publisher: { + id: '2706', + name: 'Publishers Name', + domain: 'publisher.com' + }, + tagid: 'tag-id', + bcat: ['IAB1-1'], + badv: ['example.com'] + } + }] +]; +``` diff --git a/dev-docs/bidders/outbrain_old.md b/dev-docs/bidders/outbrain_old.md index e0529b8eee..f2d1a646d6 100644 --- a/dev-docs/bidders/outbrain_old.md +++ b/dev-docs/bidders/outbrain_old.md @@ -4,7 +4,7 @@ title: Outbrain - Old description: Outbrain Prebid Bidder Adapter biddercode: outbrain aliasCode: zemanta -gdpr_supported: true +tcfeu_supported: true gvl_id: 164 usp_supported: true coppa_supported: true @@ -14,12 +14,14 @@ pbjs: true pbs: true pbs_app_supported: true prebid_member: true -pbjs_version_notes: for versions 4.20-4.34 +enable_download : false +ortb_blocking_supported: partial +sidebarType: 1 --- ### Registration -The Outbrain Adapter requires setup before beginning. Please contact us at prebid.org@outbrain.com. +The Outbrain Adapter requires setup before beginning. Please contact us at . ### Configuration @@ -27,6 +29,7 @@ The Outbrain Adapter requires setup before beginning. Please contact us at prebi The Outbrain adapter does not work without setting the correct bidder and usersync URLs. You will receive the URLs when contacting us. + ``` pbjs.setConfig({ outbrain: { @@ -39,9 +42,10 @@ pbjs.setConfig({ #### Prebid server Similar to the Prebid.js configuration described above, our prebid server adapter requires you to configure the bidder and usersync URLs. -You will receive the URLs when contacting us. +You will receive the URLs when contacting us. Please note that you need to replace the `` part with the actual external URL of the prebid server host. + ``` adapters: outbrain: @@ -50,18 +54,48 @@ adapters: ``` +### First Party Data + +Publishers can use the `ortb2` configuration parameter to provide First Party Data. + +#### OpenRTB Parameters + +The following table contains currently supported parameters. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|--------------------|----------|-----------------------------------------------------------------------------------------------------------|--------------------|----------------| +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1']` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `['example.com']` | `string array` | +| `wlang` | optional | Allow list of languages for creatives using ISO-639-1-alpha-2. Omission implies no specific restrictions. | `['en', 'de']` | `string array` | + +Example configuration: + +``` +pbjs.setConfig({ + ortb2: { + bcat: ['IAB1-1'], + badv: ['example.com'], + wlang: ['en', 'de'] + } +}); +``` + ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------------------|----------|----------------------------------------------------------------|--------------------|----------------| -| `publisher.id` | required | The publisher account ID | `'2706'` | `string` | -| `publisher.name` | optional | The publisher name | `'Publisher Name'` | `string` | -| `publisher.domain` | optional | The publisher domain | `'publisher.com'` | `string` | -| `tagid` | optional | Identifier for specific ad placement or ad tag | `'tag-id'` | `string` | -| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1']` | `string array` | -| `badv` | optional | Block list of advertisers by their domains | `['example.com']` | `string array` | +| Name | Scope | Description | Example | Type | +|--------------------|----------|------------------------------------------------|--------------------|----------------| +| `publisher.id` | required | The publisher account ID | `'2706'` | `string` | +| `publisher.name` | optional | The publisher name | `'Publisher Name'` | `string` | +| `publisher.domain` | optional | The publisher domain | `'publisher.com'` | `string` | +| `tagid` | optional | Identifier for specific ad placement or ad tag | `'tag-id'` | `string` | +| `bcat` | optional | (Deprecated) | `['IAB1-1']` | `string array` | +| `badv` | optional | (Deprecated) | `['example.com']` | `string array` | + +Note: Providing `bcat` and `badv` via Bid Params is deprecated, the First Party Data method should be preferred (see above). When both methods are provided, first party data values will be used and bid param values will be ignored. #### Native example @@ -110,6 +144,7 @@ var adUnits = [ ``` #### Banner example + ``` var adUnits = [ code: '/19968336/prebid_display_example_1', diff --git a/dev-docs/bidders/outcon.md b/dev-docs/bidders/outcon.md deleted file mode 100644 index 7e97d1596b..0000000000 --- a/dev-docs/bidders/outcon.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Outcon -description: Prebid Outcon Bidder Adaptor -pbjs: true -biddercode: outcon -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------------------------------|---------------------------|---------| -| `pod` | optional |require if not send internalId and publisher|"5beeb24a306ea47660632043" | `string`| -| `internalId` | optional |require if not send pod |"563643562" | `string`| -| `publisher` | optional |require if not send pod |"5beeb24a306ea47660632043" | `string`| -| `demo` | optional |require for testing |"true" | `boolean` | diff --git a/dev-docs/bidders/ownadx.md b/dev-docs/bidders/ownadx.md new file mode 100644 index 0000000000..728d1bf543 --- /dev/null +++ b/dev-docs/bidders/ownadx.md @@ -0,0 +1,37 @@ +--- +layout: bidder +title: OwnAdX +description: Prebid OwnAdX Bidder Adaptor +biddercode: ownadx +tcfeu_supported: false +usp_supported: false +coppa_supported: false +gpp_supported: false +schain_supported: false +dchain_supported: false +userId: +media_types: banner, video +safeframes_ok: false +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: false +pbs: true +pbs_app_supported: true +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: false +--- + +### Note: + +The OwnAdX Bidding adapter requires setup before beginning. Please contact us at support@techbravo.com + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|----------------------------|-----------| +| `sspId` | required | Supply side ID | `'1816w0'` | `string` | +| `seatId` | required | Seat Id | `'4'` | `string` | +| `tokenId` | required | Token Id | `'QjBZdHs6bhFHBT1nd1AJ'` | `string` | diff --git a/dev-docs/bidders/ozone.md b/dev-docs/bidders/ozone.md index df0016915d..4f93fc6d09 100644 --- a/dev-docs/bidders/ozone.md +++ b/dev-docs/bidders/ozone.md @@ -4,18 +4,17 @@ title: Ozone Project description: Prebid Ozone Project Bidder Adaptor biddercode: ozone pbjs: true -media_types: banner -gdpr_supported: true +media_types: banner, video +tcfeu_supported: true userIds: criteo, id5Id, tdid, identityLink, liveIntentId, parrableId, pubCommonId, lotamePanoramaId, sharedId, fabrickId gvl_id: 524 deals_supported: true -fpd_supported: true schain_supported: true coppa_supported: true usp_supported: true floors_supported: true prebid_member: true - +sidebarType: 1 --- @@ -28,4 +27,75 @@ prebid_member: true | `siteId` | required | The site ID from ozone. | `"OZONENUK0001"` | `string` | | `publisherId` | required | The publisher ID. | `"4204204201"` | `string` | | `placementId` | required | The placement ID. | `"0420420421"` | `string` | -| `customData` | optional | publisher key-values used for targeting | `[{"settings":{},"targeting":{"key1": "value1", "key2": "value2"}}], ` | `array` | \ No newline at end of file +| `customData` | optional | publisher key-values used for targeting | `[{"settings":{},"targeting":{"key1": "value1", "key2": "value2"}}],` | `array` | + +### Test Parameters + +A test ad unit that will consistently return test creatives: + +```javascript +//Banner adUnit + +const adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONETST0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '8000000125', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ + } + }] + }]; + + +//Outstream adUnit + +adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + video: { + playerSize: [640, 360], + mimes: ['video/mp4'], + context: 'outstream' + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONETST0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '8000000328', /* an ID used to identify the piece of inventory - required. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ + } + }] + }]; + +//Instream adUnit + +adUnits = [{ + code: 'id-of-your-banner-div', + mediaTypes: { + video: { + playerSize: [640, 480], + mimes: ['video/mp4'], + context: 'instream' + } + }, + bids: [{ + bidder: 'ozone', + params: { + publisherId: 'OZONETST0001', /* an ID to identify the publisher account - required */ + siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ + placementId: '8000000327', /* an ID used to identify the piece of inventory - required. */ + customData: [{"settings": {}, "targeting": {"key": "value", "key2": ["value1", "value2"]}}],/* optional array with 'targeting' placeholder for passing publisher specific key-values for targeting. */ + } + }] + }]; +``` diff --git a/dev-docs/bidders/padsquad.md b/dev-docs/bidders/padsquad.md index 3a20a34765..74cf8aa84a 100644 --- a/dev-docs/bidders/padsquad.md +++ b/dev-docs/bidders/padsquad.md @@ -4,14 +4,14 @@ title: Padsquad description: Prebid Padsquad Bidder Adapter pbjs: true biddercode: padsquad -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- -### Note: +### Note The Padsquad Header Bidding adapter requires approval from the Padsquad team. Please reach out to for more information. - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/pagescience.md b/dev-docs/bidders/pagescience.md index f6b0a261c2..f22447d1e3 100644 --- a/dev-docs/bidders/pagescience.md +++ b/dev-docs/bidders/pagescience.md @@ -5,6 +5,7 @@ description: Prebid Page Science Bidder Adaptor pbjs: true biddercode: pagescience aliasCode : appnexus +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/pangle.md b/dev-docs/bidders/pangle.md index 6d4da22aea..6148fdef73 100644 --- a/dev-docs/bidders/pangle.md +++ b/dev-docs/bidders/pangle.md @@ -3,27 +3,132 @@ layout: bidder title: Pangle description: Prebid Pangle Bidder Adapter biddercode: pangle -gdpr_supported: true +tcfeu_supported: false coppa_supported: true schain_supported: false media_types: banner, video, native safeframes_ok: false deals_supported: false -pbjs: false +pbjs: true pbs: true pbs_app_supported: true prebid_member: false +userIds: sharedId +sidebarType: 1 +multiformat_supported: will-bid-on-any --- -### Note: +### Note -The Pangle Bidding adapter requires setup before beginning. Please contact us at pangle_dsp@bytedance.com. +The Pangle Bidding adapter requires setup before beginning. Please contact the Pangle team. + +**Media type support:** + +* Pangle Prebid.js adapter supports banner and video, native is not supported yet. +* Pangle Prebid Server adapter supports banner, video and native media types. ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------------------------------------------------|-------------|----------| -| token | required | access token | 'aaaa123' | string | -| appid | optional | app id (must be used in conjunction with placementid) | '5123400' | string | -| placementid | optional | placement id (must be used in conjunction with appid) | '912340000' | string | +| token | required | **Prebid.js**: please fill 'pangle' by default. **Prebid Server**: access token, please contact Pangle team to get your token | 'Pangle' | string | +| appid | optional | **(Required for Prebid.js)** The app id on Pangle platform, please get them from the platform or contact Pangle team | '5123400' | string | +| placementid | optional | **(Required for Prebid.js)** The placement id created on Pangle platform, please get them from the platform or contact Pangle team | '912340000' | string | +| test | optional | For testing, please set it to '1' so that you can test the integration. Pangle strongly recommends testing before going live. | 1 | number | + +Pangle server-side Prebid Server adapter supports `banner`, `video`, `native` media types. But Pangle client-side Prebid.js adapter supports `banner` and `video` media types, doesn't support `native`. + +### Test Parameters + +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "pangle", + params: { + token: "aaaaa", + placementid: '1234', // string + appid: '1234' // string + } + } + ] + }, + // Video adUnit + { + code: 'div-1', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[300, 250]], + mimes: ['video/mp4'], + }, + }, + bids: [ + { + bidder: 'pangle', + params: { + appid: '8149678', + placementid: '980589944', + token: '111111', + }, + }, + ], + }, + // multi format adUnit + { + code: 'div-1', + mediaTypes: { + banner: { + sizes: [[300, 250]] + }, + video: { + context: 'outstream', + playerSize: [[300, 250]], + mimes: ['video/mp4'], + }, + }, + bids: [ + { + bidder: 'pangle', + params: { + token: "Pangle", + appid: "8168169", //{YOUR_APP_ID} + placementid: "980649718", //{YOUR_PLACEMENT_ID} + test: 1 // For test ads + }, + }, + ], + }, +]; +``` + +### User Sync + +Add the following code to enable user sync. Pangle strongly recommends enabling user syncing through iFrames. This functionality improves partners' user match rates and increases the Pangle bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + userIds: [ + { + name: 'sharedId', + storage: { + name: 'sharedId', // name of the 1st party cookie + type: 'cookie', + expires: 365, + }, + }, + ], + } +}); +``` diff --git a/dev-docs/bidders/peak226.md b/dev-docs/bidders/peak226.md index 853e7e1b30..55871bea93 100644 --- a/dev-docs/bidders/peak226.md +++ b/dev-docs/bidders/peak226.md @@ -4,6 +4,7 @@ title: Peak226 description: Prebid Peak Bidder Adaptor pbjs: true biddercode: peak226 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/performax.md b/dev-docs/bidders/performax.md index dafc5f2da3..6d051a2561 100644 --- a/dev-docs/bidders/performax.md +++ b/dev-docs/bidders/performax.md @@ -1,39 +1,33 @@ --- layout: bidder title: Performax -description: Prebid Performax Bidder Adaptor -pbjs: true +description: Prebid Performax bidder Adapter biddercode: performax +tcfeu_supported: true +gvl_id: 732 +usp_supported: true +coppa_supported: false +schain_supported: true +userId: all media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x +safeframes_ok: true +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-not-bid +sidebarType: 1 --- -### Note: -Performax adapter requires setup and approval from the Performax team. Please reach out to your account team or info@performax.cz for more information. +### Note -### Bid Params +The Performax Bidding Adapter requires setup before beginning. Please contact us at [ae@performax.cz](mailto:ae@performax.cz). -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------|------------------------------|----------| -| `slotId` | required | Slot ID | `32572` | `Integer`| - -### Example +### Bid Params -```javascript - var adUnits = [ - { - code: 'performax-div', - sizes: [[300, 300]], - bids: [ - { - bidder: "performax", - params: { - slotId: 28 // required - } - } - ] - } - ]; -``` +{: .table . table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-------------|-----------| +| `tagid` | required | Placement id | `'sample'` | `string` | diff --git a/dev-docs/bidders/pgam.md b/dev-docs/bidders/pgam.md new file mode 100644 index 0000000000..0baba0ba06 --- /dev/null +++ b/dev-docs/bidders/pgam.md @@ -0,0 +1,106 @@ +--- +layout: bidder +title: PGAM +description: Prebid PGAM Bidder Adapter +biddercode: pgam +media_types: video,banner +tcfeu_supported: false +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: false +enable_download: false +sidebarType: 1 +pbjs_version_notes: removed in 8.13.0 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from PGAM. | `529814` | `integer` | + +### Description + +PGAM header bidding adapter connects with PGAM demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +```javascript +var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'pgam', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'pgam', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'pgam', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'pgam', + params: { + aid: 529814 + } + }] + } +]; +``` diff --git a/dev-docs/bidders/pgammedia.md b/dev-docs/bidders/pgammedia.md new file mode 100644 index 0000000000..14f35e5809 --- /dev/null +++ b/dev-docs/bidders/pgammedia.md @@ -0,0 +1,48 @@ +--- +layout: bidder +title: PGAM MEDIA +description: Prebid PGAM MEDIA Bidder Adapter +pbjs: true +biddercode: pgammedia +aliasCode: aniview +media_types: banner, video +gvl_id: 780 (aniview) +tcfeu_supported: true +usp_supported: true +schain_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Note + +For more information about [PGAM MEDIA](https://pgammedia.com/). + +### Bid Params + +| Name | Scope | Description | Example | Type | +|------------------|----------|------------------|------------------------------|----------| +| `AV_PUBLISHERID` | required | Publisher/Netid | `'55b88d4a181f465b3e8b4567'` | `string` | +| `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | + +### Test Parameters + +```javascript +const videoAdUnit = [ +{ + code: 'video1', + mediaTypes: { + video: { + playerSize: [[640, 480]], + context: 'outstream' + }, + }, + bids: [{ + bidder: 'pgammedia', + params: { + AV_PUBLISHERID: '55b78633181f4603178b4568', + AV_CHANNELID: '5d19dfca4b6236688c0a2fc4' + } + }] +}]; +``` diff --git a/dev-docs/bidders/pgamssp.md b/dev-docs/bidders/pgamssp.md new file mode 100644 index 0000000000..e132d8edb1 --- /dev/null +++ b/dev-docs/bidders/pgamssp.md @@ -0,0 +1,26 @@ +--- +layout: bidder +title: PGAMSSP +description: Prebid PGAMSSP Bidder Adapter +biddercode: pgamssp +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +gpp_supported: true +media_types: banner, video, native +pbjs: true +pbs: true +pbs_app_supported: true +sidebarType: 1 +multiformat_supported: will-bid-on-one +safeframes_ok: true +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement Id | `'0'` | `'string'` | diff --git a/dev-docs/bidders/pilotx.md b/dev-docs/bidders/pilotx.md new file mode 100644 index 0000000000..138e34f265 --- /dev/null +++ b/dev-docs/bidders/pilotx.md @@ -0,0 +1,16 @@ +--- +layout: bidder +title: PilotX +description: Pilotx Prebid Adapter +biddercode: pilotx +media_types: banner, video +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------|---------|----------| +| `placementId` | required | id to represent placement for pilotx | `'234234'` | `string` | diff --git a/dev-docs/bidders/pixad.md b/dev-docs/bidders/pixad.md new file mode 100644 index 0000000000..54296770e1 --- /dev/null +++ b/dev-docs/bidders/pixad.md @@ -0,0 +1,91 @@ +--- +layout: bidder +title: Pixad +description: Prebid Pixad Bidder Adapter. +pbjs: true +pbs: true +biddercode: pixad +media_types: banner,video,native +gvl_id: 1281 (admatic) +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_sids: tcfeu, tcfca, usnat, usstate_all, usp +schain_supported: true +dchain_supported: false +userIds: criteo, id5Id, sharedId, unifiedId +safeframes_ok: true +floors_supported: true +aliasCode: admatic +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Description + +Pixad header bidding adapter connects with Pixad demand sources to fetch bids for network ID. Please reach out to your account manager or for more information. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-------------------------------------|----------|----------| +| `networkId` | required | The network ID from Pixad | `12345` | `number` | +| `host` | required | RTB Host | `rtb.network.pixad.com.tr` | `string` | + +### Test Parameters + +300x250 banner test + +```javascript +var adUnits = [{ + code: 'your-slot_1-div', + mediaTypes: { + banner: { sizes: [[300, 250]] }, + }, + bids: [{ + bidder: 'pixad', + params: { + networkId: 12345, + host: 'rtb.network.pixad.com.tr' + } + }] +},{ + code: 'your-slot_2-div', + mediaTypes: { + native: { ... }, + }, + bids: [{ + bidder: 'pixad', + params: { + networkId: 12345, + host: 'rtb.network.pixad.com.tr' + } + }] +},{ + code: 'your-slot_3-div', + mediaTypes: { + video: { ... }, + }, + bids: [{ + bidder: 'pixad', + params: { + networkId: 12345, + host: 'rtb.network.pixad.com.tr' + } + }] +}]; +``` + +## UserSync example + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + syncEnabled: true, + syncDelay: 1, + aliasSyncEnabled: true + } +}); +``` diff --git a/dev-docs/bidders/pixfuture.md b/dev-docs/bidders/pixfuture.md index 58159bb843..40ccdb338b 100644 --- a/dev-docs/bidders/pixfuture.md +++ b/dev-docs/bidders/pixfuture.md @@ -4,14 +4,15 @@ title: PixFuture description: Prebid PixFuture Bidder Adapter biddercode: pixfuture media_types: banner -gdpr_supported: true +gvl_id: 839 +tcfeu_supported: true prebid_member: false coppa_supported: true usp_supported: true -fpd_supported: true -userIds: flocId, criteoId, unifiedId, id5Id, sharedId, identityLink, liveIntentId, fabrickId +userIds: criteoId, unifiedId, id5Id, sharedId, identityLink, liveIntentId, fabrickId pbs: false pbjs: true +sidebarType: 1 --- #### Bid Params diff --git a/dev-docs/bidders/piximedia.md b/dev-docs/bidders/piximedia.md deleted file mode 100644 index cc5072f0cd..0000000000 --- a/dev-docs/bidders/piximedia.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: Piximedia -description: Piximedia Bidder Adaptor -pbjs: true -biddercode: piximedia -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------|---------------|----------| -| `siteId` | required | the site ID | `'SITE'` | `string` | -| `placementId` | required | the placement ID | `'PLACEMENT'` | `string` | diff --git a/dev-docs/bidders/platformio.md b/dev-docs/bidders/platformio.md deleted file mode 100644 index 3c1b68fcc5..0000000000 --- a/dev-docs/bidders/platformio.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -layout: bidder -title: Platform.io -description: Prebid Platform.io Bidder Adapter -pbjs: true -biddercode: platformio -media_types: native, video -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Disclosure - -This bidder sets `adId` on the bid response and hasn't responded to the Prebid.js team to confirm uniqueness -of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381). - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|----------------------------------|----------------|----------| -| `pubId` | required | The publisher account ID | `'28082'` | `string` | -| `siteId` | required | The publisher site ID | `'26047'` | `string` | -| `placementId` | required | Identifies specific ad placement | `'17394'` | `string` | -| `bidFloor` | optional | The bid floor | `'0.001'` | `string` | -| `ifa` | optional | IFA ID | `'XXX-XXX'` | `string` | -| `latitude` | optional | Latitude | `'40.712775'` | `string` | -| `longitude` | optional | Longitude | `'-74.005973'` | `string` | - -### test params - -``` - var adUnits = [{ - code: 'dfp-native-div', - mediaTypes: { - native: { - title: { - required: true, - len: 75 - }, - image: { - required: true - }, - body: { - len: 200 - }, - icon: { - required: false - } - } - }, - bids: [{ - bidder: 'platformio', - params: { - pubId: '29521', - siteId: '26048', - placementId: '123', - bidFloor: '0.001', // optional - ifa: 'XXX-XXX', // optional - latitude: '40.712775', // optional - longitude: '-74.005973', // optional - } - }] - }, - { - code: 'dfp-banner-div', - mediaTypes: { - banner: { - sizes: [ - [300, 250],[300,600] - ], - } - }, - bids: [{ - bidder: 'platformio', - params: { - pubId: '29521', - siteId: '26049', - placementId: '123', - } - }] - }, - { - code: 'dfp-video-div', - mediaTypes: { - video: { - playerSize: [[640, 480]], - context: "instream" - } - }, - bids: [{ - bidder: 'platformio', - params: { - pubId: '29521', - siteId: '26049', - placementId: '123', - video: { - skippable: true, - } - } - }] - } - ]; -``` diff --git a/dev-docs/bidders/playdigo.md b/dev-docs/bidders/playdigo.md new file mode 100644 index 0000000000..8dbdb1c13d --- /dev/null +++ b/dev-docs/bidders/playdigo.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Playdigo +description: Prebid Playdigo Bidder Adapter +biddercode: playdigo +gpp_sids: usstate_all +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +deals_supported: false +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +media_types: banner, video, native +multiformat_supported: will-not-bid +pbjs: true +pbs: true +pbs_app_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------|---------------------------------|------------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/playwire.md b/dev-docs/bidders/playwire.md index 69270e0e21..09e8ddf142 100644 --- a/dev-docs/bidders/playwire.md +++ b/dev-docs/bidders/playwire.md @@ -6,7 +6,8 @@ pbjs: true biddercode: playwire aliasCode: grid media_types: banner, video -gdpr_supported: true +gvl_id: 686 (grid) +tcfeu_supported: true usp_supported: true schain_supported: true floors_supported: true @@ -14,8 +15,18 @@ userIds: all tcf2_supported: true coppa_supported: true fpd_supported: true +prebid_member: true +sidebarType: 1 --- +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [Bidder Config](#bidder-config) +- [First Party Data](#first-party-data) + + ### Bid Params @@ -25,3 +36,41 @@ fpd_supported: true | `uid` | required | Represents the Playwire bidder system Ad Slot ID associated with the respective div id from the site page. | `1` | `integer` | | `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | | `bidFloor` | optional | Floor of the impression opportunity. If present in the request overrides XML info. | `0.8` | `float` | + + + +### Bidder Config + +You can allow writing in localStorage `pbjs.setBidderConfig` for the bidder `playwire` + +```javascript +pbjs.setBidderConfig({ + bidders: ["playwire"], + config: { + localStorageWriteAllowed: true + } +}) +``` + +If it will be "true" this allow Playwire Bid Adapter to write userId in first party localStorage + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.ext.device`: Non standard arbitrary user device +- `ortb2.user.keywords`: Standard IAB OpenRTB 2.5 user.keywords field. It will be included in ext.keywords.user.ortb2 +- `ortb2.site.keywords`: Standard IAB OpenRTB 2.5 site.keywords field. It will be included in ext.keywords.site.ortb2 +- `ortb2.site.cat[]`: Standard IAB OpenRTB 2.5 site.cat field. It will be sent as part of site.cat array +- `ortb2.site.pagecat[]`: Standard IAB OpenRTB 2.5 site.pagecat field. It will be sent as part of site.cat array +- `ortb2.site.content.genre`: Standard IAB OpenRTB 2.5 site.content.genre field + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` +- `ortb2.imp[].instl` diff --git a/dev-docs/bidders/pollux.md b/dev-docs/bidders/pollux.md index 193e50d8a9..c9beed486b 100644 --- a/dev-docs/bidders/pollux.md +++ b/dev-docs/bidders/pollux.md @@ -4,6 +4,7 @@ title: Pollux Network description: Prebid Pollux Network Bidder Adaptor pbjs: true biddercode: pollux +sidebarType: 1 --- diff --git a/dev-docs/bidders/polymorph.md b/dev-docs/bidders/polymorph.md index b63dc85192..7e3dac6d8d 100644 --- a/dev-docs/bidders/polymorph.md +++ b/dev-docs/bidders/polymorph.md @@ -5,10 +5,12 @@ description: Polymorph Prebid Adaptor pbjs: true biddercode: polymorph media_types: native, video, banner +sidebarType: 1 --- -### Note: -Polymorph adapter requires setup and approval from the Polymorph team. Please reach out to your account team or support@getpolymorph.com for more information. +### Note + +Polymorph adapter requires setup and approval from the Polymorph team. Please reach out to your account team or for more information. ### Bid Params diff --git a/dev-docs/bidders/prebidServer.md b/dev-docs/bidders/prebidServer.md deleted file mode 100644 index f599598761..0000000000 --- a/dev-docs/bidders/prebidServer.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -layout: bidder -title: Prebid Server -description: Prebid Server S2S Adaptor -biddercode: prebidServer -pbjs: true -media_types: banner, video -gdpr_supported: true ---- - -### Overview - -The Prebid Server Adapter is a meta-adapter. It's not an actual bidder, but -rather a way to get a batch of bids from other bidders with one request. -A request for the set of auctions is sent to Prebid Server, which performs -all the auctions server side (S2S), responding in time for Prebid.js to -send the results to the ad server. This lightens the performance load on the user's device. - -### Bid Params - -Bid params are sourced from the adapter configurations set for client side. These do not need to change for Prebid Server. - -{: .alert.alert-warning :} -**Errors in bidder parameters will cause Prebid Server to reject the -entire request.** The Prebid Server philosophy is to avoid silent failures -- -we assume you will test changes, and that it will be easier to notice a -4xx error coming from the server than a silent failure where it skips just -the bad parameter. - -### Configuration -To enable prebid server, set the following configuration. - -``` -pbjs.setConfig({ - s2sConfig: { - accountId : '12345', - bidders : ['appnexus','pubmatic', 'rubicon'], - defaultVendor: 'appnexus', - timeout: 300 - } -}); -``` - -To use multiple prebid servers, just define `s2sConfig` as an array. -The same bidder cannot be set in both configs. For example: - -``` -pbjs.setConfig({ - s2sConfig: [ - { - accountId: '12345', - bidders: ['appnexus','rubicon'], - defaultVendor: 'appnexus', - timeout: 300, - }, - { - accountId: '678910', - bidders: ['pubmatic'], - defaultVendor: 'rubicon', - timeout: 300, - }, - ], -}); -``` -Configuration options - -{: .table .table-bordered .table-striped } -| Field | Type | Required? | Description | -|--------------+---------------+-----------+--------------------------------------------------------------------------| -| `accountId` | String | yes | Prebid Server account ID. | -| `bidders` | Array[String] | yes | List of bidder codes; must have been enabled during Prebid.js build. | -| `defaultVendor` | String | no | Automatically includes all following options in the config with vendor's default values. Individual properties can be overridden by including them in the config along with this setting. | -| `enabled` | Boolean | no | Enables S2S; default: `false` (`true` when defaultVendor is set). | -| `endpoint` | String | no | Set the endpoint. For example: `https://prebid.adnxs.com/pbs/v1/openrtb2/auction` | -| `timeout` | Number | no | Bidder timeout, in milliseconds; default: `1000`. | -| `syncEndpoint` | String | no | Configures the user-sync endpoint. Highly recommended. | -| `adapter` | String | no | Adapter code; default: `"prebidServer"`. | -| `secure` | Integer | no | Override Prebid Server's determination of whether the request needs secure assets. Set to `1` to force secure assets on the response, or `0` for non-secure assets. | -| `adapterOptions` | Object | no | Arguments will be added to resulting OpenRTB payload to Prebid Server. | -| `extPrebid` | Object | no | Arguments will be added to resulting OpenRTB payload to Prebid Server. | - -### Examples - -**Video (Outstream):** -Note that currently, outstream video rendering must be configured by the publisher. In the adUnit, a `renderer` object must be defined, which includes a `url` pointing to the video rendering script, and a `render` function for creating the video player. See https://prebid.org/dev-docs/show-outstream-video-ads.html for more information. - -```javascript -var adUnits = [{ - code: 'div-gpt-ad-1460505748561-0', - mediaTypes: { - video: { - playerSize: [640, 480], - context: 'outstream', - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 13232392 - }, - - } - ], - renderer: { - url: 'https://cdn.adnxs.com/renderer/video/ANOutstreamVideo.js', - render: function (bid) { - adResponse = { - ad: { - video: { - content: bid.vastXml, - player_height: bid.playerHeight, - player_width: bid.playerWidth - } - } - } - // push to render queue because ANOutstreamVideo may not be loaded yet. - bid.renderer.push(() => { - ANOutstreamVideo.renderAd({ - targetId: bid.adUnitCode, // target div id to render video. - adResponse: adResponse - }); - }); - } - } -}]; -``` diff --git a/dev-docs/bidders/preciso.md b/dev-docs/bidders/preciso.md new file mode 100644 index 0000000000..52523c39c1 --- /dev/null +++ b/dev-docs/bidders/preciso.md @@ -0,0 +1,63 @@ +--- +layout: bidder +title: Preciso +description: Prebid Preciso Bidder Adapter +gvl_id: 874 +media_types: display, video, native +gdpr_supported: true +usp_supported: true +pbjs: true +pbs: true +biddercode: preciso +prebid_member: true +floors_supported: true +safeframes_ok: true +schain_supported: true +userIds: id5Id, identityLink, pubProvidedId +pbs_app_supported: true +coppa_supported: true +multiformat_supported: will-bid-on-any +ortb_blocking_supported: partial +sidebarType: 1 +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------|---------------|----------| +| `publisherId` | required | Unique publisher ID | `'ABCDEF'` | `string` | +| `region` | required | Assigned region | `'prebid-eu'` | `string` | +| `bidfloor` | optional | Minimal CPM value | `0.01` | `float` | +| `channel` | optional | Inventory channel identifier, limited to 50 characters | `Partner 1 - News` | `string` | + + +### ORTB Blocking +Preciso supports blocking advertisers in `badv` and categories in `bcat` parameters. +The blocked advertisers/categories list has no length limitation, but response timeout is more likely to occur as the number of entries grow. +Blocked advertisers list (`badv`) is an array of domains as strings. +Blocked categories list (`bcat`) is an array of IAB categories as strings. + +For example: +#### Globally defined ORTB Blocking: +```javascript +pbjs.setConfig({ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } +)}; +``` +#### ORTB Blocking specific only to preciso bidder: +```javascript +pbjs.setBidderConfig({ + bidders: ['preciso'], + config:{ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } + } +}); +``` \ No newline at end of file diff --git a/dev-docs/bidders/prisma.md b/dev-docs/bidders/prisma.md new file mode 100644 index 0000000000..d69141996c --- /dev/null +++ b/dev-docs/bidders/prisma.md @@ -0,0 +1,66 @@ +--- +layout: bidder +title: Prisma +description: Prebid Prisma Bidder Adapter +pbjs: true +biddercode: prisma +tcfeu_supported: true +usp_supported: true +schain_supported: true +userIds: id5Id +media_types: banner, video +gvl_id: 965 +pbs: false +sidebarType: 1 + +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|--------------------------------------|-----------| +| `account` | required | Prisma account ID | `'1067'` | `string` | +| `tagId` | required | Prisma tag ID | `'luvxjvgn'` | `string` | + +### Test Parameters + +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'prisma', + params: { + account: '1067', + tagId: 'luvxjvgn' + } + }] + }, + // Video adUnit + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'prisma', + params: { + account: '1067', + tagId: 'luvxjvgn' + } + }] + }; + +]; +``` diff --git a/dev-docs/bidders/programmatica.md b/dev-docs/bidders/programmatica.md new file mode 100644 index 0000000000..98bc2a5c95 --- /dev/null +++ b/dev-docs/bidders/programmatica.md @@ -0,0 +1,27 @@ +--- +layout: bidder +title: Programmatica +description: programmatica bid adapter +pbjs: true +biddercode: programmatica +media_types: banner, video +safeframes_ok: true +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: false +deals_supported: false +floors_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------|--------------------------|----------| +| `siteId` | required | Site id | `'cjssg576snkvrj1qbd50'` | `string` | +| `placementId` | required | Placement id | `'cjsu4an6snkvrj1qbd6g'` | `string` | diff --git a/dev-docs/bidders/projectLimelight.md b/dev-docs/bidders/projectLimelight.md deleted file mode 100644 index 2efcfe9ebd..0000000000 --- a/dev-docs/bidders/projectLimelight.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: Project Limelight -description: Prebid Project Limelight Bidder Adaptor -pbjs: true -biddercode: project-limelight -aliasCode: projectLimeLight -media_types: video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example |type| -| :----------- | :--------- | :------------ | :----------------- |:---| -| `host` | required | Ad network's RTB host | `'exchange.ortb.net'` | `string` | -| `adUnitId` | required | Ad Unit Id will be generated on Limelight Digital Platform. | 0 |integer| -| `adUnitType` | required | Type of Ad Unit (`'video'`, `'banner'`) | `'banner'` |string| diff --git a/dev-docs/bidders/projectagora.md b/dev-docs/bidders/projectagora.md new file mode 100644 index 0000000000..19cdddbdf3 --- /dev/null +++ b/dev-docs/bidders/projectagora.md @@ -0,0 +1,27 @@ +--- +layout: bidder +title: Project Agora +description: Prebid Project Agora Bidder Adapter +biddercode: projectagora +pbjs: true +pbs: false +aliasCode: appnexus +tcfeu_supported: true +media_types: banner, video, native +gvl_id: 1032 +schain_supported: true +userId: all +sidebarType: 1 +--- +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement id | `'11111'` | `integer` | + +Project Agora is an aliased bidder for AppNexus. + +### Note: + +The Project Agora bidder adapter requires setup before beginning. Please contact us at pub_growth@projectagora.com. diff --git a/dev-docs/bidders/proxistore.md b/dev-docs/bidders/proxistore.md index 1b111d30da..2fa119fb54 100644 --- a/dev-docs/bidders/proxistore.md +++ b/dev-docs/bidders/proxistore.md @@ -4,8 +4,9 @@ title: Proxistore description: Prebid Proxistore Bidder Adapter pbjs: true biddercode: proxistore -gdpr_supported: true -fpd_supported: true +gvl_id: 418 +tcfeu_supported: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/pstudio.md b/dev-docs/bidders/pstudio.md new file mode 100644 index 0000000000..d425ddc8cd --- /dev/null +++ b/dev-docs/bidders/pstudio.md @@ -0,0 +1,129 @@ +--- +layout: bidder +title: PStudio +description: Prebid PStudio Bidder Adapter +biddercode: pstudio +tcfeu_supported: false +gvl_id: none +usp_supported: false +coppa_supported: true +gpp_supported: false +schain_supported: false +dchain_supported: false +userId: UID 2.0 +media_types: banner, video +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: true +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-not-bid +ortb_blocking_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `pubid` | required | UUID of the publisher | `'7ccf149e-06e4-4fdc-80a8-426374010b4a'` | `string (UUID)` | +| `floorPrice` | required | Minimum price for the impression expressed in CPM in USD currency. | `1.15` | `float` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `['IAB1-1', 'IAB1-3']` | `Array` | +| `bapp` | optional | Block list of applications by their platform-specific exchange-independent application identifiers | `['com.foo.mygame']` | `Array` | +| `badv` | optional | Block list of advertisers by their domains | `['ford.com']` | `Array` | + +### First-Party Data + +PStudio adapter supports below described first-party data passed as configuration options to the adapter itself. +These are the standard objects that are also well described in the OpenRTB 2.5 specification but +not all of the properties from the OpenRTB standard are supported. + +- `user` + - `yob` - Year of birth as a 4-digit integer. + - `gender` - Gender, where "M" = male, "F" = female, "O" = known to be other (i.e., omitted is unknown). +- `device` + - `ua` - Browser user agent string. + - `dnt` - Standard “Do Not Track” flag as set in the header by the browser, where 0 = tracking is unrestricted, 1 = do not track. + - `lmt` - "Limit Ad Tracking" signal commercially endorsed (e.g., iOS, Android), where 0 = tracking is unrestricted, 1 = tracking must be limited per commercial guidelines. + - `ip` - IPv4 address closest to device. + - `ipv6` - IP address closest to device as IPv6. + - `devicetype` - General device type as specified in OpenRTB 2.5. + - `make` - Device make (e.g., "Apple"). + - `model` - Device model (e.g., "iPhone"). + - `os` - Device operating system. + - `osv` - Device operating system version (e.g., "8.0.3"). + - `js` - Support for JavaScript. + - `language` - Browser language using ISO-639-1-alpha-2. + - `carrier` - Carrier or ISP (e.g., "Verizon"). "WiFi" is often used in mobile to indicate high bandwidth. + - `connectiontype` - Network connection type. See OpenRTB 2.5 docs for valid values. + - `ifa` - ID sanctioned for advertiser use like IDFA or AAID (not hashed). + - `geo` + - `lat` - Latitude from -90.0 to +90.0, where negative is south. + - `lon` - Longitude from -180.0 to +180.0, where negative is west. + - `country` - Country code using ISO-3166-1-alpha-3. + - `region` - Region code using ISO-3166-2; 2-letter state code if USA. + - `regionfips104` - Region of a country using FIPS 10-4 notation (alternative to ISO 3166-2). + - `metro` - Google metro code. + - `city` - City using United Nations Code for Trade & Transport Locations. + - `zip` - Zip or postal code. + - `type` - Source of location data (GPS, IP address, user provided), recommended when passing lat / lon. Values as specified in OpenRTB 2.5. + - `ext` + - `ifatype` - IFA type as described by IAB. +- `site` + - `id` - Exchange-specific site ID. + - `name` - Site name. + - `domain` - Domain of the site (e.g., "mysite.foo.com"). + - `page` - URL of the page where the impression will be shown. + - `cat` - Array of IAB content categories of the site. + - `sectioncat` - Array of IAB content categories that describe the current section of the site. + - `pagecat` - Array of IAB content categories that describe the current page or view of the site. + - `ref` - Referrer URL that caused navigation to the current page. + - `publisher` + - `name` - Publisher name. + - `cat` - Array of IAB content categories that describe the publisher. + - `domain` - Highest level domain of the publisher. + - `content` + - `id` - ID uniquely identifying the content. + - `episode` - Episode number. + - `title` - Content title. + - `series` - Content series. + - `artist` - Artist credited with the content. + - `genre` - Genre that best describes the content (e.g., rock, pop, etc). + - `album` - Album to which the content belongs; typically for audio. + - `isrc` - International Standard Recording Code conforming to ISO-3901. + - `season` - Content season (e.g., "Season 3"). + - `mobile` - Indicates if the web page is viewed on a mobile platform, where 0 = desktop, 1 = mobile. +- `app` + - `id` - Exchange-specific app ID. + - `name` - App name. + - `bundle` - On Android, this should be a bundle or package name (e.g., com.foo.mygame). On iOS, it is typically a numeric ID. + - `domain` - Domain of the app (e.g., "mygame.foo.com"). + - `storeurl` - App store URL for an installed app; for IQG 2.1 compliance. + - `cat` - Array of IAB content categories of the app. + - `sectioncat` - Array of IAB content categories that describe the current section of the app. + - `pagecat` - Array of IAB content categories that describe the current page or view of the app. + - `ver` - Application version. + - `privacypolicy` - Indicates if the app has a privacy policy, where 0 = no, 1 = yes. + - `paid` - Indicates if the app is paid, where 0 = app is free, 1 = app is paid. + - `publisher` - Same as described in the `site` object. + - `keywords` - Comma separated list of keywords about the app. + - `content` - Same as described in the `site` object. +- `regs` + - `coppa` - Inndicates whether this request is subject to the United States Children’s Online Privacy Protection Act (COPPA Regulations established by the USA FTC. Possible values include the following - 0(no) or 1 (yes) + +**Note:** Publisher id for `app.publisher.id` or `site.publisher.id` is already sent in `params` as `pubid`, since it's a required parameter. + +**Note:** Devicetype needs to be provided in `device.devicetype` field. +Otherwise the ad server is not able to determine a platform type for a prebid bid reqeust. If a request is sent from a mobile device, then `device.os` field needs to be provided too. + +**Note:** User id is automatically assigned by the adapter to `user.id`. Adapter retrieves user.id from pstudio cookie. When user visits the publisher page for the first time the cookie is not present so user.id is not sent. + +### User ID Data + +PStudio adapter supports below described userIds data passed as configuration options to the adapter itself. + +- `user_ids` + - `uid2_token` - Advertising token of Unified ID 2.0 diff --git a/dev-docs/bidders/pubcircle.md b/dev-docs/bidders/pubcircle.md new file mode 100644 index 0000000000..ad9d50f323 --- /dev/null +++ b/dev-docs/bidders/pubcircle.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: PubCircle +description: Prebid PubCircle Bidder Adaptor +biddercode: pubcircle +filename: pubCircleBidAdapter +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +userId: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId, lotamePanoramaId, idx, uid2 +media_types: banner, video, native +safeframes_ok: true +deals_supported: true +pbjs: true +pbs: false +sidebarType: 1 +--- + +### Note + +The Example Bidding adapter requires setup before beginning. Please contact us at + +### Prebid.JS Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | Placement ID | `'123'` | `string` | diff --git a/dev-docs/bidders/pubgenius.md b/dev-docs/bidders/pubgenius.md index 3085968a32..cd0748de2d 100644 --- a/dev-docs/bidders/pubgenius.md +++ b/dev-docs/bidders/pubgenius.md @@ -6,11 +6,12 @@ pbjs: true biddercode: pubgenius media_types: banner floors_supported: true -gdpr_supported: true +tcfeu_supported: false usp_supported: true schain_supported: true coppa_supported: true userIds: unifiedId +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/publir.md b/dev-docs/bidders/publir.md new file mode 100644 index 0000000000..3ef9f519f3 --- /dev/null +++ b/dev-docs/bidders/publir.md @@ -0,0 +1,57 @@ +--- +layout: bidder +title: Publir +description: Prebid Publir Bidder Adapter +multiformat_supported: will-bid-on-any +pbjs: true +biddercode: publir +media_types: banner, video +schain_supported: true +tcfeu_supported: false +gvl_id: none +usp_supported: true +floors_supported: true +userIds: all +sidebarType: 1 +safeframes_ok: true, +coppa_supported: true +--- + +### Note + +The Publir adapter requires setup and approval. Please reach out to [info@publir.com] to setup an Publir account. + +### Bid Parameters + +#### Banner, Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `pubId` | required | String | Publir publisher Id provided by your Publir representative | "1234567890abcdef12345678" + +## Example + +```javascript +var adUnits = [{ + code: 'hre_div-hre-vcn-1', + sizes: [[1080, 1920]]], + mediaTypes: { + banner: { + sizes: [ + [1080, 1920], + ], + }, + }, + bids: [{ + bidder: 'publir', + params: { + pubId: '1234567890abcdef12345678' + } + }] +}]; +``` + +### Configuration + +Publir required setting UserSync by iframe for monetization. diff --git a/dev-docs/bidders/pubmatic.md b/dev-docs/bidders/pubmatic.md index f8cbcd0a12..26af4168e8 100644 --- a/dev-docs/bidders/pubmatic.md +++ b/dev-docs/bidders/pubmatic.md @@ -4,10 +4,12 @@ title: PubMatic description: Prebid PubMatic Bidder Adaptor biddercode: pubmatic media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true +gpp_supported: true schain_supported: true +dchain_supported: true floors_supported: true userIds: all prebid_member: true @@ -16,41 +18,41 @@ pbjs: true pbs: true pbs_app_supported: true fpd_supported: true +ortb_blocking_supported: true gvl_id: 76 +multiformat_supported: will-bid-on-one +sidebarType: 1 --- -### Prebid Server Note: -Before configuring the PubMatic adapter as S2S, you must reach out to the PubMatic team for approval and setup steps. +### Prebid Server Note -### Prebid 1.0 Upgrade Note: -If you upgrading from a Prebid version prior to 1.0, please reach out to your PubMatic Customer Success Manager prior to your upgrade. Publisher accounts need new settings to function correctly with the PubMatic Prebid 1.0 adapter and your Customer Success Manager will ensure your account is setup correctly. +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|--------------------|------------------------------|----------| -| `publisherId` | required | Publisher ID | `'32572'` | `string` | +| `publisherId` | required | Publisher ID | `'32572'` | `string` | | `adSlot` | optional | Ad Slot Name (see below)| `'38519891'` | `string` | -| `pmzoneid` | optional | Zone ID | `'zone1,zone2'` | `string` | -| `lat` | optional | Latitude | `'40.712775'` | `string` | -| `lon` | optional | Longitude | `'-74.005973'` | `string` | -| `yob` | optional | Year of Birth | `'1982'` | `string` | -| `gender` | optional | Gender | `'M'` | `string` | -| `kadpageurl` | optional | Overrides Page URL | `'http://www.yahoo.com/'`| `string` | -| `kadfloor` | optional | Bid Floor | `'1.75'` | `string` | -| `currency` | optional | Bid currency | `'AUD'` (Value configured only in the 1st adunit will be passed on.
      Values if present in subsequent adunits, will be ignored.) | `string` | -| `dctr` | optional | Deal Custom Targeting
      (Value configured only in the 1st adunit will be passed on.
      Values if present in subsequent adunits, will be ignored.) | `'key1=123|key2=345'` | `string` | -| `bcat` | optional | Blocked IAB Categories
      (Values from all slots will be combined and only unique values will be passed. An array of strings only. Each category should be a string of a length of more than 3 characters.) | `[ 'IAB1-5', 'IAB1-6', 'IAB1-7' ]` | `array of strings` | -| `deals` | optional | PMP deals
      (Values from each slot will be passed per slot. An array of strings only. Each deal-id should be a string of a length of more than 3 characters.) | `[ 'deal-id-5', 'deal-id-6', 'deal-id-7' ]` | `array of strings` | -| `outstreamAU` | optional | Oustream AdUnit described in Blue BillyWig UI. This field is mandatory if mimeType is described as video and context is outstream (i.e., for outstream videos) | `'renderer_test_pubmatic'` | `string` | +| `pmzoneid` | optional | Zone ID | `'zone1,zone2'` | `string` | +| `lat` | optional | Latitude
      (Supported until Prebid version 7.54.4 and starting from Prebid version 8.11.0 we have option to configure this using ortb2.(device OR user)) | `'40.712775'` | `string` | +| `lon` | optional | Longitude
      (Supported until Prebid version 7.54.4 and starting from Prebid version 8.11.0 we have option to configure this using ortb2.(device OR user)) | `'-74.005973'` | `string` | +| `yob` | optional | Year of Birth | `'1982'` | `string` | +| `gender` | optional | Gender | `'M'` | `string` | +| `kadpageurl` | optional | Overrides Page URL | `'http://www.yahoo.com/'` | `string` | +| `kadfloor` | optional | Bid Floor | `'1.75'` | `string` | +| `currency` | optional | Bid currency | `'AUD'` (Value configured only in the 1st adunit will be passed on.
      Values if present in subsequent adunits, will be ignored.) | `string` | +| `dctr` | optional | Deal Custom Targeting
      (Value configured in each adunit will be passed on inside adunit configs i.e. imp.ext), `'key1=123|key2=345'` | `string` | +| `acat` | optional | Allowed categories
      (List of allowed categories for a given auction to be sent in either using ortb2 config (request.ext.prebid.bidderparams.pubmatic.acat) or using slot level params. If categories sent using both then priority will be given to ortb2 over slot level params.) | `[ 'IAB1-5', 'IAB1-6', 'IAB1-7' ]` | `array of strings` | +| `bcat` | optional | Blocked IAB Categories
      (Values from all slots will be combined and only unique values will be passed. An array of strings only. Each category should be a string of a length of more than 3 characters.) | `[ 'IAB1-5', 'IAB1-6', 'IAB1-7' ]` | `array of strings` | +| `deals` | optional | PMP deals
      (Values from each slot will be passed per slot. An array of strings only. Each deal-id should be a string of a length of more than 3 characters.) | `[ 'deal-id-5', 'deal-id-6', 'deal-id-7' ]` | `array of strings` | +| `outstreamAU` | optional | Oustream AdUnit described in Blue BillyWig UI. This field is mandatory if mimeType is described as video and context is outstream (i.e., for outstream videos) | `'renderer_test_pubmatic'` | `string` | ### Configuration PubMatic recommends the UserSync configuration below. Without it, the PubMatic adapter will not able to perform user syncs, which lowers match rate and reduces monetization. -For Prebid.js v1.15.0 and later: - ```javascript pbjs.setConfig({ userSync: { @@ -64,16 +66,6 @@ pbjs.setConfig({ }); ``` -For Prebid.js v1.14.0 and before: - -```javascript -pbjs.setConfig({ - userSync: { - iframeEnabled: true, - enabledBidders: ['pubmatic'] - }}); -``` - Note: Combine the above the configuration with any other UserSync configuration. Multiple setConfig() calls overwrite each other and only last call for a given attribute will take effect. ### adSlot Specification and Multi-Size Ad Units @@ -86,45 +78,31 @@ The adSlot parameter supports two different formats: | Without Size | `'38519891'` | | With Size | `'38519891@300x205'` | -Support and behavior differs by Prebid.js version - -Prebid.js v2.13.0 and later: - -adSlot parameter is now optional. To omit the adSlot parameter, your publisher account must have default site and tag enabled. Consult your account manager to find out if default site and tag is enabled on your account. If used, both formats are supported. Without Size is the recommended option. If you are using Prebid Server, Prebid Server v0.69.0 or higher (Go version) or v1.18.0 or higher (Java version) is required to use Without Size. If you are using a managed service provider for Prebid Server, consult the provider to find out which version of Prebid Server they are using. All options will send the ad request with all sizes specified in the Prebid ad unit configuration. - -Prebid.js v2.9.0 to v2.12.0: - -Both formats are supported. Without Size is the recommended option. If you are using Prebid Server, Prebid Server v0.69.0 or higher (Go version) or v1.18.0 or higher (Java version) is required to use Without Size. If you are using a managed service provider for Prebid Server, consult the provider to find out which version of Prebid Server they are using. Both formats will send the ad request with all sizes specified in the Prebid ad unit configuration. - -Prebid.js v1.18.0 to v2.8.0: - -Both formats are supported. Without Size is the recommended option. If you are using Prebid Server, Prebid Server v0.69.0 or higher (Go version) or v1.18.0 or higher (Java version) is required to use Without Size. If you are using a managed service provider for Prebid Server, consult the provider to find out which version of Prebid Server they are using. Without Size will send the ad request with all sizes specified in the Prebid ad unit configuration. With Size will only request the specified size. Mutli-sized ad units are not supported when using Prebid Server. - -Prebid.js v1.17.0 and earlier: - -Only With Size is supported. To support multi-size ad units, list the PubMatic bidder entry multiple times, once for each size. Mutli-sized ad units are not supported when using Prebid Server. +adSlot parameter is optional. To omit the adSlot parameter, your publisher account must have default site and tag enabled. Consult your account manager to find out if default site and tag is enabled on your account. If used, both formats are supported. Without Size is the recommended option. Both options will send the ad request with all sizes specified in the Prebid ad unit configuration. ### video parameters + The PubMatic adapter supports video as of Prebid v1.16.0 {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | +| Name | Scope | Description | Example | | :----------------------| :------- | :---------------------------------------------------------- | :------ | -| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | -| `video.skippable` | optional | If 'true', user can skip ad | `true` | -| `video.minduration` | optional | Minimum ad duration in seconds | `5` | -| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | -| `video.startdelay` | optional | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | -| `video.playbackmethod` | optional | Defines whether inventory is user-initiated or autoplay sound on/off
      Values:
      `1`: Auto-play, sound on
      `2`: Auto-play, sound off
      `3`: Click-to-play
      `4`: mouse-over | `1` | -| `video.api` | optional | API frameworks supported
      Values:
      `1`: VPAID 1.0
      `2`: VPAID 2.0
      `3`: MRAID-1
      `4`: ORMMA
      `5`: MRAID-2 | `[1, 2]` | -| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | -| `video.battr` | optional | Blocked creative attributes, See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.3 for values | `[3, 9]` | -| `video.linearity` | optional | Indicates if the impression is linear or nonlinear
      Values:
      `1`: Linear/In-Stream
      `2`: Non-Linear/Overlay. | `1` | -| `video.placement` | optional | Video placement type. See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.9 for Values | `1` | -| `video.minbitrate` | optional | Minumim bit rate in Kbps. | 50 | -| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | 70 | +| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | +| `video.skippable` | optional | If 'true', user can skip ad | `true` | +| `video.minduration` | optional | Minimum ad duration in seconds | `5` | +| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | +| `video.startdelay` | optional | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | +| `video.playbackmethod` | optional | Defines whether inventory is user-initiated or autoplay sound on/off
      Values:
      `1`: Auto-play, sound on
      `2`: Auto-play, sound off
      `3`: Click-to-play
      `4`: mouse-over | `1` | +| `video.api` | optional | API frameworks supported
      Values:
      `1`: VPAID 1.0
      `2`: VPAID 2.0
      `3`: MRAID-1
      `4`: ORMMA
      `5`: MRAID-2 | `[1, 2]` | +| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | +| `video.battr` | optional | Blocked creative attributes, See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.3 for values | `[3, 9]` | +| `video.linearity` | optional | Indicates if the impression is linear or nonlinear
      Values:
      `1`: Linear/In-Stream
      `2`: Non-Linear/Overlay. | `1` | +| `video.placement` | optional | Video placement type. See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.9 for Values | `1` | +| `video.minbitrate` | optional | Minumim bit rate in Kbps. | 50 | +| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | 70 | ### AdUnit Format for Video + ```javascript var videoAdUnits = [ { @@ -158,8 +136,8 @@ var videoAdUnits = [ }] ``` - ### AdUnit Format for Native + ```javascript var adUnits = [ { @@ -192,10 +170,11 @@ var adUnits = [ }]; ``` - ### Configuration for video + For Video ads, prebid cache needs to be enabled for PubMatic adapter. -``` + +```javascript pbjs.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' @@ -209,10 +188,11 @@ The following test parameters can be used to verify that Prebid Server is workin PubMatic adapter. This example includes an `imp` object with an PubMatic test publisher ID, ad slot, and sizes that would match with the test creative. -``` +```json +{ "imp":[ { - "id":“"some-impression-id”, + "id":"some-impression-id", "banner":{ "format":[ { @@ -227,11 +207,21 @@ and sizes that would match with the test creative. }, "ext":{ "pubmatic":{ - "publisherId":“156276”, + "publisherId": "156276", "adSlot":"pubmatic_test" } } } ] +} ``` + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). The following fields are supported: + +- `ortb2.site.*` +- `ortb2.user.*` + +AdUnit-specific data is supported using `AdUnit.ortb2Imp.ext.*` diff --git a/dev-docs/bidders/pubnative.md b/dev-docs/bidders/pubnative.md index 858c2b454e..39d609beea 100644 --- a/dev-docs/bidders/pubnative.md +++ b/dev-docs/bidders/pubnative.md @@ -4,19 +4,21 @@ title: PubNative pbs: true media_types: banner, video, native biddercode: pubnative -gdpr_supported: true +tcfeu_supported: false prebid_member: true schain_supported: true coppa_supported: true usp_supported: true +sidebarType: 1 --- ### Registration Before adding PubNative as a new bidder, there are 3 prerequisites: + - As a Publisher, you need to have Prebid Mobile SDK integrated. - You need a configured Prebid Server (either self-hosted or hosted by 3rd party). -- You need to be integrated with Ad Server SDK (e.g. Mopub) or internal product which communicates with Prebid Mobile SDK. +- You need to be integrated with Ad Server SDK or internal product which communicates with Prebid Mobile SDK. Please see [documentation](https://developers.pubnative.net/docs/prebid-adding-pubnative-as-a-bidder) for more info. diff --git a/dev-docs/bidders/pubnx.md b/dev-docs/bidders/pubnx.md deleted file mode 100644 index 9fb104d64a..0000000000 --- a/dev-docs/bidders/pubnx.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: PubNX -description: Prebid PubNX Bidder Adaptor -pbjs: true -biddercode: pubnx ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -| :--- | :---- | :---------- | :------ | :---- | -| `siteId` | required | The site ID from PubNX. | `12345` | Integer | -| `zoneIds` | optional | An array of integer zone IDs from PubNX. | `[12345, 4567]` | Array of integers | -| `networkId` | required | The network ID from PubNX. | `9969` | Integer | diff --git a/dev-docs/bidders/pubtech.md b/dev-docs/bidders/pubtech.md new file mode 100644 index 0000000000..b7a27f103d --- /dev/null +++ b/dev-docs/bidders/pubtech.md @@ -0,0 +1,118 @@ +--- +layout: bidder +title: Pubtech +description: Prebid Pubtech Bidder Adapter +pbjs: true +biddercode: pubtech +aliasCode : nexx360 +gvl_id: 965 (nexx360) +tcfeu_supported: true +usp_supported: true +schain_supported: true +floors_supported: true +userIds: all +tcf2_supported: true +media_types: banner, video, native +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------------|-------------------------------------- |-----------| +| `tagId` | required | tag ID | `"luvxjvgn"` | `string` | +| `videoTagId` | optional | Video tag ID | `"luvxjvgn"` | `string` | +| `nativeTagId` | optional | Native tag ID | `"luvxjvgn"` | `string` | +| `allBids` | optional | Return all bids | `true` | `boolean` | +| `divId` | optional | divId linked to adUnit | `"div-1"` | `string` | +| `adUnitName` | optional | A code to identify adUnit | `"header-ad"` | `string` | +| `adUnitPath` | optional | A reference to adUnit Path | `"/12345/pubtech/Homepage/HP/Header-Ad"` | `string` | + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +### Test Parameters + +```javascript +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'pubtech', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Video adUnit + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bids: [{ + bidder: 'pubtech', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Native adUnit + { + code: 'native1', + mediaTypes: + native: { + title: { + required: true + }, + image: { + required: true + }, + sponsoredBy: { + required: true + } + } + }, + bids: [{ + bidder: 'pubtech', + params: { + tagId: 'luvxjvgn' + } + }] + }, + // Multiformat Ad + { + code: 'multi1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + }, + banner: { + sizes: [[300, 250], [300,600]] + }, + native: { + + } + }, + bids: [{ + bidder: 'pubtech', + params: { + tagId: 'luvxjvgn', + videoTagId: 'luvxjvgn' + } + }] + }; +]; +``` diff --git a/dev-docs/bidders/pubx.md b/dev-docs/bidders/pubx.md index e734c91ed6..045f8f12d1 100644 --- a/dev-docs/bidders/pubx.md +++ b/dev-docs/bidders/pubx.md @@ -4,11 +4,12 @@ title: Pub-X description: Prebid Pub-X Bidder Adapter biddercode: pubx media_types: banner -gdpr_supported: false +tcfeu_supported: false coppa_supported: false usp_supported: false schain_supported: true pbjs: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/pulsepoint.md b/dev-docs/bidders/pulsepoint.md index ae43c9a5e7..9b1d52d947 100644 --- a/dev-docs/bidders/pulsepoint.md +++ b/dev-docs/bidders/pulsepoint.md @@ -3,52 +3,34 @@ layout: bidder title: PulsePoint description: Prebid PulsePoint Bidder Adaptor biddercode: pulsepoint -gdpr_supported: true +tcfeu_supported: true usp_supported: true schain_supported: true media_types: banner, video, native -userIds: britepoolId, criteo, fabrickId, hadronId, id5Id, identityLink, liveIntentId, lotamePanoramaId, merkleId, parrableId, pubCommonId, sharedId, unifiedId, verizonMediaId +userIds: all pbjs: true pbs: true gvl_id: 81 +sidebarType: 1 +safeframes_ok: true +coppa_supported: true +floors_supported: true +pbs_app_supported: true +fpd_supported: true +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one --- -### Disclosure +### Prebid Server Note -This bidder sets `adId` on the bid response and hasn't responded to the Prebid.js team to confirm uniqueness -of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381). +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------|----------|-------------------------------------------------------|------------------------------|---------------------| -| `cf` | required | Ad size identifier | `'300X250'` | `string` | | `cp` | required | Publisher Id | `12345` | `integer` | | `ct` | required | Ad Tag Id | `12345` | `integer` | -| `bcat` | optional | Blocked IAB Categories | `[ 'IAB1-5', 'IAB1-6' ]` | `array of strings` | | `battr` | optional | Blocked Creative Attributes | `[ 1, 2, 5 ]` | `array of integers` | -| `badv` | optional | Blocked Advertisers by their domains | `['ford.com', 'pepsi.com']` | `array of strings` | -| `bidfloor` | optional | Bid floor price CPM | `1.23` | `float` | -| `video` | required | Required for video requests. OpenRTB Video object. | `{ w: 400, h: 300 }` | `object` | - -### Video parameters -Parameters on the Video object in Bid params for PulsePoint. [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Video object specification is used. Below are some sample parameters from the OpenRTB Video specs. -Please use `mediaTypes.video` to specify video params in place of this parameter for PBJS 5.0 and later. - - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | -|------------------------|----------|------------------------------------------------------------|-------------------------------| -| `video.mimes` | required | Content MIME types supported | `['video/mp4','video/x-flv']` | -| `video.minduration` | optional | Minimum video ad duration in seconds | `8` | -| `video.maxduration` | optional | Maximum video ad duration in seconds | `20` | -| `video.protocols` | optional | Array of supported video protocols | `[2, 3]` | -| `video.w` | optional | Width of the video player in device independent pixels | `400` | -| `video.h` | optional | Height of the video player in device independent pixels | `300` | -| `video.startdelay` | optional | Start delay in seconds | `5` | -| `video.skip` | optional | Indicates if the player will allow the video to be skipped | `1` | -| `video.minbitrate` | optional | Minumim bit rate in Kbps. | `200` | -| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | `500` | -| `video.api` | optional | List of supported API frameworks for this impression | `[1, 2]` | - +| `deals` | required | Required for PMP requests. Array of OpenRTB Deal object. | `[{ id: 'DEAL_ONE', bidfloor: 1.23 }, ...]` | `array of objects` | diff --git a/dev-docs/bidders/pwbid.md b/dev-docs/bidders/pwbid.md index 26715707a2..9919486e76 100644 --- a/dev-docs/bidders/pwbid.md +++ b/dev-docs/bidders/pwbid.md @@ -3,23 +3,28 @@ layout: bidder title: PubWise description: PubWise Bidder Adaptor pbjs: true +pbs: true biddercode: pwbid aliasCode: pubwise -media_types: banner, native -gdpr_supported: true +media_types: banner, native, video +tcfeu_supported: true usp_supported: true schain_supported: true prebid_member: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, pubProvidedId, sharedId, unifiedId tcf1_supported: true -floors_supported: false +floors_supported: true gvl_id: 842 +sidebarType: 1 --- -### Note: -The PubWise bid adapter requires approval. Visit http://www.PubWise.io/ to get started. +### Note -### Bid params +The PubWise bid adapter is now availalbe self service. Visit to get started. + +### Global Bid params + +siteID is sufficient for bidding. {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | @@ -28,10 +33,32 @@ The PubWise bid adapter requires approval. Visit http://www.PubWise.io/ to get s | `bidFloor` | optional | Value to pass as the bidfloor for this bid | `2.50` | `currency` | | `isTest` | optional | A boolean to indicate 100% fill test placement request | `false` | `boolean` | +### video parameters + +The PubWise adapter supports video as of Prebid v7.39.0. Outstream is NOT supported currently. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | +| :----------------------| :------- | :---------------------------------------------------------- | :------ | +| `video.mimes` | required | Video MIME types | `['video/mp4','video/x-flv']` | +| `video.skippable` | optional | If 'true', user can skip ad | `true` | +| `video.minduration` | optional | Minimum ad duration in seconds | `5` | +| `video.maxduration` | optional | Maximum ad duration in seconds | `30` | +| `video.startdelay` | optional | Start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | +| `video.playbackmethod` | optional | Defines whether inventory is user-initiated or autoplay sound on/off
      Values:
      `1`: Auto-play, sound on
      `2`: Auto-play, sound off
      `3`: Click-to-play
      `4`: mouse-over | `1` | +| `video.api` | optional | API frameworks supported
      Values:
      `1`: VPAID 1.0
      `2`: VPAID 2.0
      `3`: MRAID-1
      `4`: ORMMA
      `5`: MRAID-2 | `[1, 2]` | +| `video.protocols` | optional | Supported video bid response protocols
      Values
      `1`: VAST 1.0
      `2`: VAST 2.0
      `3`: VAST 3.0
      `4`: VAST 1.0 Wrapper
      `5`: VAST 2.0 Wrapper
      `6`: VAST 3.0 Wrapper | `[5, 6]` | +| `video.battr` | optional | Blocked creative attributes, See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.3 for values | `[3, 9]` | +| `video.linearity` | optional | Indicates if the impression is linear or nonlinear
      Values:
      `1`: Linear/In-Stream
      `2`: Non-Linear/Overlay. | `1` | +| `video.placement` | optional | Video placement type. See [OpenRTB 2.5 specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), List 5.9 for Values | `1` | +| `video.minbitrate` | optional | Minumim bit rate in Kbps. | 50 | +| `video.maxbitrate` | optional | Maximum bit rate in Kbps. | 70 | + ### Example #### Banner -``` + +```javascript var adUnits = [ { code: "div-gpt-ad-1460505748561-0", @@ -50,9 +77,10 @@ var adUnits = [ } ] ``` + #### Native -``` +```javascript var adUnits = [ { code: 'div-gpt-ad-1460505748561-1', @@ -88,3 +116,38 @@ var adUnits = [ } ] ``` + +### Video + +```javascript +var videoAdUnits = [ +{ + code: 'div-gpt-ad-1460505748561-1', + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream', + mimes: ['video/mp4','video/x-flv'], // required + skip: 1, // optional + minduration: 5, // optional + maxduration: 30, // optional + startdelay: 5, // optional + playbackmethod: [1,3], // optional + api: [ 1, 2 ], // optional + protocols: [ 2, 3 ], // optional + battr: [ 13, 14 ], // optional + linearity: 1, // optional + placement: 2, // optional + minbitrate: 10, // optional + maxbitrate: 10 // optional + } + }, + bids: [{ + bidder: 'pwbid', + params: { + siteId: 'xxxxxx', // required + isTest: 'true' // required + } + }] +}] +``` diff --git a/dev-docs/bidders/pxyz.md b/dev-docs/bidders/pxyz.md index 3f35ab073a..46ad51f1ec 100644 --- a/dev-docs/bidders/pxyz.md +++ b/dev-docs/bidders/pxyz.md @@ -2,11 +2,13 @@ layout: bidder title: Playground XYZ description: Prebid Playground XYZ Bidder Adapter -gdpr_supported: true +gvl_id: 490 +tcfeu_supported: true usp_supported: true pbjs: true biddercode: pxyz prevBiddercode: playgroundxyz +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/qortex.md b/dev-docs/bidders/qortex.md new file mode 100644 index 0000000000..9eafaff1d3 --- /dev/null +++ b/dev-docs/bidders/qortex.md @@ -0,0 +1,32 @@ +--- +layout: bidder +title: Qortex +description: Qortex Bidder Adaptor +biddercode: qortex +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | RTB host | `'cpm.qortex.ai'` | `string` | +| `zoneId` | required | Zone Id | 76156 | `integer`| diff --git a/dev-docs/bidders/quantcast.md b/dev-docs/bidders/quantcast.md index 9d6e9764e7..f8f1f285de 100644 --- a/dev-docs/bidders/quantcast.md +++ b/dev-docs/bidders/quantcast.md @@ -5,10 +5,12 @@ description: Prebid Quantcast Bidder Adaptor pbjs: true biddercode: quantcast media_types: video -gdpr_supported: true +gvl_id: 11 +tcfeu_supported: true usp_supported: true coppa_supported: true prebid_member: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/quantum.md b/dev-docs/bidders/quantum.md index dfab352962..58041d1716 100644 --- a/dev-docs/bidders/quantum.md +++ b/dev-docs/bidders/quantum.md @@ -5,6 +5,7 @@ description: Prebid Quantum Bidder Adaptor pbjs: true biddercode: quantum media_types: native +sidebarType: 1 --- diff --git a/dev-docs/bidders/quantumdex.md b/dev-docs/bidders/quantumdex.md index 7391497300..a4eee3de31 100644 --- a/dev-docs/bidders/quantumdex.md +++ b/dev-docs/bidders/quantumdex.md @@ -6,14 +6,16 @@ pbjs: true biddercode: quantumdex aliasCode: apacdex media_types: banner, video -gdpr_supported: true +tcfeu_supported: false schain_supported: true usp_supported: true userIds: all floors_supported: true pbs: true pbs_app_supported: true +sidebarType: 1 --- -# Description +## Description + Quantumdex is an aliased bidder of Apacdex bid adapter. Please refer to [Apacdex documentation](https://docs.prebid.org/dev-docs/bidders/apacdex) for bid parameters and implementation guide. diff --git a/dev-docs/bidders/qwarry.md b/dev-docs/bidders/qwarry.md index 703e377226..abf2a5c19e 100644 --- a/dev-docs/bidders/qwarry.md +++ b/dev-docs/bidders/qwarry.md @@ -5,6 +5,7 @@ description: Prebid Qwarry Bidder Adaptor biddercode: qwarry media_types: banner, video pbjs: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/r2b2.md b/dev-docs/bidders/r2b2.md new file mode 100644 index 0000000000..0ec35ca5cd --- /dev/null +++ b/dev-docs/bidders/r2b2.md @@ -0,0 +1,49 @@ +--- +layout: bidder +title: r2b2 +description: Prebid R2B2 bidder Adapter +biddercode: r2b2 +tcfeu_supported: true +gvl_id: 1235 +usp_supported: true +coppa_supported: true +schain_supported: true +userId: all +media_types: banner +safeframes_ok: false +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: true +pbs: false +prebid_member: false +multiformat_supported: will-not-bid +sidebarType: 1 +--- +### Note + +The R2B2 Bidding adapter requires registration before beginning. Please contact us at [partner@r2b2.io](mailto:partner@r2b2.io). + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `pid` | required | Placement id | `'r2b2.io/generic/300x600'` | `string` | + +### Bidder config + +In the bidder config, publishers can specify an endpoint domain for bidding, which may vary by region. For more information, please contact us at +[partner@r2b2.io](mailto:partner@r2b2.io). + +```javascript +pbjs.bidderSettings = { + r2b2: { + endpoint: 'hb.r2b2.cz' + } +}; +``` + +### 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](mailto:partner@r2b2.io) diff --git a/dev-docs/bidders/rads.md b/dev-docs/bidders/rads.md index ba3baa6f51..ae82a70fd0 100644 --- a/dev-docs/bidders/rads.md +++ b/dev-docs/bidders/rads.md @@ -5,9 +5,10 @@ description: Prebid Rads Bidder Adaptor pbjs: true biddercode: rads media_types: banner, video -gdpr_supported: true +tcfeu_supported: true gvl_id: 602 userIds: uid2, netId +sidebarType: 1 --- diff --git a/dev-docs/bidders/rakuten.md b/dev-docs/bidders/rakuten.md index 5bb4f254c3..ee4d169db4 100644 --- a/dev-docs/bidders/rakuten.md +++ b/dev-docs/bidders/rakuten.md @@ -5,6 +5,7 @@ description: Prebid Rakuten Bidder Adaptor pbjs: true biddercode: rakuten prebid_member: true +sidebarType: 1 --- diff --git a/dev-docs/bidders/ras.md b/dev-docs/bidders/ras.md new file mode 100644 index 0000000000..e8f9ce3837 --- /dev/null +++ b/dev-docs/bidders/ras.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: RingierAxelSpringer +description: Prebid RingierAxelSpringer Bidder Adapter +biddercode: ras +media_types: banner, native +pbjs: true +gvl_id: 1021 +tcfeu_supported: true +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: false +sidebarType: 1 +multiformat_supported: will-bid-on-one +--- + + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|------------------------------------------------------------------------------------------------------|---------------------------------------------|----------| +| `network` | required | Specific identifier provided by RAS | `'4178463'` | `string` | +| `site` | required | Specific identifier name (case-insensitive) that is associated with this ad unit and provided by RAS | `'example_com'` | `string` | +| `area` | required | Ad unit category name; only case-insensitive alphanumeric with underscores and hyphens are allowed | `'sport'` | `string` | +| `slot` | required | Ad unit placement name (case-insensitive) provided by RAS | `'slot'` | `string` | +| `pageContext` | optional | Web page context data | `{}` | `object` | +| `pageContext.dr` | optional | Document referrer URL address | `'https://example.com/'` | `string` | +| `pageContext.du` | optional | Document URL address | `'https://example.com/sport/football/article.html?id=932016a5-02fc-4d5c-b643-fafc2f270f06'` | `string` | +| `pageContext.dv` | optional | Document virtual address as slash-separated path that may consist of any number of parts (case-insensitive alphanumeric with underscores and hyphens); first part should be the same as `site` value and second as `area` value; next parts may reflect website navigation | `'example_com/sport/football'` | `string` | +| `pageContext.keyWords` | optional | List of keywords associated with this ad unit; only case-insensitive alphanumeric with underscores and hyphens are allowed | `['euro', 'lewandowski']` | `string[]` | +| `pageContext.keyValues` | optional | Key-values associated with this ad unit (case-insensitive); following characters are not allowed in the values: `" ' = ! + # * ~ ; ^ ( ) < > ] [ & @` | `{}` | `object` | +| `pageContext.keyValues.ci` | optional | Content unique identifier | `'932016a5-02fc-4d5c-b643-fafc2f270f06'` | `object` | +| `pageContext.keyValues.adunit` | optional | Ad unit name | `'example_com/sport'` | `string` | diff --git a/dev-docs/bidders/readpeak.md b/dev-docs/bidders/readpeak.md index b882b6dc96..ec0f3fb3e1 100644 --- a/dev-docs/bidders/readpeak.md +++ b/dev-docs/bidders/readpeak.md @@ -3,11 +3,16 @@ layout: bidder title: Readpeak description: Readpeak Bidder Adaptor pbjs: true +pbs: true biddercode: readpeak -media_types: native +media_types: native, banner gdpr_supported: true +tcfeu_supported: true tcf2_supported: true +deals_supported: true +pbs_app_supported: true gvl_id: 290 +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/redtram.md b/dev-docs/bidders/redtram.md new file mode 100644 index 0000000000..f92873ed89 --- /dev/null +++ b/dev-docs/bidders/redtram.md @@ -0,0 +1,70 @@ +--- +layout: bidder +title: Redtram +description: Prebid Redtram Bidder Adapter. +pbjs: true +pbs: false +gvl_id: none +biddercode: redtram +media_types: banner +tcfeu_supported: false +usp_supported: false +coppa_supported: false +schain_supported: false +safeframes_ok: false +dchain_supported: false +deals_supported: false +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +prebid_member: false +sidebarType: 1 +--- + +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Description](#description) +- [Bid params](#bid-params) +- [Test Parameters](#test-parameters) + + + +### Description + +Redtram header bidding adapter connects with redtram demand sources to fetch bids for display placements. Please reach out to your account manager or for more information. + + + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|----------|------------------------------------|------------|----------| +| `placementId`| optional | The placement ID from Redtram | `'23611'` | `string` | +| `bidFloor` | optional | Lowest value of expected bid price | `1.1` | `float` | + + + +### Test Parameters + +300x250 banner test + +```javascript +var adUnits = [{ + code: 'prebid-place', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + // Replace this object to test a new Adapter! + bids: [{ + bidder: 'redtram', + params : { + placementId : "23611" //test, please replace after test + } + }] +}]; +``` diff --git a/dev-docs/bidders/reklamstore.md b/dev-docs/bidders/reklamstore.md deleted file mode 100644 index 10d1b5909e..0000000000 --- a/dev-docs/bidders/reklamstore.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: ReklamStore -description: Prebid ReklamStore Bidder Adaptor -biddercode: reklamstore -pbjs: true -gdpr_supported: true -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|----------------------------------------|---------------|----------| -| `regionId` | required | The placement id provided by ReklamStore | `1234567` | `integer` | diff --git a/dev-docs/bidders/relaido.md b/dev-docs/bidders/relaido.md index 08ef84f34f..6fba60b6cd 100644 --- a/dev-docs/bidders/relaido.md +++ b/dev-docs/bidders/relaido.md @@ -6,6 +6,7 @@ biddercode: relaido userIds: imuid pbjs: true media_types: banner, video +sidebarType: 1 --- ### Bid Params @@ -14,3 +15,5 @@ media_types: banner, video | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| | `placementId` | required | Relaido placement id | `1234567` | `string` | +| `video.playerSize` | optional | Video Player Size
      This field is mandatory if mediaTypes.video.playerSize is undefined. | `[1, 1]` or `[300, 250] over` | `array of number` | +| `ogUrl` | optional | Get from og:url if canonicalUrl cannot be obtained. defaults to `false`. | `true` | `boolean` | diff --git a/dev-docs/bidders/relay.md b/dev-docs/bidders/relay.md new file mode 100644 index 0000000000..c932c2de0e --- /dev/null +++ b/dev-docs/bidders/relay.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: Relay +description: Prebid Relay Bidder Adapter +biddercode: relay +media_types: banner, video, native +pbjs: true +pbs: false +safeframes_ok: true +floors_supported: true +fpd_supported: true +multiformat_supported: will-bid-any +ortb_blocking_supported: partial +pbs_app_supported: true +gdpr_supported: false +usp_supported: false +coppa_supported: true +deals_supported: true +schain_supported: true +dchain_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|------------| +| `accountId` | required | Relay Account Id | `9778` | `'number'` | + +### Note + +The Relay Bid Adapter makes requests to the Relay Exchange API which supports OpenRTB. + +Therefore the only bid param required is the the `accountId`, all Prebid Ad Unit fields will be automatically inferred via Prebid's ORTB Converter. If any field on the request requires customization it is configurable using [First Party Data - Prebid.js](https://docs.prebid.org/features/firstPartyData.html#supplying-adunit-specific-data) via `ortb2` interface. We support all FPD fields: site.content.data, site.ext.data., user.data, user.ext.data. diff --git a/dev-docs/bidders/relevantdigital.md b/dev-docs/bidders/relevantdigital.md new file mode 100644 index 0000000000..25b90a6e48 --- /dev/null +++ b/dev-docs/bidders/relevantdigital.md @@ -0,0 +1,139 @@ +--- +layout: bidder +title: Relevant Digital +description: Relevant Digital Bid Adapter +biddercode: relevantdigital +pbjs: true +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +floors_supported: true +media_types: banner, video, native +userIds: all +prebid_member: true +safeframes_ok: true +deals_supported: true +pbs: true +pbs_app_supported: true +fpd_supported: true +ortb_blocking_supported: no +gvl_id: 1100 +multiformat_supported: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------------------------------------------|----------------------------|--------------| +| `placementId` | required | The placement id. | `'6204e83a077_620f9e8e4fe'` | `String` | +| `pbsHost` | required if not set in config | Host name of the server. | `'pbs-example.relevant-digital.com'` | `String` | +| `accountId` | required if not set in config | The account id. | `'6204e5fa70e3ad108'` | `String` | +| `useSourceBidderCode` | optional | Set to `true` in order to use the bidder code of the actual server-side bidder in bid responses. You **MUST** also use `allowAlternateBidderCodes: true` in `bidderSettings` if you enabled this - as otherwise the bids will be rejected.| `true` | `Boolean` | + +### Config Parameters + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------------------------------------------|----------------------------|--------------| +| `pbsHost` | required if not set in bid parameters | Host name of the server. | `'pbs-example.relevant-digital.com'` | `String` | +| `accountId` | required if not set in bid parameters | The account id. | `'6204e5fa70e3ad108'` | `String` | +| `pbsBufferMs` | optional | How much less in *milliseconds* the server's internal timeout should be compared to the normal Prebid timeout. Default is *250*. To be increased in cases of frequent timeouts. | `250` | `Integer` | +| `useSourceBidderCode` | optional | Set to `true` in order to use the bidder code of the actual server-side bidder in bid responses. You **MUST** also use `allowAlternateBidderCodes: true` in `bidderSettings` if you enabled this - as otherwise the bids will be rejected.| `true` | `Boolean` | + +### Example setup using pbjs.setConfig() + +This is the recommended method to set the global configuration parameters. + +```javascript +pbjs.setConfig({ + relevantdigital: { + pbsHost: 'pbs-example.relevant-digital.com', + accountId: '6204e5fa70e3ad10821b84ff', + }, +}); + +var adUnits = [ + { + code: 'test-div', + mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }}, + bids: [ + { + bidder: 'relevantdigital', + params: { + placementId: '6204e83a077c5825441b8508_620f9e8e4fe67c1f87cd30ed', + } + } + ], + } +]; +``` + +## Example setup using only bid params + +This method to set the global configuration parameters (like **pbsHost**) in **params** could simplify integration of a provider for some publishers. Setting different global config-parameters on different bids is not supported in general*, as the first settings found will be used and any subsequent global settings will be ignored. + + * The exception is `useSourceBidderCode` which can be overriden individually per ad unit. + +```javascript +var adUnits = [ + { + code: 'test-div', + mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }}, + bids: [ + { + bidder: 'relevantdigital', + params: { + placementId: '6204e83a077c5825441b8508_620f9e8e4fe67c1f87cd30ed', + pbsHost: 'pbs-example.relevant-digital.com', + accountId: '6204e5fa70e3ad10821b84ff', + } + } + ], + } +]; +``` + +### Example setup with multiple providers + +**Notice:** Placements below are *not* live test placements + +```javascript + +pbjs.aliasBidder('relevantdigital', 'providerA'); +pbjs.aliasBidder('relevantdigital', 'providerB'); + +pbjs.setConfig({ + providerA: { + pbsHost: 'pbs-example-a.relevant-digital.com', + accountId: '620533ae7f5bbe1691bbb815', + }, + providerB: { + pbsHost: 'pbs-example-b.relevant-digital.com', + accountId: '990533ae7f5bbe1691bbb815', + }, +}); + +var adUnits = [ + { + code: 'test-div', + mediaTypes: { banner: { sizes: [[300, 250], [320, 320]] }}, + bids: [ + { + bidder: 'providerA', + params: { + placementId: '610525862d7517bfd4bbb81e_620523b7d1dbed6b0fbbb817', + } + }, + { + bidder: 'providerB', + params: { + placementId: '990525862d7517bfd4bbb81e_770523b7d1dbed6b0fbbb817', + } + }, + ], + } +]; +``` diff --git a/dev-docs/bidders/reload.md b/dev-docs/bidders/reload.md deleted file mode 100644 index 6a6abca44e..0000000000 --- a/dev-docs/bidders/reload.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -layout: bidder -title: Reload -description: Reload Prebid Adaptor -pbjs: true -biddercode: reload -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -| ------------- | -------- | ----------------------------------------------- | ---------------------------------- |----------| -| `plcmID` | required | Placement ID (provided by Reload) | "4234897234" | `string` | -| `partID` | required | Partition ID (provided by Reload) | "part_01" | `string` | -| `opdomID` | required | Internal parameter (provided by Reload) | 0 | `int` | -| `bsrvID` | required | Internal parameter (provided by Reload) | 12 | `int` | -| `type` | optional | Internal parameter (provided by Reload) | "pcm" | `string` | - - -## Example - -```javascript -var adUnits = [ - // Banner adUnit - { - code: 'banner-div', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ], - } - }, - bids: [{ - bidder: 'reload', - params: { - plcmID: '4234897234', - partID: 'part_2', - opdomID: 0, - bsrvID: 0, - type: 'pcm' - } - }] - }]; -``` diff --git a/dev-docs/bidders/resetdigital.md b/dev-docs/bidders/resetdigital.md index 1b827e844a..3f0b072ec8 100644 --- a/dev-docs/bidders/resetdigital.md +++ b/dev-docs/bidders/resetdigital.md @@ -2,11 +2,22 @@ layout: bidder title: ResetDigital description: Reset Digital Bidder Module -hide: true pbjs: true +pbs: true biddercode: resetdigital -gdpr_supported: true +gvl_id: 1162 +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +floors_supported: true +userIds: check with bidder +prebid_member: false +deals_supported: true +pbs_app_supported: true +multiformat_supported: will-bid-on-any media_types: banner, video +sidebarType: 1 --- ### bid params @@ -15,6 +26,37 @@ media_types: banner, video | Name | Scope | Description | Example | Type | |----------|----------|-------------|------------------------------------|----------| -| `pubId` | required | Publisher account id | `'123pubid'` | `string` | -| `zoneId` | optional | Ad zone specific id if provided | `'456zoneId'` | `string` | +| `pubId` | required | Publisher account id | `'123pubId'` | `string` | +| `siteID` | optional | Publisher site id | `'123siteId'` | `string` | +| `zoneId` | optional | Used for extra fields | `{}` | `object` | | `forceBid` | optional | Returns test bid | true | `boolean` | +| `position` | optional | Set the page position. Valid values are "atf" and "btf". | `'atf'` | `string` | +| `bidFloor` | optional | Sets the global floor -- no bids will be made under this value. | `0.50` | `float` | +| `latLong` | optional | Sets the latitude and longitude for the visitor | `[40.7608, 111.8910]` | `Array` | +| `inventory` | optional | This parameter allows the definition of an object defining arbitrary key-value pairs concerning the page for use in targeting. The values must be arrays of strings. | `{"rating":["5-star"], "prodtype":["tech","mobile"]}` | `object` | +| `visitor` | optional | This parameter allows the definition of an object defining arbitrary key-value pairs concerning the visitor for use in targeting. The values must be arrays of strings. | `{"ucat":["new"], "search":["iphone"]}` | `object` | +| `keywords` | optional | This can be used to influence reports for client-side display. To get video or server-side reporting, please use First Party data or the inventory/visitor parameters. | `["travel", "tourism"]` | `Array` | + +#### mediaTypes.video + +The following video parameters are supported here so publishers may fully declare their video inventory: + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| context | required | instream or outstream |"outstream" | string | +| playerSize| required | width, height of the player in pixels | [640,360] - will be translated to w and h in bid request | array | +| mimes | required | List of content MIME types supported by the player (see openRTB v2.5 for options) | ["video/mp4"]| array| +| protocols | required | Supported video bid response protocol values
      1: VAST 1.0
      2: VAST 2.0
      3: VAST 3.0
      4: VAST 1.0 Wrapper
      5: VAST 2.0 Wrapper
      6: VAST 3.0 Wrapper
      7: VAST 4.0
      8: VAST 4.0 Wrapper | [2,3,5,6] | array| +| api | required | Supported API framework values:
      1: VPAID 1.0
      2: VPAID 2.0
      3: MRAID-1
      4: ORMMA
      5: MRAID-2 | [2] | array | +| linearity | required | OpenRTB2 linearity. 1: linear (in-stream ad), 2: non-linear (overlay ad) | 1 | integer | +| maxduration | recommended | Maximum video ad duration in seconds. | 30 | integer | +| minduration | recommended | Minimum video ad duration in seconds | 6 | integer | +| playbackmethod | recommended | Playback methods that may be in use. Only one method is typically used in practice. (see openRTB v2.5 section 5.10 for options)| [2]| array | +| skip | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes. | 1 | integer | +| skipafter| optional | Number of seconds a video must play before skipping is enabled; only applicable if the ad is skippable. | 6 | integer| +| minbitrate | optional | Minimum bit rate in Kbps. | 300 | integer | +| maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | integer | +| startdelay | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements.
      >0: Mid-Roll (value indicates start delay in second)
      0: Pre-Roll
      -1: Generic Mid-Roll
      -2: Generic Post-Roll | 0 | integer | +| placement | recommended | Placement type for the impression. (see openRTB v2.5 section 5.9 for options) | 1 | integer | diff --git a/dev-docs/bidders/resultsmedia.md b/dev-docs/bidders/resultsmedia.md deleted file mode 100644 index 1bc0d46203..0000000000 --- a/dev-docs/bidders/resultsmedia.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: ResultsMedia -description: Prebid ResultsMedia Bidder Adaptor -pbjs: true -biddercode: resultsmedia -media_types: video, banner -gdpr_supported: true -schain_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| zoneId | required | The zone ID from ResultsMedia. | 12345 | integer | diff --git a/dev-docs/bidders/retailspot.md b/dev-docs/bidders/retailspot.md new file mode 100644 index 0000000000..b37cf4213b --- /dev/null +++ b/dev-docs/bidders/retailspot.md @@ -0,0 +1,33 @@ +--- +layout: bidder +title: RetailSpot +description: Prebid RetailSpot Bidder Adaptor +pbjs: true +pbs: false +media_types: banner, video +biddercode: retailspot +tcfeu_supported: false +usp_supported: true +floors_supported: false +schain_supported: false +coppa_supported: false +userIds: +safeframes_ok: true +deals_supported: true +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Note: + +The RetailSpot Header Bidding adaptor requires setup and approval from the RetailSpot team. Please reach out to your account manager or contact@retail-spot.io for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------------------|--------------------------------------|----------| +| `placement` | required | The placement ID from RetailSpot | `'test-1234'` | `string` | + diff --git a/dev-docs/bidders/revcontent.md b/dev-docs/bidders/revcontent.md index 3ba3d9869d..79b8c4350d 100644 --- a/dev-docs/bidders/revcontent.md +++ b/dev-docs/bidders/revcontent.md @@ -4,19 +4,21 @@ title: RevContent description: RevContent Bidder Adaptor biddercode: revcontent media_types: native -gdpr_supported: false +tcfeu_supported: false coppa_supported: false usp_supported: false pbjs: true pbs: true gvl_id: 203 +sidebarType: 1 --- ### Note -To use RevContent bidder, you need to have an existing RevContent account. To create a new account visit https://www.RevContent.com. If you are an existing user, contact the account rep for api access and information. +To use RevContent bidder, you need to have an existing RevContent account. To create a new account visit . If you are an existing user, contact the account rep for api access and information. For prebid server, Revcontent only uses basic OpenRTB requests, so only the endpoint will need to be customized. Your request must contain either `app.name` or `site.domain` to be considered valid. Revcontent will provide you with a custom endpoint that will contain your account details that you will specify in your adapater configuration, and you must manually enable the adapter. For example, your pbs.yaml would contain the following: + ``` adapters: revcontent: @@ -26,7 +28,6 @@ adapters: ### Prebid.js Bid Params - {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | @@ -38,4 +39,3 @@ adapters: | `endpoint` | optional | Api Endpoint - Used for testing | `'trends.revcontent.com'` | `string` | | `bidfloor` | optional | Bid Floor | `0.1` | `float` | | `template` | optional | Format of the display ad | `'{title}'` | `string` | - diff --git a/dev-docs/bidders/rexrtb.md b/dev-docs/bidders/rexrtb.md index f712f2b6a9..0e3b6d33f9 100644 --- a/dev-docs/bidders/rexrtb.md +++ b/dev-docs/bidders/rexrtb.md @@ -4,6 +4,7 @@ title: REXRTB description: Prebid REXRTB Bidder Adaptor pbjs: true biddercode: rexrtb +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/rhythmone.md b/dev-docs/bidders/rhythmone.md index c4bee7f668..d89b63628e 100644 --- a/dev-docs/bidders/rhythmone.md +++ b/dev-docs/bidders/rhythmone.md @@ -6,12 +6,15 @@ pbjs: true pbs: true biddercode: rhythmone media_types: video -gdpr_supported: true +tcfeu_supported: true schain_supported: true gvl_id: 36 +sidebarType: 1 +enable_download: false --- - +{: .alert.alert-warning :} +The rhythmone bidder is deprecated, and will be removed in a future release of Prebid.js and Prebid Server. ### Bid Params diff --git a/dev-docs/bidders/richaudience.md b/dev-docs/bidders/richaudience.md index 9a75adbc75..f452b0d9a6 100644 --- a/dev-docs/bidders/richaudience.md +++ b/dev-docs/bidders/richaudience.md @@ -5,12 +5,15 @@ description: Prebid Rich Audience Bidder Adapter biddercode: richaudience userIds: criteo, id5Id, identityLink, liveIntentId, pubCommonId, unifiedId media_types: banner, video -gdpr_supported: true +tcfeu_supported: true gvl_id: 108 safeframes_ok: false prebid_member: true pbjs: true pbs: true +schain_supported: true +floors_supported: true +sidebarType: 1 --- ### Bid Params @@ -25,8 +28,8 @@ pbs: true | `keywords` | optional | A key-value applied only to the configured bid. This value is optional. Strings separated by semicolon. | `car=mercedes;car=audi;` | `string` | | `player` | optional | Object containing video targeting parameters. See [Video Object](#ra-video-object) for details. | `player: {init: 'open', end: 'close', skin: 'dark'}` | `object` | + - ### Video Object {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/rise.md b/dev-docs/bidders/rise.md index 01585fbb75..c873396d55 100644 --- a/dev-docs/bidders/rise.md +++ b/dev-docs/bidders/rise.md @@ -1,62 +1,99 @@ --- layout: bidder title: Rise -description: Prebid Bidder Adaptor +description: Prebid Rise Bidder Adapter +multiformat_supported: will-bid-on-any pbjs: true biddercode: rise -media_types: video +media_types: banner, video schain_supported: true -gdpr_supported: true +coppa_supported: true +pbs: true +pbs_app_supported: true +tcfeu_supported: true +gpp_supported: true +gpp_sids: tcfeu, usstate_all, usp usp_supported: true floors_supported: true userIds: all -fpd_supported: true gvl_id: 1043 +sidebarType: 1 --- ### Note -The Rise adapter requires setup and approval. Please reach out to prebid-rise-engage@risecodes.com to setup an Rise account. +The Rise adapter requires setup and approval. Please reach out to [prebid-rise-engage@risecodes.com] to setup an Rise account. ### Bid Parameters -#### Video +#### Banner, Video {: .table .table-bordered .table-striped } | Name | Scope | Type | Description | Example | ---- | ----- | ---- | ----------- | ------- -| `org` | required | String | Rise publisher Id provided by your Rise representative | "56f91cd4d3e3660002000033" +| `org` | required | String | Rise publisher Id provided by your Rise representative | "1234567890abcdef12345678" | `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 | `placementId` | optional | String | A unique placement identifier | "12345678" | `testMode` | optional | Boolean | This activates the test mode | false +| `rtbDomain` | optional | String | Sets the seller end point | "www.test.com" +| `is_wrapper` | private | Boolean | Please don't use unless your account manager asked you to | false ## Example + ```javascript -var adUnits = [ - { +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'rise', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } + }] + }, + { code: 'dfp-video-div', - sizes: [[640, 480]], + sizes: [ + [640, 480] + ], mediaTypes: { - video: { - playerSize: [[640, 480]], - context: 'instream' - } + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } }, bids: [{ - bidder: 'rise', - params: { - org: '56f91cd4d3e3660002000033', // Required - floorPrice: 5.00, // Optional - placementId: '12345678', // Optional - testMode: false // Optional - } + bidder: 'rise', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } }] - } - ]; + } +]; ``` ### Configuration + Rise recommends setting UserSync by iframe for monetization. ### Versions + Prebid versions 5.0-5.3 are not supported +Banner >= 6.14.0 diff --git a/dev-docs/bidders/risexchange.md b/dev-docs/bidders/risexchange.md new file mode 100644 index 0000000000..1d1de616f5 --- /dev/null +++ b/dev-docs/bidders/risexchange.md @@ -0,0 +1,98 @@ +--- +layout: bidder +title: RiseXChange +description: Prebid RiseXChange Bidder Adapter +multiformat_supported: will-bid-on-any +pbjs: true +biddercode: risexchange +media_types: banner, video +schain_supported: true +coppa_supported: true +pbs: false +tcfeu_supported: true +gpp_supported: true +gpp_sids: tcfeu, usstate_all, usp +usp_supported: true +floors_supported: true +userIds: all +gvl_id: 1043 +sidebarType: 1 +--- + +### Note + +The RiseXChange adapter requires setup and approval. Please reach out to [prebid-rise-engage@risecodes.com] to setup an account. + +### Bid Parameters + +#### Banner, Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | RiseXChange publisher Id | "1234567890abcdef12345678" +| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false +| `rtbDomain` | optional | String | Sets the seller end point | "www.test.com" +| `is_wrapper` | private | Boolean | Please don't use unless your account manager asked you to | false + +## Example + +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'risexchange', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'risexchange', + params: { + org: '1234567890abcdef12345678', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false, // Optional, + rtbDomain: 'www.test.com' //Optional + } + }] + } +]; +``` + +### Configuration + +We recommend setting UserSync by iframe for monetization. + +### Versions + +Prebid versions 5.0-5.3 are not supported +Banner >= 6.14.0 diff --git a/dev-docs/bidders/rixengine.md b/dev-docs/bidders/rixengine.md new file mode 100644 index 0000000000..be1b9d6f8a --- /dev/null +++ b/dev-docs/bidders/rixengine.md @@ -0,0 +1,51 @@ +--- +layout: bidder +title: RixEngine +description: Prebid RixEngine Bidder Adapter +biddercode: rixengine +tcfeu_supported: false +coppa_supported: true +schain_supported: false +media_types: banner +safeframes_ok: false +deals_supported: false +pbjs: true +pbs: false +pbs_app_supported: false +prebid_member: true +userIds: sharedId +sidebarType: 0 +multiformat_supported: false +--- + +### Note + +The RixEngine Bidding adapter requires setup before beginning. Please contact the RixEngine team . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------|----------|-----------------------------------------------------------------------------|-------------|----------| +| endpoint| required |The endpoint created on RixEngine platform, please get them from the platform| [http://demo.svr.rixengine.com/rtb](http://demo.svr.rixengine.com/rtb) | string | +| sid | required |The sid created on RixEngine platform, please get them from the platform | '36540' | string | +| token | required |The token created on RixEngine platform, please get them from the platform | '1e05a767930d7d96ef6ce16318b4ab99' | string | + +### Test Parameters + +```javascript +var adUnits = [ +{ + sizes: [ + [300, 250] // a display size + ], + bids: [{ + bidder: 'rixengine', + params: { + endpoint: 'http://demo.svr.rixengine.com/rtb', // required + token: '1e05a767930d7d96ef6ce16318b4ab99', // required + sid: '36540', // required + } + }] +}]; +``` diff --git a/dev-docs/bidders/rockyou.md b/dev-docs/bidders/rockyou.md index f060d9891d..3658b53063 100644 --- a/dev-docs/bidders/rockyou.md +++ b/dev-docs/bidders/rockyou.md @@ -5,6 +5,7 @@ description: PreBid RockYou Bidder Adapter biddercode: rockyou pbjs: true media_types: video +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/roundel.md b/dev-docs/bidders/roundel.md index fed8e9a1f5..02e846086d 100644 --- a/dev-docs/bidders/roundel.md +++ b/dev-docs/bidders/roundel.md @@ -10,16 +10,18 @@ userIds: identityLink, netId, fabrickId, zeotapIdPlus pbs_app_supported: true schain_supported: true coppa_supported: true -gdpr_supported: true +tcfeu_supported: true usp_supported: true media_types: banner, video gvl_id: 10 prebid_member: yes +sidebarType: 1 --- ## Overview -Roundel is an aliased bidder for Index Exchange and must be configured alongside the [IdentityLink](/dev-docs/modules/userId.html#identitylink) user ID module. + +Roundel is an aliased bidder for Index Exchange and must be configured alongside the [IdentityLink](/dev-docs/modules/userId.html#identitylink) user ID module. ## Bid Params + Bidder params for roundel follow the same structure as the Index Exchange bidder. Please reference configuration examples [here](/dev-docs/bidders/ix). - diff --git a/dev-docs/bidders/rtbanalytica.md b/dev-docs/bidders/rtbanalytica.md index 3718ed244b..f1b6ffb85f 100644 --- a/dev-docs/bidders/rtbanalytica.md +++ b/dev-docs/bidders/rtbanalytica.md @@ -2,19 +2,28 @@ layout: bidder title: RtbAnalytica description: RtbAnalytica Bidder Adaptor -pbjs: true -pbs: true biddercode: rtbanalytica -aliasCode : adkernel +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The RtbAnalytica bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/rtbdemand.md b/dev-docs/bidders/rtbdemand.md deleted file mode 100644 index 77859838e8..0000000000 --- a/dev-docs/bidders/rtbdemand.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: Rtbdemand bidder -description: Prebid Rtbdemand Media Bidder Adapter -top_nav_section: dev_docs -nav_section: reference -pbjs: true -biddercode: rtbdemand -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-------------------------------------|---------------------------|----------| -| `zoneid` | required | The ad zone or tag specific ID | `'9999'` | `string` | -| `floor` | optional | The floor CPM price for the request | `0.1234` | `float` | -| `server` | optional | Bidder domain | `'bidding.rtbdemand.com'` | `string` | diff --git a/dev-docs/bidders/rtbdemand_com.md b/dev-docs/bidders/rtbdemand_com.md new file mode 100644 index 0000000000..9974bb7bf5 --- /dev/null +++ b/dev-docs/bidders/rtbdemand_com.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: RtbDemand.com +description: Prebid RtbDemand.com Bidder Adaptor +biddercode: rtbdemand_com +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The RtbDemand.com bidding adaptor requires setup and approval before beginning. Please reach out to for more details + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | Our Host | `' cpm.rtbdemand.com'` | `string` | +| `zoneId` | required | Example RTB zone id | `12345` | `integer` | diff --git a/dev-docs/bidders/rtbdemandadk.md b/dev-docs/bidders/rtbdemandadk.md deleted file mode 100644 index 76fda18e01..0000000000 --- a/dev-docs/bidders/rtbdemandadk.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Rtbdemandadk -description: Prebid RtbdemandAdk Bidder Adaptor -pbjs: true -biddercode: rtbdemandadk ---- - -### Note: - -The RtbdemandAdk Bidding adaptor requires setup and approval before beginning. Please reach out to for more details - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------|----------|-----------------------|---------------------------|----------| -| `host` | required | Ad network's RTB host | `'cpm.metaadserving.com'` | `string` | -| `zoneId` | required | RTB zone id | `'30164'` | `string` | diff --git a/dev-docs/bidders/rtbhouse.md b/dev-docs/bidders/rtbhouse.md index a2a39bfd43..9b819d39b5 100644 --- a/dev-docs/bidders/rtbhouse.md +++ b/dev-docs/bidders/rtbhouse.md @@ -2,7 +2,9 @@ layout: bidder title: RTBHouse description: Prebid RTB House Bidder Adapter -gdpr_supported: true +gvl_id: 16 +tcfeu_supported: true +dsa_supported: true pbjs: true pbs: true biddercode: rtbhouse @@ -13,6 +15,8 @@ media_types: banner, native schain_supported: true userIds: id5Id, identityLink, pubProvidedId pbs_app_supported: true +ortb_blocking_supported: partial +sidebarType: 1 --- @@ -26,9 +30,93 @@ pbs_app_supported: true | `bidfloor` | optional | Minimal CPM value | `0.01` | `float` | | `channel` | optional | Inventory channel identifier, limited to 50 characters | `Partner 1 - News` | `string` | - -### Please note: +#### Please note * Since 4.43 the bidfloor param will be ignored if a value is specified via floor module. * The channel param is available starting from Prebid 6.6.0. Please reach your RTBHouse representative for details on how to enable and use the channel param. + +### ORTB Blocking + +RTB House supports blocking advertisers in `badv` and categories in `bcat` parameters. +The blocked advertisers/categories list has no length limitation, but response timeout is more likely to occur as the number of entries grow. +Blocked advertisers list (`badv`) is an array of domains as strings. +Blocked categories list (`bcat`) is an array of IAB categories as strings. + +For example: + +#### Globally defined ORTB Blocking + +```javascript +pbjs.setConfig({ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } +)}; +``` + +#### ORTB Blocking specific only to rtbhouse bidder + +```javascript +pbjs.setBidderConfig({ + bidders: ['rtbhouse'], + config:{ + ortb2: { + badv: ["domain1.com", "domain2.com"], + bcat: ["IAB23-1", "IAB23-5", "IAB25-3", "IAB25-2"] + } + } +}); +``` + +### Setting up the Prebid Server Adapter + +If you’re a Prebid Server host company looking to enable the RTB House server-side adapter, you'll need to contact . They will guide you through the process. Do not use the default bidder config file as it will require custom partner code to be entered. It will be provided by RTB House. + +### Protected Audience API (FLEDGE) support + +There’s an option to receive demand for Protected Audience API (FLEDGE/PAAPI) +ads using RTB House bid adapter. +Prebid’s [fledgeForGpt](https://docs.prebid.org/dev-docs/modules/fledgeForGpt.html) +module and Google Ad Manager is currently required. + +The following steps should be taken to setup Protected Audience for RTB House: + +1. Reach out to your RTB House representative for setup coordination. + +2. Build and enable FLEDGE module as described in +[fledgeForGpt](https://docs.prebid.org/dev-docs/modules/fledgeForGpt.html) +module documentation. + + a. Make sure to enable RTB House bidder to participate in FLEDGE. If there are any other bidders to be allowed for that, add them to the **bidders** array: + + ```javascript + pbjs.setBidderConfig({ + bidders: ["rtbhouse"], + config: { + fledgeEnabled: true + } + }); + ``` + + b. If you as a publisher have your own [decisionLogicUrl](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) + you may utilize it by setting up a dedicated `fledgeConfig` object: + + ```javascript + pbjs.setBidderConfig({ + bidders: ["rtbhouse"], + config: { + fledgeEnabled: true, + fledgeConfig: { + seller: 'https://seller.domain', + decisionLogicUrl: 'https://seller.domain/decisionLogicFile.js', + sellerTimeout: 100 + } + } + }); + ``` + + The `decisionLogicUrl` must be in the same domain as `seller` and has to respond with `X-Allow-FLEDGE: true` http header. + + `sellerTimeout` is optional, defaults to 50 as per spec, will be clamped to 500 if greater. diff --git a/dev-docs/bidders/rtbsape.md b/dev-docs/bidders/rtbsape.md index de4dcbe73a..4f5d7ff9ae 100644 --- a/dev-docs/bidders/rtbsape.md +++ b/dev-docs/bidders/rtbsape.md @@ -5,13 +5,13 @@ description: Prebid RtbSape Bidder Adaptor pbjs: true biddercode: rtbsape media_types: banner, video +sidebarType: 1 --- -### Note: +### Note The RtbSape Header Bidding adaptor requires setup and approval before beginning. Please reach out to for more details. - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/rtbsolutions.md b/dev-docs/bidders/rtbsolutions.md deleted file mode 100644 index 994d9693fc..0000000000 --- a/dev-docs/bidders/rtbsolutions.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: bidder -title: RTB Solutions -description: Prebid RTB Solutions Bidder Adaptor -pbjs: true -biddercode: rtbsolutions -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------|----------|-------------|---------|----------| -| `blockId` | required | Block ID assigned in settings | | `string` | -| `s1` | optional | Sub 1 | | `string` | -| `s2` | optional | Sub 2 | | `string` | -| `s3` | optional | Sub 3 | | `string` | -| `s4` | optional | Sub 4 | | `string` | - diff --git a/dev-docs/bidders/rubicon.md b/dev-docs/bidders/rubicon.md index b47744cb4c..c701ed3427 100644 --- a/dev-docs/bidders/rubicon.md +++ b/dev-docs/bidders/rubicon.md @@ -1,14 +1,16 @@ --- layout: bidder title: Rubicon Project -description: Rubicon Project Prebid Bidder Adaptor +description: Rubicon Project Prebid Bidder Adapter biddercode: rubicon -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true +gpp_sids: tcfeu, usnat, usstate_all, usp usp_supported: true coppa_supported: true schain_supported: true floors_supported: true -media_types: banner, video +media_types: banner, video, native userIds: all prebid_member: true safeframes_ok: true @@ -17,12 +19,16 @@ pbjs: true pbs: true pbs_app_supported: true fpd_supported: true +ortb_blocking_supported: partial gvl_id: 52 +multiformat_supported: will-bid-on-one +privacy_sandbox: paapi, topics +sidebarType: 1 --- ### Registration -For both Prebid.js and Prebid Server, the Rubicon Project adapter requires setup and approval from the Magnite team, even for existing accounts. Please reach out to your account team or globalsupport@magnite.com for more information. +For both Prebid.js and Prebid Server, the Rubicon Project adapter requires setup and approval from the Magnite team, even for existing accounts. Please reach out to your account manager for more information. ### Bid Params @@ -30,30 +36,34 @@ For both Prebid.js and Prebid Server, the Rubicon Project adapter requires setup | Name | Scope | Description | Example | Type | |-------------|---------|--------------------|-----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|------------------| | `accountId` | required | The publisher account ID | `4934` | `integer` | -| `siteId` | required | The site ID | `13945` | `integer` | -| `zoneId` | required | The zone ID | `23948` | `integer` | +| `siteId` | required | A unique ID for your site | `13945` | `integer` | +| `zoneId` | required | A unique ID for your site's ad placements | `23948` | `integer` | | `position` | optional | Set the page position. Valid values are "atf" and "btf". | `'atf'` | `string` | | `userId` | optional | Site-specific user ID may be reflected back in creatives for analysis. Note that userId needs to be the same for all slots. | `'12345abc'` | `string` | | `floor` | optional | Sets the global floor -- no bids will be made under this value. | `0.50` | `float` | | `latLong` | optional | Sets the latitude and longitude for the visitor (avail since PBJS 1.10) | `[40.7608, 111.8910]` | `Array` | -| `inventory` | optional | See below for details on First Party Data. In release 4.29 and earlier, this parameter allows the definition of an object defining arbitrary key-value pairs concerning the page for use in targeting. The values must be arrays. | `{"rating":["5-star"], "prodtype":["tech","mobile"]}` | `object` | -| `visitor` | optional | See below for details on First Party Data. In release 4.29 and earlier, this parameter allows the definition of an object defining arbitrary key-value pairs concerning the visitor for use in targeting. The values must be arrays. | `{"ucat":["new"], "search":["iphone"]}` | `object` | -| `keywords` | optional | See below for details on First Party Data. In release 4.29 and earlier, this can be used to influence reports for client-side display. To get video or server-side reporting, please use First Party data or the inventory/visitor parameters. | `['travel', 'tourism']` | `Array` | -| `video` | required for video | Video targeting parameters. See the [video section below](#rubicon-video). | `{"language": "en"}` | `object` | +| `inventory` | optional | See below for details on First Party Data. In release 4.29 and earlier, this parameter allows the definition of an object defining arbitrary key-value pairs concerning the page for use in targeting. The values must be arrays of strings. | `{"rating":["5-star"], "prodtype":["tech","mobile"]}` | `object` | +| `visitor` | optional | See below for details on First Party Data. In release 4.29 and earlier, this parameter allows the definition of an object defining arbitrary key-value pairs concerning the visitor for use in targeting. The values must be arrays of strings. | `{"ucat":["new"], "search":["iphone"]}` | `object` | +| `keywords` | optional | See below for details on First Party Data. In release 4.29 and earlier, this can be used to influence reports for client-side display. To get video or server-side reporting, please use First Party data or the inventory/visitor parameters. | `["travel", "tourism"]` | `Array` | +| `video` | required for video | Video targeting parameters. See the [video section below](#mediatypesvideo). | `{"language": "en"}` | `object` | +| pchain | optional | deprecated option that was an early alternative to schain | "GAM:11111-reseller1:22222" | string | +| `bidonmultiformat` | optional | By default, the Magnite exchange will bid on only one media type in this order: video, banner, native. Setting this flag to true will cause it to bid on all mediatypes. | `boolean` | `true` | #### First Party Data In release 4.30 and later, publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: -- ortb2.site.ext.data.* -- ortb2.site.keywords -- ortb2.site.content.data[] -- ortb2.user.ext.data.* -- ortb2.user.data[] + +* ortb2.site.ext.data.* +* ortb2.site.keywords +* ortb2.site.content.data[] +* ortb2.user.ext.data.* +* ortb2.user.data[] With regards to Contextual and Audience segments, the Magnite exchange supports the IAB standard taxonomies. See [the segment management user guide](https://resources.rubiconproject.com/resource/publisher-resources/segment-management-user-guide/) for more information. Example first party data that's available to all bidders and all adunits: -``` + +```javascript pbjs.setConfig({ ortb2: { site: { @@ -76,7 +86,8 @@ pbjs.setConfig({ ``` Example of first party data available only to the Rubicon Project bidder. Applies across all ad units. -``` + +```javascript pbjs.setBidderConfig({ bidders: ["rubicon"], config: { @@ -102,7 +113,8 @@ pbjs.setBidderConfig({ ``` For Prebid.js 4.29 and before, use the bidder specific AdUnit parameters noted above: -``` + +```javascript var adUnit = { ... bids: [{ @@ -122,44 +134,66 @@ var adUnit = { }; ``` -#### mediaTypes.video +#### ORTB Blocking -The following video parameters are supported here so publishers may fully declare their video inventory: +Rubicon supports passing up to 50 domains in `badv` for anything hitting Prebid Server, which includes these scenarios: + +1. client-side video +2. s2sConfig +3. App +4. AMP + +For example: + +```javascript +pbjs.setConfig({ + ortb2: { + badv: ["domain1.com", "domain2.com"] + } +}); +``` + +### Media Types + +#### Video + +##### mediaTypes.video + +The following video parameters are supported here so publishers may fully declare their video inventory. These apply to both instream and outstream. {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| -| context | required | instream or outstream |"outstream" | string | +| context | required | instream or outstream |"outstream" | string | | playerSize| required | width, height of the player in pixels | [640,360] - will be translated to w and h in bid request | array | | mimes | required | List of content MIME types supported by the player (see openRTB v2.5 for options) | ["video/mp4"]| array| | protocols | required | Supported video bid response protocol values
      1: VAST 1.0
      2: VAST 2.0
      3: VAST 3.0
      4: VAST 1.0 Wrapper
      5: VAST 2.0 Wrapper
      6: VAST 3.0 Wrapper
      7: VAST 4.0
      8: VAST 4.0 Wrapper | [2,3,5,6] | array| -| api | required | Supported API framework values:
      1: VPAID 1.0
      2: VPAID 2.0
      3: MRAID-1
      4: ORMMA
      5: MRAID-2 | [2] | array | | linearity | required | OpenRTB2 linearity. 1: linear (in-stream ad), 2: non-linear (overlay ad) | 1 | integer | | maxduration | recommended | Maximum video ad duration in seconds. | 30 | integer | | minduration | recommended | Minimum video ad duration in seconds | 6 | integer | | playbackmethod | recommended | Playback methods that may be in use. Only one method is typically used in practice. (see openRTB v2.5 section 5.10 for options)| [2]| array | +| api | optional | Supported API framework values:
      1: VPAID 1.0
      2: VPAID 2.0
      3: MRAID-1
      4: ORMMA
      5: MRAID-2 | [2] | array | | skip | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes. | 1 | integer | | skipafter| optional | Number of seconds a video must play before skipping is enabled; only applicable if the ad is skippable. | 6 | integer| | minbitrate | optional | Minimum bit rate in Kbps. | 300 | integer | | maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | integer | -| startdelay* | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements.
      >0: Mid-Roll (value indicates start delay in second)
      0: Pre-Roll
      -1: Generic Mid-Roll
      -2: Generic Post-Roll | 0 | integer | -| placement* | recommended | Placement type for the impression. (see openRTB v2.5 section 5.9 for options) | 1 | integer | -| | | | | | +| startdelay | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements.
      >0: Mid-Roll (value indicates start delay in second)
      0: Pre-Roll
      -1: Generic Mid-Roll
      -2: Generic Post-Roll | 0 | integer | +| placement | recommended | Placement type for the impression. (see OpenRTB v2.5 section 5.9 for options) | 1 | integer | +| plcmt | recommended | Placement type for the impression. (See [OpenRTB v2.6](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/develop/AdCOM%20v1.0%20FINAL.md) Plcmt Subtypes - Video) | 1 | integer | - -#### bids.params.video +##### bids.params.video The following Rubicon Project-specific video parameters are supported: {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| -| `size_id` | optional for Prebid.js, required for Prebid Server | Integer indicating the Rubicon Project video ad format ID. If not set, Prebid.js can infer from mediaTypes.video.context, placement, startDelay | `201` | `integer` | +| `size_id` | optional | Integer indicating the Rubicon Project video ad format ID. If not set, will be inferred from mediaTypes.video.context, placement, startDelay | `201` | `integer` | | `language` | recommended | Indicates the language of the content video, in ISO 639-1/alpha2. Highly recommended for successful monetization for pre-, mid-, and post-roll video ads. Not applicable for interstitial and outstream. | `'en'` | `string` | Here's a video example for Prebid.js 2.5 or later: -``` +```javascript var videoAdUnit = { code: 'myVideoAdUnit', mediaTypes: { @@ -193,23 +227,22 @@ We recommend discussing video demand with your Magnite account representative. Lists of values are in the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) documentation as referenced above. - -#### Outstream Video +##### Outstream Video As of Prebid.js 4.37 Magnite's Rubicon Project adapter supports outstream video in two ways: using your own renderer or using ours. See the [Prebid.org Outstream documentation](/dev-docs/show-outstream-video-ads.html) for more information on using your own renderer. -#### Outstream Renderer +##### Outstream Renderer The Magnite outstream renderer is a JavaScript tag that will load our outstream video player and render when it is 50% or more in view, pause when it’s more than 50% out of view, and close when the ad has completed playing. The renderer appearance can be configured with the following parameters, all of them optional. If any parameter is missing, the default value will be used. All options are case-sensitive and unknown options will be ignored. Additional advanced options are available by calling your Magnite account representative. -``` +```javascript pbjs.setConfig({ rubicon: { rendererConfig: { align: 'center', // player placement: left|center|right (default is center) - position: 'append' // position relative to ad unit: append|prepend|before|after (default is after) + position: 'append', // position relative to ad unit: append|prepend|before|after (default is after) closeButton: true, // display 'Close' button (default is false) label: 'Advertisement', // custom text to display above the player (default is '-') collapse: true // remove the player from the page after ad playback (default is true) @@ -218,34 +251,94 @@ pbjs.setConfig({ }); ``` +#### Native + +Note: the client-side adapter supports native as of PBJS 7.39. + +We recommend using the ORTB Native spec 1.2, but do support versions 1.0 and 1.1. Here the parameters required for each version: -* The Rubicon Project adapter does not make concurrent banner and video requests. Instead, the adapter will send a video request if bids[].params.video is supplied, else a banner request will be made. +{: .table .table-bordered .table-striped } +| Native Version | Required Fields | +|----------------|-----------------| +| 1.0 and 1.1 | layout, adunit, assets | +| 1.2 | context, plcmttype, assets, eventtrackers. privacy is a recommended field. | + +Here's an example for Prebid.js 7.39 or later: -### Configuration +```javascript +var nativeAdUnit = { + code: 'myNativeAdUnit', + mediaTypes: { + native: { + sendTargetingKeys: false, + ortb: { + ver:"1.2", + context: 2, // required for 1.2 + plcmttype: 11, // required for 1.2 + privacy: 1, // recommended for 1.2 + assets: [{ + id: 1, + required: 1, + img: { + type: 3, + w: 150, + h: 50, + } + },{ + ... other assets ... + }], + eventtrackers: [{ // required for 1.2 + event:1, methods:[1,2] + }] + } + }, + bids: [{ + bidder: 'rubicon', + params: { + accountId: 7780, // replace params + siteId: 87184, + zoneId: 413290 + } + }] +}; +``` + +### Setting up the Prebid Server Adapter + +If you're a Prebid Server host company looking to enable the Rubicon server-side adapter, you'll need to contact your Magnite account team. They will provide: + +* a Magnite DV+ XAPI login and password that you'll place in the PBS config +* a partner code you can use for cookie-syncing with Magnite's service + +### Configuration Options #### Single-Request By default, the Rubicon Project adapter sends one request to rubiconproject.com for each AdUnit. For example, if there are 4 PBJS AdUnits defined on the page, you'll see 4 calls out to rubiconproject.com/fastlane.json. As of PBJS 1.12, the Rubicon Project adapter supports `Single Request` mode, where all AdUnit requests are made in a single call to rubiconproject.com. To turn this feature on, call `setConfig`: -``` + +```javascript pbjs.setConfig({ rubicon: {singleRequest: true} }); ``` -### Notes - -1) There can only be one siteId and zoneId in an AdUnit bid. To get bids on multiple sitesIds or zoneIds, just add more 'rubicon' entries in the bids array. -
      -2) Bids through the Rubicon Project Exchange are by default 'net'. For certain use cases it is possible for publishers to define a bid as either 'net' or 'gross'. In either case the Rubicon platform does not signal externally to other systems either bid state. +#### Net Revenue + +Bids through the Magnite Exchange are by default 'net'. For certain use cases it is possible for publishers to define a bid as either 'net' or 'gross'. In either case the Rubicon platform does not signal externally to other systems either bid state. For Prebid, the Rubicon Project bid adapter reports the revenue type as ‘gross’ by default before 2.35 and ‘net’ by default in 2.35 and later (as the vast majority of accounts are net and all new accounts are net). -It’s important to note that what the Rubicon Prebid bid adapter reports is not directly related to the setting with the Rubicon Project exchange. If you are a publisher who has set your Rubicon exchange revenue type set to ‘gross’ and you'd like the Rubicon bid adapter to also report 'gross', you can change the 2.35+ default 'net' setting in Prebid.js with: +It’s important to note that what the Rubicon Prebid bid adapter reports is not directly related to the setting with the Magnite exchange. If you are a publisher who has set your Magnite exchange revenue type set to ‘gross’ and you'd like the Rubicon bid adapter to also report 'gross', you can change the 2.35+ default 'net' setting in Prebid.js with: -``` +```javascript pbjs.setConfig({ rubicon: {netRevenue: false} }); ``` + +### Notes + +1. There can only be one siteId and zoneId in an AdUnit bid. To get bids on multiple sitesIds or zoneIds, just add more 'rubicon' entries in the bids array. +2. PAAPI and Topics support released in PBJS 8.23 diff --git a/dev-docs/bidders/rxrtb.md b/dev-docs/bidders/rxrtb.md index c506346d4c..3a0ff5b823 100644 --- a/dev-docs/bidders/rxrtb.md +++ b/dev-docs/bidders/rxrtb.md @@ -4,6 +4,7 @@ title: rxrtb description: Prebid rxrtb Bidder Adaptor pbjs: true biddercode: rxrtb +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/sa_lunamedia.md b/dev-docs/bidders/sa_lunamedia.md index 47a6a9b53a..17c4cd3438 100644 --- a/dev-docs/bidders/sa_lunamedia.md +++ b/dev-docs/bidders/sa_lunamedia.md @@ -6,18 +6,19 @@ biddercode: sa_lunamedia usp_supported: true schain_supported: true media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true pbjs: false pbs: true pbs_app_supported: true gvl_id: 998 enable_download: false -pbjs_version_notes: not ported to 5.x +sidebarType: 1 --- ### Prebid Server Bid Params + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------|----------|----------------------------------------------------------|------------|-----------| | `key` | required | Placement integration key | `'1234'` | `string` | -| `type` | optional | Supported values are `publisher` and `network`. | `'publisher'` | `string` | +| `type` | required | Supported values are `publisher` and `network`. | `'publisher'` | `string` | diff --git a/dev-docs/bidders/saambaa.md b/dev-docs/bidders/saambaa.md index ca38b82722..242b9cba9e 100644 --- a/dev-docs/bidders/saambaa.md +++ b/dev-docs/bidders/saambaa.md @@ -4,17 +4,19 @@ title: Saambaa description: Prebid Saambaa Bidder Adapter pbjs: true biddercode: saambaa +sidebarType: 1 --- -### Note: -For more information about Saambaa, please contact matt.voigt@saambaa.com +### Note + +For more information about Saambaa, please contact ### Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------------|----------|------------------|------------------------------------------|-------------------| -| `placement ` | required | | `'263'` | `string` | +| `placement` | required | | `'263'` | `string` | | `pubid` | required | | `'0cf8d6d643e13d86a5b6374148a4afac'` | `string` | | `size` | optional | | `'320x50'` | `string` | | `mimes` | optional | video only | `['video/mp4', 'application/javascript']`| `array of strings`| diff --git a/dev-docs/bidders/sara.md b/dev-docs/bidders/sara.md index de4014779c..b28c4062b8 100644 --- a/dev-docs/bidders/sara.md +++ b/dev-docs/bidders/sara.md @@ -4,6 +4,7 @@ title: SARA description: SARA Bidder Adapter pbjs: true biddercode: sara +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/scattered.md b/dev-docs/bidders/scattered.md new file mode 100644 index 0000000000..a1330f453b --- /dev/null +++ b/dev-docs/bidders/scattered.md @@ -0,0 +1,48 @@ +--- +layout: bidder +title: Scattered +description: Scattered Prebid Bidder Adaptor +biddercode: scattered +media_types: banner +coppa_supported: false +tcfeu_supported: true +usp_supported: false +prebid_member: false +pbjs: true +pbs: false +schain_supported: false +userIds: none +gvl_id: 1179 +floors_supported: false +fpd_supported: false +deals_supported: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: false +safeframes_ok: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| -------------- | -------- | ------------- | --------------- | --------- | +| `bidderDomain` | required | Bidder domain | `"Leaderboard"` | `string` | +| `test` | optional | Is test bid | 0 | `integer` | + +### OpenRTB request config + +OpenRTB bid request `app`, `site`, `device` properties configured using prebid config. + +``` javascript +pbjs.setConfig({ + ortb2: { + site: { + id: '876', + publisher: { + domain: 'publisher1.eu' + } + } + } +}); +``` diff --git a/dev-docs/bidders/screencore.md b/dev-docs/bidders/screencore.md new file mode 100644 index 0000000000..2aef78ac89 --- /dev/null +++ b/dev-docs/bidders/screencore.md @@ -0,0 +1,35 @@ +--- +layout: bidder +title: Screencore +description: Prebid Screencore Bidder Adaptor +biddercode: screencore +tcfeu_supported: true +usp_supported: true +coppa_supported: true +schain_supported: true +media_types: banner, video, native +safeframes_ok: true +deals_supported: true +pbs: true +sidebarType: 1 +floors_supported: true +prebid_member: false +fpd_supported: false +gvl_id: none +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +userIds: all +--- + +### Note + +The Screencore Bidding adapter requires setup before beginning. Please contact us at [connect@screencore.io](mailto:connect@screencore.io). +Screencore will bid on first impression in request. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | required | placement id | `'hash'` | `string` | +| `accountId` | required | account id | `'id'` | `string` | diff --git a/dev-docs/bidders/seedingAlliance.md b/dev-docs/bidders/seedingAlliance.md index 0683e3a3d8..d99a4fdd2f 100644 --- a/dev-docs/bidders/seedingAlliance.md +++ b/dev-docs/bidders/seedingAlliance.md @@ -1,11 +1,25 @@ --- layout: bidder -title: SeedingAlliance -description: Prebid SeedingAlliance Bidder Adaptor -pbjs: true +title: Seeding Alliance +description: Prebid Seeding Alliance Bidder Adapter biddercode: seedingAlliance -media_types: native -gdpr_supported: true +tcfeu_supported: true +gvl_id: 371 +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +userId: none +media_types: banner, native +safeframes_ok: true +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: true +pbs: true +pbs_app_supported: false +prebid_member: false +sidebarType: 1 --- ### Bid params @@ -14,4 +28,5 @@ gdpr_supported: true | Name | Scope | Description | Example | Type | |-------------|----------|----------------------|--------------------|-----------| | `adUnitId` | required | ID of the Ad Unit | `8ao` | `string` | +| `accountId` | optional | Your identifier for the account (Prebid Server only) | `12345` | `string` | | `url` | optional | URL from the Page | `example.tld` | `string` | diff --git a/dev-docs/bidders/seedtag.md b/dev-docs/bidders/seedtag.md index 17b7c1b7b4..768fae2ecd 100644 --- a/dev-docs/bidders/seedtag.md +++ b/dev-docs/bidders/seedtag.md @@ -3,10 +3,17 @@ layout: bidder title: seedtag description: Prebid Seedtag Bidder Adapter pbjs: true -gdpr_supported: true +tcfeu_supported: true +usp_supported: true +schain_supported: true +safeframes_ok: true gvl_id: 157 media_types: banner, video biddercode: seedtag +coppa_supported: true +ortb_blocking_supported: partial +sidebarType: 1 +gpp_supported: true --- ### Note @@ -14,7 +21,6 @@ biddercode: seedtag Please reach out to your seedtag account team before using this plugin. The publisher id 0000-0000-01 returns demo responses. - ### Bid Params {: .table .table-bordered .table-striped } @@ -22,32 +28,63 @@ The publisher id 0000-0000-01 returns demo responses. |-------------------|---------------------|--------------------------------------------------------------------------------|-----------------------|----------| | `publisherId` | required | The publisher id. | 0000-0000-01 | `string` | | `adUnitId` | required | The adunit id. | 00000 | `string` | -| `placement` | required | Adunit placement, posibles values: banner, video, inImage, inScreen, inArticle | banner | `string` | -| `adPosition` | optional | 0 - Below the Fold, 1 - Above the Fold | 0 | `number` | -| `video` | optional for video | Video targeting parameters. See the video section below. | {} | `object` | +| `placement` | required | Adunit placement, posibles values: inScreen, inArticle | inScreen | `string` | + +### InScreen example +The integration for Seedtag uses banner mediaTypes for all types of creatives (display/video) -### Video Param +```js +const adUnits = [ + { + code: '/21804003197/prebid_test_320x100', + mediaTypes: { + banner: { + sizes: [[320, 100]] + } + }, + bids: [ + { + bidder: 'seedtag', + params: { + publisherId: '0000-0000-01', // required + adUnitId: '0000', // required + placement: 'inScreen', // required + } + } + ] + } +] +``` -All parameters are optional and correspond to the the OpenRTB 2.5 specification. +### InArticle example -{: .table .table-bordered .table-striped } -| Name | Example | -|---------------------|---------------| -| `mimes` | ['video/mp4'] | -| `minduration` | 5 | -| `maxduration` | 60 | -| `boxingallowed` | 1 | -| `skip` | 1 | -| `startdelay` | 1 | -| `linearity` | 1 | -| `battr` | [1, 2] | -| `maxbitrate` | 10 | -| `playbackmethod` | [1] | -| `delivery` | [1] | -| `placement` | 1 | +The integration for Seedtag uses banner mediaTypes for all types of creatives (display/video) -### Banner example +```js +const adUnits = [ + { + code: '/21804003197/prebid_test_300x250', + mediaTypes: { + banner: { + sizes: [[300, 250], [1, 1]] + } + }, + bids: [ + { + bidder: 'seedtag', + params: { + publisherId: '0000-0000-01', // required + adUnitId: '0000', // required + placement: 'inArticle', // required + } + } + ] + } +] +``` + +## InBanner example ```js const adUnits = [ @@ -64,8 +101,7 @@ const adUnits = [ params: { publisherId: '0000-0000-01', // required adUnitId: '0000', // required - placement: 'banner', // required - adPosition: 0 // optional + placement: 'inBanner', // required } } ] @@ -73,7 +109,7 @@ const adUnits = [ ] ``` -### Video InStream Example +## inStream example ```js var adUnits = [{ @@ -81,7 +117,20 @@ var adUnits = [{ mediaTypes: { video: { context: 'instream', // required - playerSize: [600, 300] // required + playerSize: [640, 360], // required + // Video object as specified in OpenRTB 2.5 + mimes: ['video/mp4'], // recommended + minduration: 5, // optional + maxduration: 60, // optional + boxingallowed: 1, // optional + skip: 1, // optional + startdelay: 1, // optional + linearity: 1, // optional + battr: [1, 2], // optional + maxbitrate: 10, // optional + playbackmethod: [1], // optional + delivery: [1], // optional + placement: 1, // optional } }, bids: [ @@ -90,23 +139,7 @@ var adUnits = [{ params: { publisherId: '0000-0000-01', // required adUnitId: '0000', // required - placement: 'video', // required - adPosition: 0, // optional - // Video object as specified in OpenRTB 2.5 - video: { - mimes: ['video/mp4'], // recommended - minduration: 5, // optional - maxduration: 60, // optional - boxingallowed: 1, // optional - skip: 1, // optional - startdelay: 1, // optional - linearity: 1, // optional - battr: [1, 2], // optional - maxbitrate: 10, // optional - playbackmethod: [1], // optional - delivery: [1], // optional - placement: 1, // optional - } + placement: 'inStream', // required } } ] diff --git a/dev-docs/bidders/segmento.md b/dev-docs/bidders/segmento.md deleted file mode 100644 index b6ed585a0d..0000000000 --- a/dev-docs/bidders/segmento.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: Segmento -description: Prebid Segmento Bidder Adaptor -pbjs: true -biddercode: segmento -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------------------------------------------|---------|----------| -| `placementId` | required | Placement id will be generated by Segmento DSP. | `548` | `number` | diff --git a/dev-docs/bidders/sekindoUM.md b/dev-docs/bidders/sekindoUM.md deleted file mode 100644 index a51d4d63e4..0000000000 --- a/dev-docs/bidders/sekindoUM.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: SekindoUM -description: Prebid SekindoUM Bidder Adaptor -pbjs: true -biddercode: sekindoUM -media_types: video -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------|----------|-------------|---------|----------| -| `spaceId` | required | | | `string` | diff --git a/dev-docs/bidders/selectmedia.md b/dev-docs/bidders/selectmedia.md index 9b582590ed..de8fd31d0a 100644 --- a/dev-docs/bidders/selectmedia.md +++ b/dev-docs/bidders/selectmedia.md @@ -3,9 +3,13 @@ layout: bidder title: Select Media Display description: Prebid Select Media Bidder Adapter pbjs: true +media_types: banner,video +tcfeu_supported: true +gpp_supported: true biddercode: selectmedia aliasCode: adtelligent -media_types: banner, video +sidebarType: 1 +gvl_id: 775 --- ### Bid params @@ -15,9 +19,9 @@ media_types: banner, video |-------|----------|---------------------------------|----------|-----------| | `aid` | required | The traffic source ID | `232131` | `integer` | - ### Test Parameters -``` + +``` javascript var adUnits = [ // Video instream adUnit diff --git a/dev-docs/bidders/selectmediavideo.md b/dev-docs/bidders/selectmediavideo.md index b83990023e..ac048305e0 100644 --- a/dev-docs/bidders/selectmediavideo.md +++ b/dev-docs/bidders/selectmediavideo.md @@ -6,14 +6,17 @@ pbjs: true biddercode: selectmediavideo aliasCode: aniview media_types: banner, video -gdpr_supported: true +gvl_id: 780 (aniview) +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true +sidebarType: 1 --- -### Note: -For more information about [SelectMedia](https://www.selectmedia.asia/), please contact info@selectmedia.asia. +### Note + +For more information about [SelectMedia](https://www.selectmedia.asia/), please contact . ### Bid Params @@ -24,8 +27,9 @@ For more information about [SelectMedia](https://www.selectmedia.asia/), please | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` -videoAdUnit = [ + +```javascript +const videoAdUnit = [ { code: 'video1', mediaTypes: { diff --git a/dev-docs/bidders/setupad.md b/dev-docs/bidders/setupad.md new file mode 100644 index 0000000000..a6ce0dad27 --- /dev/null +++ b/dev-docs/bidders/setupad.md @@ -0,0 +1,50 @@ +--- +layout: bidder +title: Setupad +description: Setupad bid adapter +gvl_id: 1241 +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: false +dchain_supported: false +safeframes_ok: false +deals_supported: false +floors_supported: false +fpd_supported: false +pbs_app_supported: false +pbjs: true +pbs: false +biddercode: setupad +media_types: banner +prebid_member: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------+-------+-----------------------------------+-----------+---------| +| `placement_id` | required | Placement ID, provided by setupad | `'12345'` | String | +| `account_id` | optional | Account ID, provided by setupad | `'12345'` | String | + +### Additional options + +#### User Sync + +Add the following code to activate user sync. Setupad advises enabling user syncing through iFrames, as it significantly improves partners' user match rates and increases the Setupad bid rate and bid price. Be sure to call `pbjs.setConfig()` only once. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: ['setupad'], + filter: 'include', + }, + }, + }, +}); +``` diff --git a/dev-docs/bidders/sharethrough.md b/dev-docs/bidders/sharethrough.md index 94d783ef0e..f3673a5291 100644 --- a/dev-docs/bidders/sharethrough.md +++ b/dev-docs/bidders/sharethrough.md @@ -3,30 +3,86 @@ layout: bidder title: Sharethrough biddercode: sharethrough description: Prebid Sharethrough Adaptor -gdpr_supported: true +tcfeu_supported: true coppa_supported: true +gpp_supported: true floors_supported: true -media_types: video +media_types: banner, video, native safeframes_ok: true schain_supported: true -userIds: pubCommonId, unifiedId, identityLink, id5Id, sharedId, liveIntentId +gvl_id: 80 +userIds: all usp_supported: true -fpd_supported: true pbjs: true pbs: true +prebid_member: true +fpd_supported: true +ortb_blocking_supported: partial +sidebarType: 1 --- -### Note: +### Note + The Sharethrough bidder adapter requires additional setup and approval from the Sharethrough Integrations team. Please reach out to your account manager for more information to start using it. ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------|----------------------| -| `bidfloor` | optional | The floor price, or minimum amount, a publisher will accept for an impression, given in CPM in USD. | `1.00` | `float` | -| `iframe` | optional | If `true`, the ad will render in an iframe. Defaults to `false`. | `true` | `boolean` | -| `iframeSize`| optional | `[width, height]` If provided, use this size for the iframe size. Only applicable if `iframe` is `true`. If omitted, the largest size from the ad unit sizes array will be used. | `[300, 250]` | `[integer, integer]` | -| `bcat` | optional | Array of blocked IAB Categories | `['IAB1-2', 'IAB1-3']` | `string[]` | -| `badv` | optional | Array of blocked Advertisers by their domains | `['ford.com', 'pepsi.com']` | `string[]` | -| `pkey` | required | The placement key | `'DfFKxpkRGPMS7A9f71CquBgZ'` | `string` | +| Name | Scope | Description | Example | Type | +|-------------|----------|------------------------------------------------------------|------------------------------|----------------------| +| `pkey` | required | The placement key | `'DfFKxpkRGPMS7A9f71CquBgZ'` | `string` | +| `bcat` | optional | (deprecated) Array of blocked IAB Categories | `['IAB1-2', 'IAB1-3']` | `string[]` | +| `badv` | optional | (deprecated) Array of blocked Advertisers by their domains | `['ford.com', 'pepsi.com']` | `string[]` | + +Note: Providing `bcat` and `badv` via Bid Params is deprecated, the First Party Data method should be preferred (see below). +When both methods are provided, first party data values will be used and bid param values will be ignored. + +#### First Party Data + +Publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: + +- `ortb2.site.*` +- `ortb2.user.*` + +For example: + +```js +pbjs.setConfig({ + ortb2: { + site: { + name: "example", + cat: ["IAB2"], + keywords: "power tools, drills", + content: { + userrating: "4" + } + }, + user: { + yob: 1985, + gender: "m", + keywords: "a,b", + ext: { + data: { + registered: true, + interests: ["cars"] + } + } + } + } +}); +``` + +#### ORTB Blocking + +Sharethrough supports blocking advertiser domains (`badv`) and/or IAB Categories (`bcat`) via First Party Data. + +For example: + +```js +pbjs.setConfig({ + ortb2: { + bcat: ["IAB1", "IAB2-1"], + badv: ["domain1.com", "domain2.com"], + } +}); +``` diff --git a/dev-docs/bidders/shinez.md b/dev-docs/bidders/shinez.md index d1254a4dd4..8340d8e589 100644 --- a/dev-docs/bidders/shinez.md +++ b/dev-docs/bidders/shinez.md @@ -1,43 +1,85 @@ ---- -layout: bidder -title: Shinez -description: Prebid Shinez Bidder Adapter -biddercode: shinez -media_types: banner -pbjs: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Registration - -The Shinez adapter requires setup and approval from the Shinez team. Please reach out to tech-team@shinez.io for more information. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|----------------------|------------|----------| -| `placementId` | required | A Shinez-specific identifier that is associated with a specific domain provided by your Shinez representative. | `'00654321'` | `string` | -| `unit` | optional | An alphanumerical value used to identify the slot_id in reporting. | `'__header-bid-1'` | `string` | - -### Examples - -#### Example Banner Ad Unit - -```javascript -var adUnit = { - code: "test-div", - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [{ - bidder: "shinez", - params: { - placementId: "00654321" - } - }] -}; -``` +--- +layout: bidder +title: Shinez +description: Prebid Shinez Bidder Adapter +multiformat_supported: will-bid-on-any +pbjs: true +biddercode: shinez +media_types: banner, video +schain_supported: true +usp_supported: true +floors_supported: true +userIds: all +fpd_supported: true +safeframes_ok: false +sidebarType: 1 +--- + +### Note + +The Shinez adapter requires setup and approval. Please reach out to to setup an Shinez account. + +### Bid Parameters + +#### Banner, Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | Shinez publisher Id provided by your Shinez representative | "56f91cd4d3e3660002000033" +| `floorPrice` | optional | Number | Minimum price in USD. | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false + +## Example + +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'shinez', + params: { + org: '56f91cd4d3e3660002000033', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: true // Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'shinez', + params: { + org: '56f91cd4d3e3660002000033', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: true // Optional + } + }] + } +]; +``` + +### Configuration + +Shinez recommends setting UserSync by iframe for monetization. diff --git a/dev-docs/bidders/shinezRtb.md b/dev-docs/bidders/shinezRtb.md new file mode 100644 index 0000000000..cccc377eb5 --- /dev/null +++ b/dev-docs/bidders/shinezRtb.md @@ -0,0 +1,70 @@ +--- +layout: bidder +title: ShinezRTB +description: Prebid Shinez RTB Bidder Adaptor +biddercode: shinezRtb +filename: shinezRtbBidAdapter +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +gpp_supported: true +floors_supported: true +media_types: banner, video +prebid_member: false +safeframes_ok: false +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|-------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from shinezRtb. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from shinezRtb. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | optional | The minimum bid value desired. shinezRtb will not respond with bids lower than this value. | `0.90` | `float` | + +## Example + + ```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'shinezRtb', + params: { + cId: '562524b21b1c1f08117fc7f9', // Required - PROVIDED DURING SETUP... + pId: '59ac17c192832d0011283fe3', // Required - PROVIDED DURING SETUP... + bidFloor: 1.23 // Optional + } + }] + } +]; + +// configure pbjs to enable user syncing +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: 'shinezRtb', + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/showheroes-bs.md b/dev-docs/bidders/showheroes-bs.md index bdd15680b0..a4e3fba3a4 100644 --- a/dev-docs/bidders/showheroes-bs.md +++ b/dev-docs/bidders/showheroes-bs.md @@ -5,7 +5,11 @@ description: Prebid ShowHeroes Bidder Adapter pbjs: true biddercode: showheroes-bs media_types: video, banner -gdpr_supported: true +gvl_id: 111 +tcfeu_supported: true +usp_supported: true +schain_supported: true +sidebarType: 1 --- @@ -13,7 +17,8 @@ gdpr_supported: true ### bid params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|-------------------------------------|------------------------------------------|-----------| -| `playerId` | required | ShowHeroes player ID | `'0151f985-fb1a-4f37-bb26-cfc62e43ec05'` | `string` | -| `vpaidMode` | optional | Vpaid wrapper; default: `false`. | `true` | `boolean` | +| Name | Scope | Description | Example | Type | +|-------------|----------------------------------|-------------------------------------|------------------------------------------|-----------| +| `playerId` | required (if not send unitId) | VideoLibrary player ID | `'0151f985-fb1a-4f37-bb26-cfc62e43ec05'` | `string` | +| `unitId` | required (if not send playerId) | Monetize unit ID | `'AACBTwsZVANd9NlB'` | `string` | +| `vpaidMode` | optional | Vpaid wrapper; default: `false`. | `true` | `boolean` | diff --git a/dev-docs/bidders/silvermob.md b/dev-docs/bidders/silvermob.md index b362f42eb9..1c3eb81b22 100644 --- a/dev-docs/bidders/silvermob.md +++ b/dev-docs/bidders/silvermob.md @@ -3,16 +3,26 @@ layout: bidder title: SilverMob description: SilverMob Bidder Adapter biddercode: silvermob -gdpr_supported: true/false media_types: banner, video, native -pbjs: false +pbjs: true pbs: true -prebid_member: false +prebid_member: true +tcfeu_supported: true +gvl_id: 1058 +usp_supported: true +coppa_supported: true +schain_supported: true +safeframes_ok: true +deals_supported: true +fpd_supported: false +floors_supported: true +multiformat_supported: will-bid-on-one +sidebarType: 1 --- -### Note: +### Note -The SilverMob Bidding adapter requires setup before beginning. Please contact us at partners@silvermob.com +The SilverMob Bidding adapter requires setup before beginning. Please contact us at ### Bid Params diff --git a/dev-docs/bidders/silverpush.md b/dev-docs/bidders/silverpush.md new file mode 100644 index 0000000000..b750390d4d --- /dev/null +++ b/dev-docs/bidders/silverpush.md @@ -0,0 +1,161 @@ +--- +layout: bidder +title: Silverpush +description: Prebid Silverpush Bidder Adaptor +pbjs: true +pbs: true +biddercode: silverpush +media_types: banner, video +schain_supported: true +tcfeu_supported: false +usp_supported: true +coppa_supported: true +gpp_supported: true +floors_supported: true +userIds: +prebid_member: false +fpd_supported: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Registration +The Silverpush Bidding adapter requires setup before beginning. Please contact us at [prebid@silverpush.co](mailto:prebid@silverpush.co). + +### Bid Parameters + +#### Banner + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| -------------- | ----------- | ------------------------------------------ | ------------- | ------------ | +| `publisherId` | required | Publisher id provided by silverpush | "123456" | String | +| `bidFloor` | optional | Minimum price in USD. bidFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50.
      | 1.50 | Number | + +#### mediaTypes.banner + +The following banner parameters are supported here so publishers may fully declare their banner inventory: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| --------- | ------------| ----------------------------------------------------------------- | --------- | --------- | +| sizes | required | Avalaible sizes supported for banner ad unit | [ [300, 250], [300, 600] ] | [[Integer, Integer], [Integer, Integer]] | + +### AdUnit Format for Banner + +```javascript +const adUnits = [{ + code: 'div-1', + mediaTypes: { + banner: { + sizes: [ [300, 250], [300,600] ] + } + }, + bids: [{ + bidder: 'silverpush', + params: { + publisherId: "123456", + bidFloor: 1.2 + } + }] +}]; +``` + +#### Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ---- | ----- | ----------- | ------- | ---- | +| `publisherId` | required | Publisher id provided by silverpush | "123456" | String | +| `bidFloor` | optional | Minimum price in USD. bidFloor applies to a specific unit. For example, use the following value to set a $1.50 floor: 1.50. | 1.50 | Number | + +#### mediaTypes.video + +The following video parameters are supported here so publishers may fully declare their video inventory: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| --------- | ------------| ----------------------------------------------------------------- | --------- | --------- | +| context | required | instream or outstream |"outstream" | string | +| playerSize | required | Avalaible sizes supported for video ad unit. | [300, 250] | [Integer, Integer] | +| mimes | required | List of content MIME types supported by the player. | ["video/mp4"]| [String]| +| protocols | required | Supported video bid response protocol values. | [2,3,5,6] | [integers]| +| api | required | Supported API framework values. | [2] | [integers] | +| maxduration | required | Maximum video ad duration in seconds. | 30 | Integer | +| minduration | required | Minimum video ad duration in seconds. | 6 | Integer | +| startdelay | required | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. | 0 | Integer | +| placement | required | Placement type for the impression. | 1 | Integer | +| minbitrate | optional | Minimum bit rate in Kbps. | 300 | Integer | +| maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | Integer | +| playbackmethod | optional | Playback methods that may be in use. Only one method is typically used in practice. | [2]| [Integers] | +| linearity | optional | OpenRTB2 linearity. in-strea,overlay... | 1 | Integer | +| skip | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes . | 1 | Integer | +| skipafter | optional | Number of seconds a video must play before skipping is enabled; only applicable if the ad is skippable. | 5 | Integer | +| delivery | optional | OpenRTB2 delivery. Supported delivery methods (e.g., streaming, progressive). If none specified, assume all are supported. | 1 | [Integer] | + +### AdUnit Format for Video + +```javascript +var videoAdUnits = [{ + code: 'video-1', + mediaTypes: { + video: { + api: [1, 2, 4, 6], + mimes: ['video/mp4'], + context: 'instream', // or 'outstream' + playerSize: [ 640, 480 ], + protocols: [4,5,6,7], + placement: 1, + minduration: 0, + maxduration: 60, + startdelay: 0 + } + }, + bids: [ + { + bidder: 'silverpush', + params: { + publisherId: "123456", + bidfloor: 2.5 + } + } + ] +}] +``` + +### First Party Data +Publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: + +- ortb2.user.ext.data + +## Prebid Server + +```javascript +pbjs.setConfig({ + s2sConfig : { + accountId:"someaccountId" // replace with accountId + bidders : ['silverpush'], + timeout : 1000, //default value is 1000 + adapter : 'prebidServer', //if we have any other s2s adapter, default value is s2s + }, + ortb2: { + user: { + ext: { + data: { + eids: [{ + source: "pubcid.org", + uids:[ + { + id:"01EAJWWNEPN3CYMM5N8M5VXY22", + atype:1 + } + ] + }]} + } + } + } +}); +``` + +## Additional Details +For any queries, reach us at . diff --git a/dev-docs/bidders/slimcut.md b/dev-docs/bidders/slimcut.md index 598794aeac..5522645470 100644 --- a/dev-docs/bidders/slimcut.md +++ b/dev-docs/bidders/slimcut.md @@ -5,17 +5,21 @@ description: SlimCut Bidder Adapter pbjs: true biddercode: slimcut media_types: video, banner -gdpr_supported: true +tcfeu_supported: true +gvl_id: 102 +sidebarType: 1 --- ### Overview -This documentation covers the parameters for the **SlimCut** bidder adapter. And is intended to be referenced by publishers using prebid 1.0 and later. +This documentation covers the parameters for the **SlimCut** bidder adapter. And is intended to be referenced by publishers using prebid 1.0 and later. ### Bid Params + Only **placementId** is required and will be sent to you by your SlimCut account manager. ### Example Ad Unit + ```javascript var adUnit = { "code": "scm_outstream", diff --git a/dev-docs/bidders/smaato.md b/dev-docs/bidders/smaato.md index c058c1e91a..f298759132 100644 --- a/dev-docs/bidders/smaato.md +++ b/dev-docs/bidders/smaato.md @@ -3,12 +3,13 @@ layout: bidder title: Smaato description: Prebid Smaato Bidder Adaptor biddercode: smaato -gdpr_supported: true +tcfeu_supported: true gvl_id: 82 usp_supported: true coppa_supported: true -media_types: banner, video -userId: criteo, pubCommonId, unifiedId +gpp_supported: true +media_types: banner, video, native +userIds: all pbjs: true pbs: true pbs_app_supported: true @@ -16,31 +17,37 @@ prebid_member: true floors_supported: true fpd_supported: true schain_supported: true +sidebarType: 1 --- ### Table of Contents -- [Registration](#smaato-registration) -- [Note](#smaato-note) -- [Bid Params](#smaato-bid-params) -- [App Object](#smaato-app-object) -- [Example Ad Units](#smaato-example-ad-units) -- [First Party Data](#smaato-first-party) -- [Test Parameters](#smaato-test-parameters) +- [Table of Contents](#table-of-contents) +- [Registration](#registration) +- [Note](#note) +- [Bid Params](#bid-params) + - [App Object](#app-object) +- [Example Ad Units](#example-ad-units) + - [Example Banner Ad Unit](#example-banner-ad-unit) + - [Example Video Ad Unit](#example-video-ad-unit) + - [Example Native Ad Unit](#example-native-ad-unit) + - [Example AdPod (long-form) Video Ad Unit](#example-adpod-long-form-video-ad-unit) +- [First Party Data](#first-party-data) +- [Test Parameters](#test-parameters) - + ### Registration -The Smaato adapter requires setup and approval from the Smaato team, even for existing Smaato publishers. Please reach out to your account team or prebid@smaato.com for more information. +The Smaato adapter requires setup and approval from the Smaato team, even for existing Smaato publishers. Please reach out to your account team or for more information. - + ### Note The Smaato adapter will convert bidfloors to 'USD' currency as needed. - + ### Bid Params @@ -52,7 +59,11 @@ The Smaato adapter will convert bidfloors to 'USD' currency as needed. | `adbreakId` | required | Your Smaato adbreak id. Required for adpod (long-form video) requests | `'41002234'` | `string` | | `app` | optional | Object containing mobile app parameters. See the [App Object](#smaato-app-object) for details.| `app : { ifa: '56700000-9cf0-22bd-b23e-46b96e40003a'}` | `object` | - +##### Note + +In case of AdPods, the Smaato adapter will only read the first `imp[].skadn` entry for each AdPod, such that there should only be one `skadn` occurrence per AdPod. + + #### App Object @@ -64,7 +75,7 @@ Smaato supports using prebid within a mobile app's webview. | `ifa` | String that contains the advertising identifier of the user (e.g. idfa or aaid). | `'56700000-9cf0-22bd-b23e-46b96e40003a'` | `string` | | `geo` | Object that contains the latitude (`lat`) and longitude (`lon`) of the user. | `{ lat: 33.3, lon: -88.8 }` | `object` | - + ### Example Ad Units @@ -118,6 +129,51 @@ var adUnit = { }] }; ``` + +#### Example Native Ad Unit + +```javascript +var adUnit = { + "code": "native unit", + "mediaTypes": { + native: { + sendTargetingKeys: false, + image: { + required: true, + sizes: [150, 50] + }, + icon: { + required: true, + sizes: [50, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + body: { + required: true + }, + cta: { + required: false + }, + rating: { + required: false + } + } + }, + "bids": [{ + "bidder": "smaato", + "params": { + "publisherId": "1100012345", + "adspaceId": "11002234" + } + }] +}; +``` + #### Example AdPod (long-form) Video Ad Unit ```javascript @@ -149,16 +205,20 @@ var adUnit = { }; ``` - + ### First Party Data + Publishers should use the `ortb2` method of setting First Party Data. The following fields are supported: + - ortb2.site.keywords - ortb2.site.content - ortb2.user.keywords - ortb2.user.yob - ortb2.user.gender - ortb2.user.ext.eids +- ortb2.device.geo +- ortb2.device.ifa The IAB standard taxonomies are not supported. @@ -178,18 +238,25 @@ pbjs.setConfig({ keywords: "a,b", gender: "M", yob: 1984 + }, + device: { + ifa: "identifier", + geo: { + lat: 53.5488, + lon: 9.9872 + } } } }); ``` - + ### Test Parameters Following example includes sample `imp` object with publisherId and adSlot which can be used to test Smaato Adapter -``` +```json "imp":[ { "id":"1C86242D-9535-47D6-9576-7B1FE87F282C", diff --git a/dev-docs/bidders/smartadline.md b/dev-docs/bidders/smartadline.md new file mode 100644 index 0000000000..150a907337 --- /dev/null +++ b/dev-docs/bidders/smartadline.md @@ -0,0 +1,47 @@ +--- +layout: bidder +title: smartadline +description: Prebid Smartadline Bidder Adaptor +pbjs: true +pbs: false +biddercode: smartadline +media_types: banner +deals_supported: false +floors_supported: false +fpd_supported: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-----------------|----------|--------------------------|--------------|----------| +| `publisherId` | required | Unique identificator per widget integration provided by Smartadline team | `'1234567'` | `string` | + +### Note + +The Smartadline bidder adaptor requires setup and approval from the Smartadline team. Please reach out to [smartadline@gmail.com](mailto:smartadline@gmail.com) for more information.
      + +### Banner - Ad Unit Setup + +```javascript +var adUnits = [ + { + code: 'slot123', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "smartadline", + params: { + publisherId: '1234567', //required + } + } + ] + } + ] +``` diff --git a/dev-docs/bidders/smartadserver.md b/dev-docs/bidders/smartadserver.md index 12db35618c..d30a06f619 100644 --- a/dev-docs/bidders/smartadserver.md +++ b/dev-docs/bidders/smartadserver.md @@ -1,21 +1,24 @@ --- layout: bidder title: Smart AdServer -description: Prebid Smart AdServer Bidder Adaptor +description: Prebid Smart AdServer Bidder Adapter biddercode: smartadserver -media_types: display, video -gdpr_supported: true +media_types: display, video, native +gvl_id: 45 +tcfeu_supported: true +gpp_supported: true schain_supported: true usp_supported: true -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +userIds: all pbjs: true pbs: true floors_supported: true +sidebarType: 1 --- ### Registration -The Smart AdServer bidder adaptor requires setup and approval from the Smart AdServer Service team. Please reach out to your account manager for more information and start using it. +The Smart AdServer bidder adapter requires setup and approval from the Equativ (former Smart AdServer) service team. Please reach out to your account manager for more information and start using it. ### Bid params @@ -37,7 +40,7 @@ The Smart AdServer bidder adaptor requires setup and approval from the Smart AdS **Note:** The site, page and format identifiers have to all be provided or all empty. - + #### Video Object @@ -47,50 +50,69 @@ The Smart AdServer bidder adaptor requires setup and approval from the Smart AdS | `protocol` | optional | Maximum open RTB video protocol supported | `8` (VAST 4.0 wrapper) | `integer` | | `startDelay` | optional | Allowed values: 1 (generic pre-roll, default), 2 (generic mid-roll), 3 (generic post-roll) | `1` | `integer` | -### Examples +### Supported Media Types (Prebid.js) + +{: .table .table-bordered .table-striped } +| Type | Support | +|---|---| +| `banner` | Supported | +| `video` | Supported | +| `native` | Not currently supported | + +### Supported Media Types (Prebid Server) + +{: .table .table-bordered .table-striped } +| Type | Support | +|------|-------| +| `banner` | Supported | +| `video` | Supported | +| `native` | Supported | + +### Examples Without site/page/format : -``` - "imp": [{ - "id": "some-impression-id", - "banner": { - "format": [{ - "w": 600, - "h": 500 - }, { - "w": 300, - "h": 600 - }] - }, - "ext": { - "smartadserver": { - "networkId": 73 - } - } - }] + +```json + "imp": [{ + "id": "some-impression-id", + "banner": { + "format": [{ + "w": 600, + "h": 500 + }, { + "w": 300, + "h": 600 + }] + }, + "ext": { + "smartadserver": { + "networkId": 73 + } + } + }] ``` With site/page/format : -``` - "imp": [{ - "id": "some-impression-id", - "banner": { - "format": [{ - "w": 600, - "h": 500 - }, { - "w": 300, - "h": 600 - }] - }, - "ext": { - "smartadserver": { +```json + "imp": [{ + "id": "some-impression-id", + "banner": { + "format": [{ + "w": 600, + "h": 500 + }, { + "w": 300, + "h": 600 + }] + }, + "ext": { + "smartadserver": { "networkId": 73 "siteId": 1, "pageId": 2, "formatId": 3 - } - } - }] + } + } + }] ``` diff --git a/dev-docs/bidders/smarthub.md b/dev-docs/bidders/smarthub.md index 9bee0fd5ce..c1853bd9c4 100644 --- a/dev-docs/bidders/smarthub.md +++ b/dev-docs/bidders/smarthub.md @@ -6,12 +6,25 @@ biddercode: smarthub usp_supported: true schain_supported: true media_types: banner, video, native -gdpr_supported: true -pbjs: false +tcfeu_supported: false +pbjs: true pbs: true pbs_app_supported: true +sidebarType: 1 --- +### Prebid.js Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|---------------------------------|-------------------------------------|-----------| +| `partnerName` | required | Unique partner name | `'partnertest'` | `string` | +| `seat` | required | Seat value | `'9Q20EdGxzgWdfPYShScl'` | `string` | +| `token` | required | Token | `'eKmw6alpP3zWQhRCe3flOpz0wpuwRFjW'` | `string` | +| `iabCat` | optional | Array of IAB content categories that describe the content producer | `['IAB1-1', 'IAB3-1', 'IAB4-3']` | `Array(String)` | +| `minBidfloor` | optional | Minimal CPM value | `0.03` | `float` | +| `pos` | optional | The position of the placement on the page, see Open RTB spec v2.5. | `4` | `number` | + ### Prebid Server Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/smartico.md b/dev-docs/bidders/smartico.md index f05859f3b3..290c5e5894 100644 --- a/dev-docs/bidders/smartico.md +++ b/dev-docs/bidders/smartico.md @@ -5,6 +5,7 @@ description: Prebid Smartico Bidder Adaptor pbjs: true biddercode: smartico media_types: banner +sidebarType: 1 --- ### Bid Params @@ -26,9 +27,10 @@ The Smartico bidder adaptor requires setup and approval from the Smartico team. • Parameters 'region' and 'regions' are used as creatives feed filters, making sure creatives of specified region(s) to be only provided. The complete list of regions aliases must be predefined per each customer during the adapter integration.
      • Parameter 'regions' can a array of region aliases or a string of comma separated region aliases
      • Parameter 'bannerFormat' is needed in cases when it is not possible to precisely resolve the banner format by provided sizes as two or more banner formats could match that. The list supported banner formats could vary per customer thus must be predefined during the adapter integration.
      -• Parameter 'language' is used as creatives feed filter, making sure creatives of specified or no language content to be only provided and simultaneously making sure labels of specified language to be displayed inside creatives. The default label language is German. +• Parameter 'language' is used as creatives feed filter, making sure creatives of specified or no language content to be only provided and simultaneously making sure labels of specified language to be displayed inside creatives. The default label language is German. ### Banner - Ad Unit Setup + ```javascript var adUnits = [ { @@ -44,7 +46,7 @@ var adUnits = [ params: { placementId: 'placement123', //required token: "FNVzUGZn9ebpIOoheh3kEJ2GQ6H6IyMH39sHXaya", // required - region: "sample-region-code-1", // optional + region: "sample-region-code-1", // optional regions: ["sample-region-code-1","sample-region-code-2"], // optional bannerFormat: "medium_rectangle", // optional language:"de" // optional @@ -53,4 +55,4 @@ var adUnits = [ ] } ] -``` +``` diff --git a/dev-docs/bidders/smartrtb.md b/dev-docs/bidders/smartrtb.md deleted file mode 100644 index f2f55a61d6..0000000000 --- a/dev-docs/bidders/smartrtb.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -layout: bidder -title: SmartRTB -description: SmartRTB / smrtb.com Bidder Module -biddercode: smartrtb -gdpr_supported: true -media_types: banner, video -userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId -pbjs: true -pbs: true -pbs_app_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Registration - -Please contact us to create a new Smart RTB Marketplace account, and for any assistance in configuration. -You may email info@smrtb.com for inquiries. - -### Prebid.js Bid Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|----------|----------|-------------|------------------------------------|----------| -| `zoneId` | required | | `z_261b6c7e7d4d4985393b293cc903d1` | `string` | -| `forceBid` | optional | Returns test bid | true | `boolean` | - -### Prebid Server Bid Params - -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | Type | -|----------|----------|-------------|------------------------------------|----------| -| `pub_id` | required | Publisher ID assigned to you. | `'siteA'` | `string` | -| `zone_id` | optional | Enables mapping for further settings and reporting in the Marketplace UI. | `'z_261b6c7e7d4d4985393b293cc903d1'` | `string` | -| `force_bid` | optional | If zone ID is mapped, this may be set to always return fake sample bids (banner, video) | true | `boolean` | - -### Test Prebid Server Request - -This sample request is our global test placement and should always return a branded banner bid. - -``` - { - "id": "abc", - "site": { - "page": "prebid.org" - }, - "imp": [{ - "id": "test", - "banner": { - "format": [{ - "w": 300, - "h": 250 - }] - }, - "ext": { - "smartrtb": { - "pub_id": "test", - "zone_id": "N4zTDq3PPEHBIODv7cXK", - "force_bid": true - } - } - }] - } -``` diff --git a/dev-docs/bidders/smartx.md b/dev-docs/bidders/smartx.md index ed78dc7b10..fc028e4483 100644 --- a/dev-docs/bidders/smartx.md +++ b/dev-docs/bidders/smartx.md @@ -4,40 +4,57 @@ title: smartx description: Prebid smartx Bidder Adapter biddercode: smartx media_types: no-display, video -gdpr_supported: true +gvl_id: 115 +tcfeu_supported: true userIds: none prebid_member: true -schain_supported: false +schain_supported: true usp_supported: true safeframes_ok: false pbjs: true -pbjs_version_notes: avoid 4.31-4.39 +pbs: true +floors_supported: false +sidebarType: 1 --- ### Registration -Please reach out to your smartclip business contact for any questions and assistance in configuration. -### Bid Params +This adapter requires setup and approval from the smartclip team. Please contact us at --- + +### Prebid Server Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | | -------------------- | -------- | ------------------------------------------------------------------------------------------------------- | ----------------------- | ----------- | | `tagId` | required | A unique ID. | `'Nu68JuOWAvrbzoyrOR9a7A'` | `string` | -| `publisherId` | required | A unique PublisherID. | `'publisher_Id'` | `string` | -| `siteId` | required | A unique SiteID. | `'site_id'` | `string` | +| `publisherId` | required | A unique PublisherID. Is provided by smartclip | `'publisher_Id'` | `string` | +| `siteId` | required | A unique SiteID or AppID. Is provided by smartclip | `'site_id'` | `string` | +| `secure` | optional | Boolean identifying whether the requests should be https or not (used to override the protocol if the page isn't secure). | `true`| `boolean` | +| `mimes` | optional | List of MIME types to allow in ad. | `['application/javascript', 'video/mp4', 'video/webm']` | `array` | +| `price_floor` | optional | Set the current channel price floor in real time. | `10` | `integer` | +| `min_duration` | optional | Minimum video ad duration in seconds | `15` | `integer` | +| `max_duration` | optional | Maximum video ad duration in seconds | `60` | `integer` | + +### Prebid.js Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| -------------------- | -------- | ------------------------------------------------------------------------------------------------------- | ----------------------- | ----------- | +| `tagId` | required | A unique ID. | `'Nu68JuOWAvrbzoyrOR9a7A'` | `string` | +| `publisherId` | required | A unique PublisherID. Is provided by smartclip | `'publisher_Id'` | `string` | +| `siteId` | required | A unique SiteID or AppID. Is provided by smartclip | `'site_id'` | `string` | | `bidfloor` | required | Value of Bidfloor. | `0.3` | `float` | | `bidfloorcur` | required | Used Currency. (e.g. EUR, USD etc.) | `'EUR'` | `string` | | `context` | optional | Token that describes which context to play: 'instream' or 'outstream' | `'outstream'` | `string` | -| `outstream_options` | required | Object to set options on the smartx renderer. (Only required when setting mediaType.video.context = 'outstream') | `{}` | `object` | | `secure` | optional | Boolean identifying whether the requests should be https or not (used to override the protocol if the page isn't secure). | `true`| `boolean` | | `mimes` | optional | List of MIME types to allow in ad. | `['application/javascript', 'video/mp4', 'video/webm']` | `array` | | `price_floor` | optional | Set the current channel price floor in real time. | `10` | `integer` | | `min_duration` | optional | Minimum video ad duration in seconds | `15` | `integer` | | `max_duration` | optional | Maximum video ad duration in seconds | `60` | `integer` | +| `sitekey` | optional | Sitekey provided by smartclip. | `'foo.bar.baz'` | `string` | +| `outstream_options` | required | Object to set options on the smartx renderer, see below. Only required when setting mediaType.video.context = 'outstream'. | `{}` | `object` | - - -#### outstream_options Object +#### outstream_options {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | diff --git a/dev-docs/bidders/smartyads.md b/dev-docs/bidders/smartyads.md index 671cf75ef0..5629f1890a 100644 --- a/dev-docs/bidders/smartyads.md +++ b/dev-docs/bidders/smartyads.md @@ -1,29 +1,42 @@ --- layout: bidder title: SmartyAds -description: Prebid SmartyAds Bidder Adaptor +description: Prebid SmartyAds Bidder Adapter biddercode: smartyads -gdpr_supported: true +gvl_id: 534 +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true media_types: banner, video, native safeframes_ok: true deals_supported: true +fpd_supported: false pbjs: true pbs: true +multiformat_supported: will-bid-on-one +sidebarType: 1 --- -### Note: +### Note -The Example Bidding adapter requires setup before beginning. Please contact us at sales@smartyads.com +The Example Bidding adapter requires setup before beginning. Please contact us at -### Bid Params +### Prebid.JS Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required (for prebid.js) | placement Id | `'0'` | `string` | -| `host` | required (for prebid-server) | Region id | `'ns1'` | `string` | -| `sourceid` | required (for prebid-server) | Partner id | `'smartyads'` | `string` | -| `accountid` | required (for prebid-server) | Endpoint id | `'hash'` | `string` | +| `sourceid` | required | placement ID | `'0'` | `string` | +| `host` | required | const value, set to "prebid" | `'prebid'` | `string` | +| `accountid` | optional | publisher ID | `'1901'` | `string` | +| `traffic` | optional | Configures the mediaType that should be used. Values can be `'banner'`, `'native'` or `'video'` | `'banner'` | `string`| + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `host` | required | Region id | `'ns1'` | `string` | +| `sourceid` | required | Partner id | `'smartyads'` | `string` | +| `accountid` | required | Endpoint id | `'hash'` | `string` | diff --git a/dev-docs/bidders/smartytech.md b/dev-docs/bidders/smartytech.md new file mode 100644 index 0000000000..012851cbe4 --- /dev/null +++ b/dev-docs/bidders/smartytech.md @@ -0,0 +1,60 @@ +--- +layout: bidder +title: SmartyTech +description: Prebid SmartyTech Bidder Adaptor +pbjs: true +biddercode: smartytech +media_types: banner, video +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------------|----------|--------------|---------|-----------| +| `endpointId` | required | Endpoint ID. | `14` | `integer` | + +### Sample Banner Ad Unit Example + +``` +var adUnits = [{ + code: '/123123123/prebidjs-banner', + mediaTypes: { + banner: { + sizes: [ + [300, 301], + [300, 250] + ] + } + }, + bids: [{ + bidder: 'smartytech', + params: { + endpointId: 14 + } + }] +}]; +``` + +### Sample Video Ad Unit Example + +``` +var videoAdUnit = { + code: '/123123123/video-vast-banner', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4'], + } + }, + bids: [{ + bidder: 'smartytech', + params: { + endpointId: 14 + } + }] +}; +``` diff --git a/dev-docs/bidders/smilewanted.md b/dev-docs/bidders/smilewanted.md index aae2f17d16..42429175b0 100644 --- a/dev-docs/bidders/smilewanted.md +++ b/dev-docs/bidders/smilewanted.md @@ -6,11 +6,17 @@ media_types: banner, video pbjs: true pbs: true biddercode: smilewanted -gdpr_supported: true +tcfeu_supported: false usp_supported: true +userIds: all gvl_id: 639 +sidebarType: 1 --- +### Disclosure + +Note: This bidder appears to only consider gdprApplies if a consent string is available.. This may result in some incorrect TCF2 processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See + ### Note To use us as a bidder you must have an account and an active "zoneId" on our Smile Wanted platform. diff --git a/dev-docs/bidders/smms.md b/dev-docs/bidders/smms.md deleted file mode 100644 index 821bffed34..0000000000 --- a/dev-docs/bidders/smms.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: SMMS -description: Prebid SMMS Bidder Adaptor -pbjs: true -biddercode: smms -media_types: banner, native -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `placementId` | required | This is placement Id | `1440837` | `integer` | -| `currency` | optional | 3-letter ISO 4217 code defining the currency of the bid (currently support USD and JPY), default is JPY | `'USD'` | `string` | diff --git a/dev-docs/bidders/smn.md b/dev-docs/bidders/smn.md new file mode 100644 index 0000000000..0ec6ae5354 --- /dev/null +++ b/dev-docs/bidders/smn.md @@ -0,0 +1,27 @@ +--- +layout: bidder +title: SMN +description: Prebid SMN Bidder Adaptor +pbjs: true +biddercode: smn +aliasCode: admixer +media_types: banner, video +tcfeu_supported: true +usp_supported: true +gvl_id: 511 +fpd_supported: false +schain_supported: true +coppa_supported: false +deals_supported: true +ortb_blocking_supported: false +safeframes_ok: false +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------|----------| +| `zone` | required | The unique identifier of the ad placement. Could be obtained from the SMN UI or from your account manager. | "e5ff8e48-4bd0-4a2c-9236-55530ab8981d" | `string` | +| `kvTargeting` | optional | Key/Value - a pair of the unique values that will be used for the custom targeting option. | {key1: value2, key2: value2} | `object` | diff --git a/dev-docs/bidders/smrtconnect.md b/dev-docs/bidders/smrtconnect.md new file mode 100644 index 0000000000..1413afa1d0 --- /dev/null +++ b/dev-docs/bidders/smrtconnect.md @@ -0,0 +1,38 @@ +--- +layout: bidder +title: Smrtconnect +description: Prebid Smrtconnect Bidder Adapter +biddercode: smrtconnect +tcfeu_supported: false +gvl_id: none +usp_supported: true +coppa_supported: true +gpp_sids: none +schain_supported: true +dchain_supported: false +media_types: banner, native, video, audio +safeframes_ok: false +deals_supported: true +floors_supported: true +fpd_supported: false +pbjs: false +pbs: true +pbs_app_supported: true +prebid_member: false +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +privacy_sandbox: no +sidebarType: 1 +--- + +### Note + +Bidding adapter requires setup before beginning. +Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `supply_id` | required | Supply Id | `'1'` | `string` | diff --git a/dev-docs/bidders/snigel.md b/dev-docs/bidders/snigel.md new file mode 100644 index 0000000000..d604869807 --- /dev/null +++ b/dev-docs/bidders/snigel.md @@ -0,0 +1,34 @@ +--- +layout: bidder +title: Snigel +description: Snigel Prebid Bidder Adapter +biddercode: snigel +gvl_id: 1076 +media_types: banner +tcfeu_supported: true +prebid_member: false +schain_supported: true +coppa_supported: true +usp_supported: true +gpp_supported: true +deals_supported: false +floors_supported: true +pbjs: true +sidebarType: 1 +--- + +#### Note + +This bid adapter requires our ad operation experts to create an optimized setup for the desired placements on your property. +Please reach out to us at . + +#### Prebid.js Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-----------|----------|---------------------------|------------|----------| +| `accountId` | required | Account identifier from Snigel | `"1870"` | `string` | +| `site` | required | Site identifier from Snigel | `"site.com"` | `string` | +| `placement` | required | Placement identifier from Snigel | `"top_leaderboard"` | `string` | + +Use placement `"prebid_test_placement"` to receive unbilled test ads. diff --git a/dev-docs/bidders/somo.md b/dev-docs/bidders/somo.md deleted file mode 100644 index bd903ebbfc..0000000000 --- a/dev-docs/bidders/somo.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: bidder -title: Somo Audience -description: Somo Audience Bidder Adapter -pbjs: true -biddercode: somo -prevBiddercode: somoAudience -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Disclosure - -This bidder sets `adId` on the bid response and hasn't responded to the Prebid.js team to confirm uniqueness -of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381). - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|----------------------------------------|--------------------------------------|----------| -| `placementId` | required | Placement ID provided by Somo Audience | `'22a58cfb0c9b656bff713d1236e930e8'` | `string` | diff --git a/dev-docs/bidders/somoaudience.md b/dev-docs/bidders/somoaudience.md index 1d3e7ab55f..bdb8018af2 100644 --- a/dev-docs/bidders/somoaudience.md +++ b/dev-docs/bidders/somoaudience.md @@ -4,9 +4,10 @@ title: Somo Audience description: Somo Audience Bidder Adapter biddercode: somoaudience media_types: banner, native, video -pbs: true +pbs: false enable_download: false -pbjs_version_notes: not ported to 5.x +pbs_version_notes: they've pulled their PBS adapter +sidebarType: 1 --- diff --git a/dev-docs/bidders/sonic_twist.md b/dev-docs/bidders/sonic_twist.md new file mode 100644 index 0000000000..85abfb58dc --- /dev/null +++ b/dev-docs/bidders/sonic_twist.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Sonic Twist Media +description: Sonic Twist Media +biddercode: sonic_twist +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 +--- + +### Note + +The Sonic Twist Media Bidding adaptor requires setup and approval before beginning. Please reach out to for more details + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------|----------|-----------------------|---------------------------|----------| +| `host` | required | Our Host | `'cpm.andbeyond.media'` | `string` | +| `zoneId` | required | Example RTB zone id | `12345` | `integer` | diff --git a/dev-docs/bidders/sonobi.md b/dev-docs/bidders/sonobi.md index 73d3b538ff..78c09e4467 100644 --- a/dev-docs/bidders/sonobi.md +++ b/dev-docs/bidders/sonobi.md @@ -4,7 +4,8 @@ title: Sonobi description: Prebid Sonobi Bidder Adaptor biddercode: sonobi media_types: banner, video -gdpr_supported: true +gvl_id: 104 +tcfeu_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId, lotamePanoramaID pbjs: true pbs: true @@ -12,12 +13,14 @@ usp_supported: true coppa_supported: true schain_supported: true pbs_app_supported: true -fpd_supported: true +floors_supported: true +sidebarType: 1 --- -### Note: +### Note + The Sonobi Bidder adapter requires setup and approval from your Sonobi Account Manager. If you require assistance -implementing our adapter please don't hesitate to contact us at apex.prebid@sonobi.com. +implementing our adapter please don't hesitate to contact us at . ### Bid Params @@ -34,10 +37,17 @@ implementing our adapter please don't hesitate to contact us at apex.prebid@sono | `bid_request_url`| optional | String representing the url the Sonobi adapter should make to request bids | `'https://iad-2-apex.go.sonobi.com/trinity.json'` | `string` | ### Configuration -*You *must* only include one ID field - either `placement_id` or `ad_unit`, not both. If you have questions on which parameter to use, please reach out to your Account Manager. +*You*must* only include one ID field - either `placement_id` or `ad_unit`, not both. If you have questions on which parameter to use, please reach out to your Account Manager. The `ad_unit` and `placement_id` are **mutually exclusive** but at least one is required. If you pass both, `ad_unit` takes precedence. If you pass the optional `sizes` Array in your bid params it will override the global config sizes for the Sonobi Adapter only. The `hfa` parameter requires your Sonobi Account Manager to enable this feature for you. Please contact them for further information. + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `TagID` | required | The placement ID or The adunit ID | `'1a2b3c4d5e6f1a2b3c4d' or '/1234567/example/adUnit/code'` | `string` | diff --git a/dev-docs/bidders/sortable.md b/dev-docs/bidders/sortable.md deleted file mode 100644 index 2ac98e8707..0000000000 --- a/dev-docs/bidders/sortable.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: bidder -title: Sortable -description: Prebid Sortable Bidder Adaptor -biddercode: sortable -pbjs: true -media_types: banner, native, video -gdpr_supported: true -usp_supported: true -schain_supported: true -prebid_member: true -gvl_id: 145 -floors_supported: true -userIds: all ---- - -**Table of Contents** - -- [Bid params](#sortable-bid-params) -- [Banner Ads](#sortable-banner) -- [Configuration](#sortable-configuration) - - - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | -|------+-------+-------------+---------| -| `tagId` | required | The tag ID from Sortable. | `"test-pb-leaderboard"` | -| `siteId` | optional | Override the global Sortable site ID, [see here](#sortable-configuration). Please reach out to your Sortable Account Manager for more details. | `"example.com"` | -| `floor` | optional | The minumum CPM (in USD) requred to participate | `0.25` | -| `keywords` | optional | Publisher-defined key-value string pairs | `{ "key1": "val1", "key2": "val2" }` | - - - -### Banner Ads - -Sortable supports the banner features described in: - -- [The `adUnit` banner documentation](/dev-docs/adunit-reference.html#adUnit-banner-example) -- [Getting Started for Developers](/dev-docs/getting-started.html) - - - - -### Configuration - -The Sortable site ID should be set globally in order to improve user sync. How to do so: - -``` javascript -pbjs.setConfig({ - sortable: { - siteId: "example.com" - } -}); -``` - -The Sortable adapter has the ability to initiate user-sync requests that will improve DSP user ID match rate, -with the aim of generating higher bid prices. By default, Sortable sync requests are off. Setting the Sortable site ID globally as described above is required for user-sync requests. - -``` javascript -pbjs.setConfig({ - userSync: { - enabledBidders: ['sortable'], - iframeEnabled: true - }}); -``` - -Note: these configs should be combined with any other UserSync config calls, as subsequent calls to setConfig for the same attribute overwrite each other. diff --git a/dev-docs/bidders/sovrn.md b/dev-docs/bidders/sovrn.md index 98c383cbeb..10518d325d 100644 --- a/dev-docs/bidders/sovrn.md +++ b/dev-docs/bidders/sovrn.md @@ -5,20 +5,182 @@ description: Prebid Sovrn Bidder Adaptor pbjs: true pbs: true biddercode: sovrn -gdpr_supported: true +tcfeu_supported: true usp_supported: true userIds: all prebid_member: true schain_supported: true gvl_id: 13 floors_supported: true -fpd_supported: true +media_types: banner, video +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|----------------------|------------|----------| -| `tagid` | required | The sovrn Ad Tag ID | `'315045'` | `string` | -| `bidfloor` | optional | Bid floor in dollars | `'0.04'` | `string` | +| Name | Scope | Description | Example | Type | +|--------------|----------|----------------------|------------------|----------| +| `tagid` | required | The sovrn Ad Tag ID | `'315045'` | `string` | +| `bidfloor` | optional | Bid floor in dollars | `0.04` | `float` | +| `adunitcode` | optional | Ad unit identifier | `'example_code'` | `string` | + +Bid Params for video ads. These params should be added to `mediatype.video`. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------|-----------------|-----------------| +| `mimes` | required | Content MIME types supported | `['video/mp4']` | `string array` | +| `minduration` | recommended | Minimum video ad duration in seconds | `5` | `integer` | +| `maxduration` | required | Maximum video ad duration in seconds | `10` | `integer` | +| `protocols` | required | The array of supported video protocols | `[1, 2]` | `integer array` | +| `w` | recommended | Width of the video player in device independent pixels (DIPS) | `5` | `integer` | +| `h` | recommended | Height of the video player in device independent pixels (DIPS) | `5` | `integer` | +| `startdelay` | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements | `5` | `integer` | +| `placement` | recommended | Placement type for the impression. Refer to List 5.9 | `5` | `integer` | +| `linearity` | recommended | Indicates if the impression must be linear, nonlinear, etc. Allowed by default | `0` | `integer` | +| `skip` | optional | Indicates if the player will allow the video to be skipped, where 0 = no, 1 = yes | `0` | `integer` | +| `skipmin` | optional | Only if the ad is skippable. Videos of total duration greater than this number of seconds can be skippable | `5` | `integer` | +| `skipafter` | optional | Only if the ad is skippable. Number of seconds a video must play before skipping is enabled | `5` | `integer` | +| `sequence` | optional | For multiple ad in the same bid request. This value allow will for the coordinated delivery of multiple ad | `5` | `integer` | +| `battr` | optional | Blocked creative attributes | `[1]` | `integer array` | +| `maxextended` | optional | Max extended ad duration beyond the maxduration if extension is allowed. Blank or 0 - blocked. -1 - allowed without time limit | `5` | `integer` | +| `minbitrate` | optional | Minimum bit rate in Kbps | `5` | `integer` | +| `maxbitrate` | optional | Maximum bit rate in Kbps | `5` | `integer` | +| `boxingallowed` | optional | Indicates if letter-boxing of 4:3 content into a 16:9 window is allowed, where 0 = no, 1 = yes | `5` | `integer` | +| `playbackmethod` | optional | Playback methods that may be in use. See [Video Playback Methods](#video-playback-methods) | `[1]` | `integer array` | +| `playbackend` | optional | The event that causes playback to end. Refer to Playback Cessation Modes | `5` | `integer` | +| `delivery` | optional | Supported delivery methods (1 = streaming, 2 = progressive, 3 = download). If none specified, assume all are supported. | `[1, 2]` | `integer array` | +| `pos` | recommended | Ad position on screen. Refer to [Ad Position](#ad-position) | `5` | `integer` | +| `api` | recommended | List of supported API frameworks for this impression. Refer to [API Frameworks](#sovrn-api-frameworks) | `[1, 2, 3]` | `integer array` | + +### Note + +[Protocols list](https://docs.prebid.org/dev-docs/bidders/epsilon.html#protocols) + +#### MIME types + +##### With VPAID2 + +video/mp4, +video/3gpp, +application/javascript + +##### Without VPAID2 + +video/mp4, +video/3gpp + +#### Video Playback Methods + +{: .table .table-bordered .table-striped } +| Value | Description | +|-------|----------------------------------------------------------| +| `1` | Initiates on Page Load with Sound On | +| `2` | Initiates on Page Load with Sound Off by Default | +| `3` | Initiates on Click with Sound On | +| `4` | Initiates on Mouse-Over with Sound On | +| `5` | Initiates on Entering Viewport with Sound On | +| `6` | Initiates on Entering Viewport with Sound Off by Default | + +#### Playback Cessation Modes + +{: .table .table-bordered .table-striped } +| Value | Description | +|-------|-----------------------------------------------------------------------------------------------------------| +| `1` | On Video Completion or when Terminated by User | +| `2` | On Leaving Viewport or when Terminated by User | +| `3` | On Leaving Viewport Continues as a Floating/Slider Unit until Video Completion or when Terminated by User | + +#### Ad Position + +{: .table .table-bordered .table-striped } +| Value | Description | +|-------|----------------| +| `0` | Unknown | +| `1` | Above the Fold | +| `2` | DEPRECATED | +| `3` | Below the Fold | +| `4` | Header | +| `5` | Footer | +| `6` | Sidebar | +| `7` | Full Screen | + + + +#### API Frameworks + +{: .table .table-bordered .table-striped } +| Value | Description | +|-------|-------------| +| `1` | VPAID 1.0 | +| `2` | VPAID 2.0 | +| `3` | MRAID-1 | +| `4` | ORMMA | +| `5` | MRAID-2 | +| `6` | MRAID-3 | + +Source: [OpenRTB scpecification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) + +### Example + +#### Video instream adUnit + +```javascript + var instreamAdUnit = { + code: 'instream-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + mimes: ['video/mp4'], + minduration: 4, + maxduration: 6, + context: 'instream' + } + }, + bids: [{ + bidder: 'sovrn', + params: { + tagid: '315045' + } + }] + } +``` + +#### Video outstream adUnit + +```javascript + var outstreamAdUnit = { + code: 'outstream-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + mimes: ['video/mp4'], + minduration: 4, + maxduration: 6, + context: 'outstream' + } + }, + bids: [{ + bidder: 'sovrn', + params: { + tagid: '315045' + } + }] + } +``` + +#### Banner adUnit + +```javascript + var bannerAdUnit = { + code: 'banner-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'sovrn', + params: { + tagid: '315045' + } + }] + } +``` diff --git a/dev-docs/bidders/sparteo.md b/dev-docs/bidders/sparteo.md new file mode 100644 index 0000000000..7a5d574333 --- /dev/null +++ b/dev-docs/bidders/sparteo.md @@ -0,0 +1,61 @@ +--- +layout: bidder +title: Sparteo +description: Prebid Sparteo Bidder Adaptor +pbjs: true +pbs: false +biddercode: sparteo +media_types: banner, video +tcfeu_supported: true +gvl_id: 1028 +usp_supported: true +prebid_member: false +schain_supported: false +safeframes_ok: true +deals_supported: false +floors_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Note + +Sparteo Header Bidding adapter requires setup and approval. Please reach out to for more details. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------------------------------------------------------------------------|------------|-----------| +| `publisherId` | required | Your publisher ID. This information will be given to you by the Sparteo team. | `1234` | `integer` | +| `networkId` | required | Your network ID. This information will be given to you by the Sparteo team. | `1234` | `integer` | + +Only the `publisherId` OR `networkId` is required. + +### Banner Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------|----------|--------------------------------------------------------|--------------|-----------| +| `size` | required | The size (width, height) of the banner, in pixels. | `[640, 480]` | `String` | +| `pos` | optional | The position of the banner following the OpenRTB spec. | `0` | `integer` | + +### Video Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|--------------------------------------------------------------------------|----------------|------------------| +| `context` | required | The video context, either 'instream', 'outstream'. | `'instream'` | `String` | +| `playerSize` | required | The size (width, height) of the video player on the page, in pixels. | `[640, 480]` | `Array` | +| `playbackmethod` | optional | Defines how the video inventory is initiated following the OpenRTB spec. | `[4, 5]` | `Array` | +| `protocols` | optional | Defines the video protocols allowed. | `[1, 2]` | `Array` | +| `api` | optional | Defines the video api allowed. | `[1, 2]` | `Array` | +| `mimes` | optional | Defines the video mimes allowed. | `['video/mp4']` | `Array` | +| `skip` | optional | Defines if skip is allowed. | `1` | `integer` | +| `startdelay` | optional | Defines the startDelay. | `0` | `integer` | +| `placement` | optional | Defines the placement. | `1` | `integer` | +| `linearity` | optional | Defines the linearity. | `1` | `integer` | +| `minduration` | optional | Defines the video minduration. | `1` | `integer` | +| `maxduration` | optional | Defines the video maxduration. | `160` | `integer` | diff --git a/dev-docs/bidders/spotx.md b/dev-docs/bidders/spotx.md index 0aa1701a9e..0c4fa8ce6b 100644 --- a/dev-docs/bidders/spotx.md +++ b/dev-docs/bidders/spotx.md @@ -4,15 +4,16 @@ title: SpotX description: Prebid SpotX Bidder Adaptor biddercode: spotx media_types: no-display, video -gdpr_supported: true +tcfeu_supported: true userIds: id5Id, sharedId, unifiedId prebid_member: true schain_supported: true usp_supported: true safeframes_ok: false pbjs: true -gvl_id: 52 +gvl_id: 165 floors_supported: true +sidebarType: 1 --- ### Registration @@ -33,15 +34,14 @@ The SpotX adapter requires setup and approval from your Magnite account manager. | `ad_volume` | optional | Value between 0 and 1 to denote the volume the ad should start at | `0.7` | `float` | | `price_floor` | optional | Set the current channel price floor in real time. | `10` | `float` | | `hide_skin` | optional | Set to true to hide the SpotX skin | | `boolean` | -| `custom` | optional | An object containing key-value pairs for reporting. See SpotX documentation [here](https://developer.spotxchange.com/content/local/docs/sdkDocs/DirectSdk/dsdk-custom-configs.md#custom-key-value-pair-reporting) | | `object` | +| `custom` | optional | An object containing key-value pairs for reporting. See SpotX documentation. | | `object` | | `min_duration` | optional | Minimum video ad duration in seconds | | `integer` | | `max_duration` | optional | Maximum video ad duration in seconds | | `integer` | -| `placement_type` | optional | Number corresponding to the type of ad placement. See SpotX documentation [here](https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/easi-integration.md#common-javascript-attributes) | | `integer` | -| `position` | optional | Number corresponding to the position of the ad. See SpotX documentation [here](https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/easi-integration.md#common-javascript-attributes) | | `integer` | +| `placement_type` | optional | Number corresponding to the type of ad placement. See SpotX documentation. | | `integer` | +| `position` | optional | Number corresponding to the position of the ad. See SpotX documentation. | | `integer` | | `page` | optional | The URL of the page the ad is being displayed on. Used to override the detected referrer if necessary | `'https://www.spotx.tv'` | `string` | - - + #### outstream_options Object @@ -52,4 +52,4 @@ The SpotX adapter requires setup and approval from your Magnite account manager. | `ad_mute` | optional | Set to true to start the ad with the volume muted. | `true` | `boolean` | | `playersize_auto_adapt` | optional | Set to true to make video auto-adapt to the ad's dimensions | `true` | `boolean` | | `in_iframe` | optional | ID of iFrame element to insert EASI script tag. | `'iframe1'` | `string` | -| `custom_override` | optional | Object of script tag attributes to override from the list here: [EASI Attributes](https://developer.spotxchange.com/content/local/docs/sdkDocs/EASI/easi-integration.md#common-javascript-attributes). (Note: Exclude `data-spotx_` from attribute name; `channel_id`, `vast_url`, `content_page_url`, and `ad_unit` overrides are ignored.) | `{content_height: 300, content_width: 400}` | `object` | +| `custom_override` | optional | Object of script tag attributes to override. (Note: Exclude `data-spotx_` from attribute name; `channel_id`, `vast_url`, `content_page_url`, and `ad_unit` overrides are ignored.) | `{content_height: 300, content_width: 400}` | `object` | diff --git a/dev-docs/bidders/ssmas.md b/dev-docs/bidders/ssmas.md new file mode 100644 index 0000000000..f9d3b1fdc5 --- /dev/null +++ b/dev-docs/bidders/ssmas.md @@ -0,0 +1,25 @@ +--- +layout: bidder +title: SSMas +description: Prebid SSMas Bidder Adapter +pbjs: true +pbs: false +biddercode: ssmas +deals_supported: false +media_types: banner +gvl_id: 1183 +sidebarType: 1 +tcfeu_supported: true +userIds: sharedId +floors_supported: true +safeframes_ok: true + +--- + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------------|----------|----------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|------------| +| `placementId` | required | The placement ID from SSMas. | `234234` | `integer` | diff --git a/dev-docs/bidders/sspBC.md b/dev-docs/bidders/sspBC.md index 18889255a4..ea3a9992f7 100644 --- a/dev-docs/bidders/sspBC.md +++ b/dev-docs/bidders/sspBC.md @@ -3,12 +3,13 @@ layout: bidder title: sspBC description: Prebid sspBC Bidder Adaptor pbjs: true +pbs: true biddercode: sspBC media_types: banner, video, native floors_supported: true -gdpr_supported: true -fpd_supported: true +tcfeu_supported: true gvl_id: 676 +sidebarType: 1 --- diff --git a/dev-docs/bidders/stickyadstv.md b/dev-docs/bidders/stickyadstv.md index 4988f443c6..ead5d3181c 100644 --- a/dev-docs/bidders/stickyadstv.md +++ b/dev-docs/bidders/stickyadstv.md @@ -7,5 +7,6 @@ nav_section: reference pbjs: true biddercode: stickyadstv media_types: native +sidebarType: 1 --- diff --git a/dev-docs/bidders/stn.md b/dev-docs/bidders/stn.md new file mode 100644 index 0000000000..3373e93b07 --- /dev/null +++ b/dev-docs/bidders/stn.md @@ -0,0 +1,88 @@ +--- +layout: bidder +title: STN +description: Prebid STN Bidder Adapter +pbjs: true +biddercode: stn +media_types: banner, video +multiformat_supported: will-bid-on-any +schain_supported: true +tcfeu_supported: false +usp_supported: true +gpp_supported: true +gpp_sids: tcfeu, usstate_all, usp +pbs: false +floors_supported: true +userIds: all +fpd_supported: true +sidebarType: 1 +--- + +### Note + +The STN adapter requires setup and approval. Please reach out to to setup an STN account. + +### Bid Parameters + +#### Banner ,Video + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | Example +| ---- | ----- | ---- | ----------- | ------- +| `org` | required | String | STN publisher Id provided by your STN representative | "0987654321abcdef87654321" +| `floorPrice` | optional | Number | Minimum price in USD.

      **WARNING:**
      Misuse of this parameter can impact revenue | 2.00 +| `placementId` | optional | String | A unique placement identifier | "12345678" +| `testMode` | optional | Boolean | This activates the test mode | false + +## Example + +```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'stn', + params: { + org: '0987654321abcdef87654321', // Required + floorPrice: 0.05, // Optional + placementId: '12345678', // Optional + testMode: false // Optional + } + }] + }, + { + code: 'dfp-video-div', + sizes: [ + [640, 480] + ], + mediaTypes: { + video: { + playerSize: [ + [640, 480] + ], + context: 'instream' + } + }, + bids: [{ + bidder: 'stn', + params: { + org: '0987654321abcdef87654321', // Required + floorPrice: 5.00, // Optional + placementId: '12345678', // Optional + testMode: false // Optional + } + }] + } +]; +``` + +### Configuration + +STN recommends setting UserSync by iframe for monetization. diff --git a/dev-docs/bidders/streamkey.md b/dev-docs/bidders/streamkey.md index 9cd2cffbc5..32156607e1 100644 --- a/dev-docs/bidders/streamkey.md +++ b/dev-docs/bidders/streamkey.md @@ -4,9 +4,13 @@ title: Streamkey description: Prebid Streamkey.tv Bidder Adapter pbjs: true pbs: true +media_types: video,banner +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true biddercode: streamkey aliasCode: adtelligent -media_types: video +sidebarType: 1 --- ### Bid params @@ -16,9 +20,9 @@ media_types: video |-------|----------|---------------------------------|----------|-----------| | `aid` | required | The traffic source ID | `232131` | `integer` | - ### Test Parameters -``` + +``` javascript var adUnits = [ // Video instream adUnit diff --git a/dev-docs/bidders/stroeerCore.md b/dev-docs/bidders/stroeerCore.md index 307ccd4b25..4a8875fbe1 100644 --- a/dev-docs/bidders/stroeerCore.md +++ b/dev-docs/bidders/stroeerCore.md @@ -3,46 +3,85 @@ layout: bidder title: StroeerCore description: Stroeer Bidder Adapter biddercode: stroeerCore -media_types: banner -gdpr_supported: false -schain_supported: false +media_types: banner, video +tcfeu_supported: true +dsa_supported: true +schain_supported: true coppa_supported: false usp_supported: false safeframes_ok: true prebid_member: false pbjs: true -pbs: false +pbs: true gvl_id: 136 +pbs_app_supported: true deals_supported: true +userIds: criteo, id5Id, netId, pubCommonId, sharedId +multiformat_supported: will-bid-on-one +floors_supported: true +fpd_supported: false +sidebarType: 1 --- ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|--------------------|------------------------------|----------| +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------------|-----------------------------------------|----------| | `sid` | required | Slot ID | `'06b782cc-091b-4f53-9cd2-0291679aa1ac'`| `string` | -### Config Notes +### Ad Unit Configuration -* Slot id (`sid`) is required. The adapter will ignore bid requests from prebid if `sid` is not provided. This must be in the decoded form. For example, "1234" as opposed to "MTM0ODA=". -* The server ignores dimensions that are not supported by the slot or by the platform (such as 987x123). +#### Banner -### Ad unit configuration for publishers +* The server will ignore sizes that are not supported by the slot or by the platform (such as 987x123). + +##### Example + +```javascript +var adUnits = [ + { + code: 'your-banner-adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [{ + bidder: 'stroeerCore', + params: { + sid: '06b782cc-091b-4f53-9cd2-0291679aa1ac' + } + }] + } +]; +``` + +#### Video + +* Both instream and outstream contexts are supported. +* We do not provide an outstream renderer. You will need to set up your own. See [Show Outstream Video Ads](/dev-docs/show-outstream-video-ads.html) for more information. +* On `mediaTypes.video`, the fields `context` and `mediaTypes` are required. + +##### Example ```javascript -const adUnits = [{ - code: 'div-gpt-ad-1460505748561-0', +var adUnits = [ + { + code: 'your-video-adunit-code', mediaTypes: { - banner: { - sizes: [[300, 250]], - } + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4', 'video/quicktime', 'video/x-ms-wmv'] + } }, bids: [{ - bidder: 'stroeerCore', - params: { - sid: "06b782cc-091b-4f53-9cd2-0291679aa1ac" - } + bidder: 'stroeerCore', + params: { + sid: '35d4225e-f8e3-4f45-b1ea-77913afd00d1' + } }] -}]; + } +]; ``` diff --git a/dev-docs/bidders/stv.md b/dev-docs/bidders/stv.md index 9cde162f24..935436d463 100644 --- a/dev-docs/bidders/stv.md +++ b/dev-docs/bidders/stv.md @@ -1,22 +1,34 @@ --- layout: bidder -title: Stv -description: Prebid Stv Bidder Adaptor +title: SMARTSTREAM.TV +description: Prebid STV Bidder Adapter pbjs: true biddercode: stv media_types: banner,video -gdpr_supported: false -enable_download: false -pbjs_version_notes: not ported to 5.x +gvl_id: 134 +tcfeu_supported: true --- -### Bid Params +### Banner Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|----------------------------------------------------------------------------|------------------------|-----------------| -| `placement` | required | Placement ID from stv. | `'prer0-0%3D4137'` | `string` | -| `pfilter` | optional | Selection filter. See [here](https://github.com/prebid/Prebid.js/blob/master/modules/stvBidAdapter.md) for more details. | {`min_duration:1`} | `object` | -| `noskip` | optional | No skip flag: 0 - false, 1 - true | `1` | `integer` | +| `placement` | required | Placement ID from STV. | `'101'` | `string` | +| `bcat` | optional | List of Blocked Categories (IAB) - comma separated. | `'IAB2,IAB4'` | `string` | + +### Video Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------------------------------------------------------------------|------------------------|-----------------| +| `placement` | required | Placement ID from STV. | `'106'` | `string` | +| `bcat` | optional | List of Blocked Categories (IAB) - comma separated. | `'IAB2,IAB4'` | `string` | +| `floorprice` | optional | input min_cpm_micros, CPM in EUR * 1000000 | `1000000` | `integer` | +| `max_duration` | optional | in seconds | `60` | `integer` | +| `min_duration` | optional | in seconds | `5` | `integer` | +| `max_bitrate` | optional | | `600` | `integer` | +| `api` | optional | | `[1,2]` | `array` | diff --git a/dev-docs/bidders/sublime.md b/dev-docs/bidders/sublime.md index 3b01b3f2e9..e889f44417 100644 --- a/dev-docs/bidders/sublime.md +++ b/dev-docs/bidders/sublime.md @@ -4,15 +4,15 @@ title: Sublime description: Prebid Sublime Bidder Adapter pbjs: true biddercode: sublime -gdpr_supported: true +tcfeu_supported: true gvl_id: 114 +sidebarType: 1 --- ### Note Please contact your Sublime account manager before using this adapter. - ### Bid params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/suntContent.md b/dev-docs/bidders/suntContent.md new file mode 100644 index 0000000000..b6a398fa1d --- /dev/null +++ b/dev-docs/bidders/suntContent.md @@ -0,0 +1,31 @@ +--- +layout: bidder +title: SUNT Content +description: Prebid SUNT Content Bidder Adapter +biddercode: suntContent +tcfeu_supported: true +gvl_id: 1097 +usp_supported: false +coppa_supported: false +schain_supported: false +dchain_supported: false +userId: none +media_types: banner, native +safeframes_ok: true +deals_supported: false +floors_supported: true +fpd_supported: false +pbjs: true +pbs: true +pbs_app_supported: false +prebid_member: false +sidebarType: 1 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------|--------------------|-----------| +| `adUnitId` | required | ID of the Ad Unit | `8ao` | `string` | +| `url` | optional | URL from the Page | `example.tld` | `string` | diff --git a/dev-docs/bidders/supply2.md b/dev-docs/bidders/supply2.md index f216b5f167..f488bb3188 100644 --- a/dev-docs/bidders/supply2.md +++ b/dev-docs/bidders/supply2.md @@ -4,7 +4,8 @@ title: Supply2 description: Prebid Media Donuts Bidder Adaptor pbjs: true biddercode: supply2 -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/synacormedia.md b/dev-docs/bidders/synacormedia.md index a33aec42f1..e271f11c7b 100644 --- a/dev-docs/bidders/synacormedia.md +++ b/dev-docs/bidders/synacormedia.md @@ -1,96 +1,30 @@ --- layout: bidder title: Synacor Media -description: Prebid Synacor Media Bidder Adapter +description: Prebid Synacor Media Bidder Adapter (replaced by "imds") pbjs: true pbs: true biddercode: synacormedia +tcfeu_supported: false +usp_supported: true +userIds: all media_types: banner, video -userIds: identityLink, verizonMediaId, pubCommonId, nextrollId -gdpr_supported: false +coppa_supported: false schain_supported: true -usp_supported: true +dchain_supported: false +safeframes_ok: true pbs_app_supported: true +deals_supported: false +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-any +prebid_member: false +gvl_id: none +sidebarType: 1 +pbjs_version_notes: use imds after 8.0 --- -### Note: - -The Synacor Media bidder adapter requires setup and approval from Synacor. Please reach out to your account manager for more information and to start using it. - -### Configuration - -Synacor Media requires that iframe is used for user syncing. - -Example configuration: - -```javascript -pbjs.setConfig({ - userSync: { - filterSettings: { - iframe: { - bidders: '*', // represents all bidders - filter: 'include' - } - } - } -}); -``` - -### DFP Video Creative -To use video, setup a `VAST redirect` creative within Google AdManager (DFP) with the following VAST tag URL: - -``` -https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm%%&AUCTION_PRICE=%%PATTERN:hb_pb_synacormedia%% -``` - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -| ---- | ----- | ----------- | ------- | ---- | -| `seatId` | required | The seat ID from Synacor Media. This will be the same for all ad units. | `'prebid'` | `string` | -| `tagId` | required | The placement or tag ID from Synacor Media. | `'demo1'` | `string` | -| `bidfloor` | optional | The floor price for the request. | `0.1` | `float` | -| `pos` | optional | The position of the placement on the page, see Open RTB spec v2.5. | `0` | `int` | -| `video` | optional | Optional properties specific to video, see next table | `{ }` | Object | - -### Example Ad Unit -```javascript -var adUnits = [{ - "code": "test-div", - "mediaTypes": { - "video": { - "playerSize": [300, 250], - "context": "instream", - "minduration": 15, - "maxduration": 30, - "startdelay": 1, - "linearity": 1 - } - }, - "bids": [{ - "bidder": "synacormedia", - "params": { - "seatId": "prebid", - "tagId": "demo1", - "bidfloor": 0.20, - "pos": 1 - } - }] -}] -``` - -### Video Parameters (see openrtb 2.5 spec) +# Note -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Default | Type | -| ---- | ----- | ----------- | ------- | ---- | -| `minduration` | optional | Minimum ad duration in seconds | `2` | `int` | -| `maxduration` | optional | Maximum ad duration in seconds | `60` | `int` | -| `startdelay` | optional | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements. | `0` | `int` | -| `placement` | optional | Placement type for the impression. | `null` | `int` | -| `linearity` | optional | Indicates if the impression must be linear, nonlinear, etc. | `1` | `int` | -| `mimes` | optional | Content MIME types supported. | `["video/mp4", "application/javascript"]` | Array(`String`) | -| `protocols` | optional | Array of supported video protocols. | `[1,2,3,4,5,6,7]` | Array(`int`) | -| `api` | optional | List of supported API frameworks for this impression. | `[1,2]` | Array(`int`) | -| `playbackmethod` | optional | Single element array with supported playback methods for this video impression. If multiple values are supplied, first element will be used. | `[1]` | Array(`int`) | +The Synacor Media bidder adapter has been renamed to the [iMedia Digital Services (iMDS)](/dev-docs/bidders/imds.html) adapter, using an bidder code of `imds`. Please update your implementation accordingly. diff --git a/dev-docs/bidders/taboola.md b/dev-docs/bidders/taboola.md new file mode 100644 index 0000000000..8ae4fe2cd5 --- /dev/null +++ b/dev-docs/bidders/taboola.md @@ -0,0 +1,118 @@ +--- +layout: bidder +title: Taboola +description: Prebid Taboola Bidder Adapter +pbjs: true +pbs: true +biddercode: taboola +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +schain_supported: false +media_types: banner +gvl_id: 42 +prebid_member: true +floors_supported: true +safeframes_ok: true +fpd_supported: true +ortb_blocking_supported: partial +deals_supported: false +pbs_app_supported: false +multiformat_supported: will-not-bid +sidebarType: 1 +--- + +### Note + +- Supports `display` format. +- Supports `native` format only in the Prebid Sever. +- Uses `OpenRTB` standard. + +### Registration + +The Taboola Adapter requires setup before beginning. Please contact us at . + +### First Party Data + +Publishers can use the `ortb2` configuration parameter to provide First Party Data. + +#### OpenRTB Parameters + +The following table contains currently supported parameters we parse. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|--------------------|----------|---------------------------------------------------------------|-------------------|----------------| +| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `string array` | +| `badv` | optional | Blocked Advertiser Domains | `['example.com']` | `string array` | +| `wlang` | optional | Allow List of languages for creatives using ISO-639-1-alpha-2 | `['fr', 'en']` | `string array` | + +Notes: + +- will extract the page,ref,domain if passed within `ortb2.site` +- will extract the pageType if passed within the preferred field `ortb2.ext.data.pageType` or `ortb2.ext.data.section` + +Example configuration: + +```javascript +pbjs.setConfig({ + ortb2: { + bcat: ['IAB1-1'], + badv: ['example.com'], + wlang: ['fr', 'en'] + } +}); +``` + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|-------------------|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------|--------------| +| `tagId` | required | Tag ID / Unique Placement Name
      | `'Below The Article'` | `String` | +| `publisherId` | required | Numeric Publisher ID
      (as provided by Taboola) | `'1234567'` | `String` | +| `pageType` | optional, recommended | Kind of content present in the page | `'homepage'` | `String` | +| `position` | optional, recommended | Identify the placement position on screen. Possible values: 0 - 7

      0 Unknown
      1 Above The Fold
      2 Locked (i.e., fixed position)
      3 Below The Fold
      4 Header
      5 Footer
      6 Sidebar
      7 Fullscreen
      | `2` | `Integer` | +| `publisherDomain` | optional | Publisher Domain (server-side adapter only) | `'example.com'` | `String` | +| `bidfloor` | optional | CPM bid floor | `0.25` | `Float` | +| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | +| `badv` | optional | Blocked Advertiser Domains | `'example.com'` | `String Url` | + +Notes: + +- Preferred to provide the `bcat` and `badv` within the first party data (above). When both methods are provided, first party data values will be prioritized. +- If `pageType` or `publisherDomain` provided within the first party data (as explained above), first party data properties will be prioritized. +- `tagId` is an identifier for specific ad placement, and should be the same unique `tagId` per placement/ad unit in all Bid Requests. + +### Example Ad Unit + +```javascript + var adUnits = [{ + code: 'your-unit-container-id', + mediaTypes: { + banner: { + sizes: [[300, 250], [300,600]] + } + }, + bids: [{ + bidder: 'taboola', + params: { + tagId: 'Placement Name', + publisherId: 'your-publisher-id', + publisherDomain: 'example.com',// Optional (server-side adapter only) + pageType: 'news',// Optional + position: 6,// Optional + bidfloor: 0.25, // Optional - default is null + bcat: ['IAB1-1'], // Optional - default is [] + badv: ['example.com'] // Optional - default is [] + } + }] +}]; +``` + +### Native - Prebid Server Adapter + +Currently, supporting native and multi-format (banner and native mixed) requests in the prebid server adapter only. diff --git a/dev-docs/bidders/tagoras.md b/dev-docs/bidders/tagoras.md new file mode 100644 index 0000000000..6c231f97ad --- /dev/null +++ b/dev-docs/bidders/tagoras.md @@ -0,0 +1,70 @@ +--- +layout: bidder +title: Tagoras +description: Prebid Tagoras Bidder Adaptor +biddercode: tagoras +filename: tagorasBidAdapter +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +tcfeu_supported: true +usp_supported: true +coppa_supported: false +schain_supported: true +gpp_supported: true +floors_supported: true +media_types: banner, video +prebid_member: false +safeframes_ok: false +deals_supported: false +pbs_app_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|-------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from Tagoras. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from Tagoras. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | optional | The minimum bid value desired. Tagoras will not respond with bids lower than this value. | `0.90` | `float` | + +## Example + + ```javascript +var adUnits = [{ + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [728, 90] + ] + } + }, + bids: [{ + bidder: 'tagoras', + params: { + cId: '562524b21b1c1f08117fc7f9', // Required - PROVIDED DURING SETUP... + pId: '59ac17c192832d0011283fe3', // Required - PROVIDED DURING SETUP... + bidFloor: 1.23 // Optional + } + }] + } +]; + +// configure pbjs to enable user syncing +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: 'tagoras', + filter: 'include' + } + } + } +}); +``` diff --git a/dev-docs/bidders/talkads.md b/dev-docs/bidders/talkads.md index 8a8dfe4419..262bb30915 100644 --- a/dev-docs/bidders/talkads.md +++ b/dev-docs/bidders/talkads.md @@ -3,8 +3,8 @@ layout: bidder title: Talkads description: Talkads Prebid Bidder Adapter biddercode: talkads -gdpr_supported: true -gvl_id: +tcfeu_supported: true +gvl_id: 1074 usp_supported: false coppa_supported: false media_types: banner, native @@ -12,12 +12,12 @@ safeframes_ok: false pbjs: true pbs: false prebid_member: false -pbjs_version_notes: v4.35 and later +sidebarType: 1 --- ### Registration -The Talkads Adapter requires setup before beginning. Please contact us at www.natexo.com and register to the publisher side. +The Talkads Adapter requires setup before beginning. Please contact us at and register to the publisher side. ### Configuration @@ -55,6 +55,7 @@ var adUnits = [ ``` #### Banner example + ``` var adUnits = [ code: '/19968336/prebid_display_example_1', diff --git a/dev-docs/bidders/taphype.md b/dev-docs/bidders/taphype.md deleted file mode 100644 index d95fe94236..0000000000 --- a/dev-docs/bidders/taphype.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: TapHype -description: Prebid TapHype Bidder Adaptor -pbjs: true -biddercode: taphype -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -The TapHype adaptor requires setup and approval from your TapHype account manager. Please reach out to your account manager to enable Prebid.js for your account. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|------------------------------------|---------|-----------| -| `placementId` | required | The placement ID from TapHype. | `12345` | `integer` | diff --git a/dev-docs/bidders/tappx.md b/dev-docs/bidders/tappx.md index 0797111f67..cdbabb1c7c 100644 --- a/dev-docs/bidders/tappx.md +++ b/dev-docs/bidders/tappx.md @@ -5,18 +5,19 @@ pbs: true pbjs: true media_types: banner, video biddercode: tappx -gdpr_supported: true +tcfeu_supported: true usp_supported: true coppa_supported: true schain_supported: true pbs_app_supported: true gvl_id: 628 userIds: all +sidebarType: 1 --- ### Registration -Please contact tappx@tappx.com to get set up. +Please contact to get set up. ### Bid Params @@ -33,7 +34,8 @@ Please contact tappx@tappx.com to get set up. ### Test Parameters -Use the official test parameter specified in the oRTB standard (https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/OpenRTB%20v3.0%20FINAL.md#object_request) +Use the official test parameter specified in the oRTB standard () ### Other notes + - Parameters host is required in prebidjs and the old versions of prebid server. In case of doubt, always add the parameter. diff --git a/dev-docs/bidders/targetvideo.md b/dev-docs/bidders/targetvideo.md index 34ed9148c9..20658bb2c8 100644 --- a/dev-docs/bidders/targetvideo.md +++ b/dev-docs/bidders/targetvideo.md @@ -4,9 +4,11 @@ title: TargetVideo description: Prebid TargetVideo Bidder Adaptor biddercode: targetVideo media_types: banner -gdpr_supported: true +gvl_id: 786 +tcfeu_supported: true schain_supported: true pbjs: true +sidebarType: 1 --- #### Bid Params diff --git a/dev-docs/bidders/teads.md b/dev-docs/bidders/teads.md index 905567f301..3099d222e9 100644 --- a/dev-docs/bidders/teads.md +++ b/dev-docs/bidders/teads.md @@ -2,25 +2,37 @@ layout: bidder title: Teads description: Prebid Teads Bidder Adapter +prebid_member: true +pbs: true +pbs_app_supported: true pbjs: true +pbjs_version_notes: please avoid using v7.20.0 and v7.21.0 biddercode: teads -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true usp_supported: true schain_supported: true -userIds: flocId, uid2Id +userIds: uid2Id, identityLinkId, lotamePanoramaId, id5Id, criteoId, connectId, quantcastId, publinkId, sharedId, merkleId, kinessoId media_types: banner, video gvl_id: 132 deals_supported: true +multiformat_supported: will-not-bid +ortb_blocking_supported: true +floors_supported: true +coppa_supported: true +gpp_sids: false +fpd_supported: false +sidebarType: 1 --- -### Note: +### Note -The Teads Bidding adapter requires setup before beginning. Please contact us on https://teads.tv/teads-contact/ +The Teads Bidding adapter requires setup before beginning. Please contact us on ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-----------------------|-----------|-----------| -| `pageId` | required | Teads page id | `2453` | `integer` | -| `placementId` | required | Teads placement id | `113244` | `integer` | +| Name | Scope | Description | Example | Type | +|---------------|--------------------|-----------------------|-----------|-----------| +| `pageId` | required(pbjs) | Teads page id | `2453` | `integer` | +| `placementId` | required(pbs,pbjs) | Teads placement id | `113244` | `integer` | diff --git a/dev-docs/bidders/telaria.md b/dev-docs/bidders/telaria.md index 19a99a112d..eac13bda09 100644 --- a/dev-docs/bidders/telaria.md +++ b/dev-docs/bidders/telaria.md @@ -6,7 +6,7 @@ pbjs: true pbs: false biddercode: telaria media_types: video, no-display -gdpr_supported: true +tcfeu_supported: true usp_supported: false coppa_supported: false schain_supported: true @@ -16,7 +16,8 @@ safeframes_ok: false deals_supported: false pbs_app_supported: false fpd_supported: false -gvl_id: 52 +gvl_id: 202 +sidebarType: 1 --- ### Registration @@ -35,6 +36,7 @@ The Telaria adapter requires setup and approval from your Magnite account manage For other parameters, please refer to the **Tag Parameters** section in the [Telaria Console](https://console.telaria.com) ### Example Ad Unit + ```javascript var adUnit = { "code": "video1", @@ -54,7 +56,9 @@ var adUnit = { }] } ``` -### Supply Chain Object: + +### Supply Chain Object + ```javascript // There are two ways of passing the SupplyChain Object to our adapter: // 1) set it in the config @@ -91,6 +95,7 @@ var adUnit = { }] } ``` + [Telaria Prebid Example](https://console.telaria.com/examples/hb/headerbidding.jsp) ### Delivery @@ -108,4 +113,5 @@ var adUnit = { + `3` : Download ### Supply Chain Object + The adapter has been enhanced to accept the supply chain object (schain) if provided. Please refer to [SupplyChain for Non RTB Requests](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md#supplychain-for-non-openrtb-requests) for more information diff --git a/dev-docs/bidders/temedya.md b/dev-docs/bidders/temedya.md index a1e1f1c2c1..60f7b20962 100644 --- a/dev-docs/bidders/temedya.md +++ b/dev-docs/bidders/temedya.md @@ -5,6 +5,7 @@ description: Prebid TE Medya Bidder Adapter. pbjs: true biddercode: temedya media_types: banner,native +sidebarType: 1 --- ### Description @@ -23,6 +24,7 @@ TE Medya header bidding adapter connects with TE Medya demand sources to fetch b ### Test Parameters 300x250 banner test + ``` var adUnits = [{ code: 'div-prebid', @@ -42,6 +44,7 @@ var adUnits = [{ ``` native test + ``` var adUnits = [{ code: 'div-prebid', diff --git a/dev-docs/bidders/theAdx.md b/dev-docs/bidders/theAdx.md index b688704620..261206bc27 100644 --- a/dev-docs/bidders/theAdx.md +++ b/dev-docs/bidders/theAdx.md @@ -1,10 +1,25 @@ --- layout: bidder -title: TheAdx +title: theadx description: Prebid TheAdx Bidder Adapter +pbs: true +pbs_app_supported: true pbjs: true -biddercode: theAdx -gdpr_supported: false +biddercode: theadx +tcfeu_supported: true +usp_supported: true +schain_supported: true +userIds: all +media_types: banner, video +gvl_id: 556 +deals_supported: true +multiformat_supported: will-not-bid +ortb_blocking_supported: true +floors_supported: true +coppa_supported: true +gpp_sids: false +fpd_supported: false +sidebarType: 1 --- @@ -13,7 +28,7 @@ gdpr_supported: false {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |-------------|----------|-----------------------------------------------------------------------|------------|-------| -| `pid` | required | Publisher GUID from TheAdx.com | `'1000'` | `int` | -| `wid` | required | Web Site ID from TheAdx.com | `'2000'` | `int` | -| `tagId` | required | Tag ID from TheAdx.com | `'3000'` | `int` | +| `pid` | required | Publisher GUID from theadx.com | `'1000'` | `int` | +| `wid` | required | Web Site ID from theadx.com | `'2000'` | `int` | +| `tagId` | required | Tag ID from theadx.com | `'3000'` | `int` | | | | | | | diff --git a/dev-docs/bidders/themoneytizer.md b/dev-docs/bidders/themoneytizer.md new file mode 100644 index 0000000000..dfb24508b7 --- /dev/null +++ b/dev-docs/bidders/themoneytizer.md @@ -0,0 +1,26 @@ +--- +layout: bidder +title: The Moneytizer +description: Prebid The Moneytizer Bid Adapter +biddercode: themoneytizer +media_types: display +gvl_id: 1265 +pbjs: true +tcfeu_supported: true +safeframes_ok: false +schain_supported: true +sidebarType: 1 +--- + +### Note + +The Moneytizer Bidding adapter requires setup before beginning. Please contact us at + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|-----------------------------------------|----------------------------------------------|----------| +| `pid` | required | The Moneytizer's publisher token | `1234` | `integer`| +| `test` | optional | Set to 1 to receive a test bid response | `1` | `integer`| +| `baseUrl` | optional | Call on custom endpoint | `'https://custom-endpoint.biddertmz.com/m/'` | `string` | diff --git a/dev-docs/bidders/tim.md b/dev-docs/bidders/tim.md deleted file mode 100644 index 133c062064..0000000000 --- a/dev-docs/bidders/tim.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: Tim Media -description: Prebid Tim Bidder Adaptor -pbjs: true -biddercode: tim -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|----------|----------| -|`placementCode`| required | |'testcode'| `string` | -| `publisherid` | required | |'testid' | `string` | -| `bidfloor` | optional | | 1 | `number` | diff --git a/dev-docs/bidders/topRTB.md b/dev-docs/bidders/topRTB.md deleted file mode 100644 index 2c2a8f83d3..0000000000 --- a/dev-docs/bidders/topRTB.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: bidder -title: TOPRTB -description: Prebid topRTB Bidder Adapter -pbjs: true -biddercode: topRTB -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|----------------------------------------------------------------------------------------|-----------------------------|-----------| -| `adUnitId` | required | adUnit id associated with topRTB | `'3ec5a94f00cf4cc2858bc21533542827'` | `string` | diff --git a/dev-docs/bidders/tpmn.md b/dev-docs/bidders/tpmn.md index 822dfe7308..854dcddb5e 100644 --- a/dev-docs/bidders/tpmn.md +++ b/dev-docs/bidders/tpmn.md @@ -1,17 +1,104 @@ --- layout: bidder title: TPMN -description: Prebid TPMN Bidder Adaptor -pbjs: true +description: Prebid TPMN Bidder Adapter biddercode: tpmn -gdpr_supported: false +gpp_supported: true +safeframes_ok: true +media_types: banner, video, native +tcfeu_supported: false +prebid_member: false +schain_supported: true +coppa_supported: true +usp_supported: true +floors_supported: false +fpd_supported: false +pbjs: true +pbs: true +pbs_app_supported: true +multiformat_supported: will-bid-on-one +ortb_blocking_supported: true +sidebarType: 1 --- +### Note + +TPMN Support media types + +{: .table .table-bordered .table-striped } +| Name | banner | video | native | audio | +|-----------------------|--------|-------|--------|--------| +| Prebid.js | O | O | X | X | +| Prebid Server Adapter | O | O | O | X | + +### Registration -### Bid Params +To use this bidder you will need an account and a valid unit from us. +For further information, please contact `info@tpmn.io` + +### Prebid.js Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|--------------------------------------|------------------|-----------| -| `inventoryId` | required | Inventory ID | `'1'` | `integer` | -| `publisherId` | required | Publisher ID | `'TPMN'` | `string` | +| `inventoryId` | required | Inventory ID | `1` | `integer` | + +### User Sync + +Add the following code to enable user sync. +TPMN strongly recommends enabling user syncing through iFrames. +This functionality improves partners' user match rates and increases the TPMN bid rate and bid price. +Even if iFrame is not active, user sync of some partners is performed. +Be sure to call `pbjs.setConfig()` only once. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + filterSettings: { + iframe: { + bidders: '*', // '*' means all bidders + filter: 'include' + } + } + } +}); +``` + +### Prebid Server Adapter Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|----------------|------------------|-----------| +| `inventoryId` | required | Inventory ID | `1` | `integer` | + +### Prebid Server Adapter Test Request + +The following test parameters can be used to verify that Prebid Server is working properly with the +TPMN adapter. + +```json +{ + "id": "request_id", + "imp": [ + { + "id": "imp_id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "tpmn": { + "inventoryid": 1 + } + } + } + ], + "device": { + "os": "some-Os", + "ua": "some-agent" + }, + "tmax": 500, + "test": 1 +} +``` diff --git a/dev-docs/bidders/trafficgate.md b/dev-docs/bidders/trafficgate.md new file mode 100644 index 0000000000..357660317f --- /dev/null +++ b/dev-docs/bidders/trafficgate.md @@ -0,0 +1,116 @@ +--- +layout: bidder +title: TrafficGate +description: Prebid TrafficGate Bidder Adaptor +pbs: true +pbjs: true +biddercode: trafficgate +media_types: banner, video +tcfeu_supported: false +pbs_app_supported: true +multiformat_supported: will-bid-on-any +usp_supported: true +schain_supported: true +coppa_supported: true +dchain_supported: false +deals_supported: true +floors_supported: false +fpd_supported: false +prebid_member: true +sidebarType: 1 +ortb_blocking_supported: true +safeframes_ok: true +--- + +### Note + +{% include dev-docs/pbjs-adapter-required-for-pbs.md %} + +The TrafficGate Bidding adapter requires setup before beginning. Please contact us at + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|------------------|-------------|----------| +| `placementId` | required | Placement ID | `'12345'` | `string` | +| `host` | required | Host | `'example'` | `string` | +| `customFloor` | optional | Custom Bid Floor | `2.55` | `number` | + +### AdUnit Format for Banner + +```javascript +var adUnits = [{ + code: 'test-banner-div ', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [{ + bidder: 'trafficgate', + params: { + placementId: '16', + host: 'example' + } + }] +}]; +``` + +#### Video + +#### mediaTypes.video + +The following video parameters are supported here so publishers may fully declare their video inventory: + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-----------| +| context | required | instream or outstream |"outstream" | string | +| playerSize| required | width, height of the player in pixels | [640,360] - will be translated to w and h in bid request | array | +| mimes | required | List of content MIME types supported by the player (see openRTB v2.5 for options) | ["video/mp4"]| array| +| protocols | recommended | Supported video bid response protocol values
      1: VAST 1.0
      2: VAST 2.0
      3: VAST 3.0
      4: VAST 1.0 Wrapper
      5: VAST 2.0 Wrapper
      6: VAST 3.0 Wrapper
      7: VAST 4.0
      8: VAST 4.0 Wrapper | [2,3,5,6] | array| +| api | recommended | Supported API framework values:
      1: VPAID 1.0
      2: VPAID 2.0
      3: MRAID-1
      4: ORMMA
      5: MRAID-2 | [2] | array | +| linearity | recommended | OpenRTB2 linearity. 1: linear (in-stream ad), 2: non-linear (overlay ad) | 1 | integer | +| maxduration | recommended | Maximum video ad duration in seconds. | 30 | integer | +| minduration | recommended | Minimum video ad duration in seconds | 6 | integer | +| playbackmethod | recommended | Playback methods that may be in use. Only one method is typically used in practice. (see openRTB v2.5 section 5.10 for options)| [2]| array | +| minbitrate | optional | Minimum bit rate in Kbps. | 300 | integer | +| maxbitrate | optional | Maximum bit rate in Kbps. | 9600 | integer | +| battr | optional | Blocked creative attributes | [13,14] | array| +| startdelay | recommended | Indicates the start delay in seconds for pre-roll, mid-roll, or post-roll ad placements.
      >0: Mid-Roll (value indicates start delay in second)
      0: Pre-Roll
      -1: Generic Mid-Roll
      -2: Generic Post-Roll | 0 | integer | +| placement | recommended | Placement type for the impression. (see openRTB v2.5 section 5.9 for options) | 1 | integer | +| | | | | | + +### AdUnit Format for Video + +```javascript +var videoAdUnits = [{ + code: 'test-div-video', + mediaTypes: { + video: { + playerSize: [640, 480], // required + context: 'instream', // required + mimes: ['video/mp4','video/x-flv'], // required + minduration: 5, // optional + maxduration: 30, // optional + startdelay: 5, // optional + playbackmethod: [1,3], // optional + api: [ 1, 2 ], // optional + protocols: [ 2, 3 ], // optional + battr: [ 13, 14 ], // optional + linearity: 1, // optional + placement: 2, // optional + minbitrate: 10, // optional + maxbitrate: 10 // optional + } + }, + bids: [{ + bidder: 'trafficgate', + params: { + placementId: '10', + host: 'example' + } + }] +}] +``` diff --git a/dev-docs/bidders/trafficroots.md b/dev-docs/bidders/trafficroots.md index 3246eb6b43..6787ccacaf 100644 --- a/dev-docs/bidders/trafficroots.md +++ b/dev-docs/bidders/trafficroots.md @@ -4,7 +4,8 @@ title: Trafficroots description: Prebid Trafficroots Bidder Adapter pbjs: true biddercode: trafficroots -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/tremor.md b/dev-docs/bidders/tremor.md index d1071eeb50..ea9c1d3bb3 100644 --- a/dev-docs/bidders/tremor.md +++ b/dev-docs/bidders/tremor.md @@ -6,6 +6,7 @@ top_nav_section: dev_docs nav_section: reference pbjs: true biddercode: tremor +sidebarType: 1 --- ### Bid Params @@ -25,7 +26,7 @@ biddercode: tremor |`floor` | optional | This is a formatted string of values. The format is a comma separated list of "currency pairs". Each pair consists of a currency code and the floor for that currency, separated by a colon. | `'USD:5.00,AUD:7.25'` | String | |`efloor` | optional | Same as floor, except the entire string is encrypted using HMAC encryption and the encryption keys set on the supply's seat from the SSP UI. | `'IFHR00cxR5ul_t20sMQ0OsvMVP7fOS-mnVsxu78%3d'` | String | |`custom` | optional | Any custom value that will be later be available for reporting. | `'myCustomValue'` | String | -|`categories` | optional | Validated against RTB table 6.1 (Send comma delimited list if more than one category applies. | `'IAB20,IAB20-1'` | +|`categories` | optional | Validated against RTB table 6.1 (Send comma delimited list if more than one category applies. | `'IAB20,IAB20-1'` | |`keywords` | optional | Comma separated list of keywords describing the supply. | `'funny,television'` | String | |`srcRelationship` | optional | Describes the relationship between the content owner and the requestor of the ad opportunity. 1 for "direct", 0 for "indirect" | `1` | Integer | |`blockDomains` | optional | A comma separated list of advertiser domains that should be added to the existing list of blocked advertiser domains that is set in the SSP console. | `'blockthis.com, blockthat.com'` | String | @@ -39,7 +40,6 @@ biddercode: tremor |`minDur` | optional | Minimum duration for an ad in seconds | `15` |Integer | |`maxDur` | optional | Maximum duration for an ad in seconds | `60` |Integer | - The following values are defined in the [ORTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). diff --git a/dev-docs/bidders/trendqube.md b/dev-docs/bidders/trendqube.md deleted file mode 100644 index 725ed5be74..0000000000 --- a/dev-docs/bidders/trendqube.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: bidder -title: Trendqube -description: Prebid Trendqube Bidder Adapter -pbjs: true -biddercode: trendqube -gdpr_supported: true -media_types: banner, video -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: - -The Trendqube Bidding adapter requires setup before beginning. Please contact us at wls_team@smartyads.com - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-----------------------|-----------|-----------| -| `placementId` | required | Adprime placement id | `'1234asdf'` | `'string'` | diff --git a/dev-docs/bidders/trion.md b/dev-docs/bidders/trion.md index 3cab06c082..388e50bbb5 100644 --- a/dev-docs/bidders/trion.md +++ b/dev-docs/bidders/trion.md @@ -5,7 +5,8 @@ description: Prebid Trion Interactive Bidder Adaptor pbjs: true biddercode: trion usp_supported: true -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- diff --git a/dev-docs/bidders/triplelift.md b/dev-docs/bidders/triplelift.md index 24f4b522f3..5cc60ff435 100644 --- a/dev-docs/bidders/triplelift.md +++ b/dev-docs/bidders/triplelift.md @@ -3,8 +3,9 @@ layout: bidder title: TripleLift description: Prebid TripleLift Bidder Adapter biddercode: triplelift -gdpr_supported: true +tcfeu_supported: true usp_supported: true +gpp_supported: true coppa_supported: true schain_supported: true floors_supported: true @@ -18,21 +19,158 @@ pbs: true pbs_app_supported: true fpd_supported: true gvl_id: 28 +sidebarType: 1 --- -{% capture version2 %} -The Triplelift Prebid Server bidding adapter and user sync endpoint require setup before beginning. Please contact us at prebid@triplelift.com. -{% endcapture %} -{% include alerts/alert_important.html content=version2 %} +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Overview](#overview) +- [Bid Params](#bid-params) + - [Banner](#banner) + - [Video](#video) +- [Example Configuration](#example-configuration) + - [Banner](#banner-configuration) + - [Video (Instream)](#video-instream) + - [Video (Outstream)](#video-outstream) +- [First Party Data](#first-party-data) +- [Programmatic DMP](#triplelift-programmatic-dmp) + + + +### Overview + +Publishers may integrate with Triplelift through our Prebid.js and/or Prebid Server adapters. See below for more information. + +{: .alert.alert-info :} +The Triplelift Prebid Server bidding adapter and user sync endpoint require setup before beginning. Please contact us at . + + ### Bid Params +#### Banner + {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|------------------------------|--------------------------------------------------------------------------------------|--------------------------------------------|----------| -| `inventoryCode` | required | TripleLift inventory code for this ad unit (provided to you by your partner manager) | `'pubname_main_feed'` | `string` | -| `floor` | optional | Bid floor | `1.00` | `float` | -| `video` | required for instream video | oRTB video object | `{ mimes: ['video/mp4'], w: 640, h: 480 }` | `object` | -| `video.w` | required for instream video | oRTB video object width dimension | `640` | `int` | -| `video.h` | required for instream video | oRTB video object height dimension | `480` | `int` | +| Name | Scope | Description | Example | Type | +|-----------------|------------------------------|--------------------------------------------------------------------------------------|---------------------------------------------|----------| +| `inventoryCode` | required | TripleLift inventory code for this ad unit (provided to you by your partner manager) | `'pubname_top_banner'` | `string` | +| `floor` | optional | Bid floor | `1.00` | `float` | + +#### Video + +Triplelift bid params for video mediaTypes are identical, but be sure to include the appropriate video.placement value to indicate instream/outstream format. Speak with your partner manager about which value to place here based on what formats are enabled. + +See the [Ad Unit Reference](https://docs.prebid.org/dev-docs/adunit-reference.html#adunitmediatypesvideo) for more info. + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|-----------------|------------------------------|--------------------------------------------------------------------------------------|---------------------------------------------|----------| +| `adUnit.mediaTypes.video.placement` | required | Instream: 1; Outstream: 3, 4, 5. | `3` | `int` | +| `adUnit.mediaTypes.video.playerSize` | required | Video player dimensions or size in pixels | `[640, 480]` | `integer array` | + + + +### Example Configuration + +#### Banner Configuration + +```javascript +var adUnits = [ + { + code: 'top-banner', + mediaTypes: { + banner: { + sizes: [ + [728, 90], + [970, 250] + ] + } + }, + bids: [{ + bidder: 'triplelift', + params: { + inventoryCode: 'pubname_top_banner' + } + }] +}]; +``` + +#### Video (Instream) + +```javascript +var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream', + placement: 1, + mimes: ['video/mp4'] + } + }, + bids: [{ + bidder: 'triplelift', + params: { + inventoryCode: 'pubname_instream1' + } + }] +}; +``` + +#### Video (Outstream) + +```javascript +var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'outstream', + placement: 3, + mimes: ['video/mp4'] + } + }, + bids: [{ + bidder: 'triplelift', + params: { + inventoryCode: 'pubname_outstream', + } + }] +}; +``` + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). The following fields are supported: + +- `ortb2.site.*`: Standard IAB OpenRTB 2.5 site fields +- `ortb2.user.*`: Standard IAB OpenRTB 2.5 user fields + +AdUnit-specific data is supported using `AdUnit.ortb2Imp.ext.*` + + + +### Programmatic DMP + +Triplelift provides audience and contextual targeting via the integration of a Programmatic DMP tag. Please reach out to your Triplelift representative to discuss specifics of the integration. + +#### Requirements + +- Prebid v7.1.0 or later +- In Prebid's `bidderSettings`, the `storageAllowed` parameter must be set to **true**. In Prebid v7.0 and later, `storageAllowed` defaults to false, so you will need to explicitly set this value to true. + + ```javascript + pbjs.bidderSettings = { + triplelift: { + storageAllowed: true + } + } + ``` + +- The Programmatic DMP **tag** must be included at the top of every webpage in order to collect audience and contextual information on the respective page. +- The Programmatic DMP **tag** should be as high up in `` as possible. diff --git a/dev-docs/bidders/triplelift_native.md b/dev-docs/bidders/triplelift_native.md index 8a8c2e00af..92ae078c5f 100644 --- a/dev-docs/bidders/triplelift_native.md +++ b/dev-docs/bidders/triplelift_native.md @@ -3,23 +3,39 @@ layout: bidder title: TripleLift Native description: Prebid TripleLift Native Bidder Adapter biddercode: triplelift_native -gdpr_supported: true +tcfeu_supported: true tcf2_supported: true usp_supported: true coppa_supported: true schain_supported: true floors_supported: true -media_types: banner, video, native +media_types: no-display, native userIds: criteo, identityLink, unifiedId prebid_member: true safeframes_ok: true deals_supported: true -pbjs: true +pbjs: false pbs: true pbs_app_supported: true +fpd_supported: true gvl_id: 28 +sidebarType: 1 --- +{: .alert.alert-info :} +This is a Prebid Server adapter for running component native only. For the standard Prebid JS Triplelift bid adapter, see the "Triplelift" bidder. If you are interested in running component native via Prebid JS, please contact us at . + +{: .alert.alert-info :} +The Triplelift Prebid Server bidding adapter and user sync endpoint require setup before beginning. Please contact us at . + +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [First Party Data](#first-party-data) + + + ### Bid Params {: .table .table-bordered .table-striped } @@ -27,3 +43,12 @@ gvl_id: 28 |------------|----------|------------------------|---------|----------| | inventoryCode | required | TripleLift inventory code for this ad unit (provided to you by your partner manager) | 'code1' | string | | floor | optional | the bid floor, in usd | 1.2 | number | + + + +### First Party Data + +Triplelift supports standard IAB OpenRTB 2.5 First Party Data fields, including: + +- `site.*` +- `user.*` diff --git a/dev-docs/bidders/truereach.md b/dev-docs/bidders/truereach.md index c3b78b7b9c..efbfc0b664 100644 --- a/dev-docs/bidders/truereach.md +++ b/dev-docs/bidders/truereach.md @@ -5,10 +5,12 @@ description: Prebid TrueReach Bidder Adapter biddercode: truereach media_types: banner pbjs: true +sidebarType: 1 --- -### Note: -For more information, please visit us at: [TrueReach Ads](http://doc.truereach.co.in/docs/prebid/js-bidder-adapter.html). +### Note + +For more information, please visit us at: ### Bid Params diff --git a/dev-docs/bidders/trustedstack.md b/dev-docs/bidders/trustedstack.md new file mode 100644 index 0000000000..db9e705a29 --- /dev/null +++ b/dev-docs/bidders/trustedstack.md @@ -0,0 +1,101 @@ +--- +layout: bidder +title: TrustedStack +description: Prebid TrustedStack Bidder Adaptor +biddercode: trustedstack +aliasCode : medianet +tcfeu_supported: false +usp_supported: true +coppa_supported: true +gpp_supported: true +media_types: banner,native,video +multiformat_supported: will-bid-on-any +safeframes_ok: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +prebid_member: false +pbjs: true +gvl_id: 1288 +schain_supported: true +floors_supported: true +fpd_supported: true +pbs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `cid` | required | The customer id provided by TrustedStack. | `'trustedstack_test_customer'` | `string` | +| `crid` | required | The placement id provided by TrustedStack. | `'trustedstack_crid'` | `string` | +| `bidfloor` | optional | Bidfloor for the impression | `1.0` | `float` | +| `video` | required for video Ad units | Object containing video targeting parameters. See [Video Object](#video-object) for details.|`video: { maxduration: 60 }` | `object` | + +#### Video Object + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Example| +|------------|----------|--------------|--------| +|mimes|array of strings|(Recommended) Specifies the video content MIME types supported; for example, video/x-ms-wmv and video/x-flv.|["video/x-ms-wmv","video/x-flv"]| +|minduration|integer|(Recommended) Specifies the minimum video ad duration, in seconds.|10| +|maxduration|integer|(Recommended) Specifies the maximum video ad duration, in seconds.|60| +|w|integer|(Recommended) Specifies the width of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|640| +|h|integer|(Recommended) Specifies the height of the video player, in pixels. Required if playerSize not present in `mediaTypes.video`|480| +|startdelay |integer | (Recommended) Specifies the start delay of the video ad|0| +|battr| array of integers|Specifies the video creative attributes to block. Refer to section 5.3 of the IAB specification for a list of attributes.| [ 13, 14 ]| +|playbackmethod| array of integers| Specifies the allowed playback methods. If not specified, all are assumed to be allowed. Currently supported values are: `1: Autoplay, sound on`; `2: Autoplay, sound off`; `3: Click to play`; `4: Mouse over to play`|[1, 3]| +|api| array of integers| Specifies the supported API frameworks for this impression. If an API is not explicitly listed, it is assumed not to be supported. Currently supported values are: `1: VPAID 1.0`; `2: VPAID 2.0`; `3: MRAID-1`; `4: ORMMA`; `5: MRAID-2`|[1, 2]| +|protocols |array of integers| Array of supported video protocols. Currently supported values are: `1: VAST 1.0`; `2: VAST 2.0`; `3: VAST 3.0`; `4: VAST 1.0 Wrapper`; `5: VAST 2.0 Wrapper`; `6: VAST 3.0 Wrapper`; `7: VAST 4.0`|[1, 2]| +|placement |integer|Placement type for the impression. Possible options: `1: In-Stream`; `2: In-banner`; `3: Outstream/In-article`; `4: In-feed`; `5: Interstitial/Slider/Floating`; `6: Long-Form`;|1| + +Besides the above-mentioned parameters, we support all other OpenRTB 2.x video objects as optional parameters. + +In addition to `bids[].params.video`, TrustedStack adapter consumes parameters specified in the `mediaTypes.video`. + +#### Example of Instream Video Ad-unit + +```javascript +var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + context: "instream", + playerSize: [640, 480], + mimes: ['video/mp4'], + placement: 1 + } + }, + bids: [{ + bidder: 'trustedstack', + params: { + cid: 'trustedstack_test_customer', + crid: 'trustedstack_crid', + } + }] +}; +``` + +#### Example of Banner Ad-unit + +```javascript +var adUnits = [{ + code: 'div-gpt-ad-6874091242345-0', + mediaTypes: { + banner: { + sizes: [ + [728, 90], + [300, 600], + [300, 250] + ], + } + }, + bids: [{ + bidder: 'trustedstack', + params: { + cid: 'trustedstack_test_customer', + crid: 'trustedstack_crid' + } + }] +}]; +``` diff --git a/dev-docs/bidders/trustx.md b/dev-docs/bidders/trustx.md index d0d938c60d..05ac4e2976 100644 --- a/dev-docs/bidders/trustx.md +++ b/dev-docs/bidders/trustx.md @@ -5,19 +5,109 @@ description: Prebid TrustX Bidder Adaptor pbjs: true pbs: true biddercode: trustx +aliasCode: grid media_types: banner, video -gdpr_supported: true +multiformat_supported: will-bid-on-any +gvl_id: 686 (grid) +tcfeu_supported: true usp_supported: true +schain_supported: true +floors_supported: true +userIds: all +tcf2_supported: true +coppa_supported: true fpd_supported: true +pbjs_version_notes: 7.0 and after +sidebarType: 1 --- +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [Bidder Config](#bidder-config) +- [First Party Data](#first-party-data) + + ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|-----------| -| `uid` | required | Represents the TrustX bidder system Ad Slot ID associated with the respective div id from the site page. | `42` | `integer` | -| `priceType` | optional (pbjs only) | Can take the values `gross` or `net`, default value is `net`. Net represents the header bid price with the TrustX header bidder margin already extracted. Gross price does contain the TrustX bidder margin within. | `'gross'` | `string` | -| `keywords` | optional (pbjs only) | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | -| `useNewFormat` | optional (pbjs only) | Indicates to use the new ad request format. | `true` | `boolean` | +| Name | Scope | Description | Example | Type | +|----------------|-----------|----------------------------------------------------------------------------------------------------------|-------------------------------------------|-----------| +| `uid` | required | Represents the TrustX bidder system Ad Slot ID associated with the respective div id from the site page. | `42` | `integer` | +| `keywords` | optional | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | +| `bidFloor` | optional | Floor of the impression opportunity. If present in the request overrides XML info. | `0.8` | `float` | + +Parameter `keywords` must have following format: + +```javascript +{ + "site":{ + "publisher1":[ + { + "name":"SomeKeywordsBlockName", + "segment1Name":[ + "segment2Value" + ], + "segment2Name":[ + "segment2Value1", + "segment2Value2", + ... + ], + ... + } + ], + ... + } +} +``` + + + +### Bidder Config + +You can allow writing in localStorage `pbjs.setBidderConfig` for the bidder `trustx` + +```javascript +pbjs.setBidderConfig({ + bidders: ["trustx"], + config: { + localStorageWriteAllowed: true + } +}) +``` + +If it will be "true" this allow TheMediaGrid Bid Adapter to write userId in first party localStorage + +If you want to make alias on TrustX Bid Adapter, you must set `forceBidderName` in bidderConfig as `"trustx"`. + +```javascript +pbjs.setBidderConfig({ + bidders: ["aliasName"], + config: { + forceBidderName: 'trustx' + } +}) +``` + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.ext.device`: Non standard arbitrary user device +- `ortb2.user.keywords`: Standard IAB OpenRTB 2.5 user.keywords field. It will be included in ext.keywords.user.ortb2 +- `ortb2.site.keywords`: Standard IAB OpenRTB 2.5 site.keywords field. It will be included in ext.keywords.site.ortb2 +- `ortb2.site.cat[]`: Standard IAB OpenRTB 2.5 site.cat field. It will be sent as part of site.cat array +- `ortb2.site.pagecat[]`: Standard IAB OpenRTB 2.5 site.pagecat field. It will be sent as part of site.cat array +- `ortb2.site.content.genre`: Standard IAB OpenRTB 2.5 site.content.genre field + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` +- `ortb2.imp[].instl` diff --git a/dev-docs/bidders/trustxstandalone.md b/dev-docs/bidders/trustxstandalone.md new file mode 100644 index 0000000000..df9726bff2 --- /dev/null +++ b/dev-docs/bidders/trustxstandalone.md @@ -0,0 +1,51 @@ +--- +layout: bidder +title: TrustX (standalone) +description: Prebid TrustX Bidder Adaptor +pbjs: true +biddercode: trustx +media_types: banner, video +multiformat_supported: will-bid-on-any +tcfeu_supported: false +usp_supported: true +fpd_supported: true +pbjs_version_notes: 6.x and before +sidebarType: 1 +--- + +#### Is relevant for versions 6.X and before + +### Table of Contents + +- [Table of Contents](#table-of-contents) +- [Bid Params](#bid-params) +- [First Party Data](#first-party-data) + + + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|-----------| +| `uid` | required | Represents the TrustX bidder system Ad Slot ID associated with the respective div id from the site page. | `42` | `integer` | +| `priceType` | optional (pbjs only) | Can take the values `gross` or `net`, default value is `net`. Net represents the header bid price with the TrustX header bidder margin already extracted. Gross price does contain the TrustX bidder margin within. | `'gross'` | `string` | +| `keywords` | optional (pbjs only) | A set of key-value pairs applied to all ad slots on the page. Values can be empty. | `keywords: { topic: ['stress', 'fear'] }` | `object` | +| `useNewFormat` | optional (pbjs only) | Indicates to use the new ad request format. | `true` | `boolean` | + + + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). + +Global site or user data using `setConfig()`, or Bidder-specific using `setBidderConfig()` supports following fields: + +- `ortb2.user.data[]`: Standard IAB segment taxonomy user data +- `ortb2.user.keywords`: Standard IAB OpenRTB 2.5 user.keywords field. It will be included in ext.keywords.user.ortb2 +- `ortb2.site.keywords`: Standard IAB OpenRTB 2.5 site.keywords field. It will be included in ext.keywords.site.ortb2 + +AdUnit-specific data using `AdUnit.ortb2Imp` supports following fields: + +- `ortb2.imp[].ext.data.*` +- `ortb2.imp[].instl` diff --git a/dev-docs/bidders/ttd.md b/dev-docs/bidders/ttd.md new file mode 100644 index 0000000000..c982c42ee5 --- /dev/null +++ b/dev-docs/bidders/ttd.md @@ -0,0 +1,192 @@ +--- +layout: bidder +title: The Trade Desk +description: The Trade Desk Prebid Bidder Adapter +biddercode: ttd +tcfeu_supported: true +gvl_id: 21 +usp_supported: true +coppa_supported: true +gpp_supported: true +schain_supported: true +dchain_supported: false +userIds: unifiedId, uid2 +media_types: banner, video +floors_supported: true +pbjs: true +pbs: false +prebid_member: true +sidebarType: 1 +--- + +### Disclosure + +This adapter is known to use an HTTP 1 endpoint. Header bidding often generates multiple requests to the same host and bidders are encouraged to change to HTTP 2 or above to help improve publisher page performance via multiplexing. + +{: .alert.alert-danger :} +Note: The Trade Desk Header Bidding adapter requires setup and approval before beginning. Please reach out to for more details. + +### Bid Params + +{: .table .table-bordered .table-striped } +Name | Scope | Description | Example | Type +--- | --- | --- | --- | ---- +`supplySourceId` | required | The TTD-provided supply source name. | `'supplier'` | `String` +`publisherId` | required | The publisher ID. If there is a sellers.json, this should be the same as the seller_id in the sellers.json for the site being trafficked. If there is no sellers.json, this should be hardcoded to "1". | `'1427ab10f2e448057ed3b422'` | `String` +`placementId` | optional | This field is optional if GPID is passed through the GPT module . If that module isn't used, the GPID value should be passed in this field. | `'/1111/home#header'` | `String` +`banner` | optional | Display banner targeting parameters. See the banner section below. | `{}` | `object` +`bidfloor` | optional | Sets a bid floor price | `0.95` | `Float` + +### Banner Object + +The following banner parameters are supported: + +{: .table .table-bordered .table-striped } +Name | Scope | Description | Example | Type +--- | --- | --- | --- | ---- +`expdir` | optional | Directions in which the banner may expand. See "Expandable Direction" in the [OpenRTB 2.5 docs](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for possible values. | `[1, 3]` | `Array[integer]` + +#### `mediaTypes.banner` Parameters + +The TTD adapter for banner uses certain parameters in the AdUnit's +[mediaTypes.banner](https://docs.prebid.org/dev-docs/adunit-reference.html#adUnit.mediaTypes.banner) definition. Specifically, `sizes` is required for banner ad units. `pos` is recommended. + +Here's a banner ad unit example: + +```javascript +var bannerAdUnit = { + code: 'myBannerAdUnit', + mediaTypes: { + banner: { + sizes: [400, 600], + pos: 1 + } + }, + bids: [ + { + bidder: 'ttd', + params: { + supplySourceId: 'supplier' + publisherId: '1427ab10f2e448057ed3b422', + siteId: 'site-123', + placementId: 'sidebar_1', + banner: { + expdir: [1, 3] + }, + bidfloor: 0.95 + } + } + ] +} +``` + +### Video + +#### `mediaTypes.video` Parameters + +The TTD adapter for video requires certain parameters in the AdUnit's +[mediaTypes.video](https://docs.prebid.org/dev-docs/adunit-reference.html#adUnit.mediaTypes.video) definition. Specifically, `maxduration`, `api`, `mimes`, `placement`, and `protocols` are all required for video ad units. `playerSize`, `startdelay`, `playbackmethod`, and `pos` are recommended. `minduration`, `minbitrate`, `maxbitrate`, `skip`, `skipmin`, and `skipafter` are optional. + +Note: TTD does not currently support `adpod` video contexts. + +Here's a video ad unit example: + +```javascript +var videoAdUnit = { + code: 'myVideoAdUnit', + mediaTypes: { + video: { + minduration: 1, + maxduration: 60, + playerSize: [640, 480], + api: [1, 3], + mimes: ['video/mp4'], + placement: 3, + protocols: [2, 3, 5, 6], + startdelay: -1, + playbackmethod: [1], + pos: 1, + minbitrate: 0, + maxbitrate: 5000, + skip: 1, + skipmin: 5, + skipafter: 10 + } + }, + bids: [ + { + bidder: "ttd", + params: { + supplySourceId: 'supplier', + publisherId: '1427ab10f2e448057ed3b422', + siteId: 'site-123', + placementId: 'video1', + bidfloor: 0.95 + } + } + ] +} +``` + +--- +Lists of `api`, `playbackmethod`, `protocols`, `pos`, and `expdir` potential values are in the [OpenRTB 2.5 docs](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf), copied here for convenience: + +`api` + +- `1` : VPAID 1.0 +- `2` : VPAID 2.0 +- `3` : MRAID-1 +- `4` : ORMMA +- `5` : MRAID-2 +- `6` : MRAID-3 +- `7` : OMID-1 + +`playbackmethod` + +- `1` : Initiates on Page Load with Sound On +- `2` : Initiates on Page Load with Sound Off by Default +- `3` : Initiates on Click with Sound On +- `4` : Initiates on Mouse-Over with Sound On +- `5` : Initiates on Entering Viewport with Sound On +- `6` : Initiates on Entering Viewport with Sound Off by Default + +`protocols` + +- `1` : VAST 1.0 +- `2` : VAST 2.0 +- `3` : VAST 3.0 +- `4` : VAST 1.0 Wrapper +- `5` : VAST 2.0 Wrapper +- `6` : VAST 3.0 Wrapper +- `7` : VAST 4.0 +- `8` : VAST 4.0 Wrapper +- `9` : DAAST 1.0 +- `10` : DAAST 1.0 Wrapper +- `11` : VAST 4.1 +- `12` : VAST 4.1 Wrapper + +`pos` + +- `0` : Unknown +- `1` : Above the Fold +- `3` : Below the Fold +- `4` : Header +- `5` : Footer +- `6` : Sidebar +- `7` : Full Screen + +`expdir` + +- `1` : Left +- `2` : Right +- `3` : Up +- `4` : Down +- `5` : Full Screen + +### First Party Data (Supported starting prebid v7.49) + +Publishers should set [First Party Data](https://docs.prebid.org/features/firstPartyData.html) in the `ortb2` and `ortb2Imp` objects. These fields are supported: + +- `ortb2.site.ext.data` +- `ortb2.user.ext.data` +- `AdUnit.ortb2Imp.ext.data` (for AdUnit data) diff --git a/dev-docs/bidders/turktelekom.md b/dev-docs/bidders/turktelekom.md index d845c7e845..c8d73022f8 100644 --- a/dev-docs/bidders/turktelekom.md +++ b/dev-docs/bidders/turktelekom.md @@ -2,21 +2,29 @@ layout: bidder title: Türk Telekom description: Türk Telekom Bidder Adaptor -pbjs: true -pbs: true biddercode: turktelekom -aliasCode : adkernel +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 673 +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true -pbjs_version_notes: v5.18+ +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel safeframes_ok: true +sidebarType: 1 --- -### Note: +### Note The Türk Telekom bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/twistDigital.md b/dev-docs/bidders/twistDigital.md new file mode 100644 index 0000000000..e5e648fce2 --- /dev/null +++ b/dev-docs/bidders/twistDigital.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: Twist Digital +description: Prebid Twist Digital Bidder Adaptor +biddercode: twistdigital +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +media_types: banner, video +gvl_id: 1292 +tcfeu_supported: true +gpp_supported: true +usp_supported: true +coppa_supported: false +multiformat_supported: will-bid-on-one +floors_supported: true +schain_supported: true +safeframes_ok: false +deals_supported: false +pbjs: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|------------------------------------------------------------------------------------------|------------------------------|----------| +| `cId` | required | The connection ID from Twist Digital. | `'562524b21b1c1f08117fc7f9'` | `string` | +| `pId` | required | The publisher ID from Twist Digital. | `'59ac17c192832d0011283fe3'` | `string` | +| `bidFloor` | optional | The minimum bid value desired. Twist Digital will not respond with bids lower than this value. | `0.90` | `float` | +| `subDomain`| optional | Sets the server subdomain, default: 'prebid'. | `'prebid'` | `string` | diff --git a/dev-docs/bidders/ucfunnel.md b/dev-docs/bidders/ucfunnel.md index 75c7140a76..9795cf52ba 100644 --- a/dev-docs/bidders/ucfunnel.md +++ b/dev-docs/bidders/ucfunnel.md @@ -6,25 +6,26 @@ pbjs: true pbs: true biddercode: ucfunnel media_types: banner, video, native -gdpr_supported: true +tcfeu_supported: true usp_supported: true userIds: unifiedId coppa_supported: true schain_supported: true gvl_id: 607 pbs_app_supported: true +sidebarType: 1 --- ### Prebid JS -#### Bid params +#### Bid params (Prebid.js) {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |--------|----------|-------------------------------------------------|---------|----------| | `adid` | required | The ad unit ID retrived from ucfunnel dashboard | | `string` | -``` +```javascript var adUnits = [{ code: 'div-gpt-ad-1460505748511-01', sizes: [ @@ -42,17 +43,17 @@ var adUnits = [{ {: .alert.alert-info :} Sizes set in the `adUnit` object will also apply to the ucfunnel bid requests. - -### Examples + - - [Banner Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_banner.html) - - [Instream Video Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_video.html) - - [Native Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_native.html) +### Examples +- [Banner Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_banner.html) +- [Instream Video Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_video.html) +- [Native Ads](https://cdn.aralego.net/ucfad/test/ucfunnel/compliance/pbjs_native.html) ### Prebid server -#### Bid params +#### Bid params (Prebid Server) {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | diff --git a/dev-docs/bidders/underdogmedia.md b/dev-docs/bidders/underdogmedia.md index 78355b842d..182a7eff30 100644 --- a/dev-docs/bidders/underdogmedia.md +++ b/dev-docs/bidders/underdogmedia.md @@ -4,8 +4,11 @@ title: Underdog Media description: Prebid Underdog Media Bidder Adapter pbjs: true biddercode: underdogmedia -gdpr_supported: true +gvl_id: 159 +tcfeu_supported: true usp_supported: true +userIds: 33acrossId, pubCommonId, unifiedId +sidebarType: 1 --- ### Bid Params @@ -14,3 +17,4 @@ usp_supported: true | Name | Scope | Description | Example | Type | |----------|----------|-------------|---------|----------| | `siteId` | required | | | `string` | +| `productId` | optional | UDM Product ID `'standard'` or `'sticky'`, defaults to `'standard'` | `'standard'` | `string` | diff --git a/dev-docs/bidders/undertone.md b/dev-docs/bidders/undertone.md index 3c079518d2..b776670229 100644 --- a/dev-docs/bidders/undertone.md +++ b/dev-docs/bidders/undertone.md @@ -4,11 +4,14 @@ title: Undertone description: Prebid undertone Bidder Adaptor biddercode: undertone media_types: display, video -gdpr_supported: true +gvl_id: 677 +tcfeu_supported: true usp_supported: true schain_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId pbjs: true +pbs: true +sidebarType: 1 --- @@ -18,10 +21,9 @@ pbjs: true {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------------------------------------|------------|-----------| -| `placementId` | required | Your placement ID (provided by undertone) | `"13as14d0"` | `string` | +| `placementId` | required | Your placement ID (provided by undertone) | `1234` | `integer` | | `publisherId` | required | publisher ID (provided by undertone) | `12345` | `integer` | - #### Video Object {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/unibots.md b/dev-docs/bidders/unibots.md index d8b859e629..f086697bf0 100644 --- a/dev-docs/bidders/unibots.md +++ b/dev-docs/bidders/unibots.md @@ -2,19 +2,28 @@ layout: bidder title: Unibots description: Unibots Bidder Adaptor -pbjs: true -pbs: true biddercode: unibots -aliasCode : adkernel +pbjs: true +pbs: false media_types: banner, native, video -gdpr_supported: true +gvl_id: 14 (adkernel) +tcfeu_supported: true +gpp_supported: true usp_supported: true coppa_supported: true pbs_app_supported: true schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true +aliasCode: adkernel +sidebarType: 1 --- -### Note: +### Note The Unibots bidding adapter requires setup and approval before implementation. Please reach out to for more details. diff --git a/dev-docs/bidders/unicorn.md b/dev-docs/bidders/unicorn.md index 21a645f404..91360b76cc 100644 --- a/dev-docs/bidders/unicorn.md +++ b/dev-docs/bidders/unicorn.md @@ -7,6 +7,7 @@ pbs: true pbs_app_supported: true media_types: banner biddercode: unicorn +sidebarType: 1 --- ### bid params @@ -14,8 +15,10 @@ biddercode: unicorn {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|-------------------------------------------|------------|-----------| -| `placementId` | optional | Your placement ID | `'rectangle-ad-1'` | `string` | -| `accountId` | required | Account ID for charge request (provided by UNICORN) | `12345` | `integer` | -| `publisherId` | optional | Account specific publisher id. | `67890` | `integer` | -| `mediaId` | required for Prebid Server, optional for Prebid.js | Publisher specific media id. | `'example'` | `string` | +| `placementId` | optional | Your placement ID | `'rectangle-ad-1'` | `string` | +| `accountId` | required | Account ID for charge request (provided by UNICORN) | `12345` | `integer` | +| `publisherId` | optional | Account specific publisher id. | `'67890'` | `string` | +| `mediaId` | optional | Publisher specific media id. | `'example'` | `string` | | `bcat` | optional for Prebid.js | Blocked IAB categories | `['IAB-1', 'IAB-2']` | `[string]` | + +`publisherId` as `integer` is also supported on Prebid.js diff --git a/dev-docs/bidders/unruly.md b/dev-docs/bidders/unruly.md index 89bdd181cd..7a0824c838 100644 --- a/dev-docs/bidders/unruly.md +++ b/dev-docs/bidders/unruly.md @@ -3,9 +3,9 @@ layout: bidder title: Unruly description: Prebid Unruly Bidder Adaptor biddercode: unruly -gdpr_supported: true +tcfeu_supported: true usp_supported: true -coppa_supported: false +coppa_supported: true schain_supported: true floors_supported: true media_types: banner, video @@ -16,7 +16,9 @@ deals_supported: check with bidder pbjs: true pbs: true pbs_app_supported: true +fpd_supported: true gvl_id: 36 +sidebarType: 1 --- ### Bid Params @@ -24,5 +26,63 @@ gvl_id: 36 {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |--------------------|----------------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|-----------| -| `siteId` | required | The site ID from Unruly. This will be provided to you by your Unruly account manager. | `123456` | `integer` | +| `siteId` | required | The site ID from Unruly(Nexxen). This will be provided to you by your Unruly account manager, this is prefered. | `123456` | `integer` | +| `siteid` | deprecated | The site ID from Unruly. This will be provided to you by your Unruly account manager, this is backward compability. | `123456` | `integer` | | `featureOverrides` | optional | This param is a generic object for configuring Unruly outstream demand. To run UNmissable, set ‘canRunUnmissable’ to true. | `"featureOverrides": {"canRunUnmissable": true}` | `object` | + +### Protected Audience API (FLEDGE) support + +There’s an option to receive demand for Protected Audience API (FLEDGE/PAAPI) +ads using Unruly's (Nexxen) bid adapter. +Prebid’s [fledgeForGpt](https://docs.prebid.org/dev-docs/modules/fledgeForGpt.html) +module and Google Ad Manager is currently required. + +The following steps should be taken to setup Protected Audience for Unruly(Nexxen): + +1. Reach out to your account manager to coordinate set up: + +2. Build and enable FLEDGE module as described in +[fledgeForGpt](https://docs.prebid.org/dev-docs/modules/fledgeForGpt.html) +module documentation. + + Make sure to enable Unruly bidder to participate in FLEDGE. If there are any other bidders to be allowed for that, add them to the **bidders** array: + + ```javascript + pbjs.setBidderConfig({ + bidders: ["unruly"], + config: { + fledgeEnabled: true + } + }); + ``` + +### First Party Data + +Publishers should use the `ortb2` method of setting [First Party Data](https://docs.prebid.org/features/firstPartyData.html). The following fields are supported: + +- `ortb2.site.*` + +AdUnit-specific data is supported using `AdUnit.ortb2Imp.ext.*` + +Example of first party data available only to the Unruly (Nexxen) bidder. Applies across all ad units. We support up to 5 custom keys. + +```javascript +pbjs.setBidderConfig({ + bidders: ["unruly"], + config: { + ortb2: { + site: { + ext: { + data: { + customkey1: "value1", + customkey2: "value2", + customkey3: "value3", + customkey4: "value4", + customkey5: "value5" + } + } + } + } + } +}); +``` diff --git a/dev-docs/bidders/uol.md b/dev-docs/bidders/uol.md index f86bbc7881..4beb2fd47d 100644 --- a/dev-docs/bidders/uol.md +++ b/dev-docs/bidders/uol.md @@ -1,27 +1,27 @@ --- layout: bidder title: UOL -description: Prebid UOL Bidder Adaptor -pbjs: true +description: UOL Bidder Adapter biddercode: uol -gdpr_supported: false -media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x +pbjs: true +pbs: false +aliasCode: appnexus +tcfeu_supported: true +media_types: banner, video, native +gvl_id: 32 (appnexus) +schain_supported: true +userId: all +sidebarType: 1 --- - - -### Note: -The UOL Project adapter requires setup and approval from the UOL Project team, even for existing UOL Project publishers. Please reach out to your account team or l-prebid@uolinc.com for more information. - ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | -|-----------------+----------+------------------------------------------------------------------+------------------------| -| `placementId` | required | UOL placement ID | '123124', 123154 | -| `test` | optional | Activate AdServer test endpoint | true, false | -| `cpmFactor` | optional | Positive Integer value that will be used by the AdServer as a cpm multiplier. If passed, also requires 'test' flag to be set to 'true' | 1, 2, 5 | +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementID` | required | Placement id | `'11111'` | `string` | + +Uol is an aliased bidder for AppNexus. + +### Note -## Note: -Currently, the UOL bidAdapter is under initial tests. Please follow this page for updates regarding required parameters and new features. +The UOL bidder adapter requires setup before beginning. Please contact us at . diff --git a/dev-docs/bidders/valueimpression.md b/dev-docs/bidders/valueimpression.md index 4b47750e85..6d2c93234b 100644 --- a/dev-docs/bidders/valueimpression.md +++ b/dev-docs/bidders/valueimpression.md @@ -6,14 +6,16 @@ pbjs: true biddercode: valueimpression aliasCode: apacdex media_types: banner, video -gdpr_supported: true +tcfeu_supported: false schain_supported: true usp_supported: true userIds: all floors_supported: true pbs: true pbs_app_supported: true +sidebarType: 1 --- -# Description +## Description + Valueimpression is an aliased bidder of Apacdex bid adapter. Please refer to [Apacdex documentation](https://docs.prebid.org/dev-docs/bidders/apacdex) for bid parameters and implementation guide. diff --git a/dev-docs/bidders/vdoai.md b/dev-docs/bidders/vdoai.md index 1ff9f59566..d4d9649ae5 100644 --- a/dev-docs/bidders/vdoai.md +++ b/dev-docs/bidders/vdoai.md @@ -5,6 +5,7 @@ description: Prebid vdo.ai Bidder Adaptor pbjs: true biddercode: vdoai media_types: banner, video +sidebarType: 1 --- diff --git a/dev-docs/bidders/ventes.md b/dev-docs/bidders/ventes.md index ce1e7c575e..f361123106 100644 --- a/dev-docs/bidders/ventes.md +++ b/dev-docs/bidders/ventes.md @@ -4,39 +4,41 @@ title: ventes description: Prebid ventes Bidder Adapter pbjs: true biddercode: ventes -gdpr_supported: false +tcfeu_supported: false usp_supported: false media_types: banner coppa_supported: false schain_supported: false dchain_supported: false prebid_member: false +sidebarType: 1 --- ### BidParams + {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | +| Name | Scope | Description | Example | Type | |-----------------|----------|-----------------------------------------------------------|----------------------------------------------|---------------| -| `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` | -| `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` | -| `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` | -| `app` | required | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` | -| `device` | required | Object containing device info mandatory for mobile devices| `device : { ifa: 'device-id'}` | `object` | +| `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` | +| `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` | +| `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` | +| `app` | required | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` | +| `device` | required | Object containing device info mandatory for mobile devices| `device : { ifa: 'device-id'}` | `object` | #### User Object {: .table .table-bordered .table-striped } -| Name | Description | Example | Type | +| Name | Description | Example | Type | |-------------------|-------------------------------------------------------------------------------------------|-----------------------|-----------------------| -| `age` | The age of the user. | `35` | `integer` | -| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | -| `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array` | -| `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` | -| `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | -| `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | - +| `age` | The age of the user. | `35` | `integer` | +| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` | +| `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array` | +| `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` | +| `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` | +| `language` | Two-letter ANSI code for this user's language. | `EN` | `string` | ### Ad Unit Setup for Banner through mobile devices + ```javascript var adUnits = [ { @@ -72,6 +74,7 @@ var adUnits = [ ``` ### Ad Unit Setup for Banner through Websites + ```javascript var adUnits = [ { diff --git a/dev-docs/bidders/verizonmedia.md b/dev-docs/bidders/verizonmedia.md deleted file mode 100644 index 52d6a41522..0000000000 --- a/dev-docs/bidders/verizonmedia.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: VerizonMedia -pbs: true -media_types: banner -biddercode: verizonmedia -prebid_member: true -gdpr_supported: true -gvl_id: 25 ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|------------------------|---------|----------| -| dcn | required | Site ID provided by One Mobile | 'site1' | string | -| pos | required | Placement ID | 'placement1' | string | diff --git a/dev-docs/bidders/vertamedia.md b/dev-docs/bidders/vertamedia.md index 6c379edef4..850f10fb23 100644 --- a/dev-docs/bidders/vertamedia.md +++ b/dev-docs/bidders/vertamedia.md @@ -5,6 +5,7 @@ description: Prebid Vertamedia Bidder Adaptor pbjs: true biddercode: vertamedia media_types: video +sidebarType: 1 --- ### Bid params @@ -14,14 +15,15 @@ media_types: video |-------|----------|--------------------------------|----------|-----------| | `aid` | required | The source ID from Vertamedia. | `350975` | `integer` | - ### Description + Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. This adapter provides a solution for accessing Video demand and display demand ### Test Parameters + ``` var adUnits = [ diff --git a/dev-docs/bidders/vertoz.md b/dev-docs/bidders/vertoz.md deleted file mode 100644 index 09023bc7cc..0000000000 --- a/dev-docs/bidders/vertoz.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: Vertoz -description: Prebid Vertoz Bidder Adaptor -pbjs: true -biddercode: vertoz ---- - -### Note: - -The Vertoz adapter currently doesn't support multiple sizes per ad placement and will favour the first one if multiple sizes exists. - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|---------------------|---------------|----------| -| placementId | required | vertoz placement id | `'VH-HB-123'` | `string` | -| cpmFloor | optional | cpm floor price | `0.1` | `float` | diff --git a/dev-docs/bidders/vi.md b/dev-docs/bidders/vi.md deleted file mode 100644 index 6720490630..0000000000 --- a/dev-docs/bidders/vi.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: bidder -title: vi -description: vi bid adapter -pbjs: true -biddercode: vi -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### bid params -{: .table .table-bordered .table-striped } - -| Name | Scope | Description | Example | -| :------------ | :------- | :---------------------------------------------- | :--------------------------------- | -| `pubId` | required | Publisher ID, provided by vi | 'sb_test' | -| `lang` | required | Ad language, in ISO 639-1 language code format | 'en-US', 'es-ES', 'de' | -| `cat` | required | Ad IAB category (top-level or subcategory), single one supported | 'IAB1', 'IAB9-1' | -| `bidFloor` | optional | Lowest value of expected bid price | 0.001 | -| `useSizes` | optional | Specifies from which section of the config sizes are taken, possible values are 'banner', 'video'. If omitted, sizes from both sections are merged. | 'banner' | diff --git a/dev-docs/bidders/viant.md b/dev-docs/bidders/viant.md new file mode 100644 index 0000000000..5fc616a4af --- /dev/null +++ b/dev-docs/bidders/viant.md @@ -0,0 +1,36 @@ +--- +layout: bidder +title: Viant +description: Prebid Viant Bidder Adapter +biddercode: viantOrtb +media_types: banner, video, native +tcfeu_supported: false +coppa_supported: true +usp_supported: true +gpp_supported: false +schain_supported: true +userId: uid2, unifiedId +pbjs: true +prebid_member: true +dchain_supported: false +safeframes_ok: false +deals_supported: true +floors_supported: true +fpd_supported: false +ortb_blocking_supported: false +gvl_id: none +pbs: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Registration + +If you have any questions regarding set up, please reach out to . + +#### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------| +| `publisherId` | required | PublisherId to identify the Site from which Bid Requests will be seen. | `12345` | `integer` | diff --git a/dev-docs/bidders/vibrantmedia.md b/dev-docs/bidders/vibrantmedia.md index 437583bcdb..fa7e0c3202 100644 --- a/dev-docs/bidders/vibrantmedia.md +++ b/dev-docs/bidders/vibrantmedia.md @@ -3,18 +3,18 @@ layout: bidder title: Vibrant Media description: Vibrant Media Prebid Bidder Adapter biddercode: vibrantmedia -gdpr_supported: true +tcfeu_supported: true gvl_id: 7 usp_supported: true media_types: banner, video, native safeframes_ok: false pbjs: true -pbjs_version_notes: 6.4.0 and later +sidebarType: 1 --- ### Preliminaries -The Vibrant Media Adapter requires set-up before being enabled. Please contact us at intellitxtsupport@vibrantmedia.com. +The Vibrant Media Adapter requires set-up before being enabled. Please contact us at . Note: For video, we support outstream only. diff --git a/dev-docs/bidders/vidazoo.md b/dev-docs/bidders/vidazoo.md index 5baf2a5a15..a058e6d9af 100644 --- a/dev-docs/bidders/vidazoo.md +++ b/dev-docs/bidders/vidazoo.md @@ -4,9 +4,13 @@ title: Vidazoo description: Prebid Vidazoo Bidder Adaptor biddercode: vidazoo userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId -gdpr_supported: true +media_types: banner, video +gvl_id: 744 +tcfeu_supported: true +gpp_supported: true usp_supported: true pbjs: true +sidebarType: 1 --- ### Bid Params @@ -16,5 +20,5 @@ pbjs: true |------------|----------|------------------------------------------------------------------------------------------|------------------------------|----------| | `cId` | required | The connection ID from Vidazoo. | `'562524b21b1c1f08117fc7f9'` | `string` | | `pId` | required | The publisher ID from Vidazoo. | `'59ac17c192832d0011283fe3'` | `string` | -| `bidFloor` | required | The minimum bid value desired. Vidazoo will not respond with bids lower than this value. | `0.90` | `float` | +| `bidFloor` | optional | The minimum bid value desired. Vidazoo will not respond with bids lower than this value. | `0.90` | `float` | | `subDomain`| optional | Sets the server subdomain, default: 'prebid'. | `'prebid'` | `string` | diff --git a/dev-docs/bidders/vidcrunch.md b/dev-docs/bidders/vidcrunch.md index 41a592a164..6b485ca8d8 100644 --- a/dev-docs/bidders/vidcrunch.md +++ b/dev-docs/bidders/vidcrunch.md @@ -6,14 +6,17 @@ pbjs: true biddercode: vidcrunch aliasCode: aniview media_types: banner, video -gdpr_supported: true +gvl_id: 780 (aniview) +tcfeu_supported: true usp_supported: true schain_supported: true safeframes_ok: true +sidebarType: 1 --- -### Note: -For more information about [VidCrunch](https://vidcrunch.com/), please contact info@vidcrunch.com. +### Note + +For more information about [VidCrunch](https://vidcrunch.com/), please contact . ### Bid Params @@ -24,8 +27,9 @@ For more information about [VidCrunch](https://vidcrunch.com/), please contact i | `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | ### Test Parameters -``` -videoAdUnit = [ + +```javascript +const videoAdUnit = [ { code: 'video1', mediaTypes: { diff --git a/dev-docs/bidders/vidcrunchllc.md b/dev-docs/bidders/vidcrunchllc.md new file mode 100644 index 0000000000..8ba5524912 --- /dev/null +++ b/dev-docs/bidders/vidcrunchllc.md @@ -0,0 +1,110 @@ +--- +layout: bidder +title: VidCrunch LLC +description: VidCrunch Bidder Adapter +biddercode: vidcrunchllc +aliasCode: adtelligent +media_types: video,banner +gvl_id: 410 (adtelligent) +tcfeu_supported: true +gpp_supported: true +userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId +schain_supported: true +coppa_supported: true +usp_supported: true +safeframes_ok: true +prebid_member: true +pbjs: true +pbs: false +deals_supported: false +sidebarType: 1 +enable_download: false +pbjs_version_notes: removed in 8.13.0 +--- + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------|----------|---------------------------------|----------|-----------| +| `aid` | required | The source ID from VidCrunch. | `529814` | `integer` | + +### Description + +VidCrunch header bidding adapter connects with VidCrunch demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand and display demand. + +### Test Parameters + +``` javascript + var adUnits = [ + + // Video instream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'vidcrunchllc', + params: { + aid: 472386 + } + }] + }, + + // Video outstream adUnit + { + code: 'test-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'vidcrunchllc', + params: { + aid: 472386 + } + }] + }, + + // Video ADPOD adUnit + { + code: 'test-div', + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'vidcrunchllc', + params: { + aid: 472386 + } + }] + }, + + // Banner adUnit + { + code: 'test-div', + mediaTypes:{ + banner:{ + sizes: [[300, 250]] + } + } + bids: [{ + bidder: 'vidcrunchllc', + params: { + aid: 529814 + } + }] + } + ]; +``` diff --git a/dev-docs/bidders/videobyte.md b/dev-docs/bidders/videobyte.md index c0c5710981..b5977f553a 100644 --- a/dev-docs/bidders/videobyte.md +++ b/dev-docs/bidders/videobyte.md @@ -6,12 +6,14 @@ pbjs: true pbs: true biddercode: videobyte media_types: display, video -gdpr_supported: true +gvl_id: 104 +tcfeu_supported: true usp_supported: true schain_supported: true +sidebarType: 1 --- -### Note: +### Note The VideoByte Prebid.js client adapter only supports video ads while our Prebid Server adapter supports both display and video. @@ -21,7 +23,6 @@ for more details about Prebid Client integration. See [Videobyte Prebid Server Documentation](https://videobyte.readme.io/reference/vbx-integration-prebid-server) for more details about Prebid Server integration. - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/videofy.md b/dev-docs/bidders/videofy.md deleted file mode 100644 index b86bd59ee7..0000000000 --- a/dev-docs/bidders/videofy.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: bidder -title: Videofy -description: Prebid Videofy Bidder Adaptor -pbjs: true -biddercode: videofy -media_types: video -gdpr_supported: true -usp_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -For more information about [Videofy](https://videofy.ai/), please contact support1@videofy.ai - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------------|----------|------------------|------------------------------|----------| -| `AV_PUBLISHERID` | required | Publisher/Netid | `'55b88d4a181f465b3e8b4567'` | `string` | -| `AV_CHANNELID` | required | Channel id | `'5a5f17a728a06102d14c2718'` | `string` | diff --git a/dev-docs/bidders/videoheroes.md b/dev-docs/bidders/videoheroes.md new file mode 100644 index 0000000000..637d9326ed --- /dev/null +++ b/dev-docs/bidders/videoheroes.md @@ -0,0 +1,29 @@ +--- +layout: bidder +title: VideoHeroes +description: Prebid VideoHeroes Bidder Adapter +biddercode: videoheroes +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +media_types: banner, video, native +safeframes_ok: true +bidder_supports_deals: true +pbjs: true +pbs: true +floors_supported: true +pbs_app_supported: true +sidebarType: 1 +--- + +### Note + +The VideoHeroes Header Bidding adapter requires setup and approval from the VideoHeroes team. Please reach out to your account manager or for more information + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------|----------|---------------------|------------------------------------------|----------| +| placementId | required | VideoHeroes platform placement id | `'1a8d9c22db19906cb8a5fd4518d05f62'` | `string` | diff --git a/dev-docs/bidders/videonow.md b/dev-docs/bidders/videonow.md index f7fd1a4f6c..b91e3aa676 100644 --- a/dev-docs/bidders/videonow.md +++ b/dev-docs/bidders/videonow.md @@ -5,22 +5,20 @@ description: Prebid Videonow Bidder Adaptor biddercode: videonow pbjs: true media_types: banner -enable_download: false -pbjs_version_notes: not ported to 5.x +sidebarType: 1 --- -### Note: +### Note The Videonow Bidder Adapter requires setup and approval from Videonow. Please reach out to for more information. - ### Bid params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------------|----------|----------------------------------------------------------------------------|-----------|----------| -| pId | required | profile ID | `'5468'` | `string` | -| placementId | required | identifier of the element on the page to which the banner will be attached | `'div-0'` | `string` | -| currency | Optional | Currency | `'RUB'` | `string` | -| bidFloor | Optional | Bid floor rate | `'1.25'` | `string` | +| Name | Scope | Description | Example | Type | +|-------------|----------|----------------------------------------------------------------------------|-----------------------------------|----------| +| pId | required | profile ID | `'5468'` | `string` | +| currency | Optional | Currency | `'RUB'` | `string` | +| url | Optional | for debug, bidder url | `'https://adx.videonow.ru/yhb'` | `string` | +| codeType | Optional | for debug, yhb codeType | `'combo'` | `string` | diff --git a/dev-docs/bidders/videoreach.md b/dev-docs/bidders/videoreach.md index a38870bea6..553e5ffead 100644 --- a/dev-docs/bidders/videoreach.md +++ b/dev-docs/bidders/videoreach.md @@ -5,9 +5,13 @@ description: Video Reach Bidder Adapter for Prebid.js pbjs: true biddercode: videoreach media_types: banner, video -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- +### Disclosure + +Note: This bidder's user syncs appear to only consider gdprApplies if a consent string is available. This may result in some incorrect TCF2 processing, such as when the consent string is not yet available but the publisher has decided GDPR always applies. See ### Bid Params diff --git a/dev-docs/bidders/vidoomy.md b/dev-docs/bidders/vidoomy.md index bb8b8f2dd2..cc5c090252 100644 --- a/dev-docs/bidders/vidoomy.md +++ b/dev-docs/bidders/vidoomy.md @@ -5,28 +5,82 @@ description: Prebid Vidoomy Bidder Adaptor pbjs: true biddercode: vidoomy media_types: banner, video -gdpr_supported: true +tcfeu_supported: true gvl_id: 380 usp_supported: true coppa_supported: true pbs: true +sidebarType: 1 +schain_supported: true +ortb_blocking_supported: true +userIds: all +floors_supported: true --- -### Note: -[Vidoomy](https://vidoomy.com/), for more info please contact support@vidoomy.com +### Note -### Bid Params +[Vidoomy](https://vidoomy.com/), for more info please contact + +### Client Side Bid Params {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------------|----------|------------------|------------------------------|----------| -| `id` | required | id | `123123` | `string` | +| `id` | required | id | `'123123'` | `string` | | `pid` | required | pid | `'123123'` | `string` | +| `bidfloor` | optional | CPM bidfloor in USD | `0.08` | `float` | + +### Server Side Bid Params (Prebid Server) + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|----------|----------|---------------------------------------------|-------------------|----------------| +| `zoneId` | required | Zone Id | `'123123'` | `string` | +| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `string array` | +| `badv` | optional | Blocked Advertiser Domains | `['example.com']` | `string array` | +| `bapp` | optional | blocked advertiser mobile app bundles | `['app.com']` | `string array` | +| `btype` | optional | blocked creative types (e.g. XHTML) | `[1, 2, 3]` | `int array` | +| `battr` | optional | blocked creative attributes (e.g. audio) | `[1, 2, 3]` | `int array` | + +Notes: + +- Preferred to provide the `bcat`, `badv`, `bapp`, `btype` and `battr` within the first party data (above). When both + methods are provided, first + party data values will be prioritized. + +### First Party Data +Publishers can use the `ortb2` configuration parameter to provide First Party Data. -### Bid Params (Prebid Server) +#### OpenRTB Parameters + +The following table contains currently supported parameters we parse. {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------------|----------|------------------|------------------------------|----------| -| `zoneId` | required | Zone Id | "123123" | `string` | + +| Name | Scope | Description | Example | Type | +|---------|----------|---------------------------------------------|-------------------|---------| +| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | +| `badv` | optional | Blocked Advertiser Domains | `['example.com']` | `Array` | +| `bapp` | optional | blocked advertiser mobile app bundles | `['app.com']` | `Array` | +| `btype` | optional | blocked creative types (e.g. XHTML) | `[1, 2, 3]` | `Array` | +| `battr` | optional | blocked creative attributes (e.g. audio) | `[1, 2, 3]` | `Array` | + +Notes: + +- will extract the bcat,badv,bapp,btype,battr if passed within `ortb2` + +Example configuration: + +``` +pbjs.setConfig({ + ortb2: { + bcat: ['IAB1-1'], + badv: ['example.com'], + bapp: ['app.com'], + btype: [1, 2, 3], + battr: [1, 2, 3] + } +}); +``` diff --git a/dev-docs/bidders/viewdeos.md b/dev-docs/bidders/viewdeos.md index aacb4a2a6d..0f0431b2d0 100644 --- a/dev-docs/bidders/viewdeos.md +++ b/dev-docs/bidders/viewdeos.md @@ -6,8 +6,9 @@ pbjs: false pbs: true biddercode: viewdeos media_types: banner,video -gdpr_supported: true +tcfeu_supported: true gvl_id: 924 +sidebarType: 1 --- ### Bid params @@ -18,6 +19,7 @@ gvl_id: 924 | `aid` | required | The source ID from member zone | `350975` | `integer` | ### Test Parameters + ``` var adUnits = [ // Banner adUnit diff --git a/dev-docs/bidders/viewdeosDX.md b/dev-docs/bidders/viewdeosDX.md index 3c8ee83b72..ccb428f03a 100644 --- a/dev-docs/bidders/viewdeosDX.md +++ b/dev-docs/bidders/viewdeosDX.md @@ -6,8 +6,9 @@ pbjs: true pbs: false biddercode: viewdeosDX media_types: banner,video -gdpr_supported: true +tcfeu_supported: true gvl_id: 924 +sidebarType: 1 --- Note that for Prebid Server, use "viewdeos" bidder code. @@ -44,6 +45,7 @@ Note that for Prebid Server, use "viewdeos" bidder code. | `detach_height` | optional | detached player's height in pixels | `200` | `integer` | ### Test Parameters + ``` var adUnits = [ diff --git a/dev-docs/bidders/viously.md b/dev-docs/bidders/viously.md new file mode 100644 index 0000000000..662f48638e --- /dev/null +++ b/dev-docs/bidders/viously.md @@ -0,0 +1,96 @@ +--- +layout: bidder +title: Viously +description: Prebid Viously Bidder Adaptor +pbjs: true +pbs: false +biddercode: viously +media_types: banner, video +tcfeu_supported: true +gvl_id: 1028 +usp_supported: true +prebid_member: false +schain_supported: false +safeframes_ok: true +deals_supported: false +floors_supported: false +fpd_supported: false +ortb_blocking_supported: false +multiformat_supported: will-bid-on-one +sidebarType: 1 +--- + +### Note + +Viously Header Bidding adapter requires setup and approval. Please reach out to for more details. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|---------------------------------------------------------------------------------------------|------------|-----------| +| `pid` | required | Your publisher ID. This information will be given to you by the Viously team. | `1234` | `integer` | + +### Banner Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|--------|----------|--------------------------------------------------------|--------------|-----------| +| `size` | required | The size (width, height) of the banner, in pixels. | `[640, 480]` | `String` | +| `pos` | required | The position of the banner following the OpenRTB spec. | `0` | `integer` | + +### Video Object + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------------|----------|--------------------------------------------------------------------------|--------------|------------------| +| `context` | required | The video context, either 'instream', 'outstream'. | `instream` | `String` | +| `playerSize` | required | The size (width, height) of the video player on the page, in pixels. | `[640, 480]` | `Array` | +| `playbackmethod` | required | Defines how the video inventory is initiated following the OpenRTB spec. | `[4, 5]` | `Array` | + +### Example + +``` +var adUnits = [ + { + code: 'test-viously', + mediaTypes: { + banner: { + size: [640, 360], + pos: 0 + } + }, + bids: [ + { + bidder: 'viously', + params: { + pid: '20d30b78-43ec-11ed-b878-0242ac120001' + } + } + ] + } +] +``` + +``` +var adUnits = [ + { + code: 'test-viously', + mediaTypes: { + video: { + playerSize: [640, 360], + context: 'instream', + playbackmethod: [1, 2, 3, 4, 5, 6] + } + }, + bids: [ + { + bidder: 'viously', + params: { + pid: '20d30b78-43ec-11ed-b878-0242ac120002' + } + } + ] + } +] +``` diff --git a/dev-docs/bidders/viqeo.md b/dev-docs/bidders/viqeo.md new file mode 100644 index 0000000000..31279abb08 --- /dev/null +++ b/dev-docs/bidders/viqeo.md @@ -0,0 +1,39 @@ +--- +layout: bidder +title: viqeo +description: Prebid Outstream Viqeo Bidder Adaptor +biddercode: viqeo +pbjs: true +floors_supported: true +media_types: video +sidebarType: 1 +--- + +### Note + +All references to the OpenRTB spec refer to OpenRtb v2.5 () + +The Viqeo Bidder Adapter requires setup and approval from Viqeo. + +Please reach out to for more information. + +### Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-----------------------------|----------|----------------------------------------------------------------------------------------------------------------------------|--------------------------|-----------| +| `user` | required | The object containing user data (See OpenRTB spec) | `user: {}` | `object` | +| `user.buyeruid` | required | User id | `"12345"` | `string` | +| `playerOptions` | required | The object containing Viqeo player options | `playerOptions: {}` | `object` | +| `playerOptions.profileId` | required | Viqeo profile id | `1382` | `number` | +| `playerOptions.videId` | optional | Viqeo video id | `"ed584da454c7205ca7e4"` | `string` | +| `playerOptions.playerId` | optional | Viqeo player id | `1` | `number` | +| `device` | optional | The object containing device data (See OpenRTB spec) | `device: {}` | `object` | +| `site` | optional | The object containing site data (See OpenRTB spec) | `site: {}` | `object` | +| `app` | optional | The object containing app data (See OpenRTB spec) | `app: {}` | `object` | +| `floor` | optional | Bid floor price | `0.5` | `number` | +| `currency` | optional | 3-letter ISO 4217 code defining the currency of the bid. | `EUR` | `string` | +| `test` | optional | Flag which will induce a sample bid response when true; only set to true for testing purposes (1 = true, 0 = false) | `1` | `integer` | +| `sspId` | optional | For debug, request id | `1` | `number` | +| `renderUrl` | optional | For debug, script player url | `"https://viqeo.tv"` | `string` | +| `endpointUrl` | optional | For debug, api endpoint | `"https://viqeo.tv"` | `string` | diff --git a/dev-docs/bidders/visiblemeasures.md b/dev-docs/bidders/visiblemeasures.md new file mode 100644 index 0000000000..ed13e64555 --- /dev/null +++ b/dev-docs/bidders/visiblemeasures.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: VisibleMeasures +description: Prebid VisibleMeasures Bidder Adapter +biddercode: visiblemeasures +usp_supported: true +tcfeu_supported: false +coppa_supported: true +schain_supported: true +floors_supported: true +media_types: banner, video, native +multiformat_supported: will-not-bid +pbjs: true +pbs: true +pbs_app_supported: true +safeframes_ok: true +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-----------------------|-----------|-----------| +| `placementId` | optional | Placement Id | `'0'` | `'string'` | +| `endpointId` | optional | Endpoint Id | `'0'` | `'string'` | + +### Note + +For the prebid server and prebid.js you only need to use one parameter: either placementId or endpointId diff --git a/dev-docs/bidders/visx.md b/dev-docs/bidders/visx.md index 53a833abf3..fc83ae526e 100644 --- a/dev-docs/bidders/visx.md +++ b/dev-docs/bidders/visx.md @@ -3,20 +3,22 @@ layout: bidder title: YOC VIS.X description: Prebid YOC VIS.X Bidder Adapter biddercode: visx -gdpr_supported: true +tcfeu_supported: true tcf2_supported: true gvl_id: 154 schain_supported: true -userIds: id5Id, unifiedId +userIds: all media_types: banner, video deals_supported: true pbjs: true pbs: true +sidebarType: 1 --- ### Note To be able to use the full bandwidth of VIS.X high impact ad products, we strongly recommend disabling SafeFrames: + - If you are using Google Ad Manager (GAM), make sure the "Serve in Safeframe" box in creative settings is unchecked, - If you are using AppNexus Seller Tag, make sure the enableSafeFrame parameter is set to False. @@ -29,6 +31,13 @@ Please reach out to your account manager to enable Prebid.js for your account. ### Configuration: Currency +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ----- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | +| `uid` | required | The publisher's ad unit ID in VIS.X. The parameter can be either an `integer` or `string` for Prebid.js, however `integer` is preferred. | `903536` | `integer` | + +### Configuration + The YOC VIS.X adapter has the ability to work in different currencies. Currently, this adapter supports `EUR`, `USD`, `GBP`, `PLN`. Defaults to `EUR`. If your Ad Server uses `EUR`, you don't need any additional currency settings. If you would like to trade with VIS.X in a currency different from `EUR`, you should implement some additional settings. @@ -66,6 +75,7 @@ pbjs.setConfig({ ``` Best practices: + - Please make sure that the currency module is set up and configured in order to trade with YOC in a currency that is not supported by the YOC VIS.X bidder. - You should set `EUR` in `bidderCurrencyDefault` parameter if you use unsupported currencies for VIS.X. - Feel free to reach out to your contact at YOC if you need additional support setting up Prebid.js and the currency config. @@ -82,28 +92,41 @@ pbjs.setConfig({ }); ``` +### Requirements: + +- In Prebid's `bidderSettings`, the `storageAllowed` parameter must be set to **true**. In Prebid v7.0 and later, `storageAllowed` defaults to false, so you will need to explicitly set this value to true. + + ```javascript + pbjs.bidderSettings = { + visx: { + storageAllowed: true + } + } + ``` + ### Bid params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|-------------------------------------|------------|----------| -| `uid` | required | The publisher's Ad unit ID in VIS.X. | `'903536'` | `string` | + +| Name | Scope | Description | Example | Type | +| ----- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | +| `uid` | required | The publisher's ad unit ID in VIS.X. The parameter can be either an `integer` or `string` for Prebid.js, however `integer` is preferred. | `903536` | `integer` | ### Media type Banner object params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|-------------------------------------|------------|----------| -| `sizes` | required | All sizes this ad unit can accept. | `[[300, 250], [300, 600]]` | `array of integer arrays` | +| Name | Scope | Description | Example | Type | +| ------- | -------- | ---------------------------------- | -------------------------- | ------------------------- | +| `sizes` | required | All sizes this ad unit can accept. | `[[300, 250], [300, 600]]` | `array of integer arrays` | ### Media type Video object params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-------|----------|-------------------------------------|------------|----------| -| `context` | required | The video context, only 'instream' is allowed. | `'instream'` | `string` | -| `playerSize` | required | The size (width, height) of the video player on the page, in pixels. | `[640, 480]` | `integer array` | -| `mimes` | optional | Content MIME types supported. | `['video/mp4', 'video/x-ms-wmv']` | `string array` | +| Name | Scope | Description | Example | Type | +| ------------ | -------- | -------------------------------------------------------------------- | --------------------------------- | --------------- | +| `context` | required | The video context, only 'instream' is allowed. | `'instream'` | `string` | +| `playerSize` | required | The size (width, height) of the video player on the page, in pixels. | `[640, 480]` | `integer array` | +| `mimes` | optional | Content MIME types supported. | `['video/mp4', 'video/x-ms-wmv']` | `string array` | ### Example of Banner Ad unit @@ -118,7 +141,7 @@ var bannerAdUnit = { bids: [{ bidder: 'visx', params: { - uid: '903536' // required + uid: 903536 // required } }] }; @@ -139,7 +162,7 @@ var videoAdUnit = { bids: [{ bidder: 'visx', params: { - uid: '921068' // required + uid: 921068 // required } }] }; diff --git a/dev-docs/bidders/vlyby.md b/dev-docs/bidders/vlyby.md index bf0d5184a7..c2b7acb5df 100644 --- a/dev-docs/bidders/vlyby.md +++ b/dev-docs/bidders/vlyby.md @@ -7,13 +7,12 @@ media_types: banner, video schain_supported: false prebid_member: false pbjs: true +sidebarType: 1 --- -### Note: - -The VLYBY Header Bidder Adapter needs a Contract with VLYBY Digital GmbH, Munich. Please contact prebid@vlyby.com for additional information. - +### Note +The VLYBY Header Bidder Adapter needs a Contract with VLYBY Digital GmbH, Munich. Please contact for additional information. ### Bid Params diff --git a/dev-docs/bidders/vmg.md b/dev-docs/bidders/vmg.md deleted file mode 100644 index b15ddbdc8c..0000000000 --- a/dev-docs/bidders/vmg.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -layout: bidder -title: VMG -description: Connects Google Ad Manager to the VMG Predict engine. -pbjs: true -biddercode: vmg -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|------------------------|---------|----------| -| (none) | optional | no params required | `''` | n/a | diff --git a/dev-docs/bidders/vox.md b/dev-docs/bidders/vox.md index 865484e139..b531bb3079 100644 --- a/dev-docs/bidders/vox.md +++ b/dev-docs/bidders/vox.md @@ -2,10 +2,15 @@ layout: bidder title: VOX description: Prebid VOX Bidder Adapter +schain_supported: true +floors_supported: true +userIds: all pbjs: true media_types: banner, video biddercode: vox -gdpr_supported: true +tcfeu_supported: true +gvl_id: 206 +sidebarType: 1 --- ### Note @@ -13,7 +18,6 @@ gdpr_supported: true You can use this adapter to get a bid from partners.hybrid.ai Please reach out to your partners account team before using this plugin to get placementId. - ### Bid Params {: .table .table-bordered .table-striped } @@ -21,8 +25,7 @@ Please reach out to your partners account team before using this plugin to get p |---------------------|------------------------|-------------------------------------------------------------------|--------------------------------------|----------| | `placementId` | required | The place id. | '5af45ad34d506ee7acad0c26' | `string` | | `placement` | required | Adunit placement, possible values: banner, video, inImage | 'banner' | `string` | -| `imageUrl` | required for inImage | URL of the image on which the banner will be displayed | 'https://hybrid.ai/images/image.jpg' | `string` | - +| `imageUrl` | required for inImage | URL of the image on which the banner will be displayed | `'https://example.com/images/image.jpg'` | `string` | ### Sample Banner Ad Unit diff --git a/dev-docs/bidders/vrtcal.md b/dev-docs/bidders/vrtcal.md index cdb1948a8e..02b95ab141 100644 --- a/dev-docs/bidders/vrtcal.md +++ b/dev-docs/bidders/vrtcal.md @@ -1,13 +1,20 @@ --- layout: bidder -title: VRTCAL Markets, Inc. -description: VRTCAL Markets, Inc. Bid Adapter +title: VRTCAL Markets Inc. +description: VRTCAL Markets Inc. Bid Adapter pbjs: true pbs: true -media_types: banner, video -gdpr_supported: false +media_types: banner, video, native biddercode: vrtcal +tcfeu_supported: true +usp_supported: true +schain_supported: true +coppa_supported: true +gpp_supported: true +floors_supported: true gvl_id: 706 +userIds: all +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/vuble.md b/dev-docs/bidders/vuble.md deleted file mode 100644 index 97f05bf68a..0000000000 --- a/dev-docs/bidders/vuble.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -layout: bidder -title: Vuble -description: Prebid Vuble Bidder Adaptor -pbjs: true -biddercode: vuble -media_types: video -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -The Vuble adapter requires setup and approval from the Vuble team, even for existing Vuble publishers. Please reach out to your account team, or contact publishers-us@vuble.tv or publishers-fr@vuble.tv for more information. - -### Bid params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|--------------|----------|---------------------------------------------------------------------------------------------------|--------------------------|-----------| -| `env` | required | The environment. Must be 'net' or 'com'. This information will be given to you by the Vuble team. | `'net'` | `string` | -| `pubId` | required | Your publisher ID. This information will be given to you by the Vuble team. | `3` | `integer` | -| `zoneId` | required | A zone ID for the SSP. | `12345` | `integer` | -| `referrer` | optional | The page's referrer. Not mandatory but recommended. | `'http://www.vuble.tv/'` | `string` | -| `floorPrice` | optional | The desired floor price. If none is given, the floor price will depend on the zone ID. | `5.00` | `float` | - -### Example - -``` -var adUnits = [ - { - code: 'test-vuble-instream', - sizes: [[640, 360]], - mediaTypes: { - video: { - context: 'instream' - } - }, - bids: [ - { - bidder: 'vuble', - params: { - env: 'net', - pubId: 18, - zoneId: '12345', - referrer: "http://www.vuble.tv/", - floorPrice: 5.00 - } - } - ] - } -] -``` - -{: .alert.alert-info :} -Sizes set in the `adUnit` object will also apply to the Vuble bid requests. diff --git a/dev-docs/bidders/vuukle.md b/dev-docs/bidders/vuukle.md index e1a9561379..501576764f 100644 --- a/dev-docs/bidders/vuukle.md +++ b/dev-docs/bidders/vuukle.md @@ -4,7 +4,14 @@ title: Vuukle description: vuukle bid adapter pbjs: true biddercode: vuukle +tcfeu_supported: true +gvl_id: 1004 +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: true --- +sidebarType: 1 ### Bid Params diff --git a/dev-docs/bidders/waardex.md b/dev-docs/bidders/waardex.md index 1a5e6942fd..a103c00358 100644 --- a/dev-docs/bidders/waardex.md +++ b/dev-docs/bidders/waardex.md @@ -6,10 +6,13 @@ hide: true biddercode: waardex media_types: banner, video pbjs: true +sidebarType: 1 --- ### Bid Params + #### Banner + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |---------------|----------|------------------------------------------------------------------|--------------------|----------| @@ -20,6 +23,7 @@ pbjs: true | `instl` | optional | 1 when ad is interstitial or full screen, 0 when not interstitial| 0 | `number` | #### Video + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |-----------------|----------|---------------------------------------------------------------------------------------------------------|---------------------------------|-----------------| diff --git a/dev-docs/bidders/waardex_ak.md b/dev-docs/bidders/waardex_ak.md index f58274d1c2..4d49887891 100644 --- a/dev-docs/bidders/waardex_ak.md +++ b/dev-docs/bidders/waardex_ak.md @@ -2,14 +2,28 @@ layout: bidder title: WaardeX description: Prebid WaardeX Bidder Adaptor - biddercode: waardex_ak +pbjs: true +pbs: false +media_types: banner, native, video +gvl_id: 14 (adkernel) +tcfeu_supported: true +usp_supported: true +coppa_supported: true +gpp_supported: true +pbs_app_supported: true +schain_supported: true +userIds: all +fpd_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: true aliasCode: adkernel -media_types: display, video -gdpr_supported: true +sidebarType: 1 --- -### Note: +### Note The WaardeX Bidding adaptor requires setup and approval before beginning. Please reach out to for more details @@ -19,4 +33,4 @@ The WaardeX Bidding adaptor requires setup and approval before beginning. Please | Name | Scope | Description | Example | Type | |----------|----------|-----------------------|---------------------------|----------| | `host` | required | Ad network's RTB host | `'cpm.webtradingspot.com'` | `string` | -| `zoneId` | required | RTB zone id | `'30164'` | `string` | +| `zoneId` | required | RTB zone id | `30164` | `integer` | diff --git a/dev-docs/bidders/welect.md b/dev-docs/bidders/welect.md deleted file mode 100644 index f1805b7f71..0000000000 --- a/dev-docs/bidders/welect.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -layout: bidder -title: Welect -description: Prebid Welect Bidder Adapter -biddercode: welect -media_types: no-display, video -gvlid: 282 -pbjs: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Note: -The Welect adapter requires setup and approval from the Welect team, even for partners that already work with us. Please reach out to our team at olaf.peters@welect.de. - -### Bid params - -| Name | Scope | Description | Example | Type | -|--------------|----------|---------------------------------------------------------------------------------------------------|--------------------------|-----------| -| `placementId` | required | Your personal id which will be given to you by the Welect team. | `'aliasexample'` | `string` | -| `domain` | optional | Not mandatory but recommended. Our Team will provide you with a domain, if not given defaults to www.welect.de | `'www.welect.de'` | `string` | - -### Example - -``` -var adUnits = [ - { - code: 'test-welect-instream', - sizes: [[640, 360]], - mediaTypes: { - video: { - context: 'instream' - } - }, - bids: [ - { - bidder: 'welect', - params: { - placementId: 'examplePlacement', - domain: 'www.welect.de', - } - } - ] - } -] -``` diff --git a/dev-docs/bidders/widespace.md b/dev-docs/bidders/widespace.md index b2780e2c27..eb2e674207 100644 --- a/dev-docs/bidders/widespace.md +++ b/dev-docs/bidders/widespace.md @@ -4,7 +4,8 @@ title: Widespace description: Prebid Widespace Bidder Adaptor pbjs: true biddercode: widespace -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/windtalker.md b/dev-docs/bidders/windtalker.md deleted file mode 100644 index 3988eb9a4d..0000000000 --- a/dev-docs/bidders/windtalker.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -layout: bidder -title: Windtalker -description: Prebid Windtalker Bidder Adapter -pbjs: true -biddercode: windtalker -media_types: native, video -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Disclosure - -This bidder sets `adId` on the bid response and hasn't responded to the Prebid.js team to confirm uniqueness -of this value. See [Issue 6381](https://github.com/prebid/Prebid.js/issues/6381). - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|----------------------------------|----------------|----------| -| `pubId` | required | The publisher account ID | `'28082'` | `string` | -| `siteId` | required | The publisher site ID | `'26047'` | `string` | -| `size` | required | Ad size identifier | `'300X250'` | `string` | -| `placementId` | required | Identifies specific ad placement | `'17394'` | `string` | -| `bidFloor` | optional | The bid floor | `'0.001'` | `string` | -| `ifa` | optional | IFA ID | `'XXX-XXX'` | `string` | -| `latitude` | optional | Latitude | `'40.712775'` | `string` | -| `longitude` | optional | Longitude | `'-74.005973'` | `string` | - -### test params - -``` - var adUnits = [{ - code: 'dfp-native-div', - mediaType: 'native', - mediaTypes: { - native: { - title: { - required: true, - len: 75 - }, - image: { - required: true - }, - body: { - len: 200 - }, - icon: { - required: false - } - } - }, - bids: [{ - bidder: 'windtalker', - params: { - pubId: '29521', - siteId: '26048', - placementId: '123', - } - }] - }, - { - code: 'dfp-banner-div', - mediaTypes: { - banner: { - sizes: [ - [300, 250] - ], - } - }, - bids: [{ - bidder: 'windtalker', - params: { - pubId: '29521', - siteId: '26049', - size: '300X250', - placementId: '123', - } - }] - }, - { - code: 'dfp-video-div', - sizes: [640, 480], - mediaTypes: { - video: { - context: "instream" - } - }, - bids: [{ - bidder: 'windtalker', - params: { - pubId: '29521', - siteId: '26049', - size: '640X480', - placementId: '123', - video: { - skippable: true, - } - } - }] - } - ]; -``` diff --git a/dev-docs/bidders/winr.md b/dev-docs/bidders/winr.md index 38a0bc7a59..51c5eabd96 100644 --- a/dev-docs/bidders/winr.md +++ b/dev-docs/bidders/winr.md @@ -5,18 +5,19 @@ description: Prebid WINR Bidder Adaptor biddercode: winr media_types: banner prebid_member: false -userIds: criteo, unifiedId, netId, identityLink, flocId, uid2 +userIds: criteo, unifiedId, netId, identityLink, uid2 schain_supported: true coppa_supported: true usp_supported: true floors_supported: true pbjs: true safeframes_ok: false -fpd_supported: true +sidebarType: 1 --- -### Note: -The WINR adapter requires setup and approval from the WINR team, even for partners that already work with us. Please reach out to our team at tech@winr.com.au +### Note + +The WINR adapter requires setup and approval from the WINR team, even for partners that already work with us. Please reach out to our team at *`domParent` and `child` position settings are usually determined and remotely controlled for each publisher site by the WINR team. If you would prefer to have control over these settings, please get in touch. diff --git a/dev-docs/bidders/wipes.md b/dev-docs/bidders/wipes.md index 25e1ed80cc..18ebffbd55 100644 --- a/dev-docs/bidders/wipes.md +++ b/dev-docs/bidders/wipes.md @@ -5,11 +5,13 @@ description: Prebid WIPES Bidder Adaptor pbjs: true biddercode: wipes media_types: video +sidebarType: 1 --- -### Note: +### Note + Publishers needs to be set up and approved by WIPES team to enable this adapter. -Please contact support@wipestream.com for further information. +Please contact for further information. ### Bid Params diff --git a/dev-docs/bidders/xe.md b/dev-docs/bidders/xe.md new file mode 100644 index 0000000000..44a50d2d88 --- /dev/null +++ b/dev-docs/bidders/xe.md @@ -0,0 +1,38 @@ +--- +layout: bidder +title: xe.works +description: Prebid Xe.works Bidder Adaptor +biddercode: xe +media_types: banner, video +coppa_supported: true +tcfeu_supported: false +usp_supported: true +prebid_member: false +pbjs: true +pbs: true +schain_supported: true +floors_supported: true +multiformat_supported: will-bid-on-any +sidebarType: 1 +--- + +### Note + +The Xe.works adapter requires setup before beginning. Please contact us at + +### Prebid.js Bid params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------|---------------|-----------| +| `placement` | required | Placement ID | `test-banner` | `string` | +| `env` | required | Environment name | `xe` | `string` | +| `ext` | optional | Specific integration config | `{}` | `object` | + +### Prebid Server Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|-------------|----------|-----------------------------|------------------------------------|-----------| +| `env` | required | Environment name | `xe-stage` | `string` | +| `pid` | required | Uniq placement ID | `dc230510222b516f0eb9a10e5913d3b5` | `string` | diff --git a/dev-docs/bidders/xendiz.md b/dev-docs/bidders/xendiz.md index f411b25d22..d6ffb2f1f1 100644 --- a/dev-docs/bidders/xendiz.md +++ b/dev-docs/bidders/xendiz.md @@ -4,12 +4,14 @@ title: Xendiz description: Prebid Xendiz Bidder Adaptor pbjs: true biddercode: xendiz +sidebarType: 1 --- ### Bid params ### Note -To enable XENDIZ bid adaptor we kindly ask you to sign up as a Publisher: hello@xendiz.com + +To enable XENDIZ bid adaptor we kindly ask you to sign up as a Publisher: {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | diff --git a/dev-docs/bidders/xhb.md b/dev-docs/bidders/xhb.md deleted file mode 100644 index 5e593c0c13..0000000000 --- a/dev-docs/bidders/xhb.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -layout: bidder -title: Xaxis -description: Prebid Xaxis Bidder Adaptor -biddercode: xhb -pbjs: true -media_types: video, native -gdpr_supported: true -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|---------------|----------|-------------|---------|----------| -| `placementId` | required | | | `string` | diff --git a/dev-docs/bidders/xtrmqb.md b/dev-docs/bidders/xtrmqb.md new file mode 100644 index 0000000000..30cbb0dabc --- /dev/null +++ b/dev-docs/bidders/xtrmqb.md @@ -0,0 +1,30 @@ +--- +layout: bidder +title: XTRM QB +description: Prebid XTRM QB Bidder Adaptor +biddercode: xtrmqb +pbjs: false +pbs: true +media_types: banner, video, audio, native +userIds: all +fpd_supported: false +tcfeu_supported: false +usp_supported: true +coppa_supported: true +schain_supported: true +prebid_member: false +ortb_blocking_supported: true +multiformat_supported: will-bid-on-one +floors_supported: false +aliasCode: limelightDigital +sidebarType: 1 +--- + +### Bid Params + +{: .table .table-bordered .table-striped } + +| Name | Scope | Description | Example | Type | +|:--------------|:---------|:----------------------|:--------------|:----------| +| `host` | required | Ad network's RTB host | `'ortb.tech'` | `string` | +| `publisherId` | required | Publisher ID | `12345` | `integer` | diff --git a/dev-docs/bidders/yahooAdvertising.md b/dev-docs/bidders/yahooAdvertising.md new file mode 100644 index 0000000000..219a7a4347 --- /dev/null +++ b/dev-docs/bidders/yahooAdvertising.md @@ -0,0 +1,79 @@ +--- +layout: bidder +title: Yahoo Advertising +description: Yahoo Advertising Bid Adapter +pbs: true +pbjs: true +media_types: banner, video +filename: yahoosspBidAdapter +biddercode: yahooAds +prebid_member: true +tcfeu_supported: true +usp_supported: true +gpp_supported: true +schain_supported: true +coppa_supported: true +floors_supported: true +fpd_supported: false +gvl_id: 25 +userIds: All +sidebarType: 1 +--- + +### Important Notice (JS vs PBS) + +There are differences between our Prebid.js & Prebid-Server Yahoo Advertising adapters. +The Prebid-server adapter currently does not support: + +1. Integration via the `pubId` method. + +### Prebid.js Mandatory Bid Params + +The Prebid.js Yahoo Advertising bid adapter supports 2 alternate integration types: + +1. **dcn & pos** (Site/App & Position explicit targeting) - For legacy "aol", "oneMobile" adapter partners/publishers. +2. **pubId** (Publisher ID) - For new partners/publishers joining Yahoo Advertising and legacy "oneVideo" partners/publishers migrating to Yahoo Advertising. + +### Prebid-Server Mandatory Bid Params + +Prebid-server Yahoo Advertising bid adapter supports one integration method: + +* **dcn & pos** (Site/App & Position explicit targeting) - For legacy "aol", "oneMobile" adapter partners/publishers. + +#### DCN & POS Integration Parameters (JS & PBS) + +For legacy "aol", "oneMobile" adapter partners/publishers. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|------------------------|---------|----------| +| dcn | Required | Site ID provided by Yahoo Advertising | 'site1' | string | +| pos | Required | Placement ID provided by Yahoo Advertising | 'placement1' | string | + +#### PubId Integration Parameters (JS Only) + +For new partners/publishers joining Yahoo Advertising and legacy "oneVideo" partners/publishers migrating to Yahoo Advertising. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|------------------------|---------|----------| +| pubId | Required | Your Publisher External ID provided by Yahoo Advertising | 'DemoPublisher' | string | +| siteId | Optional | Ability to target a specific Site using an External ID provided by Yahoo Advertising | '1234567' | string | +| placementId | Optional | Ability to target a specific Placement using an External ID provided by Yahoo Advertising | 'header' | string | + +### Prebid.js Adapter Supported Features + +For further setup details & examples please see + +* Media Types: Banner & Video +* Outstream renderer +* Multi-format adUnits +* Schain module +* Price floors module +* Advertiser domains +* End-2-End self-served testing mode +* Outstream renderer/Player +* User ID Modules - ConnectId and others +* First Party Data (ortb2 & ortb2Imp) +* Custom TTL (time to live) + diff --git a/dev-docs/bidders/yahoossp.md b/dev-docs/bidders/yahoossp.md deleted file mode 100644 index cd939bdbf9..0000000000 --- a/dev-docs/bidders/yahoossp.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -layout: bidder -title: Yahoo SSP -description: Yahoo SSP Bid Adapter -pbs: true -pbjs: true -media_types: banner, video -biddercode: yahoossp -prebid_member: true -gdpr_supported: true -usp_supported: true -schain_supported: true -coppa_supported: true -gvl_id: 25 -userIds: All ---- - -### Important Notice (JS vs PBS) -There are differences between our Prebid.js & Prebid-Server Yahoo SSP adapters. -The Prebid-server adapter currently does not support: -1. Video inventory. -2. Integration via the `pubId` method. - -### yahoossp Prebid.js Mandatory Bid Params -The 'yahoossp' bid adapter supports 2 alternate integration types: -1. **dcn & pos** (Site/App & Position explicit targeting) - For legacy "aol", "oneMobile" adapter partners/publishers. -2. **pubId** (Publisher ID) - For New partners/publishers joining Yahoo SSP and legacy "oneVideo" partners/publishers migrating to the Yahoo SSP. -### yahoossp Prebid-Server Mandatory Bid Params -Prebid-server adapter supports one integration method: -* **dcn & pos** (Site/App & Position explicit targeting) - For legacy "aol", "oneMobile" adapter partners/publishers. -#### DCN & POS Integration Parameters (JS & PBS) -For legacy "aol", "oneMobile" adapter partners/publishers. - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|------------------------|---------|----------| -| dcn | Required | Site ID provided by Yahoo SSP | 'site1' | string | -| pos | Required | Placement ID provided by Yahoo SSP | 'placement1' | string | -#### PubId Integration Parameters (JS Only) -For New partners/publishers joining Yahoo SSP -floors_supported: true and legacy "oneVideo" partners/publishers migrating to the Yahoo SSP. - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|------------|----------|------------------------|---------|----------| -| pubId | Required | Your Publisher External ID provided by Yahoo SSP | 'DemoPublisher' | string | -| siteId | Optional | Ability to target a specific Site using an External ID provided by Yahoo SSP | '1234567' | string | -| placementId | Optional | Ability to target a specific Placement using an External ID provided by Yahoo SSP | 'header' | string | - -### Prebid.js Adapter Supported Features -For further setup details & examples please see https://github.com/prebid/Prebid.js/blob/master/modules/yahoosspBidAdapter.md -* Media Types: Banner & Video -* Outstream renderer -* Multi-format adUnits -* Schain module -* Price floors module -* Advertiser domains -* End-2-End self-served testing mode -* Outstream renderer/Player -* User ID Modules - ConnectId and others -* First Party Data (ortb2 & ortb2Imp) -* Custom TTL (time to live) - -Thanks you, -Yahoo SSP \ No newline at end of file diff --git a/dev-docs/bidders/yandex.md b/dev-docs/bidders/yandex.md new file mode 100644 index 0000000000..0f284b1d8c --- /dev/null +++ b/dev-docs/bidders/yandex.md @@ -0,0 +1,151 @@ +--- +layout: bidder +title: Yandex +description: Prebid Yandex Bidder Adapter +pbjs: true +pbs: true +biddercode: yandex +media_types: banner, native +sidebarType: 1 +privacy_sandbox: topics +--- + +### Prebid Client + +This Adapter integrates with Yandex's ad services. + +{: .alert.alert-info :} +Note: For detailed auction analytics, check out our [Analytics Adapter](https://docs.prebid.org/dev-docs/analytics/yandex.html). + +#### Client Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +| ------------- | -------------------------------------------------- | -------------------------------------------------- | --------------------------------- | --------- | +| `placementId` | required | Ad unit ID. Prebid versions > 7.30 | `R-A-1234567-1` | `String` | +| `cur` | optional | CPM currency to be received. Prebid versions > 8.4 | `CHF`, `GBP`, `USD`, `EUR`, `TRY` | `String` | +| `pageId` | optional, **deprecated** in favor of `placementId` | Page ID | `123` | `Integer` | +| `impId` | optional, **deprecated** in favor of `placementId` | Imp ID | `1` | `Integer` | + +#### Client Test Parameters + +```js +// Simple banner +const adUnits = [{ + code: 'banner-1', + mediaTypes: { + banner: { + sizes: [[240, 400]], + } + }, + bids: [ + { + bidder: 'yandex', + params: { + placementId: 'R-A-1234567-1', + cur: 'USD', + }, + } + ] +}]; + +// Native +const adUnits = [{ + code: 'native-1', + mediaTypes: { + native: { + sendTargetingKeys: false, + ortb: { + assets: [{ + id: 1, + required: 1, + img: { + type: 3, + w: 300, + h: 300, + } + }, + { + id: 2, + required: 1, + title: { + len: 80 + } + }, + { + id: 3, + required: 1, + data: { + type: 1 + } + } + ] + } + } + }, + bids: [ + { + bidder: 'yandex', + params: { + placementId: 'R-A-346580-140', // native adunit ID + cur: 'USD' // EUR, TRY, etc. + }, + } + ] +}]; +``` + +#### Topics Iframe Configuration + +[Topics First Party Data (FPD) Module](/dev-docs/modules/topicsFpdModule.html) `topicsFpdModule` should be included in prebid final package to call topics API. + +```js +pbjs.setConfig({ + userSync: { + // ..., + topics: { + bidders: [{ + bidder: 'yandex', + iframeURL: 'https://yandex.ru/ads/prebid/topics_frame.html' + }] + } + // ... + } +}) +``` + +### Prebid Server + +{: .alert.alert-info :} +We maintain both **PBS Java** and **PBS Go** adapters, but **PBS Go** is recommended for integration and will receive updates first + +#### Server Bid Params + +These params are basically the same that you'd use for + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | Supported in | +| -------------- | --------------------------------------------------- | ---------------------------------- | --------------- | --------- | ---------------- | +| `placement_id` | required | Ad unit ID. Prebid versions > 7.30 | `R-A-1234567-1` | `String` | PBS Go | +| `page_id` | optional, **deprecated** in favor of `placement_id` | Page ID | `123` | `Integer` | PBS Go, PBS Java | +| `imp_id` | optional, **deprecated** in favor of `placement_id` | Imp ID | `1` | `Integer` | PBS Go, PBS Java | + +#### Prebid Server Test Request + +The following test parameters can be used to verify that Prebid Server is working properly with the +server-side adapter. + +```json +"imp": [{ + "id": "imp_id", + "banner": { + "w": 300, + "h": 600 + }, + "ext": { + "bidder": { + "placement_id": "R-A-1234567-1" + } + } +}] +``` diff --git a/dev-docs/bidders/yeahmobi.md b/dev-docs/bidders/yeahmobi.md index b04030a855..9856dcb5d4 100644 --- a/dev-docs/bidders/yeahmobi.md +++ b/dev-docs/bidders/yeahmobi.md @@ -5,6 +5,7 @@ pbs: true media_types: native biddercode: yeahmobi prebid_member: true +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/yieldbot.md b/dev-docs/bidders/yieldbot.md index 32a7c17d66..8735fbf4e4 100644 --- a/dev-docs/bidders/yieldbot.md +++ b/dev-docs/bidders/yieldbot.md @@ -4,6 +4,7 @@ title: Yieldbot description: Prebid Yieldbot Bidder Adaptor pbjs: true biddercode: yieldbot +sidebarType: 1 --- diff --git a/dev-docs/bidders/yieldlab.md b/dev-docs/bidders/yieldlab.md index 32644d6782..018fd67699 100644 --- a/dev-docs/bidders/yieldlab.md +++ b/dev-docs/bidders/yieldlab.md @@ -4,12 +4,23 @@ title: Yieldlab description: Prebid Yieldlab Bidder Adapter biddercode: yieldlab media_types: video, banner, native -gdpr_supported: true +tcfeu_supported: true +dsa_supported: true schain_supported: true userIds: britepoolId, criteo, id5Id, identityLink, liveIntentId, netId, parrableId, pubCommonId, unifiedId prebid_member: true pbjs: true pbs: true +pbs_app_supported: true +floors_supported: true +fpd_supported: true +ortb_blocking_supported: false +multiformat_supported: will-bid-on-any +deals_supported: true +gvl_id: 70 +coppa_supported: false +usp_supported: false +sidebarType: 1 --- @@ -17,36 +28,67 @@ pbs: true ### Bid Params {: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|---------------------------------------------------------------------------------------|---------------------------------------------|----------| -| `adslotId` | required | Yieldlab Adslot ID | `'12345'` | `string` | -| `supplyId` | required | Yieldlab Supply ID. Please reach out to your account management for more information. | `'12345'` | `string` | -| `adSize` | optional | Override the default prebid size | `'970x250'` | `string` | -| `targeting` | optional | Key-Value Targeting | `{ 'key1': 'value1', 'key2': 'value2' }` | `object` | -| `extId` | optional | External Id | `'abc'` | `string` | +| Name | Scope | Description | Example | Type | +|----------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|----------| +| `adslotId` | required | Yieldlab Adslot ID | `'12345'` | `string` | +| `supplyId` | required | Yieldlab Supply ID. Please reach out to your account management for more information. | `'12345'` | `string` | +| `targeting` | optional | Key-Value Targeting | `{ 'key1': 'value1', 'key2': 'value2' }` | `object` | +| `extId` | optional | External Id | `'abc'` | `string` | | `iabContent` | optional | Object of content information, see [IAB Content Object](#iab_content) for details. It will override the content object passed in [First Party Data](https://docs.prebid.org/features/firstPartyData.html) | `{ 'id': 'foo', 'title': 'bar' }` | `object` | -| `customParams` | optional | Custom parameters to append to the query string of the bidding endpoint. | `{ 'param': 'value1', 'param2': 'value2' }` | `object` | +| `customParams` | optional | Custom parameters to append to the query string of the bidding endpoint. | `{ 'param': 'value1', 'param2': 'value2' }` | `object` | - + #### IAB Content Object -Yieldlab supports passing the IAB content object in correspond to the OpenRTB Specifications. -The following attributes are supported, and all of them are optional. +Yieldlab supports passing the IAB content object according to section *3.2.16* +of the [OpenRTB 2.6 specification][openrtb-spec]. The following attributes are +supported, and all of them are optional: -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|----------------|----------|-----------------------------------------------------------------------------------------------|---------------------------------------------|------------------| -| `id` | optional | Id uniquely identifying the content | `'12345'` | `string` | -| `episode` | optional | Episode number | `'42'` | `string` | -| `title` | optional | Content title | `'some title'` | `string` | -| `series` | optional | Content series | `'some series'` | `string` | -| `season` | optional | Content season | `'s1'` | `string` | -| `artist` | optional | Artist credited with the content | `'John Doe'` | `string` | -| `genre` | optional | Genre that best describes the content | `'some genre'` | `string` | -| `isrc` | optional | International Standard Recording Code conforming to ISO3901 | `'CC-XXX-YY-NNNNN'` | `string` | -| `url` | optional | URL of the content, for buy-side contextualization or review | `'https://yieldlab.com'` | `string` | -| `cat` | optional | Array of IAB content categories that describe the content producer | `['IAB1-1', 'IAB1-2']` | `Array` | -| `context` | optional | Type of content - 1: video, 2: game, 3: music, 4: application, 5: text, 6: other, 7: unknown | `'7'` | `string` | -| `keywords` | optional | Array of keywords describing the content | `['k1', 'k2', 'k3']` | `Array` | -| `live` | optional | 0 = not live, 1 = content is live | `'0'` | `string` | +* `id` +* `episode` +* `title` +* `series` +* `season` +* `artist` +* `genre` +* `album` +* `isrc` +* `producer` + * `id` + * `name` + * `cattax` + * `cat` + * `domain` +* `url` +* `cattax` +* `cat` +* `prodq` +* `context` +* `contentrating` +* `userrating` +* `qagmediarating` +* `keywords` +* `livestream` +* `sourcerelationship` +* `len` +* `language` +* `embeddable` +* `data` + * `id` + * `name` + * `segment` + * `id` + * `name` + * `value` + * `ext` +* `network` + * `id` + * `name` + * `domain` +* `channel` + * `id` + * `name` + * `domain` + +[openrtb-spec]: https://iabtechlab.com/wp-content/uploads/2022/04/OpenRTB-2-6_FINAL.pdf diff --git a/dev-docs/bidders/yieldlift.md b/dev-docs/bidders/yieldlift.md index 97aa773866..4c473ed4d5 100644 --- a/dev-docs/bidders/yieldlift.md +++ b/dev-docs/bidders/yieldlift.md @@ -5,17 +5,18 @@ description: Prebid YieldLift Bidder Adaptor pbjs: true biddercode: yieldlift media_types: banner -gdpr_supported: true +gvl_id: 866 +tcfeu_supported: true usp_supported: true schain_supported: true +sidebarType: 1 --- -### Integration Note: +### Integration Note The YieldLift Header Bidding adapter requires approval from the YieldLift team. Please reach out to for more information. - ### Bid Params {: .table .table-bordered .table-striped } diff --git a/dev-docs/bidders/yieldlove.md b/dev-docs/bidders/yieldlove.md new file mode 100644 index 0000000000..fc78dcd370 --- /dev/null +++ b/dev-docs/bidders/yieldlove.md @@ -0,0 +1,24 @@ +--- +layout: bidder +title: Yieldlove +description: Yieldlove adapter +biddercode: yieldlove +pbjs: true +gvl_id: 251 +tcfeu_supported: true +sidebarType: 1 +safeframes_ok: true +floors_supported: false +--- + +### Note + +The Yieldlove bidder adapter requires setup and approval from the Yieldlove team. Please reach out to [adapter@yieldlove.com](mailto:adapter@yieldlove.com) for more information. + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|--------------------------------------------|-----------------------|-----------| +| `rid` | required | The publisher site ID | `website.com` | `string` | +| `pid` | required | Your placement ID (provided by Yieldlove) | `34437` | `number` | diff --git a/dev-docs/bidders/yieldmo.md b/dev-docs/bidders/yieldmo.md index 9ec5b17793..3b11512b36 100644 --- a/dev-docs/bidders/yieldmo.md +++ b/dev-docs/bidders/yieldmo.md @@ -5,18 +5,21 @@ description: Prebid Yieldmo Bidder Adaptor biddercode: yieldmo media_types: banner, video userIds: pubCommonId, unifiedId, criteo, sharedId -gdpr_supported: true +gvl_id: 173 +tcfeu_supported: true usp_supported: true schain_supported: true +gpp_supported: true prebid_member: true -fpd_supported: true pbjs: true pbs: true +sidebarType: 1 --- -# Registration -### Note: In order to use Yieldmo adapter please reach out to your Yieldmo account's person or support@yieldmo.com for more information. -
      +### Registration + +Note: In order to use Yieldmo adapter please reach out to your Yieldmo account's person or for more information. + ### Bid Params {: .table .table-bordered .table-striped } @@ -27,7 +30,8 @@ pbs: true | `lr_env` | optional | Live Ramp ATS envelope | `e3b0c44298fc1c149a` | `string` | ### video parameters -The Yieldmo adapter supports in-stream video as of Prebid v4.18. Out-stream will be supported as of Prebid v4.35.0. + +The Yieldmo adapter supports in-stream video as of Prebid v4.18. Out-stream will be supported as of Prebid v4.35.0. {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | @@ -44,7 +48,7 @@ The Yieldmo adapter supports in-stream video as of Prebid v4.18. Out-stream will | `skipafter` | optional | Number of seconds a video must play before skipping is enabled; only applicable if the ad is `skippable` | `5` | `integer` | | `mimes` | required | List of the content MIME types supported by the player | `["video/mp4"]` | `Array` | -Following video parameters might be also defined in `mediaTypes.video` in order to simplify bidders configuration. If the same parameters was also defined in `params.video` it will be overriten by `params.video`. More details - https://docs.prebid.org/dev-docs/adunit-reference.html +Following video parameters might be also defined in `mediaTypes.video` in order to simplify bidders configuration. If the same parameters was also defined in `params.video` it will be overriten by `params.video`. More details - In addition, Yieldmo adapter relies on parameters specified in the `mediaTypes.video` definition of the video ad-units, namely: @@ -52,8 +56,10 @@ In addition, Yieldmo adapter relies on parameters specified in the `mediaTypes.v | Name | Scope | Description | Example | Type | |-------------------|----------|--------------------------------------------------------|-----------------|------------------| | `playerSize` | required | Width and height of the player | `[640, 480]` | `Array` | -| `context` | required | `instream` or `outstream ` are only supported | `instream` | `string` | +| `context` | required | `instream` or `outstream` are only supported | `instream` | `string` | + ### Example of in-stream Video Ad-unit + ```javascript var videoAdUnits = [{ code: 'div-video-ad-1234567890', @@ -82,7 +88,9 @@ var videoAdUnits = [{ }] }]; ``` + ### Example of out-stream Video Ad-unit + ```javascript var videoAdUnit = [{ code: 'div-video-ad-1234567890', diff --git a/dev-docs/bidders/yieldnexus.md b/dev-docs/bidders/yieldnexus.md index e8a7461bba..5b8e5b6a66 100644 --- a/dev-docs/bidders/yieldnexus.md +++ b/dev-docs/bidders/yieldnexus.md @@ -5,7 +5,8 @@ description: Yield Nexus Bidder Adapter biddercode: yieldnexus pbjs: true media_types: banner, video -gdpr_supported: true +tcfeu_supported: false +sidebarType: 1 --- ### Bid params diff --git a/dev-docs/bidders/yieldone.md b/dev-docs/bidders/yieldone.md index 979b13be28..c2cb8ef6b3 100644 --- a/dev-docs/bidders/yieldone.md +++ b/dev-docs/bidders/yieldone.md @@ -1,20 +1,20 @@ --- layout: bidder -title: YIELDONE -description: Prebid YIELDONE Bidder Adaptor +title: YieldOne +description: Prebid YieldOne Bidder Adaptor biddercode: yieldone media_types: banner, video -userIds: identityLink, imuid +userIds: identityLink, imuid, AudienceOne ID, ID5 pbjs: true pbs: true - +multiformat_supported: will-bid-on-any +sidebarType: 1 --- -### Note: - -THE YIELDONE adapter requires setup and approval from the YIELDONE team.
      -Please reach out to your account team or y1s@platform-one.co.jp for more information. +### Note +THE YieldOne adapter requires setup and approval from the YieldOne team.
      +Please reach out to your account team or for more information. ### Bid Params @@ -27,17 +27,16 @@ Please reach out to your account team or y1s@platform-one.co.jp for more informa | `playerParams.wrapperWidth` | optional | Video Player Width | `"320px"` | `string` | | `playerParams.wrapperHeight` | optional | Video Player Height | `"180px"` | `string` | - ### Multi-Format Ad Units If you use Multi-Format Ad Units, "video" bid object should be placed before "banner" bid object.
      And if Bid Params contains playerParams, it will request a "video" media type ad.
      If it does not, it will request a "banner" media type ad. - ### AdUnit Format Example #### AdUnit Format for Banner + ```javascript var bannerAdUnits = [{ code: "test-div-banner", @@ -58,8 +57,8 @@ var bannerAdUnits = [{ }] ``` - #### AdUnit Format for Video + ```javascript var videoAdUnits = [{ code: "test-div-video", @@ -82,8 +81,8 @@ var videoAdUnits = [{ }] ``` - #### AdUnit Format for Multi Ads + ```javascript var multiAdUnits = [{ code: "test-div-multi", @@ -121,8 +120,8 @@ var multiAdUnits = [{ }]; ``` - #### AdUnit Format for Video (mediaTypes.video.playerSize: [1,1]) + ```javascript var videoAdUnits = [{ code: "test-div-video", @@ -146,8 +145,8 @@ var videoAdUnits = [{ }] ``` - #### AdUnit Format for Multi Ads (mediaTypes.video.playerSize: [1,1]) + ```javascript var multiAdUnits = [{ code: "test-div-multi", diff --git a/dev-docs/bidders/zedo.md b/dev-docs/bidders/zedo.md deleted file mode 100644 index 7584492769..0000000000 --- a/dev-docs/bidders/zedo.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: bidder -title: ZEDO -description: Prebid ZEDO Bidder Adapter -pbjs: true -biddercode: zedo -enable_download: false -pbjs_version_notes: not ported to 5.x ---- - - -### Bid Params - -{: .table .table-bordered .table-striped } -| Name | Scope | Description | Example | Type | -|-----------------|----------|----------------------------------------------------------------------------------------|-----------------------------|-----------| -| `channelCode` | required | Publisher code associated with ZEDO | `2264004118` | `integer` | -| `dimId` | required | ZEDO dimension Id associated with the adunit | `9` | `integer` | -| `pubId` | optional | ZEDO Publisher Id associated with the adunit | `0` | `integer` | diff --git a/dev-docs/bidders/zeroclickfraud.md b/dev-docs/bidders/zeroclickfraud.md index cb7013756a..1818a7c1e4 100644 --- a/dev-docs/bidders/zeroclickfraud.md +++ b/dev-docs/bidders/zeroclickfraud.md @@ -4,6 +4,7 @@ title: ZeroClickFraud pbs: true media_types: banner biddercode: zeroclickfraud +sidebarType: 1 --- ### Bid Params diff --git a/dev-docs/bidders/zeta_global.md b/dev-docs/bidders/zeta_global.md index 08a51def28..d573119dd8 100644 --- a/dev-docs/bidders/zeta_global.md +++ b/dev-docs/bidders/zeta_global.md @@ -6,16 +6,17 @@ pbjs: true biddercode: zeta_global deals_supported: false media_types: banner -gdpr_supported: true +tcfeu_supported: true tcf2_supported: true gvl_id: 469 +sidebarType: 1 --- ### Registration -All references to the OpenRTB spec refer to OpenRtb v2.5 (https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) +All references to the OpenRTB spec refer to OpenRtb v2.5 () -To use this bidder you will need a valid definerId. For further information, please contact jzirbel@disqus.com. +To use this bidder you will need a valid definerId. For further information, please contact . ### Bid Params diff --git a/dev-docs/bidders/zeta_global_ssp.md b/dev-docs/bidders/zeta_global_ssp.md index 1a375294cc..b6d580dcae 100644 --- a/dev-docs/bidders/zeta_global_ssp.md +++ b/dev-docs/bidders/zeta_global_ssp.md @@ -1,34 +1,43 @@ --- layout: bidder -title: Zeta Global Ssp -description: Zeta Global Ssp Prebid Bidder Adapter +title: Zeta Global SSP +description: Zeta Global SSP Prebid Bidder Adapter pbjs: true +pbs: true biddercode: zeta_global_ssp deals_supported: false -media_types: banner -gdpr_supported: true +media_types: banner, video +tcfeu_supported: true usp_supported: true coppa_supported: true userIds: all prebid_member: true -fpd_supported: true -gvl_id: 833 +gvl_id: 469 +sidebarType: 1 --- ### Registration -All references to the OpenRTB spec refer to OpenRtb v2.5 (https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) +All references to the OpenRTB spec refer to OpenRtb v2.5 () +The Zeta Global SSP adapter requires setup and approval from the Zeta Global SSP team. Please reach out to your account team or for more information. ### Bid Params +#### Prebid.js Bid Params + {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |----------------------|----------|---------------------------------------------------------------------------------------------------------------------|--------------|-----------| -| `user` | optional | The object containing user data (See OpenRTB spec) | `user: {}` | `object` | -| `user.buyeruid` | optional | Zeta's user id | `"12345"` | `string` | +| `sid` | required | Seller ID. The identifier associated with the seller or reseller account within the advertising system | `123` | `integer` | +| `tagid` | optional | Identifier for specific ad placement or ad tag that was used to initiate the auction | `"footer"` | `string` | | `tags` | optional | The object containing set of Zeta's custom tags witch publisher have to supply | `tags: {}` | `object` | | `site` | optional | The object containing site data (See OpenRTB spec) | `site: {}` | `object` | | `app` | optional | The object containing app data (See OpenRTB spec) | `app: {}` | `object` | -| `sid` | optional | Seller ID. The identifier associated with the seller or reseller account within the advertising system | `"1q2w3e"` | `string` | +| `bidfloor` | optional | The minimum bid value desired | `0.2` | `float` | | `test` | optional | Flag which will induce a sample bid response when true; only set to true for testing purposes (1 = true, 0 = false) | `1` | `integer` | + +#### Prebid Server Bid Params + +Prebid Server Adapter does not support any parameters. +You must get `sid` value from Zeta Global and use it instead of the placeholder in the URL. diff --git a/dev-docs/bidders/zmaticoo.md b/dev-docs/bidders/zmaticoo.md new file mode 100644 index 0000000000..596d9aeaa5 --- /dev/null +++ b/dev-docs/bidders/zmaticoo.md @@ -0,0 +1,126 @@ +--- +layout: bidder +title: zMaticoo +description: zMaticoo Prebid Bidder Adapter +pbjs: true +biddercode: zmaticoo +deals_supported: false +tcfeu_supported: true +gvl_id: 803 +media_types: banner +sidebarType: 1 +safeframes_ok: true +ortb_blocking_supported: partial +--- + +### Note + +To use this bidder you will need a valid pubId. For further information, please contact . + +### Bid Params + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|----------------------|----------|----------------------------------------------------------------------------------------------------------------------------|-------------------------|----------------| +| `pubId` | required | The pubId provided by zmaticoo |`"prebid_test"` | `string` | +| `user` | optional | The object containing user data (See OpenRTB spec) | `user: {}` | `object` | +| `device` | optional | The object containing device data (See OpenRTB spec) | `device: {}` | `object` | +| `site` | optional | The object containing site data (See OpenRTB spec) | `site: {}` | `object` | +| `app` | optional | The object containing app data (See OpenRTB spec) | `app: {}` | `object` | +| `test` | optional | Flag which will induce a sample bid response when true; only set to true for testing purposes (1 = true, 0 = false) | `1` | `integer` | +| `at` | optional | Auction type, where 1 = First Price, 2 = Second Price Plus | `1` | `integer` | +| `tmax` | optional | Maximum time in milliseconds the exchange allows for bids to be received including Internet latency to avoid timeout | `200` | `integer` | +| `wseat` | optional | White list of buyer seats (e.g., advertisers, agencies) allowed to bid on this impression | `wseat: ["123"]` | `string array` | +| `bseat` | optional | Block list of buyer seats (e.g., advertisers, agencies) restricted from bidding on this impression | `bseat: ["123"]` | `string array` | +| `allimps` | optional | Flag to indicate that the impressions offered represent all the impressions available in context (1 = true, 0 = false) | `1` | `integer` | +| `wlang` | optional | White list of languages for creatives | `wlang: ["ENG"]` | `string array` | +| `bcat` | optional | Blocked advertiser categories using the IAB content categories | `bcat: ["123"]` | `string array` | +| `badv` | optional | Block list of advertisers by their domains | `badv: ["blocked.com"]` | `string array` | +| `bapp` | optional | Block list of applications by their platform-specific exchange independent application identifiers | `badv: ["com.blocked"]` | `string array` | +| `source` | optional | A Source object that provides data about the inventory source and which entity makes the final decision (See OpenRTB spec) | `source: {}` | `object` | +| `ext` | optional | An extension object that allows for custom fields and objects to be sent (See OpenRTB spec) | `ext: {}` | `object` | + +### AdUnit Format Example +#### AdUnit Format for Banner + +```javascript + var adUnits = [{ + code: 'banner-01', + mediaTypes: { + banner: { + sizes: [[320, 50]] + } + }, + bids: [{ + bidder: "zmaticoo", + params: { + pubId: 'prebid-test', + tagid:"001" + }, + }] +}]; +``` + +#### AdUnit Format for video + +```javascript + var adUnits = [{ + code: 'video_ad_unit_1', + mediaTypes: { + video: { + playerSize: [480, 320], + mimes: ['video/mp4'], + context: 'outstream', + } + }, + renderer: { + url: 'https://creative.cdnyeah.com/tpl/renderer/video/zmaticooOutsteam.js', + render: function (bid) { + adResponse = { + ad: { + video: { + content: bid.vastXml, + player_height: 320, + player_width: 480, + }, + }, + } + bid.renderer.push(() => { + ZMOutstreamVideo.renderAd({ + vastUrl: bid.vastXml, + adUnitCode: bid.adUnitCode + }); + }); + } + }, + bids: [{ + bidder: "zmaticoo", + params: { + pubId: 'prebid-test', + tagid:"001" + } + }] +}]; +``` + +### Use prebid.js for an Admanager + To use prebid.js,you can use an Ad Server,like:Google Ad Manager、Smart Ad Server、Xandr Monetize Ad Server。Ad Server helps you manage your ad order,and helps you record ad rendor impression. + Below these file demo implemented settings with Google Ad Manager + + {: .table .table-bordered .table-striped } + | mediaType | demo(md) | demo(html) | + |----------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| + | `Banner` | `https://creative.cdnyeah.com/tpl/renderer/template/banner-gam.md` | `https://creative.cdnyeah.com/tpl/renderer/template/banner-gam.html` | + | `outstream video` | `https://creative.cdnyeah.com/tpl/renderer/template/video-outstream-gam.md` | `https://creative.cdnyeah.com/tpl/renderer/template/video-outstream-gam.html` | + | `instream video` | `https://creative.cdnyeah.com/tpl/renderer/template/video-instream-gam.md` | `https://creative.cdnyeah.com/tpl/renderer/template/video-instream-gam.html` | + +### Use prebid.js for No Admanager +If you don't want to use third-party Ad Server,you can direct integration with zMaticoo。zMaticoo will provide you with a platform(`https://adx.zmaticoo.com`),You can count your request volume,impressions,and income. +Below, these file demos help you integrate with no Admanager + +{: .table .table-bordered .table-striped } +| mediaType | demo(md) | demo(html) | +|----------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `Banner` | `https://creative.cdnyeah.com/tpl/renderer/template/banner-noadserver.md` | `https://creative.cdnyeah.com/tpl/renderer/template/banner-noadserver.html` | +| `outstream video` | `https://creative.cdnyeah.com/tpl/renderer/template/video-outstream-noadserver.md` | `https://creative.cdnyeah.com/tpl/renderer/template/video-outstream-noadserver.html` | +| `instream video` | `https://creative.cdnyeah.com/tpl/renderer/template/video-instream-noadserver.md` | `https://creative.cdnyeah.com/tpl/renderer/template/video-instream-noadserver.html` | diff --git a/dev-docs/cmp-best-practices.md b/dev-docs/cmp-best-practices.md index 6042e90788..f431b75ea8 100644 --- a/dev-docs/cmp-best-practices.md +++ b/dev-docs/cmp-best-practices.md @@ -14,11 +14,7 @@ of Prebid.js and Consent Management Platforms. ## NOT LEGAL ADVICE -{% capture legalNotice %} - This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and/or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. - {% endcapture %} - -{% include /alerts/alert_important.html content=legalNotice %} +{% include legal-warning.html %} ## General @@ -35,17 +31,17 @@ Instead, here are some general guidelines: ### CMP/TCF gdprApplies -The indicates the determination of whether GDPR applies in this context. The CMP, in most cases, is responsible for this. The publisher provides this value when supplying [static](/dev-docs/modules/consentManagement.html) consent data. +The indicates the determination of whether GDPR applies in this context. The CMP, in most cases, is responsible for this. The publisher provides this value when supplying [static](/dev-docs/modules/consentManagement.html) consent data. ### Prebid gdpr.defaultGdprScope -This indicates the behavior of Prebid when the CMP __does not__ provide a value for `gdprApplies`. Critically, the __defaultGdprScope__ is applied if the user times-out in replying to the CMP's questions. While this also can happen if the CMP doesn't set the value in certain cases, or the CMP isn't loaded, the timeout behavior critical to understand. Essentially, the value of this config variable takes the place of the CMP `gdprApplies` when `gdprApplies` value cannot be determined. +This indicates the behavior of Prebid when the CMP **does not** provide a value for `gdprApplies`. Critically, the **defaultGdprScope** is applied if the user times-out in replying to the CMP's questions. While this also can happen if the CMP doesn't set the value in certain cases, or the CMP isn't loaded, the timeout behavior is critical to understand. Essentially, the value of this config variable takes the place of the CMP `gdprApplies` when `gdprApplies` value cannot be determined. ## What does that mean? -Prebid.js doesn't have a concept of the geographic region where it's running. It's up to the CMP and/or publisher to configure Prebid.js correctly. Here are some options for discussing with with your lawyers, engineers, and CMP provider: +Prebid.js doesn't have a concept of the geographic region where it's running. It's up to the CMP and/or publisher to configure Prebid.js correctly. Here are some options for discussing with your lawyers, engineers, and CMP provider: -- If you use a CMP and they __always__ return a proper tcfapi function for all pageviews, even when geo targeting is used, then you should set gdpr.defaultGdprScope to true and let the functionality work as intended. +- If you use a CMP and they **always** return a proper tcfapi function for all pageviews, even when geo targeting is used, then you should set gdpr.defaultGdprScope to true and let the functionality work as intended. - If you otherwise remove the CMP from the page based on Geo, then you should align your Prebid config to that and consider removing the `consentManagement` config from the Prebid.js entirely when GDPR does not apply. - Because of the timeout behavior, gdpr.defaultGdprScope should not be set to false globally. This value could be modified based on Publisher defined logic, but a blanket `false` will result in timeouts in the EEA being treated as GDPR not applying, when it should. diff --git a/dev-docs/common-issues.md b/dev-docs/common-issues.md index ac9cd05993..1096362d99 100644 --- a/dev-docs/common-issues.md +++ b/dev-docs/common-issues.md @@ -12,6 +12,7 @@ sidebarType: 1 # Common Issues with Prebid.js + {:.no_toc} This page lists some common issues publishers run into when setting up Prebid. @@ -20,24 +21,27 @@ This page lists some common issues publishers run into when setting up Prebid. {:toc} ## Price Granularity Mismatch + {:toc} -For example, if your site's price granularity setup is at $0.10 increment, but the line items are expecting $0.50 increments, bid prices such as $0.71 or $0.99 would not match any line items. +For example, if your site's price granularity setup is at $0.10 increment, but the line items are expecting $0.50 increments, bid prices such as $0.71 or $0.99 would not match any line items. ## Non-Prebid line items are at higher priority + {:toc} If you have sponsorship line items running, even with lower bid prices, the Prebid line items won't win. To find out whether you have higher-priority line items running, use your ad servers' debugging tools, such as the [Google Publisher Console](https://support.google.com/dfp_sb/answer/2462712?hl=en&visit_id=1-636195762630970892-522080225&rd=1). ## Bids are coming back, but ads don't show up + {:toc} Check the bid prices. If they are low and are getting reduced to $0 due to price granularity settings, your ad server may choose not to serve them (or you may not have line items targeting $0 bids in your ad server). For example, if you set a $0.50 price granularity and get a bid price of $0.40, the actual price key-value that your ad server will see is $0.00. ## Related Reading -{:toc} - -+ [Prebid.js FAQ](/dev-docs/faq.html) -+ [Prebid Tips for Troubleshooting](/troubleshooting/troubleshooting-guide.html) +{:toc} +* [Prebid.js FAQ](/dev-docs/faq.html) +* [Prebid Tips for Troubleshooting](/troubleshooting/troubleshooting-guide.html) +* [Price Granularity](/adops/price-granularity.html) diff --git a/dev-docs/conditional-ad-units.md b/dev-docs/conditional-ad-units.md index 586416930b..c9069fc25e 100644 --- a/dev-docs/conditional-ad-units.md +++ b/dev-docs/conditional-ad-units.md @@ -11,14 +11,15 @@ sidebarType: 1 # Conditional Ad Units + {:.no_toc} -The [global sizeConfig](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) and [Advanced Size Mapping](/dev-docs/modules/sizeMappingV2.html) features are useful for standard responsive ad designs, but a number of other scenarios are supported as well: +The [global sizeConfig](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) and [Advanced Size Mapping](/dev-docs/modules/sizeMappingV2.html) features are useful for standard responsive ad designs, but a number of other scenarios are supported as well. * TOC {:toc} -By supporting these scenarios, header bidding can be more efficient - the browser can send bids to a more surgical set of bidders based on device size or other attributes the page code can create. +By supporting these scenarios, header bidding can be more efficient; the browser can send bids to a more surgical set of bidders based on device size or other attributes the page code can create. The basic steps are: @@ -27,7 +28,7 @@ The basic steps are: See the [Publisher API reference](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) for syntax. -## What if some bidders should be skipped for some devices? +## Some Bidders Should Be Skipped for Some Devices {: .alert.alert-info :} See the [Advanced Size Mapping module](/dev-docs/modules/sizeMappingV2.html) for another way to handle this scenario. Note that you must use Advanced Size Mapping for mediaTypes other than banner. @@ -37,7 +38,7 @@ to send them requests from display or tablets. We'll start with how to set up the labels from `sizeConfig`: -{% highlight js %} +```javascript pbjs.setConfig({ sizeConfig: [{ @@ -55,12 +56,12 @@ pbjs.setConfig({ }] }); -{% endhighlight %} +``` In the above `sizeConfig`, labels are applied for each of the 3 screen sizes that can later be used in conditional ad unit logic. Now you need to label your AdUnits to match. For example: -{% highlight js %} +```javascript var AdUnits = [{ code: "ad-slot-1", @@ -85,7 +86,7 @@ var AdUnits = [{ ] }] -{% endhighlight %} +``` How this works: @@ -95,7 +96,7 @@ How this works: 1. The first bid doesn't have any conditional logic, so is present in every auction. 1. The second bid requires that "phone" be present in the label array, otherwise it won't be part of the auction. -## What if some bidders have different parameters for different devices? +## Some Bidders Have Different Parameters for Different Devices For reporting and targeting purposes, Publishers and SSPs sometimes break out different inventory structures for different platforms. @@ -113,7 +114,7 @@ Assuming the same `sizeConfig` as in the first use case above, the AdUnit would placements, but the conditional `labelAny` is added to them both. This will cause the bid to be fired only if one or more of the strings in the array matches a defined label. -{% highlight js %} +```javascript var AdUnits = [{ code: "ad-slot-1", @@ -139,7 +140,7 @@ var AdUnits = [{ ] }] -{% endhighlight %} +``` How this works: @@ -153,7 +154,7 @@ How this works: Here's another way of doing the same thing as shown in the previous section: -{% highlight js %} +```javascript var AdUnits = [{ code: "ad-slot-1", @@ -166,18 +167,18 @@ var AdUnits = [{ { bidder: "bidderA", sizeConfig: [ - { minViewPort: [0, 0], relevantMediaTypes: ['none'] }, - { minViewPort: [1200, 0], relevantMediaTypes: ['banner'] } - ], + { minViewPort: [0, 0], relevantMediaTypes: ['none'] }, + { minViewPort: [1200, 0], relevantMediaTypes: ['banner'] } + ], params: { placement: "1111" } },{ bidder: "bidderA", sizeConfig: [ - { minViewPort: [0, 0], relevantMediaTypes: ['banner'] }, - { minViewPort: [1200, 0], relevantMediaTypes: ['none'] } - ], + { minViewPort: [0, 0], relevantMediaTypes: ['banner'] }, + { minViewPort: [1200, 0], relevantMediaTypes: ['none'] } + ], params: { placement: "2222" } @@ -185,15 +186,14 @@ var AdUnits = [{ ] }] -{% endhighlight %} - +``` -## What if some ad unit auctions should be skipped entirely for some devices? +## Some Ad Unit Auctions Should Be Skipped Entirely for Some Devices Say there's a responsive page where one of the ad units only supports larger sizes, so it doesn't make sense on phones. To suppress the ad unit for mobile users, we can apply conditional logic to the entire ad unit. Here's an example using the global sizeConfig approach (banner only): -{% highlight js %} +```javascript var AdUnits = [{ code: "ad-slot-1", @@ -221,9 +221,9 @@ var AdUnits = [{ See the [Advanced Size Mapping module](/dev-docs/modules/sizeMappingV2.html) if you need to do something like this for video. -{% endhighlight %} +``` -## What if some bid requests apply only to users originating certain from countries? +## Some Bid Requests Apply Only to Users Originating from Certain Countries Labels aren't constrained to describing device size -- they can be used for many types of conditions the page maywant to define. Besides being defined as part of `sizeConfig`, labels can also be passed into the [`requestBids()`](/dev-docs/publisher-api-reference/requestBids.html) function as an argument. @@ -232,17 +232,17 @@ certain region. It's really not worth sending them bid requests for users outside of their geographic area. Assuming the page can figure out where the user's from, a label can be implemented and applied to make the bid conditional. -{% highlight js %} +```javascript // page logic determines the 'europeanUser' boolean If (europeanUser) { reqArgs={labels:['eur']}; } pbjs.requestBids(reqArgs); -{% endhighlight %} +``` Then this label can be applied to conditions in the AdUnit just like labels that originate from `sizeConfig`. E.g. -{% highlight js %} +```javascript var AdUnits = [{ code: "ad-slot-1", mediaTypes: { @@ -261,7 +261,7 @@ var AdUnits = [{ ... ] }] -{% endhighlight %} +``` This example shows that the 'euroMobileBidder' is only interested in receiving bids that have **both** labels: @@ -271,6 +271,6 @@ labels: ## Further Reading -+ [Responsive ad designs](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) -+ [Advanced Size Mapping Module](/dev-docs/modules/sizeMappingV2.html) -+ [Using Media Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) +* [Responsive ad designs](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) +* [Advanced Size Mapping Module](/dev-docs/modules/sizeMappingV2.html) +* [Using Media Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) diff --git a/dev-docs/docs-by-format.md b/dev-docs/docs-by-format.md deleted file mode 100644 index 4113fad6ee..0000000000 --- a/dev-docs/docs-by-format.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -layout: page_v2 -title: Docs by Format -description: Docs, broken out by creative format -pid: 4 -top_nav_section: dev_docs -nav_section: reference ---- - -
      - -# Docs by Format -{:.no_toc} - -This page has a list of developer docs broken out by creative format. - -For ad ops and other ad server-related information, see [our Ad Ops documentation]({{site.github.url}}/adops/before-you-start.html). - -* TOC -{:toc} - -{: .table .table-bordered .table-striped } -| Format | Page | -|---------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------| -| *Multi-Format (banner, native, outstream video all in one ad unit)* | [Show Multi-Format Ads with Prebid.js]({{site.baseurl}}/dev-docs/show-multi-format-ads.html) (Engineering setup) | -| | [Setting up Prebid Multi-Format in Google Ad Manager]({{site.baseurl}}/adops/setting-up-prebid-multi-format-in-dfp.html) (Ad ops setup) | -| *AMP* | [How Prebid on AMP Works](/prebid-server/use-cases/pbs-amp.html) | -| | [Show Prebid Ads on AMP Pages (Alpha)]({{site.github.url}}/dev-docs/show-prebid-ads-on-amp-pages.html) | -| *Video* (instream) | [Show Video Ads with a Google Ad Manager Video Tag]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html) (With lots of examples) | -| | [How to Add a New Video Bidder Adapter]({{site.github.url}}/dev-docs/how-to-add-a-new-video-bidder-adaptor.html) | -| *Video* (outstream) | [Show Outstream Video Ads]({{site.github.url}}/dev-docs/show-outstream-video-ads.html) | -| | [Outstream Video Example]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html) | -| *Standard Display* | [Basic Prebid.js Example]({{site.github.url}}/dev-docs/examples/basic-example.html) | -| | [Getting Started]({{site.github.url}}/dev-docs/getting-started.html) | -| | [Ad Unit Refresh / Infinite Scroll Example]({{site.github.url}}/dev-docs/examples/adunit-refresh.html) | -| *Native* | [Show Native Ads with Prebid.js]({{site.github.url}}/dev-docs/show-native-ads.html) (Engineering setup) | -| | [Setting up Prebid Native in Google Ad Manager]({{site.github.url}}/adops/setting-up-prebid-native-in-dfp.html) (Ad Ops setup) | - -
      diff --git a/dev-docs/examples/adunit-refresh.md b/dev-docs/examples/adunit-refresh.md index 07362a534c..4948da6ff5 100644 --- a/dev-docs/examples/adunit-refresh.md +++ b/dev-docs/examples/adunit-refresh.md @@ -6,10 +6,10 @@ description: Individual Ad Unit Refresh / Infinite Scroll sidebarType: 1 about: -- Ability to refresh individual ad units - useful for infinite scrolling ad slots -- When auto-refreshing is done incorrectly, it could cause the same bids to be rendered repeatedly. For instance, when googletag.pubads.refresh() is called directly without removing the PBJS targeting, the same hb_ variables get re-sent to GAM, re-chosen, and re-rendered. Over and over without ever asking PBJS for updated targeting variables. Please see Auction Options for more info. +- Demonstrates the ability to refresh individual ad units. This is useful for infinite scrolling ad slots. +- Keep in mind that when auto-refreshing is done incorrectly, it could cause the same bids to be rendered repeatedly. For instance, when googletag.pubads.refresh() is called directly without removing the PBJS targeting, the same hb_ variables get re-sent to GAM, re-chosen, and re-rendered over and over without ever asking PBJS for updated targeting variables. See Auction Options for more info. -jsfiddle_link: jsfiddle.net/Prebid_Examples/cu7tpexf/2/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/cu7tpexf/embedded/html,result code_height: 1540 diff --git a/dev-docs/examples/basic-example.md b/dev-docs/examples/basic-example.md index 982bb60b62..c0690ec44e 100644 --- a/dev-docs/examples/basic-example.md +++ b/dev-docs/examples/basic-example.md @@ -7,11 +7,11 @@ sidebarType: 1 about: -- Asynchronous Prebid.js integration with single Google Ad Manager ad slot +- This example demonstrates asynchronous Prebid.js integration with a single Google Ad Manager ad slot - Default keyword targeting setup (reference) - Default price granularity -jsfiddle_link: jsfiddle.net/Prebid_Examples/94jt62b8/7/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/94jt62b8/embedded/html,result code_height: 2300 diff --git a/dev-docs/examples/custom-price-buckets.md b/dev-docs/examples/custom-price-buckets.md index 6f914011e7..99bb9da56b 100644 --- a/dev-docs/examples/custom-price-buckets.md +++ b/dev-docs/examples/custom-price-buckets.md @@ -6,10 +6,10 @@ description: Custom Price Granularity Buckets sidebarType: 1 about: -- Custom price granularity buckets using pbjs.setConfig() -- See the the API reference for more detail. +- This example shows custom price granularity buckets using pbjs.setConfig(). +- See the API reference for more detail. -jsfiddle_link: jsfiddle.net/Prebid_Examples/vq05dhnj/2/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/vq05dhnj/embedded/html,result code_height: 2152 diff --git a/dev-docs/examples/instream-banner-mix.md b/dev-docs/examples/instream-banner-mix.md index 71de271dd1..0394bafa15 100644 --- a/dev-docs/examples/instream-banner-mix.md +++ b/dev-docs/examples/instream-banner-mix.md @@ -5,7 +5,10 @@ description: An example of displaying both instream video and banner ads using P sidebarType: 1 -jsfiddle_link: jsfiddle.net/Prebid_Examples/nowfejh7/2/embedded/html,result/ +about: +- This example shows how to display instream video and banner ads within the same configuration. + +jsfiddle_link: jsfiddle.net/Prebid_Examples/nowfejh7/embedded/html,result/ code_height: 3050 diff --git a/dev-docs/examples/legacy-browser-example.md b/dev-docs/examples/legacy-browser-example.md index 253e67c547..cae6e4c6c0 100644 --- a/dev-docs/examples/legacy-browser-example.md +++ b/dev-docs/examples/legacy-browser-example.md @@ -8,8 +8,8 @@ sidebarType: 1 about: - In Prebid 6.0, support for legacy browsers is no longer assured. - Publishers may conditionally deploy the 5.x branch and add polyfills -- One strategy to do this is simply the module/nomodule approach discussed here https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ -- Another strategy is to detect the user agent or the 'currentScript' mechanism as described here https://stackoverflow.com/questions/29987969/how-to-load-a-script-only-in-ie +- One strategy to do this is simply the module/nomodule approach discussed here https://philipwalton.com/articles/deploying-es2015-code-in-production-today/ +- Another strategy is to detect the user agent or the 'currentScript' mechanism as described here https://stackoverflow.com/questions/29987969/how-to-load-a-script-only-in-ie - Another strategy is to conditionally serve one file or another based on instructions to your cdn jsfiddle_link: jsfiddle.net/Prebid_Examples/kqe8L2jf/embedded/html,result diff --git a/dev-docs/examples/meta-bid-filtering.md b/dev-docs/examples/meta-bid-filtering.md index 6fe914df06..f31e6bcd0c 100644 --- a/dev-docs/examples/meta-bid-filtering.md +++ b/dev-docs/examples/meta-bid-filtering.md @@ -6,10 +6,10 @@ description: Bid filtering on meta object example sidebarType: 1 about: -- Bidders can supply metadata about the bid such as advertiser domain. See the "meta" fields in the bid response for the full list. - This is an example that filters bid responses based on the metadata object. +- Bidders can supply metadata about the bid such as advertiser domain. See the "meta" fields in the bid response for the full list of metadata. -jsfiddle_link: jsfiddle.net/Prebid_Examples/0s4eug1d/18/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/0s4eug1d/embedded/html,result code_height: 2300 --- diff --git a/dev-docs/examples/multi-format-example.md b/dev-docs/examples/multi-format-example.md index 86edf69eb3..781c7bf5c9 100644 --- a/dev-docs/examples/multi-format-example.md +++ b/dev-docs/examples/multi-format-example.md @@ -6,12 +6,12 @@ description: Multi-Format Ad Units sidebarType: 1 about: -- A multi-format ad unit allows you receive any combination of banner, video, or native demand +- A multi-format ad unit allows you to receive any combination of banner, video, or native demand - Any bidder that supports at least one of the listed media types can participate in the auction for that ad unit - For engineering setup instructions, see Show Multi-Format Ads -- For ad ops setup instructions, see Setting up Prebid Multi-Format in Google Ad Manager +- For ad ops setup instructions, see Google Ad Manager with Prebid Step by Step -jsfiddle_link: jsfiddle.net/Prebid_Examples/yxsgcj71/2/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/yxsgcj71/embedded/html,result code_height: 3050 diff --git a/dev-docs/examples/native-ad-example.md b/dev-docs/examples/native-ad-example.md index 290d3247e7..63eca29a7d 100644 --- a/dev-docs/examples/native-ad-example.md +++ b/dev-docs/examples/native-ad-example.md @@ -8,9 +8,9 @@ sidebarType: 1 about: - Native advertising is where the ad experience follows the natural form and function of the user experience in which it is placed. - For engineering setup instructions, see Show Native Ads -- For ad ops setup instructions, see Setting up Prebid Native in Google Ad Manager (Alpha) +- For ad ops setup instructions, see GAM Step by Step - Native Creatives -jsfiddle_link: jsfiddle.net/Prebid_Examples/s5L7p3yd/2/embedded/html,result/ +jsfiddle_link: jsfiddle.net/Prebid_Examples/s5L7p3yd/embedded/html,result/ code_height: 3050 diff --git a/dev-docs/examples/no-adserver.md b/dev-docs/examples/no-adserver.md new file mode 100644 index 0000000000..70fb772aac --- /dev/null +++ b/dev-docs/examples/no-adserver.md @@ -0,0 +1,16 @@ +--- +layout: example +title: No Adserver Example +left_nav_override: Examples +description: Running Prebid.js without an ad server +sidebarType: 1 + +about: +- This example demonstrates running an auction and rendering without an ad server. + +jsfiddle_link: jsfiddle.net/Prebid_Examples/svumodbe/embedded/html,result + +code_height: 2300 + +pid: 10 +--- diff --git a/dev-docs/examples/postbid.md b/dev-docs/examples/postbid.md index 9ca0a03c16..2a64381aa2 100644 --- a/dev-docs/examples/postbid.md +++ b/dev-docs/examples/postbid.md @@ -9,12 +9,12 @@ sidebarType: 1 why_link: /overview/what-is-post-bid.html about: -- Postbid is a third-party tag creative you setup in your ad server. Create one line item in the ad server targeting each ad unit on your page. This line item's creative will contain the code below. -- If your ad unit supports multiple sizes, create multiple Postbid creatives for each size. +- Postbid is a third-party tag creative you setup in your ad server that loads the whole Prebid.js package. Create a line item in the ad server targeting each ad unit on your page. The creative will contain the code below. +- If the ad unit supports multiple sizes, you'll need to do one of two things -- either create a Postbid creative for each desired size with that size hardcoded in the PBJS adunit, or use ad server macros to pass the size through to the creative. For example, in Google Ad Manager there are HEIGHT and WIDTH macros. - There is no need to create line items for each price bucket as the postbid creative is served after the ad server has chosen the line item. - This postbid creative supports passback. See how this works below. -jsfiddle_link: jsfiddle.net/Prebid_Examples/mtuq7kz0/2/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/mtuq7kz0/embedded/html,result code_height: 1450 --- diff --git a/dev-docs/examples/size-mapping.md b/dev-docs/examples/size-mapping.md index 162b2326d8..eb87f20109 100644 --- a/dev-docs/examples/size-mapping.md +++ b/dev-docs/examples/size-mapping.md @@ -7,10 +7,10 @@ sidebarType: 1 about: -- Dynamic filtering on ad unit sizes +- This example demonstrates dynamic filtering on ad unit sizes - Ad unit labels applied based on CSS media queries -jsfiddle_link: jsfiddle.net/Prebid_Examples/qourvse1/3/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/qourvse1/embedded/html,result code_height: 2400 diff --git a/dev-docs/examples/sync-tid.md b/dev-docs/examples/sync-tid.md new file mode 100644 index 0000000000..acba990c8d --- /dev/null +++ b/dev-docs/examples/sync-tid.md @@ -0,0 +1,17 @@ +--- +layout: example +title: Sync Transaction Ids With Another Library +description: Synchronize Transaction Ids With Another Library +sidebarType: 1 + + + +about: +- imp.ext.tid sync +- This example demonstrates sending the same impression transaction identifier (imp.ext.tid) to two on page libraries. + +jsfiddle_link: jsfiddle.net/50aqtrck/1/embedded/html,result + +code_height: 2400 + +--- diff --git a/dev-docs/examples/use-prebid-with-appnexus-ad-server.md b/dev-docs/examples/use-prebid-with-appnexus-ad-server.md index 4339532f37..a5d3980f5f 100644 --- a/dev-docs/examples/use-prebid-with-appnexus-ad-server.md +++ b/dev-docs/examples/use-prebid-with-appnexus-ad-server.md @@ -1,15 +1,15 @@ --- layout: example -title: Using Prebid.js with Xandr Publisher Ad Server -description: Using Prebid.js with Xandr Publisher Ad Server +title: Using Prebid.js with Microsoft Monetize Ad Server +description: Using Prebid.js with Microsoft Monetize Ad Server sidebarType: 1 about: -- An example showing how to use Prebid.js with Xandr Publisher Ad Server -- See the Seller Tag (AST) documentation for more information -- To configure the Seller Tag to use SafeFrames, refer to the SafeFrame API Reference. +- This example shows how to use Prebid.js with Micosoft Monetize Ad Server. +- See the Seller Tag (AST) documentation for more information. +- To configure the Seller Tag to use SafeFrames, refer to the SafeFrame API Reference. -jsfiddle_link: jsfiddle.net/Prebid_Examples/tr1djf9e/3/embedded/html,result +jsfiddle_link: jsfiddle.net/Prebid_Examples/tr1djf9e/embedded/html,result code_height: 2404 ---- +--- \ No newline at end of file diff --git a/dev-docs/faq.md b/dev-docs/faq.md index 805f7a1256..cfca608b86 100644 --- a/dev-docs/faq.md +++ b/dev-docs/faq.md @@ -5,8 +5,6 @@ description: FAQ on Prebid.js for header bidding. sidebarType: 1 --- - - # Prebid.js FAQ {:.no_toc} @@ -15,22 +13,87 @@ This page has answers to some frequently asked questions about Prebid.js. If yo * TOC {:toc} -## Do we need to be a member of Prebid.org to submit a bidder adapter or analytics adapter? +## General + +### Do we need to be a member of Prebid.org to submit a bidder adapter or analytics adapter? Nope. The only approval process is a code review. There are separate instructions for: -- [adding a bidder in Prebid.js](/dev-docs/bidder-adaptor.html) -- [adding an analytics adapter in Prebid.js](/dev-docs/integrate-with-the-prebid-analytics-api.html) +* [adding a bidder in Prebid.js](/dev-docs/bidder-adaptor.html) +* [adding an analytics adapter in Prebid.js](/dev-docs/integrate-with-the-prebid-analytics-api.html) As for [membership](https://prebid.org/membership/) in Prebid.org, that's entirely optional -- we'd be happy to have you join and participate in the various committees, but it's not necessary for contributing code as a community member. -## What should my timeouts be? +### How often is Prebid.js updated? + +We release almost every week. See [the GitHub release schedule](https://github.com/prebid/Prebid.js/blob/master/RELEASE_SCHEDULE.md) for more details. + +### When do I have to upgrade my version of Prebid.js? + +Prebid.org does not support any version of Prebid.js prior to the previous version. e.g. if the current version is 8.x, we'll help debug 7.x, but not 6.x. If you want continued support through updates and documentation you should upgrade to a newer version. + +### Does Prebid.js support Amazon TAM? + +We would love for Amazon to contribute a TAM adapter, but so far that's not happened. Publishers that want to sync IDs across multiple header bidding wrappers should be aware of these resources: + +* You can generate the auctionId parameter outside of Prebid and pass it when calling [pbjs.requestBids()](/dev-docs/publisher-api-reference/requestBids.html) +* [Example of Synchronizing Transaction IDs with Another Library](/dev-docs/examples/sync-tid.html) + +### Should Prebid bidders be in ads.txt? + +Publishers should be careful to list all their bidding partners in their ads.txt file. Bidders without an entry in ads.txt may be +perceived by DSPs as unauthorized sources of your inventory. The domain for any ads.txt [inventory partners](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/dc71586842e648e89c1bbe6c666ffac8ff010a96/2.6.md?plain=1#L1752), if one exists, should be specified with a `setConfig({ortb2.site.inventorypartnerdomain})` call. For details of the specification of ads.txt entries, see [ads.txt v1.1](https://iabtechlab.com/wp-content/uploads/2022/04/Ads.txt-1.1.pdf) + +## Privacy + +### How does Prebid support privacy regulations? + +Prebid understands that publishers are under increasing pressure to respond and adapt to privacy regulations. For instance, an increasing number of laws (including California’s CPRA and laws in Colorado, Virginia, Connecticut, and Utah) already require, or will require in 2023, specific disclosures around and ability to opt out of targeted advertising activities as well as “sales” of consumer data. While we cannot give legal advice, we do provide a toolkit that supports publishers in their efforts to comply with the laws that apply to them. If there’s a tool you need that you don’t see listed below, please do open an issue in the appropriate repository ([PBJS](https://github.com/prebid/Prebid.js/issues), [PBS](https://github.com/prebid/prebid-server/issues), [SDK](https://github.com/prebid/prebid-mobile-ios/issues)). + +To get started, first talk to your lawyers to determine your legal obligations. You might, for instance, want to run a Consent Management Platform (CMP) that allows consumers to opt into or out of certain practices when your users are in privacy-sensitive jurisdictions. + +After you’ve determined your legal obligations, consider the tools Prebid makes available to publishers so that their pages can determine what actions are needed based on their interpretation of the user’s actions and the company’s policies: + +* Consider utilizing an [Activity Control](/dev-docs/activity-controls.html). These are available with Prebid.js 7.48 and may help cover a number of common privacy concerns. +* Turn off Prebid.js usersync: + * [for client-side adapters](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) - either completely or for certain bidders. + * [for server-side adapters](/dev-docs/modules/prebidServer.html) - override the s2sConfig.syncEndpoint +* [Disable User ID modules](/dev-docs/modules/userId.html) - there are controls for different ID modules and which bidders can get which IDs. +* [Disable device access](/dev-docs/publisher-api-reference/setConfig.html#setConfig-deviceAccess) - no adapter or module will be able to create a cookie or HTML5 localstorage object. +* For GDPR: + * Consider the [GDPR](/dev-docs/modules/consentManagement.html) and [GDPR Enforcement](/dev-docs/modules/gdprEnforcement.html) modules, which flexibly support various actions like cancelling usersyncs, auctions, and analytics. Using these modules, bid adapters can receive the IAB TCF string from the CMP. + * Note that TCF 2.2 is functionally the same as TCF 2.0 from the Prebid.js perspective. The code has always relied on event listeners to get the TCF string, so when `getTCData` was deprecated in 2.2 the modules were unaffected. There are still references in the code only because it is still accepted as a place for statically-supplied data. + * Alternatively, the page can just avoid turning on certain bidders or modules. +* For CCPA / CPRA / US-Privacy: + * Consider the [US-Privacy](/dev-docs/modules/consentManagementUsp.html) module, which passes the IAB USP string through to bid adapters and supports data deletion events for User ID modules and other interested adapters and modules. + * Also consider implementing an [Activity Control](/dev-docs/activity-controls.html) to suppress activities upon opt-out or in environments without legal notice. An example implementation is available on the activity control documentation page. + * Also consider implementing the [GPP control module - usnat section](/dev-docs/modules/gppControl_usnat.html) to implement reasonable default expressions of activity controls when a usnat string is available as section 7 of a GPP string. +* Set the [COPPA flag](/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa), which passes this value through to modules and bid adapters. + * Also consider implementing an [Activity Control](/dev-docs/activity-controls.html) to suppress activities when COPPA applies. The implementation is very similar to the example CCPA implementation available on the activity control documentation page. +* The IAB is still refining the definition of [GPP](https://iabtechlab.com/gpp/). Prebid has built a GPP module that supports GPP 1.0, with 1.1 support coming soon after the specification is finalized and merged. Many bid adapters support both statically setting GPP strings, e.g. `pbjs.setConfig({ortb2: {regs: {gpp: "blah", gpp_sid: [1,2]}}});` and module-read consent. +* Avoid adding certain bidders or modules to the AdUnit. +* Turn off header bidding altogether. + +Prebid relies on the IAB and community members to determine what tools are needed to support publishers in meeting their legal obligations. As noted above, if there’s another tool you need, please open an issue in the appropriate repository, or join the org and help us improve the system! + +### What happened to the allowAuctionWithoutConsent flag? + +This option to the ConsentManagement module was removed a long time ago in PBJS 4.0. Why? + +* It was a poorly named flag. What it did was let the auction happen on the first page before the user had responded to the CMP. +* It was replaced by a combination of the "defaultGdprScope" flag and the ability for a publisher to disable enforcement of the `basicAds` TCF purpose. + +See the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html) documentation for more details. + +## Implementation + +### What should my timeouts be? Below is a set of recommended best practice starting points for your timeout settings: -- 1,000 milliseconds or less for the internal auction timeout -- 3,000 milliseconds or less for the Prebid tag's overall failsafe timeout +* 1,000 milliseconds or less for the internal auction timeout +* 3,000 milliseconds or less for the Prebid tag's overall failsafe timeout The former setting is used to track the auction once it started; if it expires, we will use whichever bidders have responded and select the winner(s) accordingly. @@ -40,7 +103,7 @@ For examples of setting up these timeouts, please refer to the [Basic Example]({ See the [Prebid Timeouts Reference](/features/timeouts.html) for more information about timeouts in general. -## How many header bidders should I have? +### How many bid adapters should I have? Every publisher is different. In order to answer this question you'll need to run some tests, gather data, and decide what works for you based on your performance and monetization needs. @@ -52,16 +115,16 @@ There is an analysis from the Prebid team here which may be useful: [How many bidders should I work with?](https://prebid.org/blog/how-many-bidders-for-header-bidding) -## Does Prebid.js cache bids? +### Does Prebid.js cache bids? It can. Versions 1.x of Prebid.js would re-consider previous bids under limited circumstances. In Prebid.js 2.0 and later, the [`useBidCache`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Use-Bid-Cache) option can be used to enable this functionality. The "limited bid caching" feature applies only: -- for the same AdUnit, -- on the same page view, -- for the same user, and -- up to a certain Time-to-Live (TTL) or until the bid wins and is displayed. +* for the same AdUnit, +* on the same page view, +* for the same user, and +* up to a certain Time-to-Live (TTL) or until the bid wins and is displayed. Since the storage is in the browser, cached bids only apply to a single page context. If the user refreshes the page, the bid is lost. @@ -70,9 +133,9 @@ This setting is called “Time to Live” (TTL), documented in the pbjs.ge Examples of scenarios where a bid may be reconsidered in Prebid.js: -- Auto-refresh: Some pages will reload an AdUnit on a set interval (often 60-240 seconds). Previous bids for that particular AdUnit can be reconsidered for subsequent refreshes of that unit up to the TTL or until they win the unit. -- Infinite scroll: As the user scrolls, the same AdUnit may be dynamically created over and over. The bid can be reconsidered for dynamically-created AdUnits with the same name. Again, the bid is only re-considered on that AdUnit up to the bid TTL or until it's displayed. -- Galleries: Some pages feature carousel-style galleries that contain an AdUnit that refreshes as the user cycles through the content in the gallery. +* Auto-refresh: Some pages will reload an AdUnit on a set interval (often 60-240 seconds). Previous bids for that particular AdUnit can be reconsidered for subsequent refreshes of that unit up to the TTL or until they win the unit. +* Infinite scroll: As the user scrolls, the same AdUnit may be dynamically created over and over. The bid can be reconsidered for dynamically-created AdUnits with the same name. Again, the bid is only re-considered on that AdUnit up to the bid TTL or until it's displayed. +* Galleries: Some pages feature carousel-style galleries that contain an AdUnit that refreshes as the user cycles through the content in the gallery. Here's how it works: @@ -83,13 +146,13 @@ Here's how it works: 1. A cached bid may be used if its CPM beats the new bids. 1. Bids that win are removed from the pool. This is automatic for display and native ads, and can be done manually by the publisher for video ads by using the [markWinningBidAsUsed](/dev-docs/publisher-api-reference/markWinningBidAsUsed.html) function. -## Some of my demand partners send gross bids while others send net bids; how can I account for this difference? +### Some of my demand partners send gross bids while others send net bids; how can I account for this difference? You will want to adjust the gross bids so that they compete fairly with the rest of your demand, so that you are seeing the most revenue possible. In Prebid.js, you can use a `bidCpmAdjustment` function in [the `bidderSettings` object](/dev-docs/publisher-api-reference/bidderSettings.html) to adjust any bidder that sends gross bids. -## Does Prebid.js support synchronous ad server tags? +### Does Prebid.js support synchronous ad server tags? Short answer: not out of the box, because of header bidding partners' limitations. But there are workarounds. @@ -99,37 +162,29 @@ Therefore, it requires Prebid.js to run in a blocking/synchronous fashion. **Thi Here are a couple of alternative workarounds: -- **Option 1:** +* **Option 1:** - Load a blocking script that has a load time of 300-500ms. This script does nothing but keep the page waiting. In the meantime Prebid.js can run asynchronously and return the bids. After the blocking script finishes loading, GPT can start synchronously; at this point there will be header bidding bids available. + Load a blocking script that has a load time of 300-500ms. This script does nothing but keep the page waiting. In the meantime Prebid.js can run asynchronously and return the bids. After the blocking script finishes loading, GPT can start synchronously; at this point there will be header bidding bids available. - For the best user experience, you probably want to insert this blocking script after the above the fold page content has loaded. Or if you're okay with additional 500ms latency added to your page load time, this can be easily done. + For the best user experience, you probably want to insert this blocking script after the above the fold page content has loaded. Or if you're okay with additional 500ms latency added to your page load time, this can be easily done. -- **Option 2:** +* **Option 2:** - Use post-bid. The downsides are that post-bid no longer allows your header bidding partners to compete with Google Ad Manager/AdX, but they can still compete with each other. For more information, see [What is post-bid?]({{site.baseurl}}/overview/what-is-post-bid.html). + Use post-bid. The downsides are that post-bid no longer allows your header bidding partners to compete with Google Ad Manager/AdX, but they can still compete with each other. For more information, see [What is post-bid?]({{site.baseurl}}/overview/what-is-post-bid.html). -## How do I use Prebid.js on secure (HTTPS) pages? +### How do I use Prebid.js on secure (HTTPS) pages? All prebid adapters that get merged should automatically detect if they're serving into a secure page environment and respond appropriately. In other words, you shouldn't have to do anything other than make sure your own page loads Prebid.js securely, e.g., ```html - ``` (Except that you should *never never never* use the copy of Prebid.js at that URL in production, it isn't meant for production use and may break everything at any time.) -## How often is Prebid.js updated? - -See [the GitHub release schedule](https://github.com/prebid/Prebid.js/blob/master/RELEASE_SCHEDULE.md) for more details. - -## When do I have to upgrade my version of Prebid.js? - -Prebid.org does not support any version of Prebid.js prior to the previous version. e.g. if the current version is 4.x, we'll help debug 3.x, but not 2.x. If you want continued support through updates and documentation you should upgrade to a newer version. - -## How can I change the price granularity for different ad units? +### How can I change the price granularity for different ad units? If you need different [price granularities](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity) for different AdUnits (e.g. video and display), the only way for now is to make sure the auctions don't run at the same time. e.g. Run one of them first, then kick off the other in the bidsBackHandler. e.g. here's one approach: @@ -142,7 +197,7 @@ If you need different [price granularities](/dev-docs/publisher-api-reference/se The handling of this scenario will be improved in a future release. -## How can I control how many targeting variables are sent to my ad server? +### How can I control how many targeting variables are sent to my ad server? One way to limit the number of bytes sent to the ad server is to send only the winning bid by disabling the [enableSendAllBids](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) option. However, there are optimization and reporting benefits for sending more than one bid. @@ -150,31 +205,60 @@ benefits for sending more than one bid. Once you find the right balance for your application, you can specify what's sent to the ad server with [targetingControls.auctionKeyMaxChars](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) and/or [sendBidsControl.bidLimit](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-Bids-Control) -## Can I run multiple different versions of Prebid.js concurrently? +### Can I run multiple different versions of Prebid.js concurrently? It's technically possible, but we don't recommend doing this: -- The code isn't small. For performance reasons you don't want to run two versions if you can help it -- We don't test concurrent versions -- We won't specifically support debugging problems caused by running two concurrent versions. But will take take PRs if someone finds an issue. +* The code isn't small. For performance reasons you don't want to run two versions if you can help it +* We don't test concurrent versions +* We won't specifically support debugging problems caused by running two concurrent versions. But will take take PRs if someone finds an issue. -If all this wasn't enough to warn you away from trying, it should work if you name the PBJS global differently for each instance (https://github.com/prebid/Prebid.js/blob/master/package.json#L20) +If all this wasn't enough to warn you away from trying, it should work if you name the PBJS global differently for each instance (Update the value of 'globalVarName' in ) -## Can I filter bid responses that don't meet my criteria? +### Can I filter bid responses that don't meet my criteria? Yes. Many bidders provide metadata about the bid that can be used in troubleshooting and filtering. See the [list of bid response metadata](/dev-docs/bidder-adaptor.html#interpreting-the-response) and the [filtering example](/dev-docs/examples/meta-bid-filtering.html). -## Does Prebid.js resolve the AUCTION_PRICE macro? +### Does Prebid.js resolve the AUCTION_PRICE macro? Yes, but in a way that could cause discrepancies in reporting. It's recommended that [bid adapters resolve OpenRTB macros](/dev-docs/bidder-adaptor.html#resolve-openrtb-macros-in-the-creatives) themselves before giving them to Prebid.js. -For historic reasons, Prebid will resolve the AUCTION_PRICE macro, but it will be after currency conversion and any bid adjustments. -This differs from how OpenRTB defines this value as being the clearing price in the bid currency. Header Bidding is a first-price auction, the best candidate for “clearing price” is the original bid itself. +For historic reasons, Prebid will resolve the AUCTION_PRICE macro. + Header Bidding is a first-price auction, the best candidate for “clearing price” is the original bid itself. Prebid may deprecate this resolution; it is not recommended to be resolved client-side, as it opens opportunities for abuse. + +### How does Prebid interact with the GAM yield group header bidding feature? + +Google is developing this technology to help publishers create and manage line items in bulk. This should enable more publishers to integrate their sites with header bidding on the open web. Here is Google's [official blog post](https://blog.google/products/admanager/improved-header-bidding-support-in-google-ad-manager/) on yield group. This feature is currently in beta production. + +What we know about yield group feature: + +1. The feature is limited to premium GAM accounts. +1. The beta is limited to which publishers are involved. +1. These use cases currently don't work with yield groups: [Native](/formats/native.html), [video](/formats/video.html), [AMP](/formats/amp.html), [Post-Bid](/overview/what-is-post-bid.html). Google is open to feedback from the community about these scenarios. +1. The [Prebid Universal Creative](/overview/prebid-universal-creative.html) is not utilized. Google has ported some portions of the PUC to an internal creative. For safeframes, the special creative calls postMessage, or if not a safeframe, it calls pbjs.renderAd() in the parent frame. +1. The in-page Google Publisher Toolkit (GPT) reads Prebid.js objects directly from the 'pbjs' global. If window.pbjs does not exist, it attempts to locate a non-standard Prebid global via window._pbjsGlobals; looking for the first instance that exists with the required functionality. +1. Not all Prebid bid adapters are supported. +1. Aliases are not currently supported, but Google aims to support aliases that are commonly used. There may be future updates to support custom aliases. +1. GPT determines bid values using pbjs events, specifically creating auctionEnd, bidTimeout, bidRequested, and noBid event handlers. +1. The Yield Group should win when the adjusted bid price is higher than the header bidding price bucket (hp_pb), which should typically occur if the publisher is rounding bids down, as is the Prebid default. +1. While detailed performance testing has not taken place, we hope that the improved auction dynamics from no longer using price bucketing will have beneficial effects on auction outcomes. + +## Developers + +### I'm a developer - how do I change the name of my module? + +Sometimes the owner of a bid adapter or other kind of module wants to rename their module. However, Prebid considers module renames a +'breaking change' -- publishers' build processes and pages could break as a result of a renaming, so Prebid's policy on renaming is: + +1. Create the new Prebid.js module files (js and md) +2. If they're basically the same code base, change the old file so that it includes the new file. This prevents duplicate maintenance of code. In general we don't approve modules including each other, but we'll approve it to avoid repetition. +3. The docs repo should contain both names, with the old name referring to the new name. You can add the "enable_download: false" flag to prevent installations of the old name. +4. At the next major release the old files may be removed. ## Related Reading -+ [Prebid.js Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html) -+ [Prebid.js Common Issues](/dev-docs/common-issues.html) -+ [Prebid.js issues tagged 'question'](https://github.com/prebid/Prebid.js/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20) +* [Prebid.js Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html) +* [Prebid.js Common Issues](/dev-docs/common-issues.html) +* [Prebid.js issues tagged 'question'](https://github.com/prebid/Prebid.js/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20) diff --git a/dev-docs/floors-video-overview.md b/dev-docs/floors-video-overview.md new file mode 100644 index 0000000000..0a676ebbb2 --- /dev/null +++ b/dev-docs/floors-video-overview.md @@ -0,0 +1,128 @@ +--- +layout: page_v2 +title: Video Intro to Floors for Prebid.js and Prebid Server +description: Video Intro to Floors for Prebid.js and Prebid Server +sidebarType: 1 +--- + +# Video Intro to Floors for Prebid.js and Prebid Server + +An overview of the Prebid.js and Prebid Server price floor features. + +
      + +

      +Notes: + +- [Prebid.js Price Floors Module](/dev-docs/modules/floors.html#overview) +- [Price Floors in Prebid Server](/prebid-server/features/pbs-floors.html#prebid-server--features--price-floors) +- [Prebid Floor Service Providers](/dev-docs/modules/floors.html#floors-providers) + +Related Videos: + +- [Introduction to Prebid.js](/prebid/prebidjs-video.html) +- [Components of Prebid.js](/prebid/prebidjs-components-video.html) +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview-video.html) +- [All Videos](/overview/all-videos.html) + +## Transcript + +### Introduction + +This video is an overview for publishers on price floors in Prebid.js and Prebid Server. We’ll discuss how publishers use price floors in their header bidding auctions and explain how they work in Prebid.js and Prebid Server. + +### Price Floor Basics + +A price floor sets the minimum price that a publisher is willing to accept from a bidder for an impression. A bidder must bid above the price floor if they want to serve their ad. Price floors are communicated to bidders in bid requests, so they know what the minimum eligible bid price is. Publishers have complete control over the floor prices for their auctions, and Prebid gives publishers powerful tools for fine-tuning price floor values to specific auction scenarios. Prebid also allows publishers to use dynamic price floors that adjust in real time to market conditions. + +### Why Use Price Floors? + +Before we get into the details of how price floors work in Prebid, let’s talk about why you might want to use them. + +One reason is to make sure that the cost of serving an ad doesn’t exceed the revenue earned for the ad. These costs include ad serving fees and the impact of an ad on user experience. Setting price floors in line with these costs helps publishers ensure that serving ads consistently delivers a net benefit to their business. + +Some publishers also use floors to help protect ad quality or to control the allocation of impressions between programmatic and direct-sold demand channels. + +Another common reason that publishers use floors today is to counteract the price degradation that can occur under first-price auctions. + +A first-price auction is an auction in which the price that the winning bidder pays for the impression is equal to their bid price. The benefit of first-price auctions is the transparency that they offer buyers. + +However, first price auctions can also encourage buyers to use bid prices that are below what they think the impression is worth. This is called bid shading, and it places downward pressure on impression CPMs. + +To counter the price erosion caused by bid shading, many publishers use dynamic price floors that are driven by algorithms. + +### How Floors Work in Prebid + +Next, let’s dive into how floors work in Prebid. + +We’ll start with a general model that applies to both Prebid.js and Prebid Server, then we’ll go deeper on each platform. + +Price floors govern bid prices for the auction. Price floors are always determined before the auction begins and are sent to bidders in bid requests. + +How the price floor is determined before the auction can be very simple or quite complex. Price floors are matched with bids based on targeting attributes, which can include ad unit and media type information, device and user data, first party data, and more. + +We’ll cover all this in more detail later on. + +When a bidder sends a bid, Prebid.js and Prebid Server can check to make sure that the bid price is above the price floor. By default, bids below the floor will be prevented from competing in the auction. + +Prebid’s price floors feature also automatically adjusts floors per bidder to take into account bid CPM adjustments that many publishers use to offset bidder fees or discrepancies. + +With these basics established, let’s dive into how floors work in Prebid.js and Prebid Server. + +#### Floors in Prebid.js + +Let’s start with Prebid.js + +To use price floors in Prebid.js, you must first install the Price Floors Module. The module includes Prebid.js functionality for setting, signaling, and enforcing price floors. + +Once the Price Floor Module is installed, you’ll decide where you want the price floors to be located. There are three options: Ad Unit, Package, and Dynamic. + +With the Ad Unit method, price floor values are hard-coded directly into the Prebid.js Ad Unit. If the ad unit includes multiple ad sizes or multiple formats, it is possible to specify separate price floor values for each or just use a catch all floor. + +Configuring ad-unit-based floors is much like configuring other ad unit attributes like media types or bidder parameters. If you have many ad units, configuring and routinely updating floors on the ad unit level can be a large undertaking. For this reason, we generally recommend this approach only for setting permanent baseline floors that you don’t expect to change ever. + +The Package method is more powerful and flexible than the ad unit method. With the package method, price floors live in a centralized price floors object inside the Prebid.js configuration. + +The price floors object includes rules that assign price floor values based on targeting criteria. + +The criteria may include dimensions like Prebid Ad Unit, Google Ad Manager Ad Unit, media type, dimensions, and much more. It’s even possible to create your own custom dimensions that integrate with data-gathering JavaScript running on your page. + +The package approach is well suited to publishers who need to fine tune their floors with specific targeting criteria. But it’s important to note that it is common for publishers using the package approach to have hundreds of price floors. If you consider this approach, you’ll also need to develop workflows for configuring and maintaining the price floor packages. + +The third method for implementing price floors in Prebid.js is dynamic floors. + +This method resembles the package approach, but instead of the package being bundled within the Prebid.js wrapper, it can be loaded externally and refreshed separately by a price floors service. + +The dynamic method allows your floors to adapt automatically to changing market conditions. + +The dynamic approach is best for publishers who want to improve header bidding performance through price floor optimization. + +The server-side architecture allows floor providers to use Prebid analytics data, machine learning, and A/B testing to keep price floors updated to optimal values. + +Many Prebid community companies provide dynamic price floor managed services, or you could build your own service. + +It’s worth noting that with the dynamic model, the first auction on the page may be delayed by a few milliseconds in order to fetch the price floor package from the floor provider. + +However, this delay does not affect every page load, because the price floors package will be cached by the browser. The publisher also has control over the maximum amount of time that the auction will be delayed to fetch a new floors package. + +For a list of dynamic price floor providers, visit the link in the description below. + +#### Floors in Prebid Server + +We’ll end this video with an explanation of how price floors can be set up in Prebid Server. + +If you’re using Prebid Mobile or Prebid for AMP and want to use price floors, then you will want to take advantage of Prebid Server’s price floors feature. + +Floors in Prebid Server uses a model that is very similar to the Prebid.js package and dynamic approaches. The floors are stored in a JSON object that includes a set of targeting rules that match price floor values to segments of inventory. + +It’s possible to configure the price floor file manually within Prebid Server, but it’s more common to use a price floor service that updates the price floor file dynamically. + +Like in Prebid.js, Prebid Server is able to match floors to robust targeting rules and is able to enforce floors. Floors are signaled to bidders in bid requests, and they adapt to bid adjustments. + +The differences between the Prebid.js and Prebid Server price floor solutions all trace back to the differences between the client-side and server-side platforms. + +Notably, Prebid Server is able to use additional price floor targeting fields like country, but lacks the custom dimensions feature that Prebid.js has. + +Also, the Prebid Server floor service does not need to be called prior to the auction. Instead, the floor service periodically updates the floor data object asynchronously. This means that the Prebid Server auction will never be delayed, even with dynamic floors + +That’s it for this discussion on price floors in Prebid.js and Prebid Server. For more information, check out the reference documents linked in the description below this video. diff --git a/dev-docs/getting-started.md b/dev-docs/getting-started.md index 6b49b01937..0990fa77b7 100644 --- a/dev-docs/getting-started.md +++ b/dev-docs/getting-started.md @@ -1,37 +1,50 @@ --- layout: page_v2 -title: Getting Started +title: Getting Started for Developers description: Dev docs for getting started with Prebid.js for header bidding sidebarType: 1 --- - # Getting Started for Developers + {: .no_toc } * TOC {: toc } -### Quick Start +## Overview + +To run heading bidding on your site with Prebid.js you need to [download the Prebid.js package](/download.html), including your selected bidders and adapters, and add the code to your page. This code will gather bids from your selected demand sources (bidders) and pass the information on to your ad server. For full details on how Prebid.js works, see [What is Prebid.js?](/prebid/prebidjs.html). + +Developers should work with their ad ops team to plan out your Prebid configuration. You'll need to add information to your code regarding things such as: + +* Whether you're sending all bids or only the top price bid to the ad server +* What level of price granularity you'll be using +* What key-value pairs do you need to pass to the ad server + +See the [Ad Ops Planning Guide](/adops/adops-planning-guide.html) for details. + +## Quick Start -The easiest way to get started with Prebid.js is to use the example code below. +The easiest way to get started with Prebid.js is to look at an example. Start with our [Basic Example](/dev-docs/examples/basic-example.html), then explore other examples under **Prebid.js > Examples** to find what you need. -{% include dev-docs/build-from-source-warning.md %} +## Next Steps - -

      -

      (Sorry, jsfiddle code examples aren't available with your cookie privacy settings.)

      -

      Cookie Settings


      -
      +For more developer resources, see: - +* [Publisher API Reference](/dev-docs/publisher-api-reference.html) +* [Prebid.js Module Overview](/dev-docs/modules/) +* [Prebid.js Analytics Adapters](/overview/analytics.html) -### Next Steps +To learn more about header bidding and Prebid see: -1. Set up your ad server using the [corresponding Ad Ops setup instructions]({{site.baseurl}}/adops/send-all-bids-adops.html) -2. Once you're comfortable with the basic setup, check out [the examples showing other use cases]({{site.baseurl}}/dev-docs/examples/basic-example.html) +* [Introduction to Header Bidding](/overview/intro-to-header-bidding.html) +* [Introduction to Prebid](/overview/intro.html) +* [What is Prebid.js?](/prebid/prebidjs.html) +For guidance on planning out your configuration and working with your ad server, see: +* [Ad Ops and Prebid](/adops/before-you-start.html) +* [Ad Ops Planning Guide](/adops/adops-planning-guide.html) +* [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) diff --git a/dev-docs/integrate-with-the-prebid-analytics-api.md b/dev-docs/integrate-with-the-prebid-analytics-api.md index 15aec64b6b..ba1a9dfb42 100644 --- a/dev-docs/integrate-with-the-prebid-analytics-api.md +++ b/dev-docs/integrate-with-the-prebid-analytics-api.md @@ -12,17 +12,19 @@ sidebarType: 1 # How to Add a Prebid.js Analytics Adapter + {:.no_toc} The Prebid Analytics API provides a way to get analytics data from `Prebid.js` and send it to the analytics provider of your choice, such as Google Analytics. Because it's an open source API, you can write an adapter to send analytics data to any provider you like. Integrating with the Prebid Analytics API has the following benefits: -+ It decouples your analytics from the `Prebid.js` library so you can choose the analytics provider you like, based on your needs. +* It decouples your analytics from the `Prebid.js` library so you can choose the analytics provider you like, based on your needs. + +* You can selectively build the `Prebid.js` library to include only the analytics adapters for the provider(s) you want. This keeps the library small and minimizes page load time. -+ You can selectively build the `Prebid.js` library to include only the analytics adapters for the provider(s) you want. This keeps the library small and minimizes page load time. +* Since this API separates your analytics provider's code from `Prebid.js`, the upgrade and maintenance of the two systems are separate. If you want to upgrade your analytics library, there is no need to upgrade or test the core of `Prebid.js`. -+ Since this API separates your analytics provider's code from `Prebid.js`, the upgrade and maintenance of the two systems are separate. If you want to upgrade your analytics library, there is no need to upgrade or test the core of `Prebid.js`. +[//]: # (This comment is a separator that allows the list above and the TOC to be rendered at the same time) -* TOC {:toc } ## Architecture of the Analytics API @@ -54,7 +56,9 @@ with the [module rules](/dev-docs/module-rules.html) that apply globally and to Create a markdown file under `modules` with the name of the bidder suffixed with 'AnalyticsAdapter', e.g., `exAnalyticsAdapter.md` Example markdown file: -{% highlight text %} + +```md + # Overview Module Name: Ex Analytics Adapter @@ -65,7 +69,7 @@ Maintainer: prebid@example.com Analytics adapter for Example.com. Contact prebid@example.com for information. -{% endhighlight %} +``` ### Step 2: Add analytics source code @@ -73,16 +77,16 @@ Analytics adapter for Example.com. Contact prebid@example.com for information. 2. Create an analytics adapter to listen for [Prebid events](/dev-docs/publisher-api-reference/onEvent.html) and call the analytics library or server. See the existing *AnalyticsAdapter.js files in the repo under [modules](https://github.com/prebid/Prebid.js/tree/master/modules). -3. There are two types of analytics adapters. The example here focuses on the 'endpoint' type. See [AnalyticsAdapter.js](https://github.com/prebid/Prebid.js/blob/master/src/AnalyticsAdapter.js) for more info on the 'bundle' type. +3. There are two types of analytics adapters. The example here focuses on the 'endpoint' type. See [AnalyticsAdapter.js](https://github.com/prebid/Prebid.js/blob/master/libraries/analyticsAdapter/AnalyticsAdapter.js) for more info on the 'bundle' type. - * endpoint - Calls the specified URL on analytics events. Doesn't require a global context. - * bundle - An advanced option expecting a global context. + 1. endpoint - Calls the specified URL on analytics events. Doesn't require a global context. + 2. bundle - An advanced option expecting a global context. 4. In order to get access to the configuration passed in from the page, the analytics adapter needs to specify an enableAnalytics() function, but it should also call the base class function to set up the events. -5. Doing analytics may require user permissions under [GDPR](/dev-docs/modules/consentManagement.html), which means your adapter will need to be linked to your [IAB Global Vendor List](https://iabeurope.eu/vendor-list-tcf-v2-0/) ID. If no GVL ID is found, and Purpose 7 (Measurement) is enforced, your analytics adapter will be blocked unless it is specifically listed under vendorExceptions. Your GVL ID can be added to the `registerAnalyticsAdapter()` call. +5. Doing analytics may require user permissions under [GDPR](/dev-docs/modules/consentManagement.html), which means your adapter will need to be linked to your [IAB Global Vendor List](https://iabeurope.eu/vendor-list-tcf/) ID. If no GVL ID is found, and Purpose 7 (Measurement) is enforced, your analytics adapter will be blocked unless it is specifically listed under vendorExceptions. Your GVL ID can be added to the `registerAnalyticsAdapter()` call. #### Basic prototype analytics adapter @@ -90,11 +94,11 @@ The best way to get started is to look at some of the existing AnalyticsAdapter. Here's a skeleton outline: -{% highlight js %} -import {ajax} from 'src/ajax'; -import adapter from 'src/AnalyticsAdapter'; -import CONSTANTS from 'src/constants.json'; -import adaptermanager from 'src/adaptermanager'; +```javascript +import {ajax} from '../src/ajax.js'; +import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; +import CONSTANTS from '../src/constants.json'; +import adaptermanager from '../src/adaptermanager.js'; const analyticsType = 'endpoint'; const url = 'URL_TO_SERVER_ENDPOINT'; @@ -119,7 +123,7 @@ adaptermanager.registerAnalyticsAdapter({ }); export default exAnalytics; -{% endhighlight %} +``` #### Reading TCF2 enforcement actions @@ -127,7 +131,7 @@ Analytics adapters can learn what happened with regards to GDPR TCF2 enforcement The callback will receive an object with the following attributes: -``` +```javascript { storageBlocked: ['moduleA', 'moduleB'], biddersBlocked: ['moduleB'], @@ -135,14 +139,17 @@ The callback will receive an object with the following attributes: } ``` +Note that analytics adapters can read the TCF string directly from the auction object -- look for the gdprConsent object, which contains three attributes: +gdprApplies, consentString, and apiVersion + #### Listening for errors There are two error events analytics modules may wish to listen for: auctionDebug and adRenderFailed. The former is any error that would be normally logged to console and there can be a great many. The latter may happen for the following reasons: (PREVENT_WRITING_ON_MAIN_DOCUMENT, NO_AD, CANNOT_FIND_AD, EXCEPTION, MISSING_DOC_OR_ADID) #### Analytics adapter best practices -+ listen only to the events required -+ batch up calls to the backend for post-auction logging rather than calling immediately after each event. +* listen only to the events required +* batch up calls to the backend for post-auction logging rather than calling immediately after each event. ### Step 3: Add unit tests @@ -164,12 +171,12 @@ Add a documentation file for your new analytics adapter. 3. Update the metadata fields at the top of the file to suit your needs: -``` +```markdown layout: analytics title: Your Company Name description: Your Company Analytics Adapter modulecode: exampleAnalyticsAdapter -gdpr_supported: true/false (EU GDPR support) +tcfeu_supported: true/false (TCF EU protocol support) usp_supported: true/false (US Privacy support) coppa_supported: true/false (COPPA support) prebid_member: true/false @@ -181,13 +188,11 @@ What does it mean to "support" the privacy protocols? At a high level, it means specifically discussed privacy policy actions and rules with your lawyers and implemented the results of that discussion. Some specific examples: -- GDPR support means: the analytics endpoint respects GDPR consent, Special Feature 1, and deals with any other Purposes declared in the vendor's Global Vendor List -- COPPA support means: analytics companies should not be building targeting profiles for users on sites flagged as COPPA -- USP/CCPA support means: analytics adapters cannot share user information if that user has opted out of sale - +1. GDPR support means: the analytics endpoint respects GDPR consent, Special Feature 1, and deals with any other Purposes declared in the vendor's Global Vendor List +2. COPPA support means: analytics companies should not be building targeting profiles for users on sites flagged as COPPA +3. USP/CCPA support means: analytics adapters cannot share user information if that user has opted out of sale 4. Update the body of the file to describe the options publishers have when configuring your adapter. See other adapters (e.g. rubicon.md) for a template. - 5. Submit the pull request to the prebid.github.io repo. ### Step 6: Wait for Prebid volunteers to review @@ -196,6 +201,6 @@ We sometimes get pretty busy, so it can take a couple of weeks for the review pr ## Further Reading -- [Analytics for Prebid](/overview/analytics.html) (Overview and list of analytics providers) -- [Module Rules](/dev-docs/module-rules.html) -- [Instream Video Ads Tracking](/dev-docs/modules/instreamTracking.html) +* [Analytics for Prebid](/overview/analytics.html) (Overview and list of analytics providers) +* [Module Rules](/dev-docs/module-rules.html) +* [Instream Video Ads Tracking](/dev-docs/modules/instreamTracking.html) diff --git a/dev-docs/internal-api-reference.md b/dev-docs/internal-api-reference.md new file mode 100644 index 0000000000..34db0805bd --- /dev/null +++ b/dev-docs/internal-api-reference.md @@ -0,0 +1,21 @@ +--- +layout: page_v2 +title: Internal API Reference +description: Internal API Reference for Prebid.js Header Bidding +top_nav_section: dev_docs +nav_section: reference +pid: 10 +sidebarType: 1 +--- + +# Internal API Reference + +This page has documentation for API methods that are meant for internal use by Prebid.js. + +{% assign api_pages = site.pages | where: "layout", "internal_api_prebidjs" %} + +
        +{% for page in api_pages %} +
      1. {{page.title}}
      2. +{% endfor %} +
      diff --git a/dev-docs/internal-api-reference/registerBidAdapter.md b/dev-docs/internal-api-reference/registerBidAdapter.md new file mode 100644 index 0000000000..3e651240b5 --- /dev/null +++ b/dev-docs/internal-api-reference/registerBidAdapter.md @@ -0,0 +1,25 @@ +--- +layout: internal_api_prebidjs +title: pbjs.registerBidAdapter(bidderAdapter, bidderCode) +description: register a bid adapter +sidebarType: 1 +--- + +This function provides a way to register a bid adapter for use by Prebid.js. The intended use case is in registering a non-open-source adapter that a publisher may add into their Prebid.js package. After calling this function, Prebid.js will recognize the biddercode in adunits and everywhere a bidder code can be used. + +{: .table .table-bordered .table-striped } +| Param | Scope | Type | Description | +| --- | --- | --- | --- | +| bidderAdapter | Required | `function` | bid adapter instance that returns a `callBids` function | +| bidderCode | Required | `string` | code to correlate with the bid adapter | + +```javascript +let myAdapter = function myAdapter() { + return { + callBids: function(p) { + ... + } + }; + }; + pbjs.registerBidAdapter(myAdapter, 'my'); +``` diff --git a/dev-docs/module-rules.md b/dev-docs/module-rules.md index 10f6c85650..dbf654c6d5 100644 --- a/dev-docs/module-rules.md +++ b/dev-docs/module-rules.md @@ -6,6 +6,7 @@ sidebarType: 0 --- # Prebid.js and Prebid Server Module Rules + {:.no_toc} * TOC @@ -20,19 +21,19 @@ several kinds of modules built by the community to enhance header bidding: | Bid Adapter | Obtains Open Market or Private Market bids for the current ad request. | Prebid.js, Prebid Server | | Analytics Adapter | Listens to auction events and reports to an analytics system. | Prebid.js, Prebid Server | | User ID Sub-Module | Obtains an ID for this user and makes that ID available to other types of modules. | Prebid.js | -| Real Time Data Sub-Module | Obtains data for the current user's context that may be of interest to advertisers. | Prebid.js | +| Real Time Data Sub-Module | Obtains data for the current user's context that may be of interest to advertisers. | Prebid.js, Prebid Server | | Other | Modules that don't fall into one of the other categories. | Prebid.js | ## Prebid.org Core Values Specific technical rules are needed to govern the development and review of modules in order to assure that they conform to Prebid's Core Values. The main objective of Prebid.org is to make great header bidding technology available for web publishers and mobile app developers. We believe great technology is: -- **Efficient** - Products offered by Prebid.org should not burden a user device, the network, or a company server. -- **Secure** - Prebid.org software should not open doors to security risks, including electronic attack, denial of service, fraud, or data leakage. -- **Transparent** - Our products are built in the open with community review. Changes to Prebid software and modules must be open to inspection before and after release. -- **Fair** - The Prebid.org platform doesn’t favor any one entity over another. No entity can be favored over another in technical ordering or status as a default value. No entity can gain information about another entity without approval. -- **Collaborative** - Human interactions in Prebid.org forums and events must be courteous. -- **Privacy Sensitive** - Our products are built for publishers to support users’ privacy concerns and comply with industry standards. +* **Efficient** - Products offered by Prebid.org should not burden a user device, the network, or a company server. +* **Secure** - Prebid.org software should not open doors to security risks, including electronic attack, denial of service, fraud, or data leakage. +* **Transparent** - Our products are built in the open with community review. Changes to Prebid software and modules must be open to inspection before and after release. +* **Fair** - The Prebid.org platform doesn’t favor any one entity over another. No entity can be favored over another in technical ordering or status as a default value. No entity can gain information about another entity without approval. +* **Collaborative** - Human interactions in Prebid.org forums and events must be courteous. +* **Privacy Sensitive** - Our products are built for publishers to support users’ privacy concerns and comply with industry standards. ## Module Rules @@ -40,65 +41,78 @@ Bid adapters, user ID adapters, analytics adapters, and other modules will be re This set of module rules applies to both Prebid.js and Prebid Server. However, these rules don’t necessarily apply to tools or the Prebid Mobile SDK. Rules and guidelines for those products will be determined by their respective committees as required. -The use of the terms "must" and "should" in this document is deliberate. However, some of the rules are "aspirational," in that we know there are existing exceptions to the rule that will need to get sorted out over time. These are marked with an asterisk (*). The goal is: - -- Every new module adheres to all required rules. -- Even grandfathered modules must adhere to all required rules by Prebid.js 5.0. +The use of the terms "must" and "should" in this document is deliberate. However, some of the rules are "aspirational," in that we know there are existing exceptions to the rule that will need to get sorted out over time. These are marked with an asterisk (*). ### Global Module Rules -1. Modules must(*) not load outside code files unless those libraries are approved and open source. +#### Strictly Enforced Rules + +1. Each adapter and module must include maintainer information with a group email address for Prebid.org to contact for support or maintenance. The group email address must remain current and respond to enquiries in a timely manner. +1. Modules must not load outside code files unless those libraries are approved and open source. 1. External modules may be used at build-time at the discretion of the relevant Prebid committee. Build-time modules must be locked to a particular version so that any upgrades must be done via Prebid pull request. 1. Exceptions may be made in the following cases: - - When the publisher has control over whether the file is loaded and which version, the base module should be able to work without the auxiliary file. - - If run-time code is not needed for the auction, it should support a deferred load. E.g. User ID modules. - - The file loaded must be locked to a particular version so that any upgrades must be done via Prebid pull request. - - A prominent disclosure must be made about the loading of the file and why they need the file, and a size warning provided if it’s greater than 10KB. - 1. If a functionality is supported by Prebid core or an existing module, Prebid modules must prefer the Prebid version of that functionality rather than an externally coded version. - 1. The build-time or run-time loading of required or optional external files must be disclosed. (See the disclosure section below.) - 1. Modules must not import other Prebid modules at build time. -1. Modules must not(*) add any pixel, iframe, cookie or local storage directly onto the page. Rather, they must use wrapper-provided mechanisms for usersyncs, cookies, and local storage. + * When the publisher has control over whether the file is loaded and which version, the base module should be able to work without the auxiliary file. + * If run-time code is not needed for the auction, it should support a deferred load. E.g. User ID modules. + * The file loaded is locked to a particular version so that any upgrades must be done via Prebid pull request. + * A prominent disclosure is made about the loading of the file and why they need the file, and a size warning provided if it’s greater than 10KB. + 1. If a functionality is supported by Prebid core or an existing module, modules must prefer the Prebid version of that functionality rather than an externally coded version. + 1. The build-time or run-time loading of required or optional external files must be disclosed. (See the [disclosure](#disclosure) section below.) 1. Modules must use the communication functions provided by the Prebid core (both Prebid.js and Prebid Server) for external communication. -1. Prebid.js modules must not use the $$PREBID_GLOBAL$$ variable nor otherwise obtain a pointer to the global PBJS object. This preserves data integrity. +1. Modules must not add any pixel, iframe, cookie or local storage directly onto the page. Rather, they must use wrapper-provided mechanisms for usersyncs, cookies, and local storage. 1. All modules must support the creation of multiple concurrent instances. This means, for example, they cannot rely on mutable global variables. - - Writing to the global window object must be non-intrusive, disclosed, and done in a way that supports multiple instances. -1. All modules and any external code references must disclose their support of privacy regulations such as GDPR, CCPA, COPPA, etc. (See the disclosure section below.) + * PBJS: Writing to the global window object must be non-intrusive, disclosed, and done in a way that supports multiple instances. +1. Modules must not include polyfills and must not override standard or Prebid JavaScript functions +1. Endpoint domain names cannot be fully variable. At some point, they won't be able contain any variables at all. e.g. $PARAM1.example.com. +1. To be listed on the Prebid.org website, a module must be in a Prebid open source repository. +1. Prebid.js requests and responses must be secure HTTPS. +1. Prebid.js modules must not use the PREBID_GLOBAL variable nor otherwise obtain a pointer to the global PBJS object. This preserves data integrity. + +#### Rules that May Someday Be Enforced + 1. Responses to auction or data requests should be compressed as long as the client supports that functionality (e.g. gzip, compress, deflate). -1. Prebid.js requests and responses must be secure HTTPS. Prebid Server requests should be HTTPS. 1. Endpoints should use HTTP/2 with keepalives so that connections don’t need to be re-created. -1. In order to be listed on the Prebid.org website, a module must be in a Prebid open source repository. -1. Each module must include maintainer information with a group email address for Prebid.org to contact for support or maintenance. -1. Modules must not include polyfills or override standard or Prebid JavaScript functions. -1. External modules must not use getEidPermissions function of userId module (e.g. prebidServerBidAdapter is an internal prebid module). +1. External modules must not use getEidPermissions function of userId module (e.g. prebidServerBidAdapter is an internal prebid module). +1. All modules and any external code references must disclose their support of privacy regulations such as GDPR, CCPA, COPPA, etc. (See the [disclosure](#disclosure) section below.) ### Bidder Adapter Rules -1. All global rules apply. -1. Bid adapters must(*) be able to bid. If they cannot return an auction bid, they should consider integration as a Real-Time Data or other module type. -1. Creative rendering scripts must(*) load from the creative frame and not directly in the page. In other words, creative rendering JavaScript cannot be used to bypass the “no external code” rule. -1. Bidder modules must not(*) make requests to endpoints for functionality other than auctions without: +All global rules apply. + +#### Stricly Enforced Rules + +1. Bid adapters must be able to bid. If they cannot return an auction bid, they should consider integration as a Real-Time Data or other module type. +1. Bidder modules must not make requests to endpoints for functionality other than auctions. There's no exceptions to this rule for Prebid Server, though Prebid.js may allow exceptions with: 1. Disclosure 1. Ability for the publisher to control the additional functionality. 1. Ensuring auctions are still operable if the publisher turns off the additional functionality; i.e., bid adapters may log certain analytics events, but if a publisher turns it off, the auction should still happen. 1. Building a Real-Time Data sub-module that obtains data in a way that can be utilized by other bidders as well if a bidder would like to incorporate an external data fetch that would influence the auction. -1. Bidder modules must not obtain bid information from or about any other party in the auction. E.g., they cannot listen to ad server events and forward information naming other bidders back to their endpoint - that is the job of an analytics module. -1. Bidder modules must not(*) cache bids from previous auctions. That functionality is reserved for Prebid core. -1. Bidders must(*) accept parameters in the conventional location in preference to bidder-specific parameters. The list of these parameters is in the [bidder adapter documentation](/dev-docs/bidder-adaptor.html#std-param-location). +1. Bidder modules must not obtain bid information from or about any other party in the auction. E.g., they cannot listen to ad server events and forward information naming other bidders back to their endpoint - that is the job of an analytics module. They cannot import the events system; they can only use event methods provided such as onBidWon(). +1. Bidder modules must not cache bids from previous auctions. That functionality is reserved for Prebid core. +1. Bidders must accept parameters in the conventional location in preference to bidder-specific parameters. The list of these parameters is in the bidder adapter documentation for [PBJS](/dev-docs/bidder-adaptor.html#std-param-location) and [PBS](/prebid-server/developers/add-new-bidder-go.html#bidder-parameters). 1. Bidders must not override the standard ad server targeting values: hb_adid, hb_bidder, hb_pb, hb_deal, or hb_size, hb_source, hb_format. +1. If a bidder has adapters for both Prebid.js and Prebid Server, all parameters (including biddercodes and aliases) must be consistent between client- and server-side adapters. This allows publishers to utilize the PBJS [s2sTesting module](/dev-docs/modules/s2sTesting.html). +1. Bid adapters must not create their own transaction IDs or overwrite the tids supplied by Prebid. + +#### Rules that May Someday Be Enforced + +1. Creative rendering scripts must load from the creative frame and not directly in the page. In other words, creative rendering JavaScript cannot be used to bypass the “no external code” rule. 1. If bid adapters are reporting multiple media types in the hb_format as ‘banner’, they must(*) indicate the actual mediatype in the metadata object. One use case for this is that it allows publishers to manage which creatives support safeframes. 1. Bidder modules should supply buyer metadata - including advertiser, advertiser domain, network, actual mediatype, and others defined in the Prebid documentation. 1. Creatives returned must be fully HTTPS. +1. Bid adapters should understand how their endpoints handle currency and floors, and make the necessary changes in the endpoint request. ### Analytics Adapter Rules -1. All global rules apply. +All global rules apply. + 1. Analytics adapters must not bid or supply any parameters to the auction. 1. Analytics adapters must be neutral to the bid adapters -- not favoring any particular bidder in any way. 1. Analytics adapters should minimize the number of times they call their endpoints by batching auction and event data. ### User ID Sub-Module Rules -1. All global rules apply. +All global rules apply. + 1. ID sub-modules must not gather any information from the page except for publisher-approved ID data for this user. 1. ID sub-modules must not report analytics information back to their endpoints, including use of other user IDs, auction information, bidders, bids won, etc. This is the job of an analytics module. 1. ID sub-modules must be neutral to the bid adapters -- each bidder must have the same opportunity to utilize each user ID. @@ -106,7 +120,7 @@ The use of the terms "must" and "should" in this document is deliberate. Howeve ### Real Time Data Module Rules 1. All global rules apply with one exception: - - A Real-Time Data module may load external code if it requires publisher registration and there's a prominent disclosure on the module documentation. The idea is that a publisher will not include the module if they don't approve of the external code, and since they've registered for the service, they must approve. The text of the disclosure may differ if the vendor allows Prebid to do regular reviews of a strictly versioned proprietary library. + * A Real-Time Data module may load external code if it requires publisher registration and there's a prominent disclosure on the module documentation. The idea is that a publisher will not include the module if they don't approve of the external code, and since they've registered for the service, they must approve. The text of the disclosure may differ if the vendor allows Prebid to do regular reviews of a strictly versioned proprietary library. 1. Real Time Data (RTD) modules must not bid. That functionality is reserved for bid adapters. 1. RTD modules must not supply privacy-sensitive user information (including IDs) into the auction. That functionality is reserved for User ID modules. 1. RTD modules should make data available in a cross-bidder way when possible. For example, passing data through existing mechanisms like First Party Data. @@ -120,10 +134,10 @@ Any other type of module will be evaluated on a case-by-case basis. Examples of There are already exceptions to these rules, and we recognize there will likely be more. Any module doing something that needs to be disclosed will receive a label on their prebid.org documentation like: -- Disclosure: this bidder adapter loads external JavaScript to render creatives. -- Disclosure: this bidder records win and loss events with a pixel call. -- Disclosure: this bidder listens directly to Google Ad Manager events. -- Disclosure: this bidder reports timeout events. +* Disclosure: this bidder adapter loads external JavaScript to render creatives. +* Disclosure: this bidder records win and loss events with a pixel call. +* Disclosure: this bidder listens directly to Google Ad Manager events. +* Disclosure: this bidder reports timeout events. Ideally, the disclosures should be of a limited number of standard types so they can be managed. @@ -133,8 +147,8 @@ To manage this, we plan to: 1. Create a process for generating new types of disclosures and which modules received a given disclosure/exception on which date. 1. Make sure that disclosures are applied to all existing and new adapter aliases. +# Related Reading -# Further Reading - -- Adding a bid adapter: [Prebid.js](/dev-docs/bidder-adaptor.html), [Prebid Server](/prebid-server/developers/add-new-bidder-go.html) -- Adding an analytics adapter: [Prebid.js](/dev-docs/integrate-with-the-prebid-analytics-api.html), [Prebid Server](/prebid-server/developers/pbs-build-an-analytics-adapter.html) +* Adding a bid adapter: [Prebid.js](/dev-docs/bidder-adaptor.html), [Prebid Server](/prebid-server/developers/add-new-bidder-go.html) +* Adding an analytics adapter: [Prebid.js](/dev-docs/integrate-with-the-prebid-analytics-api.html), [Prebid Server](/prebid-server/developers/pbs-build-an-analytics-adapter.html) +* Adding a module: [Prebid.js](/dev-docs/add-rtd-submodule.html), [Prebid Server](/prebid-server/developers/add-a-module.html) diff --git a/dev-docs/modules/1plusXRtdProvider.md b/dev-docs/modules/1plusXRtdProvider.md new file mode 100644 index 0000000000..70c2f215c5 --- /dev/null +++ b/dev-docs/modules/1plusXRtdProvider.md @@ -0,0 +1,67 @@ +--- +layout: page_v2 +title: 1plusX RTD Module +display_name: 1plusX RTD Module +description: 1plusX Real Time Data Module +page_type: module +module_type: rtd +module_code : 1plusXRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# 1plusX RTD Module + +{:.no_toc} + +* TOC +{:toc} + +## Description + +The 1plusX RTD module appends User and Contextual segments to the bidding object. + +## Integration + +1. Compile the 1plusX RTD Module along with your bid adapter and other modules into your Prebid build: + + ```bash + gulp build --modules="rtdModule,1plusXRtdProvider,appnexusBidAdapter,..." + ``` + +2. Use `setConfig` to instruct Prebid.js to initilize the 1plusX RTD module, as specified below. + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` + +```javascript +var TIMEOUT = 1000; +pbjs.setConfig({ + realTimeData: { + auctionDelay: TIMEOUT, + dataProviders: [{ + name: '1plusX', + waitForIt: true, + params: { + customerId: 'acme', + bidders: ['appnexus', 'rubicon'], + timeout: TIMEOUT + } + }] + } +}); +``` + +## Parameters + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Default | +| :---------------- | :------------ | :--------------------------------------------------------------- |:----------------- | +| name | String | Real time data module name | Always '1plusX' | +| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | +| params | Object | | | +| params.customerId | String | Your 1plusX customer id | | +| params.bidders | Array | List of bidders for which you would like data to be set | | +| params.timeout | Integer | timeout (ms) | 1000ms | diff --git a/dev-docs/modules/a1MediaRtdProvider.md b/dev-docs/modules/a1MediaRtdProvider.md new file mode 100644 index 0000000000..d7bcfb070f --- /dev/null +++ b/dev-docs/modules/a1MediaRtdProvider.md @@ -0,0 +1,67 @@ +--- +layout: page_v2 +title: A1Media RTD Module +display_name: A1Media RTD Module +description: A1Media Real Time Data Module +page_type: module +module_type: rtd +module_code : a1MediaRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# A1Media RTD Module + +{% include dev-docs/loads-external-javascript.md %} + +The A1Media RTD module loads a script for obtaining A1Media user segments, providing the user segment data to bid-requests. + +To use this module, you’ll need to work with [A1MediaGroup](https://a1mediagroup.jp/) to get an account and receive instructions on how to set up your pages and ad server. + +Contact for information. + +## Integration + +1) Build the A1Media RTD Module into the Prebid.js package with: + + ```bash + gulp build --modules=a1MediaRtdProvider,... + ``` + +2) Use `setConfig` to instruct Prebid.js to initilaize the A1Media RTD module, as specified below. + +## Configuration + +```javascript +pbjs.setConfig({ + realTimeData: { + auctionDelay: 1000, + dataProviders: [ + { + name: "a1Media", + waitForIt: true, + params: { + // 'tagId' is unique value for each account. + tagId: 'lb4test' + } + } + ] + } +}); +``` + +## Parameters + +{: .table .table-bordered .table-striped } +| Name |Type | Description |Required | Notes | +| :--------------- | :------------ | :------------------------------------------------------------------ |:---------|:------------ | +| `name` | String | Real time data module name | yes | Always 'a1Media' | +| `waitForIt` | Boolean | Should be `true` if there's an `auctionDelay` defined (recommended) | no | Default `false` | +| `params` | Object | | | | +| `params.tagId` | String | Publisher specific script name | yes | + +{: .alert.alert-warning :} +tagId is publisher specific tag ID. + +This module loads external code using the passed parameter (params.tagId). diff --git a/dev-docs/modules/aaxBlockmeterRtdProvider.md b/dev-docs/modules/aaxBlockmeterRtdProvider.md new file mode 100644 index 0000000000..0b3b3bdd29 --- /dev/null +++ b/dev-docs/modules/aaxBlockmeterRtdProvider.md @@ -0,0 +1,90 @@ +--- +layout: page_v2 +title: AAX Blockmeter Realtime Data Module +display_name: AAX Blockmeter +description: Measure the adblock traffic. +page_type: module +module_type: rtd +module_code : aaxBlockmeterRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# AAX Blockmeter Realtime Data Module + +{:.no_toc} + +* TOC +{:toc} + +## Overview + +The module enables publishers with an AAX relationship to measure traffic coming from visitors using adblockers. + +AAX can also help publishers monetize this traffic by allowing them to serve [acceptable ads](https://acceptableads.com/about/) to these adblock visitors and recover their lost revenue. [Reach out to us](https://www.aax.media/try-blockmeter/) to know more. + +{% include dev-docs/loads-external-javascript.md %} + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` object. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `name` | required | Real time data module name | `'aaxBlockmeter'` | `string` | +| `params` | required | | | `Object` | +| `params.pub` | required | AAX to share pub ID, [Reach out to us](https://www.aax.media/try-blockmeter/) to know more! | `'AAX000000'` | `string` | +| `params.url` | optional | AAX Blockmeter Script Url. Defaults to `'c.aaxads.com/aax.js?ver=1.2'` | `'c.aaxads.com/aax.js?ver=1.2'` | `string` | + +### Basic Example + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: 'aaxBlockmeter', + params: { + pub: 'AAX000000', + url: 'c.aaxads.com/aax.js?ver=1.2', + } + }] + } +}); +``` + +## Targeting sent to GAM + +For each prebid adUnit we pass the following key value to GAM by default + +| Google Slot Id | Prebid Adunit Code | Targeting Key | Targeting Value | +|:----------:|:--------------:|:---------------:|:---------------:| +|slotA| code-1 | `atk` | `code-1` | + +## Integration + +To install the module, follow these instructions: + +### Step 1: Prepare the base Prebid file + +* **Option 1:** Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *AAX Blockmeter Realtime Module* module + +* **Option 2:** From the command line, run `gulp build --modules=aaxBlockmeterRtdProvider,rtdModule,...` + +### Step 2: Set configuration + +Enable AAX Blockmeter Real Time Module using `pbjs.setConfig` + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: 'aaxBlockmeter', + params: { + pub: 'AAX000000' + } + }] + } +}); +``` diff --git a/dev-docs/modules/adnuntiusRtdProvider.md b/dev-docs/modules/adnuntiusRtdProvider.md index db4b5b757e..db5ac3a414 100644 --- a/dev-docs/modules/adnuntiusRtdProvider.md +++ b/dev-docs/modules/adnuntiusRtdProvider.md @@ -17,9 +17,9 @@ sidebarType: 1 1. Compile the Adnuntius RTD Module and Adnuntius Bid Adapter into your Prebid build: -``` -gulp build --modules="adnuntiusRtdProvider,adnuntiusBidAdapter,..." -``` + ```bash + gulp build --modules="adnuntiusRtdProvider,adnuntiusBidAdapter,..." + ``` 2. Use `setConfig` to instruct Prebid.js to initilize the adnuntius module, as specified below. diff --git a/dev-docs/modules/adpod.md b/dev-docs/modules/adpod.md index 0519cd9db6..c57c14149c 100644 --- a/dev-docs/modules/adpod.md +++ b/dev-docs/modules/adpod.md @@ -18,11 +18,11 @@ sidebarType : 1 The adpod module enables developers to add support for a new adserver that handles `adpod` (long-form) videos, like Freewheel. Specifically, the module provides functions to validate, cache, and modify long-form video bids. -## How to use the module as a publisher: +## How to use the module as a publisher There is a flag available for publishers to influence how this module behaves. This field can be set by adding the following to the Prebid.js configuration: -``` +```javascript pbjs.setConfig({ "adpod": { "brandCategoryExclusion": true @@ -33,27 +33,29 @@ pbjs.setConfig({ When this setting is enabled, it requires the bidder to include a brand category id on the incoming adpod bids (otherwise the bid is rejected). The bid's brand category will be processed and transformed to the corresponding brand category used by the publisher's adserver (see the [Category Translation](/dev-docs/modules/categoryTranslation.html) module page for more details). The transformed brand category is then used in the bid caching process and as well as targeting keys that get sent to the adserver for the winning bid(s). Below is an example of the targeting key's value with the setting enabled (where `123` is the category id): -``` + +```javascript '10.00_123_10s' ``` When the setting is disabled (which is the default state), bidder's don't have to supply a brand category on the adpod bids. Subsequently, the category part of the bid caching is not included, neither is it included in the generated targeting keys. Below is an example of the targeting keys with the setting not enabled: -``` + +```javascript hb_pb_cat_dur = '10.00_10s' ``` - -## How to use the module as a developer: +## How to use the module as a developer In the user's equivalent `AdServerVideo` module, import the `initAdpodHooks` function and call it from within their module. Executing the init function will initialize several key functions from the module that are designed to handle `adpod` objects (ie. adUnits, bids, etc.) as the auction proceeds. These functions will only affect `adpod` objects, other `mediaTypes` will be handled by the base Prebid code. -``` +```javascript initAdpodHooks(); ``` ## Optional values for developers + In addition to the `initAdpodHooks` function, users can import values from the Adpod module that contain the adpod specific targeting keys (as strings). These values can be used to generate the correct output (ie. targeting keys) to send to the adserver. `TARGETING_KEY_PB_CAT_DUR` @@ -63,6 +65,7 @@ This variable equates to `hb_pb_cat_dur`. This variable equates to `hb_cache_id`. ## CPM Adjustments by Deal Tier for CSAI + To enable publishers to prioritize video deals with direct buys and over deals at the same price in the FreeWheel stack two new ad pod configs have been added, `prioritzeDeals` and `dealTier`. To obtain this higher priority the method uses the deal priority tier value that is passed by the bidder. This helps inflate the bid CPM that is passed into FreeWheel and gives it a higher priority. {: .table .table-bordered .table-striped } @@ -73,9 +76,9 @@ To enable publishers to prioritize video deals with direct buys and over deals a | dealTier.BIDDER.prefix | Optional | String | The prefix required by the bidder to indicate this is a deal. | | dealTier.BIDDER.minDealTier | Optional | Integer | When an `adpod` is passed with the `prioritizeDeals` flag set to true, a higher preference is given to bids with a deal tier greater than the `minDealTier` setting. As an example, if the `dealTier.BIDDER.minDealTier` is set to 5 than all bids with a `dealTier` greater than or equal to five will be given a higher preference. Bid with a `dealTier` less than five will be considered the same as non-deal bids. | -### Examples: +### Examples -{% highlight js %} +```javascript // This will replace the cpm with dealId in cache key as well as targeting kv pair when prioritizeDeals flag is set to true. pbjs.setConfig({ adpod: { @@ -92,10 +95,11 @@ pbjs.setConfig({ } } }) -{% endhighlight %} +``` + If the bidder returns multiple bid, each bid can have a different priority/deal tier set. To give publishers control over the deal tier a `filterBids` option has been added to `pbjs.adServers.freewheel.getTargeting` to select certain deal bids. -{% highlight js %} +```javascript pbjs.adServers.freewheel.getTargeting({ codes: [adUnitCode1], @@ -103,11 +107,11 @@ pbjs.adServers.freewheel.getTargeting({ //pass targeting to player api } }); -{% endhighlight %} +``` #### Return -{% highlight js %} +```javascript // Sample return targeting key value pairs { 'adUnitCode-1': [ @@ -125,10 +129,10 @@ pbjs.adServers.freewheel.getTargeting({ } ] } -{% endhighlight %} +``` ## Further Reading -[Prebid.js](/dev-docs/getting-started.html) +[Prebid.js](/dev-docs/getting-started.html) [Prebid Video](/prebid-video/video-overview.html) [Freewheel Module](/dev-docs/modules/freewheel.html) diff --git a/dev-docs/modules/airgridRtdProvider.md b/dev-docs/modules/airgridRtdProvider.md index 71153537ca..d44922c3cd 100644 --- a/dev-docs/modules/airgridRtdProvider.md +++ b/dev-docs/modules/airgridRtdProvider.md @@ -16,20 +16,21 @@ sidebarType : 1 AirGrid is a privacy-first, cookie-less audience platform. Designed to help publishers increase inventory yield, whilst providing audience signal to buyers in the bid request, without exposing raw user level data to any party. -This real-time data module provides quality first-party data, contextual data, site-level data and more that is +This real-time data module provides quality first-party data, contextual data, site-level data and more that is injected into bid request objects destined for different bidders in order to optimize targeting. {:.no_toc} + * TOC {:toc} ## Usage -Compile the Halo RTD module into your Prebid build: +Compile the AirGrid RTD module (`airgridRtdProvider`) into your Prebid build, along with the parent RTD Module (`rtdModule`): `gulp build --modules=rtdModule,airgridRtdProvider,appnexusBidAdapter` -Add the AirGrid RTD provider to your Prebid config. In this example we will configure publisher 1234 to retrieve segments from Audigent. See the "Parameter Descriptions" below for more detailed information of the configuration parameters. +Next we configure the module, via `pbjs.setConfig`. See the **Parameter Descriptions** below for more detailed information of the configuration parameters. ```js pbjs.setConfig( @@ -68,7 +69,7 @@ pbjs.setConfig( _Note: Although the module supports passing segment data to any bidder using the ORTB2 spec, there is no way for this to be currently monetised. Please reach out to support, to discuss using bidders other than Xandr/AppNexus._ -If you do not have your own `apiKey`, `accountId` & `publisherId` please reach out to [support@airgrid.io](mailto:support@airgrid.io) +If you do not have your own `apiKey`, `accountId` & `publisherId` please reach out to [support@airgrid.io](mailto:support@airgrid.io) or you can sign up via the [AirGrid platform](https://app.airgrid.io). ## Testing @@ -80,7 +81,7 @@ gulp serve-fast --modules=rtdModule,airgridRtdProvider,appnexusBidAdapter Then in your browser access: -``` +```text http://localhost:9999/integrationExamples/gpt/airgridRtdProvider_example.html ``` @@ -93,10 +94,11 @@ gulp test --file "test/spec/modules/airgridRtdProvider_spec.js" ## Support If you require further assistance or are interested in discussing the module functionality please reach out to: -- [hello@airgrid.io](mailto:hello@airgrid.io) for general questions. -- [support@airgrid.io](mailto:support@airgrid.io) for technical questions. -You are also able to find more examples and other integration routes on the [AirGrid docs site](docs.airgrid.io). +* [hello@airgrid.io](mailto:hello@airgrid.io) for general questions. +* [support@airgrid.io](mailto:support@airgrid.io) for technical questions. + +You are also able to find more examples and other integration routes on the [AirGrid docs site](https://docs.airgrid.io), or learn more on our [site](https://airgrid.io)! Happy Coding! 😊 -The AirGrid Team. \ No newline at end of file +The AirGrid Team. diff --git a/dev-docs/modules/akamaiDapRtdProvider.md b/dev-docs/modules/akamaiDapRtdProvider.md index 879393a86a..b4efb216d6 100644 --- a/dev-docs/modules/akamaiDapRtdProvider.md +++ b/dev-docs/modules/akamaiDapRtdProvider.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # Akamai DAP Real Time Data Provider Module + {:.no_toc} * TOC @@ -19,22 +20,22 @@ sidebarType : 1 The Akamai Data Activation Platform (DAP) is a privacy-first system that protects end-user privacy by only allowing them to be targeted as part of a larger cohort. Akamai DAP Real time data Provider automatically invokes the DAP APIs and submit audience segments and the Secure Ad ID(SAID) to the bid-stream. SAID is a JWT/JWE which carries with it the cohorts and only a side-car or trusted server in the demand-side platform is allowed to see its contents. - ## Publisher Usage -1) Build the akamaiDapRTD module into the Prebid.js package with: +1. Build the akamaiDapRTD module into the Prebid.js package with: -``` -gulp build --modules=akamaiDapRtdProvider,... -``` + ```bash + gulp build --modules=akamaiDapRtdProvider,... + ``` -2) Use `setConfig` to instruct Prebid.js to initilaize the akamaiDapRtdProvider module, as specified below. +2. Use `setConfig` to instruct Prebid.js to initilaize the akamaiDapRtdProvider module, as specified below. ### Configuration -``` +```javascript pbjs.setConfig({ realTimeData: { + auctionDelay: 2000, dataProviders: [ { name: "dap", @@ -43,9 +44,10 @@ pbjs.setConfig({ apiHostname: '', apiVersion: "x1", domain: 'your-domain.com', - identityType: 'email' | 'mobile' | ... | 'dap-signature:1.0.0', - segtax: , - tokenTtl: 5, + identityType: 'email' | 'mobile' | ... | 'dap-signature:1.3.0', + segtax: 504, + dapEntropyUrl: 'https://dap-dist.akamaized.net/dapentropy.js', + dapEntropyTimeout: 1500 } } ] @@ -53,8 +55,7 @@ pbjs.setConfig({ }); ``` -Please reach out to your Akamai account representative(Prebid@akamai.com) to get provisioned on the DAP platform. - +Please reach out to your Akamai account representative() to get provisioned on the DAP platform. **Config Syntax details:** @@ -63,17 +64,21 @@ Please reach out to your Akamai account representative(Prebid@akamai.com) to get | :------------ | :------------ | :------------ |:------------ | | name | String | Akamai Dap Rtd module name | 'dap' always| | waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | -| apiHostname | String | host name | Please reach out to your Akamai account representative(Prebid@akamai.com) for this value| -| apiVersion | String | this holds the API version| It will be "x1" always | -| domain | String | the domain name | | -| identityType | String | Something like this email' | 'mobile' | ... | 'dap-signature:1.0.0' | | -| segtax | Integer | the taxonomy for Akamai | Getting this value is in progress, once done this will become optional | -| tokenTtl | Integer | time to live | | +| apiHostname | String | Hostname provided by Akamai | Please reach out to your Akamai account representative() for this value| +| apiVersion | String | This holds the API version | It should be "x1" always | +| domain | String | The domain name of your webpage | | +| identityType | String | Something like this 'email', 'mobile', ... 'dap-signature:1.3.0' | | +| segtax | Integer | The taxonomy for Akamai | The value should be 504 | +| dapEntropyUrl | String | URL to dap entropy script | Optional if the script is directly included on the webpage. Contact your Akamai account rep for more details | +| dapEntropyTimeout | Integer | Maximum time allotted for the entropy calculation to happen | | ### Testing + To view an example of available segments returned by dap: + +```bash +gulp serve --modules=rtdModule,akamaiDapRtdProvider,appnexusBidAdapter,sovrnBidAdapter ``` -‘gulp serve --modules=rtdModule,akamaiDapRtdProvider,appnexusBidAdapter,sovrnBidAdapter’ -``` + and then point your browser at: -"http://localhost:9999/integrationExamples/gpt/akamaidap_segments_example.html" +"" diff --git a/dev-docs/modules/allowActivities.md b/dev-docs/modules/allowActivities.md new file mode 100644 index 0000000000..6085218db6 --- /dev/null +++ b/dev-docs/modules/allowActivities.md @@ -0,0 +1,16 @@ +--- +layout: page_v2 +page_type: module +title: Module - allowActivities +description: Provides fine-grained controls over privacy-sensitive activities. +module_code : allowActivities +display_name : Activity controls +enable_download : true +recommended: false +vendor_specific: false +sidebarType : 1 +--- + +# allowActivities module + +This module provides the `allowActivities` configuration system for [activity controls](/dev-docs/activity-controls.html); refer to that page for more information. diff --git a/dev-docs/modules/anonymisedRtdProvider.md b/dev-docs/modules/anonymisedRtdProvider.md new file mode 100644 index 0000000000..d266b01d6f --- /dev/null +++ b/dev-docs/modules/anonymisedRtdProvider.md @@ -0,0 +1,61 @@ +--- +layout: page_v2 +title: Anonymised Real Time Data Provider Module +display_name: Anonymised Real Time Data Provider Module +description: Anonymised Real Time Data Provider Module +page_type: module +module_type: rtd +module_code : anonymisedRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Anonymised Real Time Data Provider Module + +Anonymised is a data anonymization technology for privacy-preserving advertising. Publishers and advertisers are able to target and retarget custom audience segments covering 100% of consented audiences. +Anonymised’s Real-time Data Provider automatically obtains segment IDs from the Anonymised on-domain script (via `localStorage`) and passes them to the bid-stream. + +## Publisher Usage + +- Build the anonymisedRtd module into the Prebid.js package with: + +```bash +gulp build --modules=anonymisedRtdProvider,... +``` + +- Use `setConfig` to instruct Prebid.js to initilaize the anonymisedRtdProvider module, as specified below. + +### Configuration + +```javascript + pbjs.setConfig({ + realTimeData: { + dataProviders: [ + { + name: "anonymised", + waitForIt: true, + params: { + cohortStorageKey: "cohort_ids", + bidders: ["smartadserver", "appnexus"], + segtax: 1000 + } + } + ] + } + }); +``` + +Please note that anonymisedRtdProvider should be integrated into the publisher website along with the [Anonymised Marketing Tag](https://support.anonymised.io/integrate/marketing-tag). +Please reach out to Anonymised [representative](mailto:support@anonymised.io) if you have any questions or need further help to integrate Prebid, anonymisedRtdProvider, and Anonymised Marketing Tag + +**Config Syntax details:** + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Anonymised Rtd module name | 'anonymised' always| +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| params.cohortStorageKey | String | the `localStorage` key, under which Anonymised Marketing Tag stores the segment IDs | 'cohort_ids' always | +| params.bidders | Array | Bidders with which to share segment information | Required | +| params.segtax | Integer | The taxonomy for Anonymised | '1000' always | diff --git a/dev-docs/modules/arcspanRtdProvider.md b/dev-docs/modules/arcspanRtdProvider.md new file mode 100644 index 0000000000..ce1aecb4f9 --- /dev/null +++ b/dev-docs/modules/arcspanRtdProvider.md @@ -0,0 +1,61 @@ +--- +layout: page_v2 +title: ArcSpan RTD Module +display_name: ArcSpan RTD Module +description: ArcSpan is a real-time audience monetization platform focused on the needs of the world’s finest publishers and retailers. Unlock the true value of your first-party audience data while providing advertisers the targeting performance they need. +page_type: module +module_type: rtd +module_code : arcspanRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# ArcSpan RTD Module + +{:.no_toc} + +* TOC +{:toc} + +## Prebid Config for ArcSpan RTD Module + +ArcSpan is a real-time audience monetization platform focused on the needs of the world’s finest publishers and retailers. Unlock the true value of your first-party audience data while providing advertisers the targeting performance they need. + +{% include dev-docs/loads-external-javascript.md %} + +### Usage + +Compile the ArcSpan RTD Module into your Prebid build: + +```bash +gulp build --modules=rtdModule,arcspanRtdProvider +``` + +{: .alert.alert-warning :} +Note that the global RTD module, `rtdModule`, is a prerequisite of the ArcSpan RTD Module. + +You then need to enable the ArcSpan RTD Module in your Prebid configuration, using the format below. + +{: .alert.alert-warning :} +Please replace the `silo` parameter value with the one provided by your ArcSpan representative. This will load the latest version of ArcSpan's JavaScript tag that is specific to your ArcSpan seat. + +```javascript +pbjs.setConfig({ + ..., + realTimeData: { + auctionDelay: 50, // optional auction delay + dataProviders: [{ + name: 'arcspan', + waitForIt: true, // should be true if there's an `auctionDelay` + params: { + silo: 1 + } + }] + }, + ... +}) +``` + +{: .alert.alert-info :} +For best results, we recommend that you also deploy ArcSpan's JavaScript tag in your tag management solution, as instructed in the implementation overview you received from your ArcSpan representative. This will ensure that more of your auctions contain ArcSpan's contextual signals. Please reach out to your ArcSpan representative if you have any questions. diff --git a/dev-docs/modules/azerionedgeRtdProvider.md b/dev-docs/modules/azerionedgeRtdProvider.md new file mode 100644 index 0000000000..58778d0666 --- /dev/null +++ b/dev-docs/modules/azerionedgeRtdProvider.md @@ -0,0 +1,90 @@ +--- +layout: page_v2 +title: Azerion Edge RTD Provider +display_name: Azerion Edge RTD Provider +description: Client-side contextual cookieless audiences. +page_type: module +module_type: rtd +module_code : azerionedgeRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Azerion Edge RTD Provider + +{% include dev-docs/loads-external-javascript.md %} + +Client-side contextual cookieless audiences. + +Azerion Edge RTD module helps publishers to capture users' interest audiences on their site, +and attach these into the bid request. + +Please contact [edge@azerion.com](edge@azerion.com) for more information. + +Maintainer: [azerion.com](https://www.azerion.com/) + +## Integration + +* Compile the Azerion Edge RTD module (`azerionedgeRtdProvider`) into your Prebid build, +along with the parent RTD Module (`rtdModule`): + +```bash +gulp build --modules=rtdModule,azerionedgeRtdProvider +``` + +* Set configuration via `pbjs.setConfig`. + +```js +pbjs.setConfig( + ... + realTimeData: { + auctionDelay: 1000, + dataProviders: [ + { + name: 'azerionedge', + waitForIt: true, + params: { + key: '', + bidders: ['improvedigital'], + process: {} + } + } + ] + } + ... +} +``` + +### Parameters + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Notes | +| :--- | :------- | :------------------ | :--------------- | +| name | `String` | RTD sub module name | Always "azerionedge" | +| waitForIt | `Boolean` | Required to ensure that the auction is delayed for the module to respond. | Optional. Defaults to false but recommended to true. | +| params.key | `String` | Publisher partner specific key | Mandatory. The key is required for the module to work. If you haven't received one, please reach [support@improvedigital.com](support@improvedigital.com) | +| params.bidders | `Array` | Bidders with which to share segment information | Optional. Defaults to "improvedigital". | +| params.process | `Object` | Configuration for the Azerion Edge script. | Optional. Defaults to `{}`. | + +## Context + +As all data collection is on behalf of the publisher and based on the consent the publisher has +received from the user, this module does not require a TCF vendor configuration. Consent is +provided to the module when the user gives the relevant permissions on the publisher website. + +As Prebid.js utilizes TCF vendor consent for the RTD module to load, the module needs to be labeled +within the Vendor Exceptions. If the Prebid GDPR enforcement is enabled, the module should be configured +as exception, as shown below: + +```js +[ + { + purpose: 'storage', + enforcePurpose: true, + enforceVendor: true, + vendorExceptions: ["azerionedge"] + }, + ... +] +``` diff --git a/dev-docs/modules/bidViewable.md b/dev-docs/modules/bidViewable.md index a9da963a12..5e4f390e6c 100644 --- a/dev-docs/modules/bidViewable.md +++ b/dev-docs/modules/bidViewable.md @@ -11,9 +11,10 @@ sidebarType : 1 --- # Bid Viewability - GAM + {:.no_toc} -* TOC +- TOC {:toc} ## Overview @@ -21,6 +22,7 @@ sidebarType : 1 This optional module will trigger a BID_VIEWABLE event which can be consumed by Analytics adapters. In addition, the winning bidder can implement an `onBidViewable` method to capture this event. Notes: + - The module does not work with adservers other than GAM and only with GPT integration. See the [other Bid Viewable Event](/dev-docs/modules/bidViewableIO.html) module for an ad server independent version. - The GPT API is used to find when a bid is viewable. See [GPT documentation](https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent) for more details. - This event is fired when an impression becomes viewable, according to [Active View criteria](https://support.google.com/admanager/answer/4524488). @@ -33,9 +35,10 @@ Instead of listening for events, bidders may supply a `bid.vurls` array and this This feature doesn't work with [Instream Video](/dev-docs/examples/instream-banner-mix.html), as GPT's impressionViewable event is not triggered for instream-video-creative The default logic used to find a matching Prebid.js bid for a GPT slot is -``` + +```javascript (bid, slot) => (slot.getAdUnitPath() === bid.adUnitCode || - slot.getSlotElementId() === bid.adUnitCode) + slot.getSlotElementId() === bid.adUnitCode) ``` ## Configuration @@ -49,7 +52,8 @@ The default logic used to find a matching Prebid.js bid for a GPT slot is | `bidViewability.customMatchFunction` | Optional | function(bid, slot) | this function will be used to find the matching winning bid for the GPT slot. See above for the default. | ## Example of setting module config -{% highlight js %} + +```javascript pbjs.setConfig({ bidViewability: { enabled: true, @@ -60,14 +64,15 @@ The default logic used to find a matching Prebid.js bid for a GPT slot is } } }); -{% endhighlight %} +``` ## Example of consuming BID_VIEWABLE event -{% highlight js %} - pbjs.onEvent('bidViewable', function(bid){ - console.log('got bid details in bidViewable event', bid); - }); -{% endhighlight %} + +```javascript + pbjs.onEvent('bidViewable', function(bid){ + console.log('got bid details in bidViewable event', bid); + }); +``` ## Related Reading diff --git a/dev-docs/modules/bidViewableIO.md b/dev-docs/modules/bidViewableIO.md index b483bc5b80..73998041bf 100644 --- a/dev-docs/modules/bidViewableIO.md +++ b/dev-docs/modules/bidViewableIO.md @@ -10,9 +10,10 @@ sidebarType : 1 --- # Bid Viewability - Ad Server Independent + {:.no_toc} -* TOC +- TOC {:toc} ## Overview @@ -20,9 +21,10 @@ sidebarType : 1 This optional module will trigger a BID_VIEWABLE event which can be consumed by Analytics adapters. In addition, the winning bidder can implement an `onBidViewable` method to capture this event. Notes: + - The module works with any adserver, or with no ad server at all. - Publishers using GAM/GPT might consider using the [Bid Viewable Event - GAM](/dev-docs/modules/bidViewable.html) module -- Requires the site to polyfill the [IntersectionObserver API](https://github.com/w3c/IntersectionObserver/tree/main/polyfill) (v1) to find when a bid is viewable. This implementation assumes that the publisher and the bidder are acting in good faith, and does not attempt to detect any bad behavior from either party. We assume that the ad is rendered into the element it has been told to render into, and is not hidden or obfuscated at any time. +- Requires the site to polyfill the [IntersectionObserver API](https://github.com/w3c/IntersectionObserver) (v1) to find when a bid is viewable. This implementation assumes that the publisher and the bidder are acting in good faith, and does not attempt to detect any bad behavior from either party. We assume that the ad is rendered into the element it has been told to render into, and is not hidden or obfuscated at any time. - This event is fired when an impression becomes viewable, according to IAB's viewability guidelines - When a rendered PBJS bid is determined to be viewable this module will trigger a BID_VIEWABLE event, which can be consumed by the winning bidder and analytics adapters - The module works with Banner creatives, with additional support to come. @@ -33,9 +35,15 @@ Notes: This feature is not intended to be a perfect measure of viewability. It is however intended to be a reasonable approximation of a bids viewability for creative types that are supported. 1. Only supports Banner creatives -2. Only works on browsers that support or on sites that have [polyfilled the IntersectionObserver API](https://github.com/w3c/IntersectionObserver/tree/main/polyfill) +2. Only works on browsers that support or on sites that have [polyfilled the IntersectionObserver API](https://github.com/GoogleChromeLabs/intersection-observer) 3. Results can only be trusted if both the publisher and winning bidder are assumed to be acting in good faith. +Note that there are other viewability modules in Prebid.js: + +- [Generic Viewability](/dev-docs/modules/viewability.html) +- [Bid Viewability - GAM](/dev-docs/modules/bidViewable.html) +- [Browsi Viewability](/dev-docs/modules/browsiRtdProvider.html) + ## Configuration {: .table .table-bordered .table-striped } @@ -45,22 +53,23 @@ This feature is not intended to be a perfect measure of viewability. It is howev | `bidViewabilityIO.enabled` | Required | Boolean | when set to true, the module will emit BID_VIEWABLE when applicable. Default: `false` | ## Example of setting module config -{% highlight js %} - pbjs.setConfig({ + +```javascript + pbjs.setConfig({ bidViewabilityIO: { enabled: true, } }); -{% endhighlight %} +``` ## Example of consuming BID_VIEWABLE event -{% highlight js %} - pbjs.onEvent('bidViewable', function(bid){ - console.log('got bid details in bidViewable event', bid); - }); -{% endhighlight %} + +```javascript + pbjs.onEvent('bidViewable', function(bid){ + console.log('got bid details in bidViewable event', bid); + }); +``` ## Related Reading -- [Building a PBJS analytics adapter](/dev-docs/integrate-with-the-prebid-analytics-api.html) -- [Building a PBJS bidder adapter](/dev-docs/bidder-adaptor.html) +- Alternate module: [Generic Viewability](/dev-docs/modules/viewability.html) diff --git a/dev-docs/modules/blueconicRtdProvider.md b/dev-docs/modules/blueconicRtdProvider.md new file mode 100644 index 0000000000..83772d4842 --- /dev/null +++ b/dev-docs/modules/blueconicRtdProvider.md @@ -0,0 +1,85 @@ +--- +layout: page_v2 +title: BlueConic Real Time Data Provider +display_name: BlueConic Real-time Module +description: BlueConic Real-time Data Module +page_type: module +module_type: rtd +module_code : blueconicRtdProvider +enable_download : true +coppa_supported: true +vendor_specific: true +sidebarType : 1 +--- + +# BlueConic Real-time Data Submodule + +{:.no_toc} + +* TOC +{:toc} + +BlueConic's Real-time Data Provider automatically obtains segmentation data and other user level data from the BlueConic script (via `localStorage`) and passes them to the bid-stream. Please reach out to BlueConic team() or visit our [website](https://support.blueconic.com/hc/en-us) if you have any questions or need further help to integrate Prebid or blueconicRtdProvider. + +## Publisher Usage + +Compile the BlueConic RTD module into your Prebid build: + +`gulp build --modules=rtdModule,blueconicRtdProvider,appnexusBidAdapter` + +Add the BlueConic RTD provider to your Prebid config. In this example we will configure +publisher 1234 to retrieve segments, profile data from BlueConic. See the +"Parameter Descriptions" below for more detailed information of the +configuration parameters. Please work with your BlueConic Prebid support team +() on which version of Prebid.js supports different bidder +and segment configurations. + +```javascript +pbjs.setConfig( + // ... + realTimeData: { + auctionDelay: 1000, + dataProviders: [ + { + name: "blueconic", + waitForIt: true, + params: { + requestParams: { + publisherId: 1234 + } + } + } + ] + } + //... +} +``` + +## BlueConic Configuration Parameters + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Real time data module name | Always 'blueconic' | +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| params | Object | | | +| params.requestParams | Object | Publisher partner specific configuration options, such as optional publisher id and other segment query related metadata | Optional | + +Please see the examples available in the blueconicRtdProvider_spec.js +tests. + +## Testing + +To run test suite for blueconic: + +`gulp test --modules=rtdModule,blueconicRtdProvider,appnexusBidAdapter` + +## Example + +To view an example of available segments & profile data: + +`gulp serve --modules=rtdModule,blueconicRtdProvider,appnexusBidAdapter` + +and then point your browser at: + +`http://localhost:9999/integrationExamples/gpt/blueconicRtdProvider_example.html` diff --git a/dev-docs/modules/brandmetricsRtdProvider.md b/dev-docs/modules/brandmetricsRtdProvider.md index ef2595d6e6..ec904b3d20 100644 --- a/dev-docs/modules/brandmetricsRtdProvider.md +++ b/dev-docs/modules/brandmetricsRtdProvider.md @@ -12,24 +12,24 @@ sidebarType : 1 --- # brandmetrics Real Time Data Provider Module + {:.no_toc} * TOC {:toc} -This module is intended to be used by brandmetrics (https://brandmetrics.com) partners and sets targeting keywords to bids if the browser is eligeble to see a brandmetrics survey. +This module is intended to be used by brandmetrics () partners and sets targeting keywords to bids if the browser is eligeble to see a brandmetrics survey. The module hooks in to brandmetrics events and requires a brandmetrics script to be running. The module can optionally load and initialize brandmetrics by providing the 'scriptId'- parameter. - ## Publisher Usage -1) Build the brandmetricsRtd module into the Prebid.js package with: +1. Build the brandmetricsRtd module into the Prebid.js package with: -``` -gulp build --modules=brandmetricsRtdProvider,... -``` + ```bash + gulp build --modules=brandmetricsRtdProvider,... + ``` -2) Use `setConfig` to instruct Prebid.js to initilaize the brandmetricsRtdProvider module, as specified below. +2. Use `setConfig` to instruct Prebid.js to initilaize the brandmetricsRtdProvider module, as specified below. ### Configuration @@ -53,7 +53,6 @@ pbjs.setConfig({ The scriptId- parameter is provided by brandmetrics or a brandmetrics partner. - ## Supported bidders The module currently supports the following bidders: @@ -63,7 +62,6 @@ The module currently supports the following bidders: | :----- | :---- | | Ozone | ozone | - ## Parameters {: .table .table-bordered .table-striped } diff --git a/dev-docs/modules/browsiRtdProvider.md b/dev-docs/modules/browsiRtdProvider.md index 062f47f45f..e0b7866a43 100644 --- a/dev-docs/modules/browsiRtdProvider.md +++ b/dev-docs/modules/browsiRtdProvider.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # Browsi Viewability Module + {:.no_toc} * TOC @@ -25,33 +26,33 @@ an account and receive instructions on how to set up your pages and ad server. Implementation works like this: - 1) Build the Browsi module into the Prebid.js package with: +1. Build the Browsi module into the Prebid.js package with: -``` -gulp build --modules=browsiRtdProvider&... -``` + ```bash + gulp build --modules=browsiRtdProvider&... + ``` -2) Use `setConfig` to instruct the browser to obtain the viewability data in parallel with the header bidding auction +2. Use `setConfig` to instruct the browser to obtain the viewability data in parallel with the header bidding auction ## Configuration This module is configured as part of the `realTimeData.dataProviders` object: +```javascript +pbjs.setConfig({ + "realTimeData": { + dataProviders:[{ + "name": "browsi", + "params": { + "url": "testUrl.com", // get params values + "siteKey": "testKey", // from Browsi + "pubKey": "testPub", // + "keyName":"bv" // + } + }] + } +}); ``` - pbjs.setConfig({ - "realTimeData": { - dataProviders:[{ - "name": "browsi", - "params": { - "url": "testUrl.com", // get params values - "siteKey": "testKey", // from Browsi - "pubKey": "testPub", // - "keyName":"bv" // - } - }] - } - }); -``` Syntax details: @@ -65,16 +66,14 @@ Syntax details: | params.url |String |Server URL| | | params.keyName |String |Key value name| Optional. Defaults to 'bv'. | - - - ## Output For each ad slot, the module returns expected viewability prediction in a JSON format. When the data is received, it calls `pbjs.setTargetingForGPT` to set the defined `keyName` for each adunit. Example: -``` + +```json { "slotA":{ "p":0.56, // ad server targeting variable (e.g. bv) for slotA is 0.56 @@ -84,4 +83,3 @@ Example: } } ``` - diff --git a/dev-docs/modules/captifyRtdProvider.md b/dev-docs/modules/captifyRtdProvider.md new file mode 100644 index 0000000000..e7c0e634e1 --- /dev/null +++ b/dev-docs/modules/captifyRtdProvider.md @@ -0,0 +1,76 @@ +--- +layout: page_v2 +title: Captify RTD Module +display_name: Captify RTD Module +description: Captify Real Time Data Module +page_type: module +module_type: rtd +module_code : captifyRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Captify RTD Module + +{:.no_toc} + +* TOC +{:toc} + +## Description + +Captify uses publisher first-party on-site search data to power machine learning algorithms to create a suite of +contextual based targeting solutions that activate in a cookieless environment. + +The RTD submodule allows bid requests to be classified by our live-classification service, +maximising value for publishers by increasing scale for advertisers. + +Segments will be attached to bid request objects sent to different SSPs in order to optimize targeting. + +Contact for more information. + +## Integration + +1. Compile the Captify RTD Module along with your bid adapter and other modules into your Prebid build: + + ```bash + gulp build --modules="rtdModule,captifyRtdProvider,appnexusBidAdapter,..." + ``` + +2. Use `setConfig` to instruct Prebid.js to initialize the Captify RTD module, as specified below. + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` + +```javascript +var TIMEOUT = 100; // in milliseconds +pbjs.setConfig({ + realTimeData: { + auctionDelay: TIMEOUT, + dataProviders: [ + { + name: "CaptifyRTDModule", + waitForIt: true, + params: { + pubId: 123456, + bidders: ['appnexus'], + } + } + ] + } +}); +``` + +## Parameters + +{: .table .table-bordered .table-striped } +| Name |Type | Description |Mandatory | Notes | +| :--------------- | :------------ | :------------------------------------------------------------------ |:---------|:------------ | +| `name` | String | Real time data module name | yes | Always 'CaptifyRTDModule' | +| `waitForIt` | Boolean | Should be `true` if there's an `auctionDelay` defined (recommended) | no | Default `false` | +| `params` | Object | | | | +| `params.pubId` | Integer | Partner ID, required to get results and provided by Captify | yes | Use `123456` for tests, speak to your Captify account manager to receive your pubId | +| `params.bidders` | Array | List of bidders for which you would like data to be set | yes | Currently only 'appnexus' supported | +| `params.url` | String | Captify live-classification service url | no | Defaults to `https://live-classification.cpx.to/prebid-segments` diff --git a/dev-docs/modules/categoryTranslation.md b/dev-docs/modules/categoryTranslation.md index cb1bd0f987..cce5640b06 100644 --- a/dev-docs/modules/categoryTranslation.md +++ b/dev-docs/modules/categoryTranslation.md @@ -21,17 +21,17 @@ The module provides the following: - Converts IAB subcategories to Ad server group identifier. -## How to use the module: +## How to use the module 1. A Prebid.js package is built that contains this module and the Ad server module. Prebid supports [FreeWheel](/dev-docs/modules/freewheel.html) and Google Ad Manager ad servers. -2. The inclusion of this module and long-form ad server module causes Prebid to download a mapping file to local storage. The user also has the option to provide their own mapping file. The default ad server is Freewheel. To hook to the DFP video ad server module you must configure it in the mapping url. +2. The inclusion of this module and long-form ad server module causes Prebid to download a mapping file to local storage. The user also has the option to provide their own mapping file. The default ad server is Freewheel. To hook to the DFP video ad server module you must configure it in the mapping url. 3. At runtime, brand category translation happens as needed. - ## Using A Custom Map File -The IAB Category Translation module uses a default mapping file to convert adserver categories or labels to IAB sub categories. If a publisher prefers to use their own mapping file they will need to set the URL location of that file. They can do so by adding the following to their Prebid.js configuration: -``` +The IAB Category Translation module uses a default mapping file to convert adserver categories or labels to IAB sub categories. If a publisher prefers to use their own mapping file they will need to set the URL location of that file. They can do so by adding the following to their Prebid.js configuration: + +```javascript pbjs.setConfig({ "brandCategoryTranslation": { "translationFile": "" @@ -57,10 +57,9 @@ Publishers should ensure that the JSON returned from their custom file is valid Refer to Prebid Github repository for a [custom file reference](https://github.com/prebid/category-mapping-file). - ## Further Reading -[Prebid.js](/dev-docs/getting-started.html) +[Prebid.js](/dev-docs/getting-started.html) [Prebid Video](/prebid-video/video-overview.html) [FreeWheel Module](/dev-docs/modules/freewheel.html) [Adapter Integration](/dev-docs/bidder-adaptor.html) diff --git a/dev-docs/modules/cleanioRtdProvider.md b/dev-docs/modules/cleanioRtdProvider.md index 5f7cf7923b..455b8487b6 100644 --- a/dev-docs/modules/cleanioRtdProvider.md +++ b/dev-docs/modules/cleanioRtdProvider.md @@ -24,11 +24,10 @@ Using this module requires prior agreement with [clean.io](https://clean.io) to clean.io Realtime module can be built just like any other prebid module: -``` +```bash gulp build --modules=cleanioRtdProvider,... ``` - ## Configuration When built into prebid.js, this module can be configured through the following `pbjs.setConfig` call: @@ -47,7 +46,6 @@ pbjs.setConfig({ }); ``` - ### Configuration parameters {: .table .table-bordered .table-striped } @@ -56,12 +54,11 @@ pbjs.setConfig({ | ``cdnUrl`` | ``string`` | Required | CDN URL of the script, which is to be used for protection. | | ``protectionMode`` | ``'full' or 'bids' or 'bids-nowait'`` | Required | Integration mode. Please refer to the "Integration modes" section for details. | - ## Integration modes {: .table .table-bordered .table-striped } | Integration Mode | Parameter Value | Description | | :------------ | :------------ | :------------ | -| Full page protection | ``'full'`` | Preferred mode. The module will add the protector agent script directly to the page, and it will protect all placements. This mode will make the most out of various behavioral detection mechanisms, and will also prevent typical malicious behaviors. Please note that in this mode, depending on Prebid library naming, Chrome may mistakenly tag non-ad-related content as ads: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/ad_tagging.md. | +| Full page protection | ``'full'`` | Preferred mode. The module will add the protector agent script directly to the page, and it will protect all placements. This mode will make the most out of various behavioral detection mechanisms, and will also prevent typical malicious behaviors. Please note that in this mode, depending on Prebid library naming, Chrome may mistakenly tag non-ad-related content as ads: . | | Bids-only protection | ``'bids'`` | The module will protect specific bid responses, more specifically, the HTML representing ad payload, by wrapping it into the agent script. Please note that in this mode, ads delivered directly, outside of Prebid integration, will not be protected, since the module can only access the ads coming through Prebid. | | Bids-only protection with no delay on bid rendering | ``'bids-nowait'`` | Same as above, but in this mode, the script will also *not* wrap those bid responses, which arrived prior to successful preloading of agent script. | diff --git a/dev-docs/modules/confiantRtdProvider.md b/dev-docs/modules/confiantRtdProvider.md new file mode 100644 index 0000000000..e8c8af20b7 --- /dev/null +++ b/dev-docs/modules/confiantRtdProvider.md @@ -0,0 +1,55 @@ +--- +layout: page_v2 +title: Confiant Real-Time Data Provider +display_name: Confiant Real-Time Protection Module +description: Confiant Real-Time detection and blocking of bad ads to protect your users and brand reputation +page_type: module +module_type: rtd +module_code : confiantRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Confiant Real-Time Protection Module + +## Overview + +Confiant’s module provides comprehensive detection of security, quality, and privacy threats across your ad stack. +Confiant is the industry leader in real-time detecting and blocking of bad ads when it comes to protecting your users and brand reputation. + +To start using this module, please contact [Confiant](https://www.confiant.com/contact) to get an account and customer key. + +{: .alert.alert-warning :} +Disclosure: When configured, this module will insert a script, that is loaded from Confiant's CDN and has proprietary code. + +## Integration + +1. Build Prebid bundle with Confiant module included: + + ```bash + gulp build --modules=confiantRtdProvider,... + ``` + +2. Include the resulting bundle on your page. + +# Configuration + +Configuration of Confiant module is plain simple: + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: 'confiant', + params: { + // so please get in touch with us so we could help you to set up the module with proper parameters + propertyId: '', // required, string param, obtained from Confiant Inc. + prebidExcludeBidders: '', // optional, comma separated list of bidders to exclude from Confiant's prebid.js integration + prebidNameSpace: '', // optional, string param, namespace for prebid.js integration + shouldEmitBillableEvent: false, // optional, boolean param, upon being set to true enables firing of the BillableEvent upon Confiant's impression scanning + } + }] + } +}); +``` diff --git a/dev-docs/modules/consentManagement.md b/dev-docs/modules/consentManagement.md index f3ea32002f..518ce48a02 100644 --- a/dev-docs/modules/consentManagement.md +++ b/dev-docs/modules/consentManagement.md @@ -13,17 +13,10 @@ sidebarType : 1 # GDPR Consent Management Module {: .no_toc } -* TOC +- TOC {: toc } -{% capture legalNotice %} - This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and /or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. - {% endcapture %} - -{% include /alerts/alert_important.html content=legalNotice %} - -{: .alert.alert-warning :} -Prebid.org is working on updates that will enable support for reading and parsing TCF 2.0 consent strings. See the [blog post](https://prebid.org/blog/tcf2) for timelines. +{% include legal-warning.html %} ## Overview @@ -42,8 +35,8 @@ This base EU GDPR consent management module performs these actions: The optional [GDPR enforcement module](/dev-docs/modules/gdprEnforcement.html) adds on these actions: -3. Allows the page to define which activities should be enforced at the Prebid.js level. -4. Actively enforces those activities based on user consent data (in the TCF string, not the AC string). +1. Allows the page to define which activities should be enforced at the Prebid.js level. +2. Actively enforces those activities based on user consent data (in the TCF string, not the AC string). In the case of a new user, CMPs will generally respond only after there is consent information available (i.e., the user has made their consent choices). Making these selections can take some time for the average user, so the module provides timeout settings. @@ -57,7 +50,7 @@ If the timeout period expires or an error from the CMP is thrown, one of these a Please start by understanding the IAB's [TCF Implementation Guide](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/TCF-Implementation-Guidelines.md). -To utilize this module, a Consent Management Platform (CMP) compatible with the [IAB TCF v1.1 spec](https://iabeurope.eu/all-news/the-iab-europe-transparency-consent-framework-tcf-steering-group-votes-to-extend-technical-support-for-tcf-v1-1/) or [IAB TCF v2.0 spec](https://iabeurope.eu/tcf-2-0/) needs to be implemented on the site to interact with the user and obtain their consent choices. It's important to understand the details of how the CMP works before integrating it with Prebid.js +To utilize this module, a Consent Management Platform (CMP) compatible with the IAB TCF v2.0 or [v2.2](https://iabeurope.eu/tcf-2-2-launches-all-you-need-to-know/) spec needs to be implemented on the site to interact with the user and obtain their consent choices. It's important to understand the details of how the CMP works before integrating it with Prebid.js In general, implementation details for CMPs are not covered by Prebid.org, but we do recommend to that you place the CMP code before the Prebid.js code in the head of the page in order to ensure the CMP's framework is loaded before the Prebid code executes. In addition, the community is collecting a set of [CMP best practices](/dev-docs/cmp-best-practices.html). @@ -75,26 +68,19 @@ but we recommend migrating to the new config structure as soon as possible. | gdpr | `Object` | | | | gdpr.cmpApi | `string` | The CMP interface that is in use. Supported values are **'iab'** or **'static'**. Static allows integrations where IAB-formatted consent strings are provided in a non-standard way. Default is `'iab'`. | `'iab'` | | gdpr.timeout | `integer` | Length of time (in milliseconds) to allow the CMP to obtain the GDPR consent string. Default is `10000`. | `10000` | +| gdpr.actionTimeout | `integer` | Length of time (in milliseconds) to allow the user to take action to consent if they have not already done so. The actionTimer first waits for the CMP to load, then the actionTimeout begins for the specified duration. Default is `undefined`. | `10000` | | gdpr.defaultGdprScope | `boolean` | Defines what the `gdprApplies` flag should be when the CMP doesn't respond in time or the static data doesn't supply. Defaults to `false`. | `true` | -| gdpr.allowAuctionWithoutConsent | `boolean` | (TCF v1.1 only) Determines what will happen if obtaining consent information from the CMP fails; either allow the auction to proceed (`true`) or cancel the auction (`false`). Default is `true` | `true` | | gdpr.consentData | `Object` | An object representing the GDPR consent data being passed directly; only used when cmpApi is 'static'. Default is `undefined`. | | -| gdpr.consentData.getTCData.tcString | `string` | (TCF v2.0 only) Base64url-encoded TCF v2.0 string with segments. | | -| gdpr.consentData.getTCData.addtlConsent | `string` | (TCF v2.0 only) Additional consent string if available from the cmp TCData object | | -| gdpr.consentData.getTCData.gdprApplies | `boolean` | (TCF v2.0 only) Defines whether or not this pageview is in GDPR scope. | | -| gdpr.consentData.getTCData.purpose.consents | `Object` | (TCF v2.0 only) An object representing the user's consent status for specific purpose IDs. | | -| gdpr.consentData.getTCData.purpose.legitimateInterests | `Object` | (TCF v2.0 only) An object representing the user's legitimate interest status for specific purpose IDs. | | -| gdpr.consentData.getTCData.vendor.consents | `Object` | (TCF v2.0 only) An object representing the user's consent status for specific vendor IDs. | | -| gdpr.consentData.getTCData.vendor.legitimateInterests | `Object` | (TCF v2.0 only) An object representing the user's legitimate interest status for specific vendors IDs. | | -| gdpr.consentData.getConsentData.gdprApplies | `boolean` | (TCF v1.1 only) Defines whether or not this pageview is in GDPR scope. | | -| gdpr.consentData.getConsentData.hasGlobalScope | `boolean` | (TCF v1.1 only) True if consent data is global, false if it's publisher specific. | | -| gdpr.consentData.getConsentData.consentData | `string` | (TCF v1.1 only) Encoded TCF v1.1 string. | | -| gdpr.consentData.getVendorConsents.metadata | `string` | (TCF v1.1 only) Encoded TCF v1.1 string. | | +| gdpr.consentData.getTCData.tcString | `string` | Base64url-encoded TCF v2.x string with segments. | | +| gdpr.consentData.getTCData.addtlConsent | `string` | Additional consent string if available from the cmp TCData object | | +| gdpr.consentData.getTCData.gdprApplies | `boolean` | Defines whether or not this pageview is in GDPR scope. | | +| gdpr.consentData.getTCData.purpose.consents | `Object` | An object representing the user's consent status for specific purpose IDs. | | +| gdpr.consentData.getTCData.purpose.legitimateInterests | `Object` | An object representing the user's legitimate interest status for specific purpose IDs. | | +| gdpr.consentData.getTCData.vendor.consents | `Object` | An object representing the user's consent status for specific vendor IDs. | | +| gdpr.consentData.getTCData.vendor.legitimateInterests | `Object` | An object representing the user's legitimate interest status for specific vendors IDs. | | {: .alert.alert-info :} -NOTE: The `allowAuctionWithoutConsent` parameter supported for TCF v1.1 refers to the entire consent string, not to any individual consent option. Prebid.js does not parse the GDPR consent string, so it doesn't know if the user has consented to any particular action. - -{: .alert.alert-info :} -NOTE: The `purpose` and `vendor` objects are required if you are using the `gdprEnforcement` module. If the data is not included, your bid adpaters, analytics adapters, and/or userId systems will likely be excluded from the auction as Prebid will assume the user has not given consent for these entities. +NOTE: The `purpose` and `vendor` objects are required if you are using the `gdprEnforcement` module. If the data is not included, your bid adapters, analytics adapters, and/or userId systems will likely be excluded from the auction as Prebid will assume the user has not given consent for these entities. A related parameter is `deviceAccess`, which is at the global level of Prebid.js configuration because it can be used GDPR, CCPA, or custom privacy implementations: @@ -103,12 +89,11 @@ A related parameter is `deviceAccess`, which is at the global level of Prebid.js | --- | --- | --- | --- | | deviceAccess | `boolean` | If false, Prebid.js will prevent adapters and modules from reading and setting cookies and HTML local storage. Defaults to `true`. | `false` | +### TCF v2.x Examples -### TCF v2.0 Examples - -Example 1: IAB CMP using custom timeout and setting GDPR in-scope by default +Example 1: IAB CMP using custom timeout and setting GDPR in-scope by default. -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { @@ -122,11 +107,30 @@ Example 1: IAB CMP using custom timeout and setting GDPR in-scope by default } }); }); -{% endhighlight %} +``` + +Example 2: IAB CMP using custom timeout in combination with actionTimeout and setting GDPR in-scope by default. The following will wait `500ms` for the CMP to load, if it does an additional `10000ms` will be waited for a user to provide consent (if none had yet been provided). + +```javascript + var pbjs = pbjs || {}; + pbjs.que = pbjs.que || []; + pbjs.que.push(function() { + pbjs.setConfig({ + consentManagement: { + gdpr: { + cmpApi: 'iab', + timeout: 500, + actionTimeout: 10000, + defaultGdprScope: true + } + } + }); + }); +``` -Example 2: Static CMP using custom data passing. +Example 3: Static CMP using custom data passing. -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { @@ -164,79 +168,30 @@ Example 2: Static CMP using custom data passing. } }); }); -{% endhighlight %} - -### TCF v1.1 Examples - -Example 1: IAB CMP using custom timeout and cancel-auction options. - -{% highlight js %} - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - pbjs.que.push(function() { - pbjs.setConfig({ - consentManagement: { - gdpr: { - cmpApi: 'iab', - timeout: 8000, - allowAuctionWithoutConsent: false - } - } - }); - }); -{% endhighlight %} - -Example 2: Static CMP using custom data passing. - -{% highlight js %} - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - pbjs.que.push(function() { - pbjs.setConfig({ - consentManagement: { - gdpr: { - cmpApi: 'static', - allowAuctionWithoutConsent: false, - consentData: { - getConsentData: { - 'gdprApplies': true, - 'hasGlobalScope': false, - 'consentData': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA' - }, - getVendorConsents: { - 'metadata': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA', - ... - } - } - } - } - }); - }); -{% endhighlight %} +``` ## Build the Package Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the consent management module, an additional option must be added to the **gulp build** command: -{% highlight bash %} +```bash gulp build --modules=consentManagement,bidAdapter1,bidAdapter2 -{% endhighlight %} +``` You can also use the [Prebid.js Download](/download.html) page. ## Adapter Integration {: .alert.alert-info :} -Prebid.js adapters don't need to change to support TCF v2.0 if they already support TCF 1.1 -- the consent string is passed through the same bidrequest location. The bidder's endpoint, however, will need to change to support TCF v2.0. Once the endpoint supports TCF2, you can update the documentation.md file as described below above the table showing the list of TCF2-compliant bidders. -If you are submitting changes to an adapter to support this approach, please also submit a PR to the [docs repo](https://github.com/prebid/prebid.github.io) to add the `gdpr_supported: true` variable to your respective page in the [bidders directory](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders). **This will ensure that your adapter's name will automatically appear on the list of adapters supporting GDPR.** +If you are submitting changes to an adapter to support the IAB's TCF v2.x, please also submit a PR to the [docs repo](https://github.com/prebid/prebid.github.io) to add the `tcfeu_supported: true` variable to your respective page in the [bidders directory](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders). **This will ensure that your adapter's name will automatically appear on the list of adapters supporting TCF-EU.** ### Bidder Adapter GDPR Integration To find the GDPR consent information to pass along to your system, adapters should look for the `bidderRequest.gdprConsent` field in their `buildRequests()` method. Here is a sample of how the data is structured in the `bidderRequest` object: -{% highlight js %} +```javascript { "bidderCode": "bidderA", "auctionId": "e3a336ad-2222-4a1c-bbbb-ecc7c5294a34", @@ -249,17 +204,17 @@ Here is a sample of how the data is structured in the `bidderRequest` object: }, ... } -{% endhighlight %} +``` **gdprConsent Data Fields** **_consentString_** -This field contains the user's choices on consent, represented as an encoded string value. In certain scenarios, this field might come to you with an `undefined` value; normally this happens when there was an error during the CMP interaction and the publisher had the config option `allowAuctionWithoutConsent` set to `true`. If you don't want to pass `undefined` to your system, you can check for this value and replace it with a valid consent string. See the *consent_required* code in the example below (under "gdprApplies") for a possible approach to checking and replacing values. +This field contains the user's choices on consent, represented as an encoded string value. In certain scenarios, this field might come to you with an `undefined` value; normally this happens when there was an error (or timeout) during the CMP interaction and the publisher turned off GDPR enforcement. If you don't want to pass `undefined` to your system, you can check for this value and replace it with a valid consent string. See the _consent_required_ code in the example below (under "gdprApplies") for a possible approach to checking and replacing values. **_addtlConsent_** -If the CMP responds with additional consent data as proposed at https://support.google.com/admanager/answer/9681920?hl=en then the corresponding string is stored here. +If the CMP responds with additional consent data as proposed at [support.google.com/admanager/answer/9681920?hl=en] then the corresponding string is stored here. **_vendorData_** @@ -276,7 +231,7 @@ One of two general approaches can be taken by the adapter to populate this field The following is an example of how the integration could look for the former option: -{% highlight js %} +```javascript ... buildRequests: function (bidRequests, bidderRequest) { ... @@ -290,7 +245,7 @@ buildRequests: function (bidRequests, bidderRequest) { ... } ... -{% endhighlight %} +``` The implementation of the latter option is up to the adapter, but the general premise is the same. You would check to see if the `bidderRequest.gdprConsent.gdprApplies` field is undefined and if so, set the derived value from your independent system. @@ -301,11 +256,11 @@ If neither option are taken, then there is the remote chance this field's value The `gdprConsent` object is also available when registering `userSync` pixels. The object can be accessed by including it as an argument in the `getUserSyncs` function: -{% highlight js %} +```javascript getUserSyncs: function(syncOptions, responses, gdprConsent, usPrivacy) { ... } -{% endhighlight %} +``` Depending on your needs, you could include the consent information in a query of your pixel and/or, given the consent choices, determine if you should drop the pixels at all. @@ -319,38 +274,36 @@ Here are some things that publishers can do to control various activities: 1. If the current page view is known to be in GDPR scope, make sure the adapters are aware of it even on the first page where CMP hasn't been activated by setting the defaultGdprScope: `consentManagement.gdpr.defaultGdprScope: true` 2. If the user hasn't consented to Purpose 1: - - Set [deviceAccess: false](/dev-docs/publisher-api-reference/setConfig.html#setConfig-deviceAccess) - - Don't enable [userSync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) - - Don't enable [userId](/dev-docs/modules/userId.html) modules + - Set [deviceAccess: false](/dev-docs/publisher-api-reference/setConfig.html#setConfig-deviceAccess) + - Don't enable [userSync](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-User-Syncing) + - Don't enable [userId](/dev-docs/modules/userId.html) modules 3. If you're working with bidders that don't support GDPR, consider dynamically populating adunits as needed. See the list below for bidders supporting GDPR. - ### Publishers Not Using an IAB-Compliant CMP Prebid.js and much of the ad industry rely on the IAB CMP standard for GDPR support, but there might be some publishers who have implemented a different approach to meeting the privacy rules. Those publishers can utilize Prebid.js and the whole header bidding ecosystem by building a translation layer between their consent method and the IAB method. -At a high level, this could be done as follows: -1. Build a `window.__cmp()` function, which will be seen by Prebid. +At a high level, this could be done as follows: + +1. Build a `window.__tcfapi()` function, which will be seen by Prebid. 2. If SafeFrames are in use, build a message receiver function. 3. Format consent data in a string according to the [IAB standard](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework). Below is sample code for implementing the stub functions. Sample code for formatting the consent string can be obtained [here](https://github.com/appnexus/cmp). -{% highlight js %} +```javascript var iabConsentData; // build the IAB consent string var gdprApplies; // true if gdpr applies to the user, else false -var hasGlobalScope; // true if consent data was retrieved globally var responseCode; // false if there was an error, else true -var cmpLoaded; // true if iabConsentData was loaded and processed (function(window, document) { function addFrame() { - if (window.frames['__cmpLocator']) + if (window.frames['____tcfapiLocator']) return; if ( document.body ) { var body = document.body, iframe = document.createElement('iframe'); - iframe.name = '__cmpLocator'; + iframe.name = '____tcfapiLocator'; iframe.style.display = 'none'; body.appendChild(iframe); } else { @@ -363,13 +316,15 @@ var cmpLoaded; // true if iabConsentData was loaded and processed var json = event.data; var msgIsString = typeof json === "string"; if ( msgIsString ) { - json = JSON.parse(json); + try { + json = JSON.parse(json); + } catch (error) { } } - var call = json.__cmpCall; + var call = json.__tcfapiCall; if (call) { - window.__cmp(call.command, call.parameter, function(retValue, success) { + window.__tcfapi(call.command, call.parameter, function(retValue, success) { var returnMsg = { - __cmpReturn: { + __tcfapiReturn: { returnValue: retValue, success: success, callId: call.callId } }; @@ -379,19 +334,15 @@ var cmpLoaded; // true if iabConsentData was loaded and processed } catch (e) {} // do nothing } var cmpFunc = function(command, version, callback) { - if (command === 'ping') { - callback({gdprAppliesGlobally: gdprApplies, cmpLoaded: cmpLoaded}, responseCode); - } else if (command === 'getConsentData') { - callback({consentData: iabConsentData, gdprApplies: gdprApplies, hasGlobalScope: hasGlobalScope}, responseCode); - } else if (command === 'getVendorConsents') { - callback({metadata: iabConsentData, gdprApplies: gdprApplies, hasGlobalScope: hasGlobalScope}, responseCode); + if (command === 'addEventListener') { + callback({eventStatus: 'tcloaded', tcString: iabConsentData, gdprApplies}, responseCode) } else { - callback(undefined, false); + callback(undefined, false); } }; - if ( typeof (__cmp) !== 'function' ) { - window.__cmp = cmpFunc; - window.__cmp.msgHandler = cmpMsgHandler; + if ( typeof (__tcfapi) !== 'function' ) { + window.__tcfapi = cmpFunc; + window.__tcfapi.msgHandler = cmpMsgHandler; if ( window.addEventListener ) { window.addEventListener('message', cmpMsgHandler, false); } else { @@ -399,54 +350,23 @@ var cmpLoaded; // true if iabConsentData was loaded and processed } } })(window, document); -{% endhighlight %} +``` #### Explanation of Parameters **_iabConsentData_** -For instructions on how to generate the IAB consent string see the [IAB CMP 1.1 Spec](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework) and [IAB Consent String SDK](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/tree/master/Consent%20String%20SDK). +For instructions on how to generate the IAB consent string see the [IAB CMP 2 Spec](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework) and [IAB Consent String SDK](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/tree/master/Consent%20String%20SDK). **_gdprApplies_** Use the following values in the _gdprApplies_ field: -- True: the current user is in the European Economic Area (EEA) *or* the publisher wants to have all traffic considered in-scope for GDPR. + +- True: the current user is in the European Economic Area (EEA) _or_ the publisher wants to have all traffic considered in-scope for GDPR. - False: It's known that the user is outside the EEA. - Leave the attribute unspecified if user's location is unknown. -**_hasGlobalScope_** -This should be set to true if consent data was retrieved from global "euconsent" cookie, or it was publisher-specific. For general purpose, set this to false. - **_responseCode_** This should be false if there was some error in the consent data; otherwise set to true. False is the same as calling the callback with no parameters. -**_cmpLoaded_** -This should be be set to true once the parameters listed above are processed. - -## Adapters Supporting GDPR - -Bidders on this list have self-declared their GDPR support in their https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders md file by adding "gdpr_supported: true". - - - - - -
      - -
      - ## Further Reading - [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html) diff --git a/dev-docs/modules/consentManagementGpp.md b/dev-docs/modules/consentManagementGpp.md new file mode 100644 index 0000000000..1e8ad5cb19 --- /dev/null +++ b/dev-docs/modules/consentManagementGpp.md @@ -0,0 +1,207 @@ +--- +layout: page_v2 +page_type: module +title: Consent Management - GPP +description: If you have users in regions of the world that adhere to the Global Privacy Platform, this module works with your Consent Management Platform to pass consent info to bidders and help align with regional regulations. +module_code : consentManagementGpp +display_name : Consent Management - GPP +enable_download : true +recommended: true +min_js_version: 7.30.0 +sidebarType : 1 +--- + +# GPP Consent Management Module +{: .no_toc } + +- TOC +{: toc } + +{% include legal-warning.html %} + +## Overview + +This consent management module is designed to support the Global Privacy Platform ([GPP](https://iabtechlab.com/gpp/)). GPP API 1.0 support is available; GPP 1.1 support is scheduled to be added in July 2023 in the approximate version Prebid.js 8.6. + +This module works with supported [Consent Management Platforms](https://www.cmswire.com/information-management/what-is-a-consent-management-platform/) (CMPs) to fetch an encoded string representing the user's consent choices (for their respective region) and make it available for adapters to consume and process. + +{: .alert.alert-warning :} +Prebid functionality created to address regulatory requirements does not replace each party's responsibility to determine its own legal obligations and comply with all applicable laws. +**We recommend consulting with your legal counsel before determining how to utilize these features in support of your overall privacy approach. This module is not yet intended to replace other consent modules; it supplements them.** + +Below is a summary of the actions performed by the GPP consent management module: + +1. Fetch the user's GPP consent data from the IAB-compliant CMP. +2. Incorporate this data into the auction objects for adapters to collect. +3. Proceed with the auction. + +In the case of a new user, CMPs will generally respond only after there is consent information available (i.e., the user has made their consent choices). +Making these selections can take some time for the average user, so the module provides timeout settings. + +If the timeout period expires or an error from the CMP is thrown, one of these actions occurs: + +- The auction is canceled outright. +- The auction proceeds without the user's consent information. + +## Page Integration + +To utilize this module, a Consent Management Platform (CMP) compatible with the [IAB GPP CMP spec](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md) needs to be implemented on the site to interact with the user and obtain their consent choices. It's important to understand the details of how the CMP works before integrating it with Prebid.js. + +In general, implementation details for CMPs are not covered by Prebid.org, but we do recommend that you place the CMP code before the Prebid.js code in the head of the page in order to ensure the CMP's framework is loaded before the Prebid code executes. In addition, the community is collecting a set of [CMP best practices](/dev-docs/cmp-best-practices.html). + +Once the CMP is implemented, simply include this module into your build and add a `consentManagement` object in the `setConfig()` call. Adapters that support this feature will then be able to retrieve the consent information and incorporate it in their requests. + +Here are the parameters supported in the `consentManagement` object specific for the GPP consent module: + +{: .table .table-bordered .table-striped } +| Param | Type | Description | Example | +| --- | --- | --- | --- | +| gpp | `Object` | | | +| gpp.cmpApi | `string` | The CMP interface that is in use. Supported values are **'iab'** or **'static'**. Static allows integrations where IAB-formatted consent strings are provided in a non-standard way. Default is `'iab'`. | `'iab'` | +| gpp.timeout | `integer` | Length of time (in milliseconds) to allow the CMP to obtain the GPP consent information. Default is `10000`. | `10000` | +| gpp.consentData | `Object` | An object representing the IAB GPP consent data being passed directly; only used when cmpApi is 'static'. Default is `undefined`. | | +| gpp.consentData.sectionId | `integer` | Indicates the header section of the GPP consent string, recommended to be `3`. | | +| gpp.consentData.gppVersion | `string` | The version number parsed from the header of the GPP consent string. | | +| gpp.consentData.sectionList | `Array of integers` | The sections contained within the encoded GPP string as parsed from the header. | | +| gpp.consentData.applicableSections | `Array of integers` | Section ID considered to be in force for this transaction. In most cases, this field should have a single section ID. In rare occasions where such a single section ID can not be determined, the field may contain up to 2 values. The value can be 0 or a Section ID specified by the Publisher / Advertiser, during stub / load. When no section is applicable, the value will be -1. | | +| gpp.consentData.gppString | `String` | The complete encoded GPP string. | | +| gpp.consentData.pingData | `Object` | An object representing the current status of the CMP at the time consent data was fetched. See PingReturn in [IAB's CMP API doc](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md#ping) for further information. | | + +{: .alert.alert-info :} +In addition to the static approach described above, there is another means to pass already known GPP consent data of a user via the Prebid.js [First Party Data](https://docs.prebid.org/features/firstPartyData.html) feature. The values for `gppString` and `applicableSections` can be passed via the `ortb2.regs.gpp` and `ortb2.regs.gpp_sid` fields respectively; other fields in the GPP data object listed above are not available via the `ortb2` structure. If the GPP consent module is present and successfully obtains the consent information from the CMP, it will override the GPP values set originally in the `ortb2` object (as we assume the CMP's values will be more up-to-date). Please visit the [First Party Data](https://docs.prebid.org/features/firstPartyData.html) page for more overall information and examples. + +Several default expression expressions of GPP strings as activity controls exist or are underway as the GPP adds sections and publishers request additional default expressions. For example, see [Prebid Activity Controls -- GPP control module - usnat](/dev-docs/modules/gppControl_usnat.html). If no default expression of a string into activity controls exists for a particular section, or the publisher is not satisfied with a particular module's defaults and available overrides, publishers can express the suppressions in the activity control syntax directly. + +### Examples + +Example 1: IAB CMP using a custom timeout + +```javascript + var pbjs = pbjs || {}; + pbjs.que = pbjs.que || []; + pbjs.que.push(function() { + pbjs.setConfig({ + consentManagement: { + gpp: { + cmpApi: 'iab', + timeout: 8000 + } + } + }); + }); +``` + +Example 2: Static CMP using custom data passing. + +```javascript + var pbjs = pbjs || {}; + pbjs.que = pbjs.que || []; + pbjs.que.push(function() { + pbjs.setConfig({ + consentManagement: { + gpp: { + cmpApi: 'static', + consentData: { + sectionId: 3, + gppVersion: 1, + sectionList: [5, 7] + applicableSections: [7] + gppString: 'DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN', + pingData: {...} + } + } + } + }); + }); +``` + +## Build the Package + +Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the consent management module, an additional option must be added to the **gulp build** command: + +```bash +gulp build --modules=consentManagementGpp,bidAdapter1,bidAdapter2 +``` + +You can also use the [Prebid.js Download](/download.html) page. + +## Adapter Integration + +{: .alert.alert-info :} + +If you are submitting changes to an adapter to support GPP, please also submit a PR to the [docs repo](https://github.com/prebid/prebid.github.io) to add the `gpp_supported: true` variable to your respective page in the [bidders directory](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders). **This will ensure that your adapter's name will automatically appear on the list of adapters supporting GPP.** + +### Bidder Adapter GPP Integration + +To find the GPP consent information to pass along to your system, adapters should look for the `bidderRequest.gppConsent` field in their `buildRequests()` method; this field includes a copy of the full GPPData object from the CMP, in case additional information (beyond the gppString and applicableSections values) is needed. Alternatively if only the consent string and/or the applicableSections values are needed, these two values can also be found in the `bidderRequest.ortb2.regs` field under the OpenRTB 2.6 field names (`gpp` and `gpp_sid`). +Here is a sample of how the data is structured in the `bidderRequest` object: + +```javascript +{ + "bidderCode": "bidderA", + "auctionId": "e3a336ad-2222-4a1c-bbbb-ecc7c5294a34", + ... + "timeout": 3000, + "gppConsent": { + "gppString": "BOJ/P2HOJ/P2HABABMAAAAAZ+A==", + "fullGppData": {...}, + "applicableSections": [7] + }, + "ortb2": { + "regs": { + "gpp": "BOJ/P2HOJ/P2HABABMAAAAAZ+A==", + "gpp_sid": [7] + } + }, + ... +} +``` + +### UserSync Integration + +The `gppConsent` object is also available when registering `userSync` pixels. +The object can be accessed by including it as an argument in the `getUserSyncs` function: + +```javascript +getUserSyncs: function(syncOptions, responses, gdprConsent, usPrivacy, gppConsent) { +... +} +``` + +Depending on your needs, you could include the consent information in a query of your pixel and/or, given the consent choices, determine if you should drop the pixels at all. + +## Adapters Supporting GPP + +Bidders on this list have self-declared their GPP support in their [github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders] md file by adding "gpp_supported: true". + + + + + +
      + +
      + +## Further Reading + +- [IAB Global Privacy Platform Full Specification Repository](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform) +- [IAB Global Privacy Platform CMP API Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md) +- [Prebid Consent Management - GDPR Module](/dev-docs/modules/consentManagement.html) +- [Prebid Consent Management - US Privacy Module](/dev-docs/modules/consentManagementUsp.html) +- [Prebid Activity Controls](/dev-docs/activity-controls.html) +- [Prebid Activity Controls -- GPP control module - usnat](/dev-docs/modules/gppControl_usnat.html) +- [CMP Best Practices](https://docs.prebid.org/dev-docs/cmp-best-practices.html) diff --git a/dev-docs/modules/consentManagementUsp.md b/dev-docs/modules/consentManagementUsp.md index ddfa9be3fc..90aed2ad66 100644 --- a/dev-docs/modules/consentManagementUsp.md +++ b/dev-docs/modules/consentManagementUsp.md @@ -16,18 +16,13 @@ sidebarType : 1 * TOC {: toc } -{% capture legalNotice %} - - This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and /or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. - {% endcapture %} - -{% include /alerts/alert_important.html content=legalNotice %} +{% include legal-warning.html %} ## Overview This consent management module is designed to support the California Consumer Privacy Act ([CCPA](https://www.iab.com/guidelines/ccpa-framework/)). The IAB has generalized these guidelines to cover future regulations, referring to the feature as "US Privacy." -This module works with an IAB-compatible US Privacy API (USP-API) to fetch an encoded string representing the user's notice and opt-out choices and make it available for adapters to consume and process. +This module works with an IAB-compatible US Privacy API (USP-API) to fetch an encoded string representing the user's notice and opt-out choices and make it available for adapters to consume and process. In Prebid 7+; the module defaults to working with an IAB-compatible US Privacy API; in prior versions, the module had to be configured to be in effect. {: .alert.alert-info :} See also the [Prebid Consent Management - GDPR Module](/dev-docs/modules/consentManagement.html) for supporting the EU General Data Protection Regulation (GDPR) @@ -38,20 +33,44 @@ Here's a summary of the interaction process: 2. Incorporate this data into the auction objects for adapters to collect. 3. Proceed with the auction. -In the the case of a new user, the USP-API will generally respond only after there is notice and opt-out status information available (i.e., the user has made their choices). -Making these selections can take some time for the average user, so the module provides timeout settings. +The IAB USP-API will respond immediately if it is available. The module timeout settings are not related to user selection, but only to API availability. + +If the timeout period expires or an error from the USP-API is thrown, the auction proceeds without a US Privacy string attached. + + The string has four characters: + +{: .table .table-bordered .table-striped } +| String Component | Values | +| --- | --- | +| 1) Specification Version| 1| +| 2) Explicit Notice/Opportunity to Opt Out| (N = No,Y = Yes,– = Not Applicable)| +| 3) Has user opted-out of the sale of his or her personal information?| (N = No,Y = Yes,– = Not Applicable)| +| 4) Publisher is a signatory to the IAB Limited Service Provider Agreement| (N = No,Y = Yes,– = Not Applicable)| + +### Deletes + +As of January 1st 2023, CCPA will require that requests to "delete my personal information" (right to delete) must be propagated to all 3rd parties user data is being shared with. US Privacy Consent Management Module will support this feature in 7.23.0 and above. +Prebid Modules that receive user data (bid adapters, analytics adapters), or set user data (UserId, RTD) may define a new method called `onDataDeletionRequest`. The US Privacy Consent Management Module will attach a `registerDeletion` event handler with the CMP, when triggered it will: -If the timeout period expires or an error from the USP-API is thrown, the auction proceeds without the user's notice and opt-out status information. +The USP module attaches a 'registerDeletion' event handler with the CMP; when triggered, it will: + +* invoke the methods above on all adapters +* delete all IDs from cookies/localStorage + +3rd parties can define the method like this: + +* UserID submodules can define a method onDataDeletionRequest(config, idValue) +* Bid adapters can define a method spec.onDataDeletionRequest(bidderRequests) +* Analytics adapters can define a method onDataDeletionRequest() ## Page Integration To utilize this module, software that provides the [USP-API](https://github.com/InteractiveAdvertisingBureau/USPrivacy/blob/master/CCPA/USP%20API.md) must to be implemented on the site to interact with the user and obtain their notice and opt-out status. +Though implementation details for the USP-API are not covered by Prebid.org, we do recommend to that you place the code before the Prebid.js code in the head of the page in order to ensure the framework is loaded before the Prebid code executes. Many publishers who ensure the prior availability of the `__uspapi` set the timeout parameter to zero. -Though implementation details for the USP-API are not covered by Prebid.org, we do recommend to that you place the code before the Prebid.js code in the head of the page in order to ensure the framework is loaded before the Prebid code executes. - -Once the USP-API is implemented, simply include this module into your build and add a `consentManagement` object in the `setConfig()` call. Adapters that support this feature will then be able to retrieve the notice and opt-out status information and incorporate it in their requests. +Once the USP-API is implemented, simply include this module into your build and add a `consentManagement` object in the `setConfig()` call. Without configuration, Prebid will throw a warning that the module is unconfigured, and will proceed with the default configuration parameter `cmpApi` as 'iab'. Adapters that support this feature will then be able to retrieve the notice and opt-out status information and incorporate it in their requests. Here are the parameters supported in the `consentManagement` object: @@ -60,7 +79,7 @@ Here are the parameters supported in the `consentManagement` object: | --- | --- | --- | --- | | usp | `Object` | | | | usp.cmpApi | `string` | The USP-API interface that is in use. Supported values are **'iab'** or **'static'**. Static allows integrations where IAB-formatted strings are provided in a non-standard way. Default is `'iab'`. | `'iab'` | -| usp.timeout | `integer` | Length of time (in milliseconds) to allow the USP-API to obtain the CCPA string. Default is `10000`. | `10000` | +| usp.timeout | `integer` | Length of time (in milliseconds) to allow the USP-API to obtain the CCPA string. Default is `50`. | `50` | | usp.consentData | `Object` | An object representing the CCPA notice and opt-out status data being passed directly; only used when cmpApi is 'static'. Default is `undefined`. | | {: .alert.alert-info :} @@ -71,7 +90,7 @@ to the GDPR implementation, though US-Privacy doesn't specifically use that term Example 1: Support both US Privacy and GDPR -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { @@ -88,11 +107,11 @@ Example 1: Support both US Privacy and GDPR } }); }); -{% endhighlight %} +``` -Example 2: Support US Privacy +Example 2: Support US Privacy; timeout the api availability at zero because it is always available if it applies -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { @@ -100,16 +119,16 @@ Example 2: Support US Privacy consentManagement: { usp: { cmpApi: 'iab', - timeout: 100 // US Privacy timeout 100ms + timeout: 0 // US Privacy timeout 100ms } } }); }); -{% endhighlight %} +``` -Example 3: Static CMP using custom data passing. +Example 3: Static CMP using custom data passing. Placing this config call in the command queue before loading Prebid is important to ensure the string is available before Prebid begins making external calls. -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { @@ -126,15 +145,36 @@ Example 3: Static CMP using custom data passing. } }); }); -{% endhighlight %} +``` + +Example 4: Static CMP with USP string set to does not apply for all fields, which may be useful to prevent excessive interaction with the `__uspapi` outside of the geographic scope. Placing this config call in the command queue before loading Prebid is important to ensure it is available early. + +```javascript + var pbjs = pbjs || {}; + pbjs.que = pbjs.que || []; + pbjs.que.push(function() { + pbjs.setConfig({ + consentManagement: { + usp: { + cmpApi: 'static', + consentData: { + getUSPData: { + uspString: '1---' + } + } + } + } + }); + }); +``` ## Build the Package Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the consent management module, an additional option must be added to the the **gulp build** command: -{% highlight bash %} +```bash gulp build --modules=consentManagementUsp,bidAdapter1,bidAdapter2 -{% endhighlight %} +``` ## Adapter Integration @@ -145,7 +185,7 @@ If you are submitting changes to an adapter to support this approach, please als To find the US Privacy/CCPA notice and opt-out status information to pass along to your system, adapters should look for the `bidderRequest.uspConsent` field in their `buildRequests()` method. Below is a sample of how the data is structured in the `bidderRequest` object: -{% highlight js %} +```javascript { "bidderCode": "bidderA", "auctionId": "e3a336ad-2222-4a1c-bbbb-ecc7c5554a34", @@ -153,18 +193,18 @@ Below is a sample of how the data is structured in the `bidderRequest` object: "uspConsent": "1YYY", ... } -{% endhighlight %} +``` ### UserSync Integration The `usPrivacy` object is also available when registering `userSync` pixels. The object can be accessed by including it as an argument in the `getUserSyncs` function: -{% highlight js %} +```javascript getUserSyncs: function(syncOptions, responses, gdprConsent, usPrivacy) { ... } -{% endhighlight %} +``` Depending on your needs, you could include the US-Privacy information in a query of your pixel and/or, given the notice and opt-out status choices, determine if you should drop the pixels at all. @@ -178,10 +218,10 @@ var idx_usp=0; {% assign bidder_pages = site.pages | where: "layout", "bidder" %} {% for item in bidder_pages %} {% if item.usp_supported == true %} - adaptersSupportingUsp[idx_usp]={}; - adaptersSupportingUsp[idx_usp].href="/dev-docs/bidders.html#{{item.biddercode}}"; - adaptersSupportingUsp[idx_usp].text="{{item.title}}"; - idx_usp++; + adaptersSupportingUsp[idx_usp]={}; + adaptersSupportingUsp[idx_usp].href="/dev-docs/bidders.html#{{item.biddercode}}"; + adaptersSupportingUsp[idx_usp].text="{{item.title}}"; + idx_usp++; {% endif %} {% endfor %} diff --git a/dev-docs/modules/contxtfulRtdProvider.md b/dev-docs/modules/contxtfulRtdProvider.md new file mode 100644 index 0000000000..07fc6418a0 --- /dev/null +++ b/dev-docs/modules/contxtfulRtdProvider.md @@ -0,0 +1,93 @@ +--- +layout: page_v2 +title: Contxtful RTD Provider +display_name: Contxtful RTD Provider +description: Activates Receptivity to evaluate ad success in real-time by focusing on attention and context. +page_type: module +module_type: rtd +module_code : contxtfulRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Contxtful Real Time Data Module + +## Overview + +The Contxtful RTD module enhances ad units by adding a Receptivity score to the meta-data. This score quantifies user attention in real time and can be used to guide bidding decisions. + +{% include dev-docs/loads-external-javascript.md %} + +## Integration + +To incorporate this module into your `prebid.js`, compile the module using the following command: + +```sh +gulp build --modules=contxtfulRtdProvider, +``` + +### Configuration + +Configure the `contxtfulRtdProvider` by passing the required settings through the `setConfig` function in `prebid.js`. + +```js +import pbjs from 'prebid.js'; + +pbjs.setConfig({ + "realTimeData": { + "auctionDelay": 1000, + "dataProviders": [ + { + "name": "contxtful", + "waitForIt": true, + "params": { + "version": "", + "customer": "" + } + } + ] + } +}); +``` + +#### Parameters + +{: .table .table-bordered .table-striped } +| Name | Type | Scope | Description | +|------------|----------|----------|-------------------------------------------| +| `version` | `string` | Required | Specifies the API version of Contxtful. | +| `customer` | `string` | Required | Your unique customer identifier. | + +## Usage + +The `contxtfulRtdProvider` module loads an external JavaScript file and authenticates with Contxtful APIs. The `getTargetingData` function then adds a `ReceptivityState` to each ad slot, which can have one of two values: `Receptive` or `NonReceptive`. + +```json +{ + "adUnitCode1": { "ReceptivityState": "Receptive" }, + "adUnitCode2": { "ReceptivityState": "NonReceptive" } +} +``` + +This module also integrates seamlessly with Google Ad Manager, ensuring that the `ReceptivityState` is available as early as possible in the ad serving process. + +### Example + +To view an integration example: + +1. In your CLI run: + + ```bash + gulp serve --modules=appnexusBidAdapter,contxtfulRtdProvider + ``` + +2. In your browser, navigate to: + + ```text + http://localhost:9999/integrationExamples/gpt/contxtfulRtdProvider_example.html + ``` + +## Support + +To utilize this module, you need to register for an account with [Contxtful](https://contxtful.com). For inquiries, please contact [prebid@contxtful.com](mailto:prebid@contxtful.com). diff --git a/dev-docs/modules/currency.md b/dev-docs/modules/currency.md index bc8dd3562d..be27ef75a7 100644 --- a/dev-docs/modules/currency.md +++ b/dev-docs/modules/currency.md @@ -13,6 +13,7 @@ sidebarType : 1 # Currency Module + {:.no_toc} This module supports the conversion of multiple bidder currencies into a single currency @@ -36,7 +37,6 @@ The numbered circles in this diagram are explained below. ![Currency Architecture]({{site.baseurl}}/assets/images/dev-docs/currency_architecture.png){:class="pb-lg-img"} - ### 1. Line Item Creation Ad server line items must be created so that the price bucket boundaries match @@ -53,7 +53,7 @@ For example, the default Prebid "low granularity" bucket is: The following config translates the "low granularity" bucket with a conversion rate of 108 yen to 1 US dollar. It also defines the default conversion rate as being 110 yen to the dollar. -{% highlight js %} +```javascript pbjs.setConfig({ "priceGranularity": "low", "currency": { @@ -62,7 +62,7 @@ pbjs.setConfig({ "defaultRates": { "USD": { "JPY": 110 }} } }); -{% endhighlight %} +``` This results in a granularity rule that's scaled up to make sense in Yen: @@ -122,7 +122,6 @@ to all currencies. For instance, if the current conversion rate is ¥110 to the dollar, then a bid of USD$1.55 would be converted to ¥170.50, which gets put into the low granularity bucket hb_pb=162. - ### 5. Ad Request and Decision Finally, the scaled and quantized bids are sent to the ad server, where they will match @@ -131,7 +130,6 @@ the line items set up initially. {: .alert.alert-success :} No other part of the Prebid process has changed due to currency support: creation of AdUnits, creative display, analytics, etc. - ### Full Example Running through a full set of numbers may help understand how components @@ -167,12 +165,12 @@ from USD to JPY is 110. | B | 151 | JPY | 151 | hb_pb_b=108 | | C | 0.90 | ? (USD assumed) | 99.9 | hb_pb_b=54 | - ## Page integration Adding the currency module to a page is done with a call to the setConfig API with one or more parameters. The simplest recommended implementation would be: -{% highlight js %} + +```javascript pbjs.setConfig({ "currency": { "adServerCurrency": "JPY", @@ -180,13 +178,14 @@ pbjs.setConfig({ "defaultRates": { "USD": { "JPY": 110 }} } }); -{% endhighlight %} +``` {: .alert.alert-warning :} Note that the `defaultRates` attribute is optional, but recommended in case there's an issue loading the currency file. In this example, the publisher is providing their own `conversionRateFile`: -{% highlight js %} + +```javascript pbjs.setConfig({ "currency": { // enables currency feature @@ -198,10 +197,12 @@ pbjs.setConfig({ "defaultRates": { "USD": { "GPB": 0.75 }} } }); -{% endhighlight %} +``` + And finally, here's an example where the conversion rate is specified right in the config, so the external file won't be loaded: -{% highlight js %} + +```javascript pbjs.setConfig({ "currency": { "adServerCurrency": "JPY", @@ -209,8 +210,7 @@ pbjs.setConfig({ "rates": { "USD": { "JPY": 110.21 }} } }); -{% endhighlight %} - +``` ## Building the Prebid package with Currency Support @@ -218,16 +218,16 @@ pbjs.setConfig({ Follow the basic build instructions on the Gihub repo's main README. To include the module, an additional option must be added to the the gulp build command: -{% highlight js %} +```javascript gulp build --modules=currency,exampleBidAdapter -{% endhighlight %} +``` This command will build the following files: -- build/dist/prebid-core.js - the base Prebid code -- build/dist/currency.js - additional code for the currency feature -- build/dist/exampleBidAdapter.js - a specified bidder adapter -- build/dist/prebid.js - a combined file with the base Prebid core code, bidder adapter code, and the currency module code. +* build/dist/prebid-core.js - the base Prebid code +* build/dist/currency.js - additional code for the currency feature +* build/dist/exampleBidAdapter.js - a specified bidder adapter +* build/dist/prebid.js - a combined file with the base Prebid core code, bidder adapter code, and the currency module code. ### Step 2: Publish the package(s) to the CDN @@ -235,7 +235,7 @@ After testing, get your javascript file(s) out to your Content Delivery Network Note that there are more dynamic ways of combining these components for publishers or integrators ready to build a more advanced infrastructure. - + ## Functions @@ -256,7 +256,7 @@ a currency object that may contain several parameters: ### Prebid.org's currency file -Prebid.org hosts a conversion file at [https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json](https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json). The currencies currently supported are: AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, EUR, GBP, HKD, HRK, HUF, IDR, ILS, INR, ISK, JPY, KRW, MXN, MYR, NOK, NZD, PHP, PLN, RON, RUB, SEK, SGD, THB, TRY, USD, ZAR. +Prebid.org hosts a conversion file at [cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json](https://cdn.jsdelivr.net/gh/prebid/currency-file@1/latest.json). The currencies currently supported are: AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, EUR, GBP, HKD, HRK, HUF, IDR, ILS, INR, ISK, JPY, KRW, MXN, MYR, NOK, NZD, PHP, PLN, RON, RUB, SEK, SGD, THB, TRY, USD, ZAR. {: .alert.alert-warning :} The currencies on this list could change if the underlying API source changes. If a desired currency isn't on this list, you will need to generate and host your own conversion file. diff --git a/dev-docs/modules/dataControllerModule.md b/dev-docs/modules/dataControllerModule.md new file mode 100644 index 0000000000..4243c3f1e5 --- /dev/null +++ b/dev-docs/modules/dataControllerModule.md @@ -0,0 +1,49 @@ +--- +layout: page_v2 +page_type: module +title: Data Controller Module +description: Filters the EIDs/SDA being transmitted to bid stream. +module_code : dataControllerModule +display_name : Data Controller Module +enable_download : true +sidebarType : 1 +Maintainer: eng-dmp@magnite.com + +--- + + +# Data Controller Module + +{:.no_toc} + +The module attempts to filter/supress the EIDs/SDA being transmitted to bid stream. + +The module can be added to the Prebid.js build with this command: + +```bash +gulp build --modules=dataControllerModule +``` + +## Application Flow + +This module is invoked before the start of the auction. +Based on the configuration either EIDs or SDA are filtered/supressed. + +## Configuration + +{: .table .table-bordered .table-striped } +| param name | type | Scope | Description | + | :------------ | :------------ | :------ | :------ | + | filterEIDwhenSDA | param | required | Filters user EIDs based on SDA. To supress all EID, use '*' as param value. | + | filterSDAwhenEID | param | required | Filters SDA based on configured EIDs. To supress all SDA, use '*' as param value. | + +## Example + +```javascript +pbjs.setConfig({ + dataController: { + filterEIDwhenSDA: ['*'], + filterSDAwhenEID: ['test.com'] + } + }); +``` diff --git a/dev-docs/modules/dchain.md b/dev-docs/modules/dchain.md new file mode 100644 index 0000000000..a22dcdc577 --- /dev/null +++ b/dev-docs/modules/dchain.md @@ -0,0 +1,93 @@ +--- +layout: page_v2 +page_type: module +title: Module - Demand Chain Object +description: Validates the Demand Chain object, provided by bidders, stored in the Prebid bid object. +module_code : dchain +display_name : Demand Chain Object +enable_download : true +sidebarType : 1 +--- + +# Demand Chain Object Module + +{:.no_toc} + +* TOC +{:toc} + +Publishers that interact with bidders that support the [IAB Buyers.json and DemandChain Object Specification](https://iabtechlab.com/buyers-json-demand-chain/) may ensure the incoming dchain object complies to the IAB specification, as well as automatically representing the Prebid bidder in the buying process. Including this dchain module can address these concerns and perform the needed tasks automatically for any DChain compliant bidder. + +## How to Use the Module + +First, build the dchain module into your Prebid.js package: + +```bash +gulp build --modules=dchain,... +``` + +The module will then automatically perform validations on the dchain data, provided by compliant bidders, stored in the Prebid bid object. Assuming the object is present and valid, the module will also include a final node to the dchain object to represent the Prebid.js bidder in its part of the process. + +## DChain Config Syntax + +{: .table .table-bordered .table-striped } +| DChain Param | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| validation | optional | string | `'strict'`: In this mode, dchain object will not be accepted by Prebid.js if it is invalid. Errors are thrown for invalid dchain object. `'relaxed'`: Errors are thrown for an invalid dchain object but the invalid dchain object is still accpeted. `'off'`: No validations are performed and dchain object is accepted as-is. The default value is `'strict'`. | 'strict' | + +For example: + +```javascript +pbjs.setConfig({ + "dchain": { + "validation": "strict" + } +}); +``` + +## Adapter Information + +Adapters who choose to support DChain should assign their ad server's IAB compliant dchain config object to the `bid.meta.dchain` field when creating their Prebid.js bidresponse object. When the module is enabled, this dchain object will be evaluated per the publisher's config settings. + +```javascript +bid.meta.dchain: { + "complete": 0, + "ver": "1.0", + "ext": {...}, + "nodes": [ + // ..., + { + "asi": "domain.com", + "bsid": "123", + "name": "companyname", + ... + }, + //... + ] +} +``` + +## Adapters Supporting the dchain Module + +{% assign bidder_pages = site.pages | where: "layout", "bidder" %} + +
      +{% for page in bidder_pages %} +
      + {{ page.title }} +
      +{% endfor %} +
      + + + +
      + +## Further Reading + +* [IAB Buyers.json and DemandChain Object Specification](https://iabtechlab.com/buyers-json-demand-chain/) diff --git a/dev-docs/modules/debugging.md b/dev-docs/modules/debugging.md new file mode 100644 index 0000000000..2e2d954d56 --- /dev/null +++ b/dev-docs/modules/debugging.md @@ -0,0 +1,189 @@ +--- +layout: page_v2 +page_type: module +title: Module - Debugging +description: Debugging tools to intercept bid requests and mock their response +module_code : debugging +display_name : Debugging +enable_download : true +sidebarType : 1 +--- + +# Debugging module + +This module allows to "intercept" bids and replace their contents with arbitrary data for the purposes of testing and development. + +Bids intercepted in this way are never seen by bid adapters or their backend SSPs, but they are nonetheless injected into the auction as if they originated from them. + +{: .pb-alert .pb-alert-warning :} +For convenience, `debugging` configuration is persisted to the browser's session storage, so that you may type `pbjs.setConfig({debugging: ...})` in the console and reload the page to immediately see the effects. This means that you need to remember to **deactivate debugging (or clear session storage) when you are done**. + + + +## Usage example + +The following will intercept all bids for the ad unit with code "test-div", and replace them with mocks that have `cpm: 10`: + +```javascript +pbjs.setConfig({ + debugging: { + enabled: true, + intercept: [ + { + when: { + // intercept bids from bidderA that have adUnitCode === 'test-div' + adUnitCode: 'test-div', + bidder: 'bidderA' + }, + then: { + // mock their response with sane defaults and `cpm: 10` + cpm: 10 + } + }, + ] + } +}); +``` + +## Intercept rules + +`intercept` is a list of objects each containing the following: + +{: .table .table-bordered .table-striped } +|Property |Type |Required? |Description| +|---------+------------------+----------+----------------------------------------------------------------------------------------------| +|`when` |Function or Object|yes |[Match rule](#match) - decides which bids should be intercepted by this rule | +|`then` |Function or Object|no |[Replace rule](#replace) - decides the contents of the bids that are intercepted by this rule | +|`options`|Object |no |[Rule options](#options) | + +Rules are evaluated on each bid in the order they are provided: the first one that has a matching `when` definition takes the bid out of the normal auction flow and replaces it according to its `then` definition. + + + +### Match rules + +The match rule can be provided as a function that takes the bid request as its only argument and returns `true` if the bid should be intercepted, `false` otherwise. The [example above](#example) could be written as: + +```javascript +pbjs.setConfig({ + debugging: { + enabled: true, + intercept: [ + { + when: (bidRequest) => bidRequest.adUnitCode === 'test-div', + then: { + cpm: 10 + } + } + ] + } +}) +``` + +Alternatively, the rule can be expressed as an object, and it matches if for each `key`-`value` pair: + +- `bidRequest[key] === value`, or +- `value` is a function and `value(bidRequest[key])` is `true`, or +- `value` is a regular expression and it matches `bidRequest[key]`. + +To illustrate, these definitions are equivalent: + +```javascript +{ + when: { + adUnitCode: 'test-div' + } +}; +{ + when: { + adUnitCode: (code) => code === 'test-div' + } +}; +{ + when: { + adUnitCode: /^test-div$/ + } +}; +``` + + + +### Replace rules + +The replace rule can be provided as a function that takes the bid request as its only argument and returns an object with the desired response properties. The [first example above](#example) could be written as: + +```javascript +pbjs.setConfig({ + debugging: { + enabled: true, + intercept: [ + { + when: { + adUnitCode: 'test-div', + }, + then: (bidRequest) => ({cpm: 10}) + }, + ] + } +}); +``` + +Alternatively, the rule can be expressed as an object, and its `key`-`value` pairs will appear in the response as follows: + +- if `value` is a function, then `bidResponse[key]` will be set to `value(bidRequest)`; +- otherwise, `bidResponse[key]` will be set to `value`. + +To illustrate, the following definitions are equivalent: + +```javascript +{ + then: { + cpm: 10 + } +}; +{ + then: { + cpm: (bidRequest) => 10 + } +} +``` + + + +### Rule options + +{: .table .table-bordered .table-striped } +|Property |Type |Default value |Description | +|---------+------------------+--------------+------------------------------------------------------------------------------------------------------------------------| +|`delay` |Number |0 |Delay (in milliseconds) before intercepted bids are injected into the auction. Can be used to simulate network latency. | + +## Examples + +### Force a video bid + +```javascript +pbjs.setConfig({ + debugging: { + enabled: true, + intercept: [ + { + when: { + adUnitCode: "video-adunit", + bidder: "bidderA' + }, + then: { + cpm: 10, + mediaType: "video", + source: "client", + currency: "SEK", + cpm: 50.00, + creativeId: "11111", + width: 640, + height: 360, + vastXml: "Prebid TestVAST 2.0 Linear Ad00:00:15" + } + }, + ] + } +}); +``` diff --git a/dev-docs/modules/dfp_express.md b/dev-docs/modules/dfp_express.md index fef264c9db..c0cec91ecd 100644 --- a/dev-docs/modules/dfp_express.md +++ b/dev-docs/modules/dfp_express.md @@ -13,10 +13,11 @@ sidebarType : 1 # GAM/Google Ad Manager Express Module + {:.no_toc} This module is a simplified alternate installation mechanism for publishers that have Google Publisher Tag (GPT) ad calls in their pages. Here's how it works: - + * You build a Prebid.js package that contains the extra module code and optionally the page's AdUnits. * One or two lines of javascript are added to a page already coded with GPT ad calls. * The module intercepts ad behavior by overriding certain GPT APIs, coordinating the appropriate header bidding behavior, and then calling DoubleClick. @@ -36,23 +37,25 @@ Definitions: ## Page integration Adding the module to a page is done by adding just one line of javascript: -{% highlight js %} + +```javascript + +

      +Notes: + +* [Price Floors in Prebid Server](/prebid-server/features/pbs-floors.html#prebid-server--features--price-floors) +* [Prebid Floor Service Providers](/dev-docs/modules/floors.html#floors-providers) +* [Transcript of this video](/dev-docs/floors-video-overview.html) ## How it Works -There are several places where the Floor module changes the behavior of the Prebid.js auction process. Below is a diagram describing the general flow of the Price Floors Module: + +There are several places where the Floor module changes the behavior of the Prebid.js auction process. Below is a diagram describing the general flow of the client-side Price Floors Module: ![Floors Module Flow](/assets/images/floors/floors_flow.png) 1. When building the Prebid.js package, the Price Floors Module (and any analytics adapters) needs to be included with 'gulp build --modules=priceFloors,...' 2. As soon as the setConfig({floors}) call is initiated, the Price Floors Module will build an internal hash table for each auction derived from a Rule Location (one of Dynamic, setConfig or adUnit) - - a. If an endpoint URL (a Dynamic Floor) is defined, the Price Floors Module will attempt to fetch floor data from the Floor Provider's endpoint. When requestBids is called, the Price Floors Module will delay the auction up to the supplied amount of time in floors.auctionDelay or as soon as the dynamic endpoint returns data, whichever is first. + + * If an endpoint URL (a Dynamic Floor) is defined, the Price Floors Module will attempt to fetch floor data from the Floor Provider's endpoint. When requestBids is called, the Price Floors Module will delay the auction up to the supplied amount of time in floors.auctionDelay or as soon as the dynamic endpoint returns data, whichever is first. + * If the `skipRate` flag is specified, there's an A/B test in progress, so the module will decide for this request whether floors processing should be 'skipped' or not. + 3. Bid Adapters are responsible for utilizing the getFloor() from the bidRequest object for each ad slot media type, size combination. The Price Floors Module will perform currency conversion if the bid adapter requests floors in a different currency from the defined floor data currency. 4. Bid Adapters will pass the floor values to their bidding endpoints, to request bids, responding with any bids that meet or exceed the provided floor 5. Bid adapters will submit bids to back to Prebid core, where the Price Floors Module will perform enforcement on each bid 6. The Price Floors Module will mark all bids below the floor as bids rejected. Prebid core will submit all eligible bids to the publisher ad server - - a. The Price Floors Module emits floor event / bid data to Analytics adapters to allow Floor Providers a feedback loop on floor performance for model training - + * The Price Floors Module emits floor event / bid data to Analytics adapters to allow Floor Providers a feedback loop on floor performance for model training ## Defining Floors @@ -69,13 +86,12 @@ In this approach, the Publisher configures the floors directly into the Prebid.j Below are some basic principles of ad unit floor definitions: -- Ad unit defined rules only apply to the ad unit they are created in -- Setting a rule with a value that does not match the context of that given ad unit will never be used -- If multiple ad units have configured floor objects, the first ad unit’s schema would apply to all subsequent ad unit floor definitions - - Values can differ between ad units - +* Ad unit defined rules only apply to the ad unit they are created in +* Setting a rule with a value that does not match the context of that given ad unit will never be used +* If multiple ad units have configured floor objects, the first ad unit’s schema would apply to all subsequent ad unit floor definitions + * Values can differ between ad units -{% highlight js %} +```javascript var adUnits = [ { code: 'test-div', @@ -104,14 +120,14 @@ Below are some basic principles of ad unit floor definitions: ] } ]; -{% endhighlight %} +``` {: .alert.alert-info :} -When defining floors at the adUnit level, the Price Floors Module requires the floors object to be defined in setConfig, even if the definition is an empty object as shown below: {% highlight js %}pbjs.setConfig({ floors: {} });{% endhighlight %} +When defining floors at the adUnit level, the Price Floors Module requires the floors object to be defined in setConfig, even if the definition is an empty object as shown below: ```javascriptpbjs.setConfig({ floors: {} });``` Floor definitions are set in the “values” object containing one or more rules, where the rule is the criteria that needs to be met for that given ad unit, with an associated CPM floor. In the above example, the floors are enforced when the bid from a bidder matches the “mediaType” and “size” combination. Since many bid adapters are not able to ingest floors per size, a simpler setup can be: -{% highlight js %} +```javascript floors: { currency: 'USD', skipRate: 5, @@ -124,11 +140,11 @@ floors: { 'video': 2.01 } } -{% endhighlight %} +``` For more advanced publisher setups, values can accept a “\*” to denote a catch-all when a bid comes back that the Price Floors Module does not have an exact match and for bid adapters who are not able to use a floor per size, the bid adapter will automatically receive the “\*” rule’s floor if available. Example setup can be: -{% highlight js %} +```javascript floors: { currency: 'USD', skipRate: 5, @@ -145,23 +161,23 @@ floors: { 'video|*': 2.01 } } -{% endhighlight %} +``` Alternatively, if there’s only one mediaType in the AdUnit and a single global floor, the syntax gets easier: -{% highlight js %} +```javascript ... floors: { default: 1.00 // default currency is USD }, ... -{% endhighlight %} +``` ### Package-Level Floors This approach is intended for scenarios where the Publisher or their Prebid managed service provider periodically appends updated floor data to the Prebid.js package. In this model, there could be more floor data present to cover AdUnits across many pages. -{% highlight js %} +```javascript pbjs.setConfig({ floors: { enforcement: { @@ -189,13 +205,13 @@ pbjs.setConfig({ } } }); -{% endhighlight %} +``` By defining floor data with setConfig, the Price Floors Module will map GPT ad slots to AdUnits as needed. It does this in the same way as the setTargetingForGPTAsync() function – first looking for an AdUnit.code that matches the slot name, then looking for an AdUnit.code that matches the div id of the named GPT slot. Here’s another example that includes more fields: -{% highlight js %} +```javascript pbjs.setConfig({ floors: { data: { // default if endpoint doesn't return in time @@ -215,9 +231,10 @@ pbjs.setConfig({ } } }); -{% endhighlight %} +``` ### Dynamic Floors + The final method of obtaining floor data allows the publisher to delay the auction for a certain time period to obtain up-to-date floor data tailored to each page or auction context. The assumed workflow is: 1. The Publisher signs up with a floor data provider @@ -226,7 +243,7 @@ The final method of obtaining floor data allows the publisher to delay the aucti Here’s an example defining a simple GET endpoint: -{% highlight js %} +```javascript pbjs.setConfig({ floors: { enforcement: { @@ -238,11 +255,11 @@ pbjs.setConfig({ } } }); -{% endhighlight %} +``` The Price Floors Module is flexible to handle floors set in multiple locations. Like in the below example a publisher can configure Dynamic floors in addition to Package floors (in setConfig). While the Price Floors Module is only able to use one set of rules (either Package, adUnit or Dynamic) defined as a Floor Location, setting floors in the Package will be utilized when the Dynamic floors fail to return data or another error condition occurs with the Dynamic fetch. -{% highlight js %} +```javascript pbjs.setConfig({ floors: { enforcement: { @@ -267,18 +284,20 @@ pbjs.setConfig({ } } }); -{% endhighlight %} - +``` ## Floors Syntax The examples above covered several different scenarios where floors can be applied. Below we will cover the syntax and definition of the floors data schema. As of Prebid.js version 3.24, the Price Floors Module supports a second data schema with the ability to add new schemas to future-proof the needs of additional design changes while keeping backwards compatibility. - ### Schema 1 Schema 1 restricts floors providers or publishers to applying only one data group. To test more than one floor group, floor providers or publishers are required to reset the data set with new rules after each request bids. +{: .alert.alert-info :} +Note: if you're a dynamic floor provider service, your response must be +a subset that will be merged under the 'data' object. + {: .table .table-bordered .table-striped } | Param | Type | Description | Default | |---+---+---+---+---| @@ -287,10 +306,10 @@ Schema 1 restricts floors providers or publishers to applying only one data grou | enforcement | object | Controls the enforcement behavior within the Price Floors Module.| - | | skipRate | integer | skipRate is a random function whose input value is any integer 0 through 100 to determine when to skip all floor logic, where 0 is always use floor data and 100 is always skip floor data. The use case is for publishers or floor providers to learn bid behavior when floors are applied or skipped. Analytics adapters will have access to model version (if defined) when skipped is true to signal the Price Floors Module is in floors mode. If skipRate is supplied in both the root level of the floors object and within the data object, the skipRate configuration within the data object shall prevail. | 0 | | enforcement.enforceJS | boolean | If set to true, the Price Floors Module will provide floors to bid adapters for bid request matched rules and suppress any bids not exceeding a matching floor. If set to false, the Price Floors Module will still provide floors for bid adapters, there will be no floor enforcement.| true | -| enforcement.enforcePBS | boolean | If set to true, the Price Floors Module will signal to Prebid Server to pass floors to it’s bid adapters and enforce floors. If set to false, the pbjs should still pass matched bid request floor data to PBS, however no enforcement will take place. | false | +| enforcement.enforcePBS | boolean | If set to true, the Price Floors Module will signal to Prebid Server to pass floors to it’s bid adapters and enforce floors. If set to false, the pbjs should still pass matched bid request floor data to PBS, however no enforcement will take place. | true | | enforcement.floorDeals | boolean | Enforce floors for deal bid requests. | false | | enforcement.bidAdjustment | boolean | If true, the Price Floors Module will use the bidAdjustment function to adjust the floor per bidder. If false (or no bidAdjustment function is provided), floors will not be adjusted. Note: Setting this parameter to false may have unexpected results, such as signaling a gross floor when expecting net or vice versa. | true | -| endpoint | object | Controls behavior for dynamically retrieving floors. | - | +| endpoint | object | Prebid.js only: controls behavior for dynamically retrieving floors. | - | | endpoint.url | string | URL of endpoint to retrieve dynamic floor data. | - | | data | object (required) | Floor data used by the Price Floors Module to pass floor data to bidders and floor enforcement. | - | | data.floorProvider | string | Optional atribute (as of prebid version 4.2) used to signal to the Floor Provider's Analytics adapter their floors are being applied. They can opt to log only floors that are applied when they are the provider. If floorProvider is supplied in both the top level of the floors object and within the data object, the data object's configuration shall prevail.| - | @@ -301,7 +320,7 @@ Schema 1 restricts floors providers or publishers to applying only one data grou | data.modelTimestamp | integer | Epoch timestamp associated with modelVersion. Can be used to track model creation of floor file for post auction analysis.| - | | data.schema | object |allows for flexible definition of how floor data is formatted. | - | | data.schema.delimiter | string | Character separating the floor keys. | '\|' | -| data.schema.fields | array of strings | Supported values are: gptSlot, adUnitCode, mediaType, size | - | +| data.schema.fields | array of strings | Supported values are: gptSlot, adUnitCode, mediaType, size, domain | - | | data.values | key / values | A series of attributes representing a hash of floor data in a format defined by the schema object. | - | | data.values."rule key" | string | Delimited field of attribute values that define a floor. | - | | data.values."rule floor value" | float | The floor value for this key. | - | @@ -310,45 +329,58 @@ Schema 1 restricts floors providers or publishers to applying only one data grou | additionalSchemaFields."custom key" | string | custom key name | - | | additionalSchemaFields."key map function" | function | Function used to lookup the value for that particular custom key | - | - +{: .alert.alert-info :} +When you see 'skipped' in the floors data, it indicates the status of the `skipRate` A/B test for this request. This is just a mechanism to be able to tell if the floor rules are providing value. e.g `skipRate` will often start at a high value like 90%, which means "only apply floors 10% of the time". If skipRate is 90, you would expect to see "skipped: true" 9 times out 10. ### Schema 2 Schema 2 allows floors providers to A/B-test one or more floor groups, determined at auction time. -The following principles apply to schema 2: -- The below attributes are required: - - data.floorsSchemaVersion to be set to 2 - - A valid modelGroups object must be set - - The field modelGroups.modelWeight is required for each model group - - If one of the model weights is missing, no schema 2 floor will be set and the Price Floors Module will look in other locations for floor definitions -- If common attributes are set in both the modelGroups and root level of the data object, modelGroups attributes prevail -- The Schema 2 data model can only be applied in Package level (i.e. directly in setConfig) or Dynamic level -- Sampling weights are applied at the auction level. Each new auction the dice will be rolled -- If the data.modelGroups object and the data.values (schema 1 field) are set, the data.floorsSchemaVersion will dictate what schema version is applied +The following principles apply to Schema 2: +* These attributes are required: + * data.floorsSchemaVersion to be set to 2 + * A valid modelGroups object must be set + * The field modelGroups.modelWeight is required for each model group + * If one of the model weights is missing, no schema 2 floor will be set and the Price Floors Module will look in other locations for floor definitions +* If common attributes are set in both the modelGroups and root level of the data object, modelGroups attributes prevail +* The Schema 2 data model can only be applied in Package level (i.e. directly in setConfig) or Dynamic level +* Sampling weights are applied at the auction level. Each new auction the dice will be rolled. +* If the data.modelGroups object and the data.values (schema 1 field) are set, the data.floorsSchemaVersion will dictate what schema version is applied While some attributes are common in both schema versions, for completeness, all valid schema 2 attributes are provided: +{: .alert.alert-info :} +Note: if you're a dynamic floor provider service, your response must be +a subset that will be merged under the 'data' object. + {: .table .table-bordered .table-striped } | Param | Type | Description | Default | |---+---+---+---+---| | floorMin | float | The mimimum CPM floor used by the module (as of 4.13). The module will take the greater of floorMin and the matched rule CPM when evaluating getFloor() and enforcing floors. | - | +| floorMinCur | float | Prebid Server only: the currency used for the floorMin value. | - | | floorProvider | string | Optional atribute (as of prebid version 4.1) used to signal to the Floor Provider's Analytics adapter their floors are being applied. They can opt to log only floors that are applied when they are the provider. If floorProvider is supplied in both the top level of the floors object and within the data object, the data object's configuration shall prevail.| - | -| enforcement | object | Controls the enforcement behavior within the module.| - | | skipRate | integer | skipRate is a random function whose input value is any integer 0 through 100 to determine when to skip all floor logic, where 0 is always use floor data and 100 is always skip floor data. The use case is for publishers or floor providers to learn bid behavior when floors are applied or skipped. Analytics adapters will have access to model version (if defined) when skipped is true to signal the module is in floors mode. If skipRate is supplied in both the root level of the floors object and within the data object, the skipRate configuration within the data object shall prevail. | 0 | +| enabled | boolean | Prebid Server only: provides a request level override to disable server-side floor activity. If there's server-side floor config, it must also be true in order for floor activity to take place. | true | +| fetchStatus | string | Prebid Server only: this is a read-only field set by the Prebid-Server floors feature to let analytics adapters know whether the floors data used was dynamically fetched. | n/a | +| skipped | boolean | Prebid Server only: this is a read-only field set by the Prebid-Server floors feature to let analytics adapters know whether the 'skipRate' feature was invoked. i.e. this value is 'true' when the floor activity has been turned off by the skipRate, and 'false' otherwise. | n/a | +| location | string | Prebid Server only: this is a read-only field set by the Prebid-Server floors feature to let analytics adapters know where the floors data came from. Possible values are: 'request', 'fetch' or 'noData'. | n/a | +| enforcement | object | Controls the enforcement behavior within the module.| - | | enforcement.enforceJS | boolean | If set to true, the module will provide floors to bid adapters for bid request matched rules and suppress any bids not exceeding a matching floor. If set to false, the module will still provide floors for bid adapters, but there will be no floor enforcement.| true | -| enforcement.enforcePBS | boolean | If set to true, the module will signal to Prebid Server to pass floors to it’s bid adapters and enforce floors. If set to false, Prebid.js should still pass matched bid request floor data to Prebid Server, however no enforcement will take place. | false | +| enforcement.enforcePBS | boolean | If set to true, the module will signal to Prebid Server to pass floors to it’s bid adapters and enforce floors. If set to false, Prebid.js should still pass matched bid request floor data to Prebid Server, however no enforcement will take place. | true | | enforcement.floorDeals | boolean | Enforce floors for deal bid requests. | false | | enforcement.bidAdjustment | boolean | If true, the module will use the bidAdjustment function to adjust the floor per bidder. If false (or no bidAdjustment function is provided), floors will not be adjusted. Note: Setting this parameter to false may have unexpected results, such as signaling a gross floor when expecting net or vice versa. | true | +| enforcement.enforceRate | integer | Prebid Server only: Defines a percentage for how often bid response enforcement activity should take place given that the floors feature is active. If the floors feature is skipped due to skipRate, this has no affect. For every non-skipped auction, this percent of them should be enforced: i.e. bids discarded. This feature lets publishers ease into enforcement in case bidders aren't adhering to floor rules. | 100 | +| enforcement.noFloorSignalBidders | array of strings | (Prebid.js 8.31+) Bidders which should not receive floor signals. | none | | endpoint | object | Controls behavior for dynamically retrieving floors. | - | | endpoint.url | string | URL of endpoint to retrieve dynamic floor data. | - | | data | object (required) | Floor data used by the module to pass floor data to bidders and floor enforcement. | - | | data.floorProvider | string | Optional atribute (as of prebid version 4.2) used to signal to the Floor Provider's Analytics adapter their floors are being applied. They can opt to log only floors that are applied when they are the provider. If floorProvider is supplied in both the top level of the floors object and within the data object, the data object's configuration shall prevail.| - | | data.currency | string | Currency of floor data. The module will convert currency where necessary. See Currency section for more details. | 'USD' | | data.skipRate | integer | skipRate is a random function whose input value is any integer 0 through 100 to determine when to skip all floor logic, where 0 is always use floor data and 100 is always skip floor data. The use case is for publishers or floor providers to learn bid behavior when floors are applied or skipped. Analytics adapters will have access to model version (if defined) when skipped is true to signal the module is in floors mode. If skipRate is supplied in both the root level of the floors object and within the data object, the skipRate configuration within the data object shall prevail.| 0 | -| data.floorsSchemaVersion | string | The module supports two version of the data schema. Version 1 allows for only one model to be applied in a given data set, whereas Version 2 allows you to sample multiple models selected by supplied weights. If no schema version is provided, the module will assume version 1 for the sake of backwards compatiblity.| 1 | +| data.floorsSchemaVersion | integer | The module supports two version of the data schema. Version 1 allows for only one model to be applied in a given data set, whereas Version 2 allows you to sample multiple models selected by supplied weights. If no schema version is provided, the module will assume version 1 for the sake of backwards compatiblity.| 1 | | data.modelTimestamp | int | Epoch timestamp associated with modelVersion. Can be used to track model creation of floor file for post auction analysis.| - | +| data.noFloorSignalBidders | array of strings | (Prebid.js 8.31+) Bidders which should not receive floor signals. | none | | data.modelGroups | array of objects | Array of model objects to be used for A/B sampling multiple models. This field is only used when data.floorsSchemaVersion = 2 | - | | data.modelGroups[].currency | string | Currency of floor data. Floor Module will convert currency where necessary. See Currency section for more details. | 'USD' | | data.modelGroups[].skipRate | integer | skipRate is a random function whose input value is any integer 0 through 100 to determine when to skip all floor logic, where 0 is always use floor data and 100 is always skip floor data. The use case is for publishers or floor providers to learn bid behavior when floors are applied or skipped. Analytics adapters will have access to model version (if defined) when skipped is true to signal the module is in floors mode. | 0 | @@ -361,80 +393,83 @@ While some attributes are common in both schema versions, for completeness, all | data.modelGroups[].values."rule key" | string | Delimited field of attribute values that define a floor. | - | | data.modelGroups[].values."rule floor value" | float | The floor value for this key. | - | | data.modelGroups[].default | float | Floor used if no matching rules are found. | - | +| data.modelGroups[].noFloorSignalBidders | array of strings | (Prebid.js 8.31+) Bidders which should not receive floor signals. | none | | additionalSchemaFields | object | Object contain the lookup function to map custom schema.fields. Not supported by Prebid Server. | - | | additionalSchemaFields."custom key" | string | custom key name | - | | additionalSchemaFields."key map function" | function | Function used to lookup the value for that particular custom key | - | +{: .alert.alert-info :} +As noted for Schema 1, when you see 'skipped' in the floors data, it indicates the status of the `skipRate` A/B test for this request. This is just a mechanism to be able to tell if the floor rules are providing value. e.g `skipRate` will often start at a high value like 90%, which means "only apply floors 10% of the time". If skipRate is 90, you would expect to see "skipped: true" 9 times out 10. *Example 1* Model weights add up to 100 and are sampled at a 25%, 25%, 50% distribution. Additionally, each model group has diffirent schema fields: -{% highlight js %} +```javascript pbjs.setConfig({ floors: { enforcement: { ... }, ... data: { - "currency": "EU", - "skipRate": 20, - "floorsSchemaVersion":2, - "modelGroups": [ - { - "modelWeight":25, - "modelVersion": "Model1", - "schema": { - "fields": [ "domain", "gptSlot", "mediaType", "size" ] - }, - "values": { - "www.publisher.com|/1111/homepage/top-banner|banner|728x90": 1.00, - "www.publisher.com|/1111/homepage/top-rect|banner|300x250": 1.20, - "www.publisher.com|/1111/homepage/top-rect|banner|300x600": 1.80, - ... - "www.domain.com|/1111/homepage/top-banner|banner|728x90": 2.11 - ... - "www.publisher.com|*|*|*": 0.80, - }, - "default": 0.75 - }, - { - "modelWeight": 25, - "modelVersion": "Model2", - "schema": { - "fields": [ "domain", "mediaType", "size" ] - }, - "values": { - "www.publisher.com|banner|728x90": 1.00, - "www.publisher.com|banner|300x250": 1.20, - "www.publisher.com|banner|300x600": 1.80, - ... - "www.domain.com|banner|728x90": 2.11 - ... - "www.publisher.com|*|*|*": 0.80, - }, - "default": 0.75 - }, - { - "modelWeight": 50, - "modelVersion": "Model3", - "schema": { - "fields": [ "gptSlot", "mediaType", "size" ] - }, - "values": { - "/1111/homepage/top-banner|banner|728x90": 1.00, - "/1111/homepage/top-rect|banner|300x250": 1.20, - "/1111/homepage/top-rect|banner|300x600": 1.80, - ... - "/1111/homepage/top-banner|banner|728x90": 2.11 - ... - "*|banner|*": 0.80, - }, - "default": 0.75 - } - ] - } + "currency": "EU", + "skipRate": 20, + "floorsSchemaVersion":2, + "modelGroups": [ + { + "modelWeight":25, + "modelVersion": "Model1", + "schema": { + "fields": [ "domain", "gptSlot", "mediaType", "size" ] + }, + "values": { + "www.publisher.com|/1111/homepage/top-banner|banner|728x90": 1.00, + "www.publisher.com|/1111/homepage/top-rect|banner|300x250": 1.20, + "www.publisher.com|/1111/homepage/top-rect|banner|300x600": 1.80, + ... + "www.domain.com|/1111/homepage/top-banner|banner|728x90": 2.11 + ... + "www.publisher.com|*|*|*": 0.80, + }, + "default": 0.75 + }, + { + "modelWeight": 25, + "modelVersion": "Model2", + "schema": { + "fields": [ "domain", "mediaType", "size" ] + }, + "values": { + "www.publisher.com|banner|728x90": 1.00, + "www.publisher.com|banner|300x250": 1.20, + "www.publisher.com|banner|300x600": 1.80, + ... + "www.domain.com|banner|728x90": 2.11 + ... + "www.publisher.com|*|*|*": 0.80, + }, + "default": 0.75 + }, + { + "modelWeight": 50, + "modelVersion": "Model3", + "schema": { + "fields": [ "gptSlot", "mediaType", "size" ] + }, + "values": { + "/1111/homepage/top-banner|banner|728x90": 1.00, + "/1111/homepage/top-rect|banner|300x250": 1.20, + "/1111/homepage/top-rect|banner|300x600": 1.80, + ... + "/1111/homepage/top-banner|banner|728x90": 2.11 + ... + "*|banner|*": 0.80, + }, + "default": 0.75 + } + ] + } } }); -{% endhighlight %} +``` *Example 2* Model weights do not equal 100 and are normalized. Weights will be applied in the following method: Model weight / (sum of all weights) @@ -443,59 +478,69 @@ model2 = 50 -> 50 / (20 + 50) = 71% of auctions model 2 will be applied Additionally skipRate is supplied at model group level where model1 will skip floors 20% of times when model1 is selected, whereas model2 will skip 50% of auctions when model2 is selected. -{% highlight js %} +```javascript pbjs.setConfig({ floors: { enforcement: { ... }, ... data: { - "currency": "EU", - "floorsSchemaVersion":2, - "modelGroups": [ - { - "modelWeight":25, - "skipRate": 20, - "modelVersion": "Model1", - "schema": { - "fields": [ "domain", "gptSlot", "mediaType", "size" ] - }, - "values": { - "www.publisher.com|/1111/homepage/top-banner|banner|728x90": 1.00, - "www.publisher.com|/1111/homepage/top-rect|banner|300x250": 1.20, - "www.publisher.com|/1111/homepage/top-rect|banner|300x600": 1.80, - ... - "www.domain.com|/1111/homepage/top-banner|banner|728x90": 2.11 - ... - "www.publisher.com|*|*|*": 0.80, - }, - "default": 0.75 - }, - { - "modelWeight": 50, - "skipRate": 50, - "modelVersion": "Model2", - "schema": { - "fields": [ "gptSlot", "mediaType", "size" ] - }, - "values": { - "/1111/homepage/top-banner|banner|728x90": 1.00, - "/1111/homepage/top-rect|banner|300x250": 1.20, - "/1111/homepage/top-rect|banner|300x600": 1.80, - ... - "/1111/homepage/top-banner|banner|728x90": 2.11 - ... - "*|banner|*": 0.80, - }, - "default": 0.75 - } - ] - } + "currency": "EU", + "floorsSchemaVersion":2, + "modelGroups": [ + { + "modelWeight":25, + "skipRate": 20, + "modelVersion": "Model1", + "schema": { + "fields": [ "domain", "gptSlot", "mediaType", "size" ] + }, + "values": { + "www.publisher.com|/1111/homepage/top-banner|banner|728x90": 1.00, + "www.publisher.com|/1111/homepage/top-rect|banner|300x250": 1.20, + "www.publisher.com|/1111/homepage/top-rect|banner|300x600": 1.80, + ... + "www.domain.com|/1111/homepage/top-banner|banner|728x90": 2.11 + ... + "www.publisher.com|*|*|*": 0.80, + }, + "default": 0.75 + }, + { + "modelWeight": 50, + "skipRate": 50, + "modelVersion": "Model2", + "schema": { + "fields": [ "gptSlot", "mediaType", "size" ] + }, + "values": { + "/1111/homepage/top-banner|banner|728x90": 1.00, + "/1111/homepage/top-rect|banner|300x250": 1.20, + "/1111/homepage/top-rect|banner|300x600": 1.80, + ... + "/1111/homepage/top-banner|banner|728x90": 2.11 + ... + "*|banner|*": 0.80, + }, + "default": 0.75 + } + ] + } } }); -{% endhighlight %} +``` + +### Impression-Level Floor Min + +An extension supported on Prebid Server only is the ability to define impression (adunit) level minimums for the floor. This allows publishers to put fences around +the results from a dynamic floors provider. + +The Prebid Server OpenRTB fields are imp.ext.prebid.floors.floorMin and floorMinCur. It's expected that these values will be placed in the App or AMP stored request and not supplied on a web page. (Though they could be supplied as AdUnit.ortb2Imp). ## Custom Schema Fields +{: .alert.alert-info :} +Only supported in Prebid.js, not Prebid Server + Out of the box, the Price Floors Module only supports looking up floors by AdUnit, GPT Slot, MediaType, ad size, and domain. Custom schema fields can be added to support other lookup dimensions. Here are the steps: 1. Create a lookup function to give context of the value of custom fields for that given auction @@ -503,10 +548,11 @@ Out of the box, the Price Floors Module only supports looking up floors by AdUni ### Create Lookup Function -Create a function to allow the module to understand context of a given auction. In the below example, a lookup function provides details about what deviceType this auction is for. +Create a function to allow the module to understand context of a given auction. In the below example, a lookup function provides details about what deviceType this auction is for. e.g. -{% highlight js %} + +```javascript function deviceTypes (bidRequest, bidResponse) { //while bidRequest and bidResponse are not required for this function, they are available for custom attribute mapping @@ -520,8 +566,7 @@ e.g. return 'desktop' } -{% endhighlight %} - +``` ### Define, Set and Map Custom Schema Attributes @@ -529,7 +574,7 @@ After defining a lookup function for the given context of the auction, the custo In the below example, `deviceType` is a custom field not currently supported by default in the Price Floors Module whose values are one of "mobile", "desktop" or "tablet". -{% highlight js %} +```javascript pbjs.setConfig({ floors: { @@ -559,8 +604,7 @@ In the below example, `deviceType` is a custom field not currently supported by } }); -{% endhighlight %} - +``` ## Rule Handling @@ -570,10 +614,9 @@ As defined in the overview, a Rule Location is where a particular rule is locate The module uses the below prioritization scheme on determining which Rule Location is selected at run-time: -- dynamic -- setConfig -- adUnit - +* dynamic +* setConfig +* adUnit ### Rule Selection Process @@ -585,39 +628,63 @@ Priority order behavior where “\_” is a specific value, and the “\*” is Priority order for one column rule sets: - \_ - \* +```text + _ + * +``` Priority order for two column rule set: - \_ \| \_ - \_ \| \* - \* \|\_ - \* \| \* +```text + _ | _ + _ | * + * | _ + * | * +``` Priority order for three column rule sets: - \_ \| \_ \| \_ - \_ \| \_ \| \* - \_ \| \* \| \_ - \* \| \_ \| \_ - \* \| \_ \| \* - \_ \| \* \| \* - \* \| \_ \| \* - \* \| \* \| \_ - \* \| \* \| \* - - +```text + _ | _ | _ + _ | _ | * + _ | * | _ + * | _ | _ + _ | * | * + * | _ | * + * | * | _ + * | * | * +``` + +Priority order for four column rule sets: + +```text + _ | _ | _ | _ + _ | _ | _ | * + _ | _ | * | _ + _ | * | _ | _ + * | _ | _ | _ + _ | _ | * | * + _ | * | _ | * + _ | * | * | _ + * | _ | _ | * + * | _ | * | _ + * | * | _ | _ + _ | * | * | * + * | _ | * | * + * | * | _ | * + * | * | * | _ + * | * | * | * +``` Below are some real example behaviors. #### Example 1 -Domain = www.website.com +Domain = Floor provider rule definition -{% highlight js %} +```javascript { "modelVersion": "Fancy Model", "currency": "USD", @@ -644,17 +711,17 @@ Floor provider rule definition }, "default": 0.01 } -{% endhighlight %} +``` **Bidder A Bid** mediaType = banner Size = 300x600 -Domain context = www.website.com +Domain context = The Floor module produces an internal hash table of all possible permutations of “banner”, “300x600”, “www.website.com” and “\*” with the most specific hash values up top, weighting rules priority from left column specific values to right. Each left value will weigh more than the subsequent column’s specific values. The module attempts to find the matching rule by cycling through each below possible rule (from top to bottom) against the above rule provider data set. -{% highlight js %} +```javascript { "banner|300x600|www.website.com", //Most specific possible rule match against floor provider rule set "banner|300x600|*", @@ -666,20 +733,20 @@ The Floor module produces an internal hash table of all possible permutations of "*|*|www.website.com", "*|*|*" } -{% endhighlight %} +``` Matching rule: "banner|300x600|www.website.com" Floor enforced: 3.01 - **Bidder B Bid** mediaType = video Size = 640x480 -Domain context = www.website.com +Domain context = Price Floor internal possible permutations sorted by priority: -{% highlight js %} + +```javascript { "video|640x480|www.website.com", //Fails to match due to no video specific rule "video|640x480|*", //Fails to match due to no video specific rule @@ -690,20 +757,20 @@ Price Floor internal possible permutations sorted by priority: "*|*|www.website.com", //Matching rule "*|*|*" } -{% endhighlight %} +``` Matching rule: "\*|\*|www.website.com" Enforced Floor: 15.01 - **Bidder C Bid** mediaType = video Size = 300x250 -Domain context = www.website.com +Domain context = Price Floor internal possible permutations sorted by priority: -{% highlight js %} + +```javascript { "video|300x250|www.website.com", //Fails to match due to no video specific rule "video|300x250|*", //Fails to match due to no video specific rule @@ -714,7 +781,7 @@ Price Floor internal possible permutations sorted by priority: "*|*|www.website.com", "*|*|*" } -{% endhighlight %} +``` Matching Rule "\*|300x250|www.website.com” Enforced floor: 10.01 @@ -723,11 +790,11 @@ Enforced floor: 10.01 Similar data set with slightly different rules and same bids from each bidder. Matching rules will differ from example 1. -Domain = www.website.com +Domain = Floor provider rule definition -{% highlight js %} +```javascript { "modelVersion": "Fancy Model", "currency": "USD", @@ -755,15 +822,15 @@ Floor provider rule definition }, "defaultValue": 0.01 } -{% endhighlight %} +``` **Bidder A Bid** mediaType = banner Size = 300x600 -Domain context = www.website.com +Domain context = -{% highlight js %} +```javascript { "banner|300x600|www.website.com", // Fails due to website.com does not match with banner and 300x600 @@ -777,7 +844,7 @@ Domain context = www.website.com "*|*|*" } -{% endhighlight %} +``` Matching rule: "banner|300x600|\*" Floor enforced: 4.01 @@ -786,11 +853,11 @@ Floor enforced: 4.01 mediaType = video Size = 640x480 -Domain context = www.website.com. +Domain context = . Price Floor internal possible permutations sorted by priority: -{% highlight js %} +```javascript { "video|640x480|www.website.com", //Fails to match due to no video specific rule @@ -803,21 +870,20 @@ Price Floor internal possible permutations sorted by priority: "*|*|*" } -{% endhighlight %} +``` Matching rule: "video\|\*\|\*" Enforced Floor: 9.01 - **Bidder C Bid** mediaType = video Size = 300x250 -Domain context = www.website.com +Domain context = Price Floor internal possible permutations sorted by priority: -{% highlight js %} +```javascript { "video|300x250|www.website.com", //Fails to match due to no video specific rule "video|300x250|*", //Fails to match due to no video specific rule @@ -828,41 +894,37 @@ Price Floor internal possible permutations sorted by priority: "*|*|www.website.com", "*|*|*" } -{% endhighlight %} +``` Matching Rule "\*|300x250|www.website.com” Enforced floor: 10.01 - ## Interfaces ### Floor Data Provider Interface -Floor data providers can supply data to publishers either within the setConfig as part of a Prebid.js Package if the provider is also a host provider of the Prebid library, or via a real-time Dynamic fetch, prior to the auction. +Floor data can be supplied to publishers either within the setConfig as part of a Prebid.js Package if the provider is also a host provider of the Prebid library, or via a real-time Dynamic fetch, prior to the auction. Data providers can optionally build Analytics Adapters to ingest bid data within Prebid for algorithm learning and review floor performance. Please refer to the Analytics Interface section for more details. - - {% capture warning_note %} As a floor provider, your goal is to provide effective floors, with minimal page impact. If you are performing a Dynamic fetch to retrieve data prior to auctions, the following recommendations are advised to reduce page performance issues: -- Return results to the page quickly. This implies data should be stored on a CDN or be provided by a distributed tier of high performance services -- Work with publishers on setting appropriate auction delays to retrieve dynamic data -- Implement client-side caching (such as max-age headers) whenever possible -- Evaluate data freshness vs frequency of new fetches to the CDN to reduce unnecessary calls -- Be aware of file sizes returned to the browser, implementing trimming algorithms for extremely large data sets +* Return results to the page quickly. This implies data should be stored on a CDN or be provided by a distributed tier of high performance services +* Work with publishers on setting appropriate auction delays to retrieve dynamic data +* Implement client-side caching (such as max-age headers) whenever possible +* Evaluate data freshness vs frequency of new fetches to the CDN to reduce unnecessary calls +* Be aware of file sizes returned to the browser, implementing trimming algorithms for extremely large data sets {% endcapture %} {% include /alerts/alert_important.html content=warning_note %} -For Dynamic fetches, the Price Floors Module will perform a GET request to the supplied endpoint, that must return valid JSON, formatted like the data object in the “setConfig” Package configuration. - +For Dynamic fetches, the Price Floors Module will perform a GET request to the supplied endpoint, that must return valid JSON, which will be merged into the data object in the “setConfig” Package configuration. In otherwords, the schema used for dynamic fetches is a subset of the full schema. On rule creation, we recommend supplying various rules with catch-all \(“\*”\) values with associated floors. This is to accommodate bid adapters who cannot retrieve floors on a per size basis, as well as using various permutations of rules with “\*” values to match auctions that do not have an exact match on a specific rule. Please refer to the Rule Selection Process when determining floors as attribute order and number of “\*”s may have an impact on which rule is selected. #### Example Dynamic fetch -{% highlight js %} +```javascript pbjs.setConfig({ floors: { @@ -876,13 +938,13 @@ pbjs.setConfig({ } }); -{% endhighlight %} +``` -#### Example Response 1 +#### Example Dynamic Response 1 - Schema 1 -floor determined by AdUnit code and Media Type: +In this example, the floor is determined by AdUnit code and Media Type. Note that the response does not contain the 'data' object because everything in the response is merged there. -{% highlight js %} +```javascript { floorProvider: 'floorProviderName', @@ -902,18 +964,19 @@ floor determined by AdUnit code and Media Type: default: 0.75 } -{% endhighlight %} +``` -#### Example Response 2 +#### Example Response 2 - Schema 1 -floor determined by Domain, GPT Slot, Media Type and Size: +In this example, the floor is determined by Domain, GPT Slot, Media Type and Size: -{% highlight js %} +```javascript { currency: 'EU', skipRate: 20, modelVersion: ‘High_skip_rate’ + schema: { fields: [ 'domain', 'gptSlot', 'mediaType', 'size' ] }, @@ -929,15 +992,13 @@ floor determined by Domain, GPT Slot, Media Type and Size: default: 0.75 } -{% endhighlight %} - +``` -#### Example Response 3 +#### Example Response 3 - Schema 2 -Floors Schema version 2 - -{% highlight js %} +In this example, the floor is determined by domain, gptSlot, mediaType, and size. Note again that dynamic floor responses are merged into the 'data' level of the schema. +```javascript { "currency": "USD", "floorsSchemaVersion":2, @@ -981,8 +1042,7 @@ Floors Schema version 2 } -{% endhighlight %} - +``` ### Bid Adapter Interface @@ -999,7 +1059,7 @@ Changes for bid adapters: getFloor() takes in a single object with the following params: -{% highlight js %} +```javascript if (typeof bidRequest.getFloor === 'function') { floorInfo = bidRequest.getFloor({ currency: string, @@ -1007,12 +1067,11 @@ getFloor() takes in a single object with the following params: size : [ w, h] OR "*" }); } -{% endhighlight %} +``` {: .alert.alert-warning :} Consider how floors will behave in multi-currency scenarios. A common pitfall is requesting floors without specifying currency, or specifying the wrong currency back to the bid adapter's platform. This may lead to bidders requesting one currency and bidding in an alternate currency. - {: .table .table-bordered .table-striped } | Param | Type | Description | Default | |---+---+---+---| @@ -1022,28 +1081,28 @@ Consider how floors will behave in multi-currency scenarios. A common pitfall is #### getFloor() Response -{% highlight js %} +```javascript { currency: string, floor: float } -{% endhighlight %} +``` Or empty object if a floor was not found for a given input -{% highlight js %} +```javascript { } -{% endhighlight %} +``` #### Example getFloor() scenarios Example rules file used for getFloor() -{% highlight js %} +```javascript { "data": { @@ -1062,66 +1121,65 @@ Example rules file used for getFloor() } } -{% endhighlight %} +``` **Example getFloor() 1** getFloor() for media type Banner for a bid request in GPT slot “/1111/homepage/top-rect” where the bid adapter does not support floors per size. -{% highlight js %} +```javascript getFloor({ currency: 'USD', mediatype: ‘banner’, size: ‘*’ }); -{% endhighlight %} +``` **Response** -{% highlight js %} +```javascript { currency: 'USD', floor: 1.10 } -{% endhighlight %} +``` To aid in the accuracy of floor selection when using size ”\*” in getFloor(), the Price Floors Module has built-in smart rule selection when an ad unit in the internal bidRequest to the bid adapters interface has one ad unit type and one size. In the above example, if the ad unit within the bidRequest object has an ad unit type of “banner” with only one size, say “300x250”, the module will intelligently select the rule with "banner\|300x250" in it, as opposed to the "banner\|\*" rule producing the following response: -{% highlight js %} +```javascript { currency: 'USD', floor: 0.60 } -{% endhighlight %} - +``` **Example getFloor() 2** getFloor() for media type Banner for a bid requests in GPT slot “/1111/homepage/top-rect” with size of 300x600 where bid adapter does support floors per size. -{% highlight js %} +```javascript getFloor({ currency: 'USD', size: [300,600], mediatype: ‘banner’ }); -{% endhighlight %} +``` **Response** -{% highlight js %} +```javascript { currency: 'USD', floor: 1.78 } -{% endhighlight %} +``` Here are some examples of how a bid adapter may wish to configure their adapter to handle getFloor() function: For a bid adapter who does not wish to handle making a request for each size in a given bid request they can leverage the \* attribute which is meant to be a skewed average for a floor. -{% highlight js %} +```javascript if (typeof bidRequest.getFloor === 'function') { let floorInfo = bidRequest.getFloor({ currency: 'USD', @@ -1130,7 +1188,7 @@ For a bid adapter who does not wish to handle making a request for each size in }); data['adapter_floor'] = floorInfo.currency === 'USD' ? floorInfo.floor : undefined; } -{% endhighlight %} +``` ### Analytics Adapter Interface @@ -1171,6 +1229,68 @@ The module will do this by leveraging the already-existing implementation for an The PrebidServerBidAdapter calls `getFloor()` like any other bid adapter and passes it to the server side as imp.bidfloor and imp.bidfloorcur. +### In-Page Interface + +If a publisher is defining their own floors, then all of the fields in the floors schema may be defined in the page. + +Even if a publisher is using a floors provider, they may wish to provide additional data: + +1. default floor data if dynamic data fails to load on time +2. global floorMin: allows the publisher to constrain dynamic floors with a global min +3. impression-level floor min (PBJS 6.24+): allows the publisher to constrain dynamic floors with an adunit-specific value + +Here's an example covering the first two scenarios: + +```javascript +pbjs.setConfig({ + floors: { + enforcement: { + floorDeals: false //default to false + }, + floorMin: 0.05, // global default + auctionDelay: 100, // in milliseconds + endpoint: { // where to get the dynamic floors + url: 'https://floorprovider.com/a1001-mysite.json' + }, + data: { + currency: 'USD', + skipRate: 10, + modelVersion: 'some setconfig model version', + schema: { + fields: [ 'gptSlot', 'mediaType' ] + }, + values: { + '*|banner': 0.98, + '*|video': 1.74 + } + } + } +}); +``` + +And here's an example of imp-level floorMin, which is like a form of imp-level [first party data](/features/firstPartyData.html#supplying-adunit-specific-data): + +```javascript +pbjs.addAdUnits({ + code: "test-div", + mediaTypes: { + banner: { + sizes: [[300,250]] + } + }, + ortb2Imp: { + ext: { + prebid: { + data: { + floorMin: 0.25, + floorMinCur: "USD" + } + } + } + }, + ... +}); +``` ## Currency @@ -1182,9 +1302,9 @@ For publishers requiring currency conversions (for example if the floors data cu {% include /alerts/alert_warning.html content=warning_note %} Currency conversion can occur in two areas of the Floor Module code: -- On the **getFloor()** call when Bid Adapters request a floor -- On the **enforcement** side when each bidder submits a bidResponse +* On the **getFloor()** call when Bid Adapters request a floor +* On the **enforcement** side when each bidder submits a bidResponse **Currency and getFloor()** @@ -1196,41 +1316,42 @@ Example Rule: currency = ‘USD’, ‘banner|300x250’: 1.00 -{% highlight js %} +```javascript getFloor({ currency: ‘EUR’, mediaType: ‘banner’, size: [300, 250] }); -{% endhighlight %} +``` If successfully returned the requested currency: -{% highlight js %} +```javascript { floor: 0.85, currency: ‘EUR’ } -{% endhighlight %} +``` If currency conversion is unsuccessful: -{% highlight js %} +```javascript { floor:1.0, currency: ‘USD’ } -{% endhighlight %} +``` Currency conversion can fail for the following reasons: -- Currency module is not included in the prebid bundle. -- Currency module is included but not enabled -- Currency module is included and enabled but: - - No default rates were set - - Currency rates fetch failed - - Data has not returned yet -- Bidder passes in a currency code which does not have a conversion rate -- Floors was set with a currency which does not have a conversion rate + +* Currency module is not included in the prebid bundle. +* Currency module is included but not enabled +* Currency module is included and enabled but: + * No default rates were set + * Currency rates fetch failed + * Data has not returned yet +* Bidder passes in a currency code which does not have a conversion rate +* Floors was set with a currency which does not have a conversion rate **Currency and Floor Enforcement** @@ -1238,16 +1359,16 @@ Enforcement in the Price Floors Module occurs when bidders respond with a bidRes There exist three locations where currencies can differ within enforcement: -- adServerCurrency: The currency the publisher set in their currency module setConfig call -- Price Floor Currency: Currency set in the price floors data object -- bidResponse Currency: The currency the bidder returned with their bidResponse back to Prebid +* adServerCurrency: The currency the publisher set in their currency module setConfig call +* Price Floor Currency: Currency set in the price floors data object +* bidResponse Currency: The currency the bidder returned with their bidResponse back to Prebid When a bid adapter submits a bid into the auction, the currency module will first determine if any conversion logic is necessary, afterwhich the bid is passed to the module. If currency conversion occurs at this stage, the bidResponse object will have the following attributes: -- Cpm: The adServerCurrency converted CPM currency -- Currency: The currency the adServerCurrency was set in -- originalCpm: The original CPM the bidder responded with -- originalCurrency: The original currency the bidder responded with +* Cpm: The adServerCurrency converted CPM currency +* Currency: The currency the adServerCurrency was set in +* originalCpm: The original CPM the bidder responded with +* originalCurrency: The original currency the bidder responded with Below is a chart explaining the behavior of currency conversion, if necessary, within the module when comparing bid CPM to floor CPM for enforcement: @@ -1264,12 +1385,17 @@ Below is a chart explaining the behavior of currency conversion, if necessary, w If the currency function is unable to derive the correct cpm in any of the scenarios above where a conversion is needed, then the associated bidResponse will just pass through into the auction as if a matching floor was not found. - ## Floors Providers {: .table } | Partner | Contact | About | -| | [globalsupport@magnite.com](mailto:globalsupport@magnite.com) | Magnite data-science applied to dynamic floors -| pubx.ai | [hello@pubx.ai](mailto:hello@pubx.ai) | AI-powered dynamic floor optimization | -| Assertive Yield | [assertiveyield.com](https://assertiveyield.com) | Holistic flooring covering Prebid, Amazon, GAM UPR, RTB and more | -| OpenX | Reach out to OpenX at [apollo@openx.com] | Dynamic floor optimization and more | +| magnite | Your Magnite account team | Magnite data-science applied to dynamic floors. (Currently only available to Demand Manager customers) | +| openx | Reach out to OpenX at [apollo@openx.com](mailto:apollo@openx.com) | Dynamic floor optimization and more | +| pubmatic | [header-bidding@pubmatic.com](mailto:header-bidding@pubmatic.com) | PubMatic's ML powered dynamic Floor Optimization | +| assertive_yield | [assertiveyield.com](https://assertiveyield.com) | Holistic flooring covering Prebid, Amazon, GAM UPR, RTB and more | +| pubx.ai | [hello@pubx.ai](mailto:hello@pubx.ai) | pubX is an ML-led, dynamic flooring solution covering the full programmatic revenue spectrum (the header + GAM). pubX integrates with your current set-up, so no need to replace any part of the current stack. Our team is solely focussed on delivering the best flooring technology to publishers. | +| mile.tech | [hello@mile.tech](mailto:hello@mile.tech) | Boost your Prebid stack with Mile’s AI-powered dynamic flooring module that delivers an average revenue uplift of 22%. Sign-up for a free trial. | + +## Further Reading + +* [Prebid Server Price Floors](/prebid-server/features/pbs-floors.html) diff --git a/dev-docs/modules/freewheel.md b/dev-docs/modules/freewheel.md index 2aa357c750..de8b6a0571 100644 --- a/dev-docs/modules/freewheel.md +++ b/dev-docs/modules/freewheel.md @@ -16,11 +16,11 @@ sidebarType : 1 This module returns the targeting key value pairs for the FreeWheel ad server. -## How to use the module: +## How to use the module If you are using FreeWheel as your ad server for long-form header bidding then include this module while creating Prebid.js build. Use the exposed getTargeting method to get targeting key value pairs. -#### Example: +### Example ```javascript pbjs.adServers.freewheel.getTargeting({ @@ -63,13 +63,12 @@ pbjs.adServers.freewheel.getTargeting({ The values returned by `getTargeting` are concatenation of CPM, industy code, and video duration. FreeWheel SDK will send those values to FreeWheel Ad Server within the following query: -``` +```text http://[customerId].v.fwmrm.net/ad/g/1[globalParams];hb_pb_cat_dur=10.00_400_15s&hb_pb_cat_dur=15.00_402_30s&hb_cacheid=123;[ParamsForSlot1];[ParamsForSlot2];...;[ParamsForSlotN]; ``` - ## Further Reading -[Prebid.js](http://prebid.org/dev-docs/getting-started.html) -[Prebid Video](http://prebid.org/prebid-video/video-overview.html) -[Category Translation](/dev-docs/modules/categoryTranslation.html) +- [Prebid.js for Developers](/dev-docs/getting-started.html) +- [Prebid Video](/prebid-video/video-overview.html) +- [Category Translation](/dev-docs/modules/categoryTranslation.html) diff --git a/dev-docs/modules/gdprEnforcement.md b/dev-docs/modules/gdprEnforcement.md index 2afd260ac9..27906a944b 100644 --- a/dev-docs/modules/gdprEnforcement.md +++ b/dev-docs/modules/gdprEnforcement.md @@ -2,7 +2,7 @@ layout: page_v2 page_type: module title: GDPR Enforcement Module -description: If you have users in Europe, you'll want this module that enforces GDPR consent +description: If you have users in Europe, you can use this module to enable actions for processing under the GDPR and ePrivacy module_code : gdprEnforcement display_name : GDPR Enforcement enable_download : true @@ -16,15 +16,11 @@ sidebarType : 1 * TOC {: toc } -{% capture legalNotice %} - This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and /or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. - {% endcapture %} - -{% include /alerts/alert_important.html content=legalNotice %} +{% include legal-warning.html %} {: .alert.alert-warning :} This module requires the [EU GDPR consent management module](/dev-docs/modules/consentManagement.html) (the base consent module), which reads consent values from the Consent Management Platform (CMP). The GDPR Enforcement Module -will then enforce the results. See the [base module page](/dev-docs/modules/consentManagement.html) for general background, usage, and legal disclaimers. +will then take action based on the results. See the [base module page](/dev-docs/modules/consentManagement.html) for general background, usage, and legal disclaimers. ## Overview @@ -35,19 +31,22 @@ The [base consent module](/dev-docs/modules/consentManagement.html) performs the The GDPR Enforcement Module adds the following: -3. Allows the page to define which activities should be enforced at the Prebid.js level. -4. Actively enforces those activities based on user consent data. +1. Allows the page to define which activities should be enforced at the Prebid.js level. +2. Actively enforces those activities based on user consent data. The following table details the Prebid.js activities that fall under the [Transparency and Consent Framework (TCF)](https://iabeurope.eu/iab-europe-transparency-consent-framework-policies/) scope: {: .table .table-bordered .table-striped } -| In-Scope Activity | TCF Legal Basis Required | Enforcement Activity | Prebid.js Version | +| In-Scope Activity | TCF Legal Basis Required | Activity | Prebid.js Version | | --- | --- | --- | --- | | Invoke usersync pixels | Purpose 1 - Store and/or access information on a device | May prevent one or more vendor usersyncs. | 3.14+ | | Invoke user ID modules | Purpose 1 - Store and/or access information on a device | May prevent one or more UserID modules from activating. | 3.14+ | | Read and write data to device | Purpose 1 - Store and/or access information on a device | May prevent one or more adapters or modules from being able to read or write cookies or localstorage in the user's browser. | 3.14+ | | Perform header bidding auction | Purpose 2 - Basic ads | May prevent one or more bid adapters from participating in the auction. | 4.0+ | +| Transmit user first party data to partners | Purpose 4 - Personalized ads | May prevent one or more modules from receiving user first party data | 8.16+ | +| Transmit Extended User IDs to partners | Depends on configuration (see [note](#note-transmitEids))| May prevent one or more modules from receiving user IDs and EIDs. | 8.16+ | | Invoke analytics adapters | Purpose 7 - Measurement | May prevent one or more analytics adapters from participating in the auction. | 4.x+ | +| Transmit precise geolocation data to partners | Specal Feature 1 - Use precise geolocation data | May cause geolocation data to be truncated for one or more modules | 8.16+ | ## Page Integration @@ -58,67 +57,73 @@ A page needs to define configuration rules about how Prebid.js should enforce ea {: .alert.alert-info :} To turn on Prebid.js enforcement you must: -1) Include the gdprEnforcement module in the Prebid.js build -and 2) setConfig `consentManagement.gdpr.cmp` to either 'iab' or 'static' -The following fields related to GDPR enforcement are supported in the [`consentManagement.gdpr`](/dev-docs/modules/consentManagement.html) object: +(1) Include the gdprEnforcement module in the Prebid.js build +and (2) setConfig `consentManagement.gdpr.cmpApi` to either 'iab' or 'static' + +The following fields related to GDPR enforcement are supported in the [`consentManagement`](/dev-docs/modules/consentManagement.html) object: {: .table .table-bordered .table-striped } | Param | Type | Description | Example | | --- | --- | --- | --- | | gdpr.rules | `Array of Objects` | Lets the publisher override the default behavior. | | -| gdpr.rules[].purpose | `String` | Supported values: "storage" (Purpose 1), "basicAds" (Purpose 2), "measurement" (Purpose 7) | "storage" | +| gdpr.rules[].purpose | `String` | Supported values: "storage" (Purpose 1), "basicAds" (Purpose 2), "personalizedAds" (purpose 4), "measurement" (Purpose 7), "transmitPreciseGeo" (Special Feature 1) | "storage" | | gdpr.rules[].enforcePurpose | `Boolean` | Determines whether to enforce the purpose consent. The default in Prebid.js 3.x is not to enforce purposes. Prebid.js 4.0 enforces legal basis for Purposes 1 and 2 by default. | true | | gdpr.rules[].enforceVendor | `Boolean` | Determines whether to enforce vendor signals for this purpose. The default in Prebid.js 3.x is not to enforce vendor signals. Prebid.js 4.0 enforces legal basis for Purposes 1 and 2 by default. | true | | gdpr.rules[].vendorExceptions | `Array of Strings` | Defines a list of biddercodes or module names that are exempt from the enforcement of this Purpose. | ["bidderA", "userID-module-B"] | +| gdpr.rules[].softVendorExceptions | `Array of Strings` | Defines a list of biddercodes or module names that are exempt from the enforcement of vendor signals for this purpose. Unlike with `vendorExceptions`, Purpose consent is still enforced . | ["bidderA", "userID-module-B"] | +| gdpr.rules[].eidsRequireP4Consent | `Boolean` | Only relevant on the personalizedAds `purpose`. If true, user IDs and EIDs will not be shared without evidence of consent for TCF Purpose 4. If false, evidence of consent for any of Purposes 2-10 is sufficient for sharing user IDs and EIDs. Defaults to false. See [note](#note-transmitEids) | true | +| strictStorageEnforcement | `Boolean` | If false (the default), allows some use of storage regardless of purpose 1 consent - see [note](#strictStorageEnforcement) below | true | Notes: -- To accomodate Prebid.js modules and adapters that don't have GVL IDs, the vendorExceptions list is based on Prebid.js biddercodes instead of Global Vendor List (GVL) IDs (i.e. "bidderA" instead of "12345"). -- An alternate way of establishing a GVL mapping is to define a 'gvlMapping' object: +* By default, Prebid allows some limited use of storage even when purpose 1 consent was not given: this is limited to non-PII, such as [category translation mappings](/dev-docs/modules/categoryTranslation.html), or temporary test data used to probe the browser's storage features. If `strictStorageEnforcement` is true, purpose 1 consent will always be enforced for any access to storage. +* To accomodate Prebid.js modules and adapters that don't have GVL IDs, the vendorExceptions list is based on Prebid.js biddercodes instead of Global Vendor List (GVL) IDs (i.e. "bidderA" instead of "12345"). +* An alternate way of establishing a GVL mapping is to define a 'gvlMapping' object: -``` +```javascript pbjs.setConfig({ gvlMapping: { - bidderA: 12345, + bidderA: 12345, bidderB: 67890 } }); -```` +``` ### Examples The following examples cover a range of use cases and show how Prebid.js supports configuration of different business rules. -1) Enforce device access activity and basic ads. These are the default values (in Prebid.js 4.0) if the module is included in the build. - -``` -pbjs.setConfig({ - consentManagement: { - gdpr: { - cmpApi: 'iab', // activates the enforcement module - defaultGdprScope: true, - rules: [{ // these are the default values - purpose: "storage", - enforcePurpose: true, - enforceVendor: true - },{ - purpose: "basicAds", - enforcePurpose: true, - enforceVendor: true - },{ - purpose: "measurement", - enforcePurpose: true, - enforceVendor: true - }] - } - } -}); -``` - -2) Enforce that the user consents to DeviceAccess as an activity and consider their per-vendor selection. However, idSystemA is a special case - the publisher has confirmed that this system obtains a user ID every auction and does not write to the local device. - +1. Restrict device access activity and basic ads. These are the default values (in Prebid.js 4.0) if the module is included in the build. + + ```javascript + pbjs.setConfig({ + consentManagement: { + gdpr: { + cmpApi: 'iab', // activates the enforcement module + defaultGdprScope: true, + rules: [{ // these are the default values + purpose: "storage", + enforcePurpose: true, + enforceVendor: true + },{ + purpose: "basicAds", + enforcePurpose: true, + enforceVendor: true + },{ + purpose: "measurement", + enforcePurpose: true, + enforceVendor: true + }] + } + } + }); + ``` + +2. Restrict that the user consents to DeviceAccess as an activity and consider their per-vendor selection. However, idSystemA is a special case - the publisher has confirmed that this system obtains a user ID every auction and does not write to the local device. + + ```javascript ... rules: [{ purpose: "storage", @@ -126,113 +131,112 @@ pbjs.setConfig({ enforceVendor: true, vendorExceptions: ["idSystemA"] }] + ``` -3) Enforce legal basis for both storage and basicAds, with the exception of "firstPartyBidder", which is always allowed to run an auction. Assumes the publisher has special legal basis for this entity. +3. Restrict for both storage and basicAds, with the exception of "firstPartyBidder", which is always allowed to run an auction. Assumes the publisher has special legal basis for this entity. + ```javascript ... rules: [{ purpose: "storage", enforcePurpose: true, enforceVendor: true },{ - purpose: "basicAds", - enforcePurpose: true, - enforceVendor: true, + purpose: "basicAds", + enforcePurpose: true, + enforceVendor: true, vendorExceptions: ["firstPartyBidder"] }] + ``` -4) Turn off enforcement of Purpose 1: don't enforce either the user's DeviceAccess consent or their per-vendor selection. +4. Turn off restriction of Purpose 1: don't enforce either the user's DeviceAccess consent or their per-vendor selection. + ```javascript ... rules: [{ purpose: "storage", enforcePurpose: false, enforceVendor: false }] + ``` -5) Allow the user to suppress analtyics provider A, but make an exception for analytics provider B. +5. Allow the user to suppress analtyics provider A, but make an exception for analytics provider B. + ```javascript ... rules: [{ purpose: "measurement", enforcePurpose: true, enforceVendor: true, - vendorExceptions: ["analyticsB"] + vendorExceptions: ["analyticsB"] }] + ``` ## Basic Enforcement Prebid.js does not have access to the Global Vendor List (GVL), so it implements a "basic" form of TCF 'legal basis' validation using the supplied consent string. -A goal of basic enforcement is to confirm that there's enough evidence of consent to pass data on to vendors who do have access to the GVL and can fully parse and enforce. +A goal of 'basic enforcement' is to confirm that there's enough evidence of consent to pass data on to vendors who do have access to the GVL and can fully parse and enforce. + +Evidence of consent for a particular purpose or vendor means that: + +* Prebid.js has the the user's purpose or vendor consent, or +* (for Purpose 2 only) we've confirmed the user's Legitimate Intereset (LI) Transparency is established for this purpose or vendor. Before allowing an activity tied to a TCF-protected Purpose for a given vendor, one of these scenarios must be true: -- Configuration rules enforce both consent and vendor signals and either: - - Prebid.js has the user’s purpose consent and the user’s vendor consent, or - - (for Purpose 2 only) we've confirmed the user’s Legitimate Interest (LI) Transparency is established for this purpose -- Configuration rules enforce only purpose consent and either: - - Prebid.js has the user’s purpose consent, or - - (for Purpose 2 only) we confirmed the user’s LI Transparency is established for this purpose. -- Configuration rules enforce only vendor signals and we have the user’s vendor consent -- Configuration rules enforce neither purpose consent nor vendor signal. +* Configuration rules enforce both consent and vendor signals and: + * we have evidence of consent for both, or + * we have evidence of consent for the purpose, and the vendor is excepted through `softVendorException`, or + * the vendor is excepted through `vendorExceptions`; +* Configuration rules enforce only purpose consent and either: + * we have evidence of consent for the purpose, or + * the vendor is excepted through `vendorExceptions`; +* Configuration rules enforce only vendor signals and either: + * we have evidence of consent for the vendor, or + * the vendor is excepted through either `softVendorExceptions` or `vendorExceptions`; +* Configuration rules enforce neither purpose consent nor vendor signal. See the [IAB TCF Consent String Format](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md) for details. -## Modules that Support GVL ID - -The GDPR Enforcement module requires the GVL ID for a module to be specified. If no GVL ID is found the module will be blocked by default unless it is specifically listed under `vendorExceptions`. The following modules have listed their GVL IDs. - -{% assign bidder_pages = site.pages | where: "layout", "bidder" %} - - - - - - - - - -{% for page in bidder_pages %}{% unless page.gvl_id %}{% continue %}{% endunless %} - - - - -{% endfor %} - - - - - - - - - - - - - - - - - -
      Module TypeModule
      Bid Adapter{{page.title}}
      Analytics AdapterAppNexus
      User IDID5
      User IDLotame Panorama Id
      User IDParrable ID
      + + +### Note on Extended User IDs + +{: .alert.alert-info :} +Note: the default of the eidsRequireP4Consent flag may change from false to true in a future major release. + +By default, sending user IDs and EIDs to bid adapters or RTD modules (the `transmitEids` activity) is not tied to a single TCF Purpose; instead it is allowed if one of these scenarios is true: + +* We have evidence of consent for the vendor and evidence of consent for _any_ purpose between 2 and 10; +* We have evidence of consent for any purpose between 2 and 10, and the vendor is excepted through `softVendorException` in at least one of: `basicAds`, `personalizedAds`, or `measurement`; +* The vendor is excepted through `vendorExceptions` in at least one of `basicAds`, `personalizedAds`, or `measurement`. + +This behavior can be changed to the same "basic enforcement" algorithm described above, tied to TCF Purpose 4, by setting `eidsRequireP4Consent: true` on a `personalizedAds` rule: + +```javascript + ... + rules: [{ + purpose: "personalizedAds", + eidsRequireP4Consent: true + }] +``` ## Build the Package Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). Include the base consent management module and this enforcement module as additional options on the **gulp build** command: -{% highlight bash %} +```bash gulp build --modules=consentManagement,gdprEnforcement,bidAdapter1,bidAdapter2 -{% endhighlight %} +``` You can also use the [Prebid.js Download](/download.html) page. ## Further Reading -- [EU GDPR Consent Management Module](/dev-docs/modules/consentManagement.html) -- [IAB TCF Implementation Guidelines](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/TCF-Implementation-Guidelines.md) -- [IAB TCF2 Consent String Format](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md) -- [Prebid TCF2 Support](https://docs.google.com/document/d/1fBRaodKifv1pYsWY3ia-9K96VHUjd8kKvxZlOsozm8E/edit#) -- [CMP Best Practices](/dev-docs/cmp-best-practices.html) +* [EU GDPR Consent Management Module](/dev-docs/modules/consentManagement.html) +* [IAB TCF Implementation Guidelines](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/TCF-Implementation-Guidelines.md) +* [IAB TCF2 Consent String Format](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md) +* [Prebid TCF2 Support](https://docs.google.com/document/d/1fBRaodKifv1pYsWY3ia-9K96VHUjd8kKvxZlOsozm8E/edit#) +* [CMP Best Practices](/dev-docs/cmp-best-practices.html) diff --git a/dev-docs/modules/genericAnalyticsAdapter.md b/dev-docs/modules/genericAnalyticsAdapter.md new file mode 100644 index 0000000000..8c21311c66 --- /dev/null +++ b/dev-docs/modules/genericAnalyticsAdapter.md @@ -0,0 +1,229 @@ +--- +layout: page_v2 +title: Generic analytics +description: Generic analytics adapter +module_code: genericAnalyticsAdapter +enable_download: false +--- + +## Generic analytics adapter + +### Description + +This is an analytics adapter that can interface with any backend, meant for publishers that prefer to manage their own analytics infrastructure. The simplest setup requires just a URL that will be sent all data from all Prebid events; with additional options for filtering or formatting. + +### Analytics Options + +{: .table .table-bordered .table-striped } +| Name | Scope | Type | Description | +|--------------|---------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `handler` | required unless `url` is provided | Function | Custom handler function - [example](#custom-handler) | +| `url` | required unless `handler` is provided | String | Data collection URL | +| `method` | optional | String | HTTP method used to call `url`. Defaults to `'POST'` | +| `batchSize` | optional | Number | Number of events to collect into a single call to `handler` or `url`. Defaults to `1` | +| `batchDelay` | optional | Number | Time (in milliseconds) to wait before calling `handler` or `url` with an incomplete batch (when fewer than `batchSize` events have been collected). Defaults to `100` | +| `events` | optional | Object | Map from event name to a custom format function. When provided, only events in this map will be collected, using the data returned by their corresponding function - [example](#event-formatters) | +| `gvlid` | optional | Number | Global vendor list ID to use for the purpose of GDPR purpose 7 enforcement - see [note](#gdpr) | +| `sampling` | optional | Number | Sampling rate, expressed as a number between 0 and 1. Data is collected only on this ratio of browser sessions. Defaults to `1` | + + + +### Note on GDPR enforcement + +If you are using the [GDPR enforcement module](/dev-docs/modules/gdprEnforcement.html) to enforce purpose 7, by default this module will be blocked when GDPR is in scope. +To enable it, you may either specify the `gvlid` option (if you are interfacing with a partner) or declare a `softVendorException` if you deem that vendor consent is not required for compliance: + +```javascript +pbjs.setConfig({ + consentManagement: { + gdpr: { + rules: [{ + purpose: "measurement", + enforcePurpose: true, + enforceVendor: true, + softVendorExceptions: ["generic"] + }] + } + } +}) +``` + +### Examples + +#### Send all data to given URL using single requests + +```javascript +pbjs.enableAnalytics({ + provider: 'generic', + options: { + url: 'https://example.com' + } +}) +``` + +Example request payload: + +```json +{ + "eventType": "auctionInit", + "args": { + "auctionId": "97000db4-ae78-4e93-81d1-66b83ac10a74", + "timestamp": 1666207538126, + "auctionStatus": "inProgress", + "adUnits": [ + /* ... */ + ], + "noBids": [], + "bidsReceived": [], + "bidsRejected": [], + "winningBids": [], + "timeout": 2000, + "metrics": { + /* ... */ + } + } +} +``` + +if `options.method` is set to `'GET'`, the same JSON payload is encoded into a single search parameter named `data`, e.g. `https://example.com?data=%7B%22eventType%22%3A%22auctionInit%22...` + +#### Batch multiple events together + +```javascript +pbjs.enableAnalytics({ + provider: 'generic', + options: { + url: 'https://example.com', + batchSize: 10 + } +}); +``` + +Example request payload: + +```json +[ + { + "eventType": "auctionInit", + "args": { + "auctionId": "97000db4-ae78-4e93-81d1-66b83ac10a74", + "timestamp": 1666207538126, + "auctionStatus": "inProgress", + "adUnits": [ + /* ... */ + ], + "noBids": [], + "bidsReceived": [], + "bidsRejected": [], + "winningBids": [], + "timeout": 2000, + "metrics": { + /* ... */ + } + } + }, + { + "eventType": "bidRequested", + "args": { + "bidderCode": "appnexus", + "auctionId": "db4edde6-ee66-4779-b7ed-c7295d3e3c49", + "bidderRequestId": "3cf3eaf48bd5f48", + "uniquePbsTid": "1565fd02-d4fd-4369-bf8e-0dee2a00aca5", + "bids": [ + /* ... */ + ], + "auctionStart": 1666208826440, + "timeout": 10000, + "src": "s2s", + "refererInfo": { + /* ... */ + }, + "metrics": { + /* ... */ + }, + "ortb2": { + /* ... */ + }, + "uspConsent": "1YNN", + "start": 1666208826445, + "tid": "db4edde6-ee66-4779-b7ed-c7295d3e3c49" + } + }, + /* ... */ +] +``` + + + +#### Custom formatting + +```javascript +pbjs.enableAnalytics({ + provider: 'generic', + options: { + url: 'https://example.com', + batchSize: 10, + events: { + bidRequested(request) { + return { + type: 'REQUEST', + auctionId: request.auctionId, + bidder: request.bidderCode + } + }, + bidResponse(response) { + return { + type: 'RESPONSE', + auctionId: response.auctionId, + bidder: response.bidderCode + } + } + } + } +}) +``` + +Example request payload: + +```json +[ + { + "auctionId": "e41e3fcb-6209-4995-b0be-2aed21a8bdf6", + "bidder": "appnexus", + "type": "REQUEST" + }, + { + "auctionId": "e41e3fcb-6209-4995-b0be-2aed21a8bdf6", + "bidder": "appnexus", + "type": "RESPONSE" + } + /* ... */ +] +``` + + + +#### Custom handler + +```javascript +pbjs.enableAnalytics({ + provider: 'generic', + options: { + handler(data) { + // `data` is an array of length `batchSize`. If `events` is provided, the elements are the values returned + // by the format functions defined therein; otherwise, they have the format {eventType, args}. + fetch('https://example.com', { + method: 'POST', + body: JSON.stringify({ + location: window.location.href, + data + }) + }); + } + } +}) +``` + +### See also + +[Prebid.js events](/dev-docs/publisher-api-reference/getEvents.html) diff --git a/dev-docs/modules/geoedgeRtdProvider.md b/dev-docs/modules/geoedgeRtdProvider.md index 42113e0086..6bae377267 100644 --- a/dev-docs/modules/geoedgeRtdProvider.md +++ b/dev-docs/modules/geoedgeRtdProvider.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # Geoedge Realtime Module + {:.no_toc} * TOC @@ -22,18 +23,17 @@ sidebarType : 1 The Geoedge Realtime module lets publishers block bad ads such as automatic redirects, malware, offensive creatives and landing pages. To use this module, you'll need to work with [Geoedge](https://www.geoedge.com/publishers-real-time-protection/) to get an account and cutomer key. -{: .alert.alert-warning :} -Disclosure: This module loads external code that is not open source and has not been reviewed by Prebid.org. +{% include dev-docs/loads-external-javascript.md %} ## Integration -1) Build the geoedge RTD module into the Prebid.js package with: +1. Build the geoedge RTD module into the Prebid.js package with: -``` -gulp build --modules=geoedgeRtdProvider,... -``` + ```bash + gulp build --modules=geoedgeRtdProvider,... + ``` -2) Use `setConfig` to instruct Prebid.js to initilize the geoedge module, as specified below. +2. Use `setConfig` to instruct Prebid.js to initilize the geoedge module, as specified below. ## Configuration @@ -71,15 +71,15 @@ Parameters details: ## Example To view an integration example: - -1) in your cli run: -``` -gulp serve --modules=appnexusBidAdapter,geoedgeRtdProvider -``` +1. in your cli run: -2) in your browser, navigate to: + ```bash + gulp serve --modules=appnexusBidAdapter,geoedgeRtdProvider + ``` -``` +2. in your browser, navigate to: + +```text http://localhost:9999/integrationExamples/gpt/geoedgeRtdProvider_example.html ``` diff --git a/dev-docs/modules/geolocationRtdProvider.md b/dev-docs/modules/geolocationRtdProvider.md new file mode 100644 index 0000000000..99116a1b97 --- /dev/null +++ b/dev-docs/modules/geolocationRtdProvider.md @@ -0,0 +1,72 @@ +--- +layout: page_v2 +title: Geolocation Module +display_name: Geolocation +description: Real Time Geolocation +page_type: module +module_type: rtd +module_code: geolocationRtdProvider +enable_download: true +sidebarType: 1 +--- + +# Geolocation Module + +## Overview + +The Geolocation module lets publishers get user's precise location with their permissions. The first permission that is needed is directly asked from site's navigator alert. Then if site has installed a CMP (Consent Management Platform), this module checks the geolocation permission from consent data. The module provides Geolocation coords using the [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API). + +## Integration + +1. Build the geolocation RTD module into the Prebid.js package with: + + ```bash + gulp build --modules=geolocationRtdProvider.js,... + ``` + +2. Use `setConfig` to instruct Prebid.js to initilize the geolocation module, as specified below. + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` object: + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + "name": "geolocation", + "waitForIt": true, + "params": { + "requestPermission": true + } + }] + } +}); +``` + +Parameter details: + +{: .table .table-bordered .table-striped } +|Name |Type |Description |Notes | +| :------------ | :------------ | :------------ |:------------ | +|name | String | Real time data module name |Required, always 'geolocation' | +|waitForIt | Boolean | |Required, always true | +|params | Object | | | +|params.requestPermission | Boolean | Customer permission |Required, always true | + +The Geolocation is set in ortb2Fragments.global.device.geo in requestBidsObject and looks like this: + +```javascript +{ + lat: 1, // geolocation.coords.latitude + lon: 1, // geolocation.coords.longitude + lastfix: 1, // geolocation.timestamp + type: 1 +} +``` + +This data can be accessed from a bid adapter in one of several ways: + +1. Read reqBidsConfigObj.ortb2Fragments.global.device.geo directly +2. Just merge everything in ortb2Fragments +3. Start utilizing the [ortbConverter library](https://github.com/prebid/Prebid.js/blob/master/libraries/ortbConverter/README.md) diff --git a/dev-docs/modules/goldfishAdsRtdProvider.md b/dev-docs/modules/goldfishAdsRtdProvider.md new file mode 100755 index 0000000000..e789842f51 --- /dev/null +++ b/dev-docs/modules/goldfishAdsRtdProvider.md @@ -0,0 +1,62 @@ +--- +layout: page_v2 +title: Goldfish Ads Real Time Data Provider +display_name: Goldfish Ads Real Time Data Provider +description: Goldfish Ads Real Time Data Provider +page_type: module +module_type: rtd +module_code: goldfishAdsRtdProvider +enable_download: true +vendor_specific: true +sidebarType: 1 +--- + +# Goldfish Ads Real Time Data Provider + +This RTD module provides access to the Goldfish Ads Geograph, which leverages geographic and temporal data on a privcay-first platform. This module works without using cookies, PII, emails, or device IDs across all website traffic, including unauthenticated users, and adds audience data into bid requests to increase scale and yields. + +Contact for information. + +## Integration + +1. Compile the Goldfish Ads RTD Module into your Prebid build: + + ```bash + gulp build --modules="goldfishAdsRtdProvider,..." + ``` + +2. Use `setConfig` to instruct Prebid.js to initilize the goldfishAds module, as specified below. + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` + +```javascript +var pbjs = pbjs || { que: [] } +pbjs.que.push(function () { + pbjs.setConfig({ + realTimeData: { + auctionDelay: 100, + dataProviders: [ + { + name: 'goldfishAds', + waitForIt: true, + params: { + key: 'testkey' + }, + }, + ], + }, + }) +}) +``` + +Syntax details: + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Real time data module name | Always 'goldfishAds' | +| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | +| params | Object | | | +| params.key | String | A key given by Goldfish Ads to activate your endpoint | | diff --git a/dev-docs/modules/gppControl_usnat.md b/dev-docs/modules/gppControl_usnat.md new file mode 100644 index 0000000000..b2414c5926 --- /dev/null +++ b/dev-docs/modules/gppControl_usnat.md @@ -0,0 +1,55 @@ +--- +layout: page_v2 +page_type: module +title: GPP Control - USNat +description: If your CMP populates section 7 of the Global Privacy Platform, the USNat string, this module complements the `consentManagementGpp` module to control Prebid.js accordingly. +module_code : gppControl_usnat +display_name : GPP Control - USNat +enable_download : true +recommended: true +min_js_version: 8.2.0 +sidebarType : 1 +--- + +# GPP Control Module - USNat string +{: .no_toc } + +- TOC +{: toc } + +{% include legal-warning.html %} + +## Overview + +This consent management control module is designed to support the [Global Privacy Platform](https://iabtechlab.com/gpp/) Section 7 string, USNat. For more Prebid-related background, see [Prebid MSPA Support](/features/mspa-usnat.html). In sum, the USNat string is intended to unify various state laws into a single privacy string, with participants' behavior governed by the IAB's ([MSPA](https://www.iabprivacy.com/#)). It is intended to complement, not replace, the GPP consent management module, which gathers GPP consent strings and makes them available to vendor integrations. The goal is to gather sensible and conservative [activity controls](/dev-docs/dev-docs/activity-controls.html) for elements of Prebid.js given various expressions of the [USNat consent string](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md). + +This module does not support any other GPP section id or local GPP api. For US state section see the [GPP Control - US State module](/dev-docs/modules/gppControl_usstates.html). In order to control activities in a section without a control module, publishers can express their controls directly in the syntax of the [activity control infrastructure](/dev-docs/dev-docs/activity-controls.html). If a publisher wants finer control over section 7 implications on Prebid.js behavior than this module provides (eg not invalidating certain strings), they are able to achieve that using the activity control syntax as an alternative to this module. + +{: .alert.alert-warning :} +Prebid functionality created to address regulatory requirements does not replace each party's responsibility to determine its own legal obligations and comply with all applicable laws. **We recommend consulting with your legal counsel before determining how to utilize these features in support of your overall privacy approach. This module is not yet intended to replace other consent modules; it supplements them.** + +## Page Integration + +This module activates if the `gpp` object in the consent management configuration section exists and the consentManagementGpp module exists. See that [module's documentation](/dev-docs/modules/consentManagementGpp.html) for parameter definitions. This module does **not** work with static GPP section 7 strings provided in the first-party data `regs.gpp` object, but **does** work if the `gpp.cmpApi` is set to `static` and `gpp.consentData` is appropriately populated via setConfig. + +## Build the Package + +Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the consent management module and the GPP Control - USNat module, an additional option must be added to the **gulp build** command: + +```bash +gulp build --modules=consentManagementGpp,gppContol_usnat,bidAdapter1,bidAdapter2 +``` + +You can also use the [Prebid.js Download](/download.html) page. + +## Further Reading + +- [IAB Global Privacy Platform Full Specification Repository](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform) +- [IAB Global Privacy Platform CMP API Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md) +- [IAB Global Privacy Platform USNat string Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md) +- [Prebid MSPA Support](/features/mspa-usnat.html) +- [Prebid Activity Controls](/dev-docs/dev-docs/activity-controls.html) +- [Prebid Consent Management - US Privacy Module](/dev-docs/modules/consentManagementUsp.html) +- [Prebid Consent Management - GPP Module](/dev-docs/modules/consentManagementGpp.html) +- [Prebid Consent Management - GPP Control - US States module](/dev-docs/modules/gppControl_usstates.html) +- [CMP Best Practices](https://docs.prebid.org/dev-docs/cmp-best-practices.html) diff --git a/dev-docs/modules/gppControl_usstates.md b/dev-docs/modules/gppControl_usstates.md new file mode 100644 index 0000000000..e82ba32b91 --- /dev/null +++ b/dev-docs/modules/gppControl_usstates.md @@ -0,0 +1,127 @@ +--- +layout: page_v2 +page_type: module +title: GPP Control - US States +description: If your CMP populates sections 8-12 of the Global Privacy Platform, this module complements the `consentManagementGpp` module to control Prebid.js accordingly. +module_code : gppControl_usstates +display_name : GPP Control - US States +enable_download : true +recommended: true +min_js_version: 8.10.0 +sidebarType : 1 +--- + +# GPP Control Module - US state strings +{: .no_toc } + +- TOC +{: toc } + +{% include legal-warning.html %} + +## Overview + +This consent management control module is designed to support the [Global Privacy Platform](https://iabtechlab.com/gpp/) US state strings, [GPP sections](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/Section%20Information.md) 8 through 12. +It works by translating them into an equivalent US national string as detailed in [Interpreting USNat strings](/features/mspa-usnat.html#interpreting-usnat-strings), and using it to apply the same [activity restricitons](/features/mspa-usnat.html#usnat-activity-restrictions). + +{: .alert.alert-warning :} +Prebid functionality created to address regulatory requirements does not replace each party's responsibility to determine its own legal obligations and comply with all applicable laws. **We recommend consulting with your legal counsel before determining how to utilize these features in support of your overall privacy approach. This module is not intended to replace other consent modules; it supplements them.** + +## Page Integration + +By default, including this module enables activity restrictions for GPP sections from ID 8 to 12, as long as the [consentManagementGpp](/dev-docs/modules/consentManagementGpp.html) module is also included and configured. +Optional configuration options are: + +{: .table .table-bordered .table-striped } +| Param | Type | Description | Example | +| --- | --- | --- | --- | +| gpp.mspa | `Object` | | | +| gpp.mspa.sids | `Array` | GPP SIDs that should be covered by activity restrictions. Defaults to all US state SIDs (`[8, 9, 10, 11, 12]`). This is the only value needed for normal operation. Other options are for special cases and future-proofing. | `[8, 9]` | +| gpp.mspa.sections | `Object` | Map from section ID to per-section configuration options | `{8: {name: 'usca'}}` | +| gpp.mspa.sections.name | `String` | GPP API name to use for the section. Defaults to the names given listed under [section information -> section IDs](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/Section%20Information.md#section-ids). This option would only be used if your CMP has named their sections in a non-standard way. | `uscav3` | +| gpp.mspa.sections.normalizeAs | `integer` | Normalize the flags for this section as if it were the number provided. See [example](#normalize-example). Each section defaults to its own ID. | `8` | + +### Examples + +#### Enable activity controls for certain sections only + +```javascript +pbjs.setConfig({ + consentManagement: { + gpp: { + mspa: { + sids: [8, 9] // enable only for CA and VA + } + } + } +}) +``` + +#### Non-standard GPP API names + +If the CMP has a non-standard label for a given section, the `name` parameter may be used: + +```javascript +pbjs.setConfig({ + consentManagement: { + gpp: { + mspa: { + sections: { + 8: { + name: 'uspcav1' // Use 'uspcav1' instead of 'usca' to retrieve section 8 from the CMP + } + } + } + } + } +}) +``` + +#### Select normalization rule + + + +This module provides a [normalization algorithm](/features/mspa-usnat.html#interpreting-usnat-strings) for each section from 8 to 12, which it uses to translate each section's data into its equivalent section 7 (usnat) representation. +It is possible to re-use them for other sections; this can be useful if new GPP sections are released and they happen to follow the same format as an exising one. For example, if a new US GPP SID 51 comes along that should be read from the CMP as 'uss51' and normalized the same as California's string, here's the config: + +```javascript +pbjs.setConfig({ + consentManagement: { + gpp: { + mspa: { + sids: [51], // SID for the 51st state + sections: { + 51: { + // expect the CMP to provide section 51, with API name 'uss51', and the same format as section 8 (CA) + name: 'uss51', + normalizeAs: 8 + } + } + } + } + } +}) +``` + +## Build the Package + +Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the consent management module and the GPP Control - US states module, an additional option must be added to the **gulp build** command: + +```bash +gulp build --modules=consentManagementGpp,gppContol_usstates,bidAdapter1,bidAdapter2 +``` + +You can also use the [Prebid.js Download](/download.html) page. + +## Further Reading + +- [IAB Global Privacy Platform Full Specification Repository](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform) +- [IAB Global Privacy Platform CMP API Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Core/CMP%20API%20Specification.md) +- [IAB Global Privacy Platform USNat string Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md) +- [Prebid MSPA Support](/features/mspa-usnat.html) +- [Prebid Activity Controls](/dev-docs/activity-controls.html) +- [Prebid Consent Management - US Privacy Module](/dev-docs/modules/consentManagementUsp.html) +- [Prebid Consent Management - GPP Module](/dev-docs/modules/consentManagementGpp.html) +- [Prebid Consent Management - GPP Control - USNat module](/dev-docs/modules/gppControl_usnat.html) +- [Prebid Activity Controls -- GPP control module - USNat](/dev-docs/modules/gppControl_usnat.html) +- [CMP Best Practices](https://docs.prebid.org/dev-docs/cmp-best-practices.html) diff --git a/dev-docs/modules/gpt-pre-auction.md b/dev-docs/modules/gpt-pre-auction.md index db71b18ce6..a35a8af71c 100644 --- a/dev-docs/modules/gpt-pre-auction.md +++ b/dev-docs/modules/gpt-pre-auction.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # GPT Pre-Auction Module + {:.no_toc} * TOC @@ -24,15 +25,15 @@ This module enables bidder targeting and tracking at the ad server ad slot level This module is enabled by default if it's compiled into your PBJS package. It will add the [Prebid Ad Slot and GPID](/features/pbAdSlot.html) along with the matching GAM ad unit name to each ad unit's first-party data before bid requests are sent to the adapters. * **Prebid.js Adapters** - will be able to utilize these values as: - * AdUnit.ortb2Imp.ext.gpid="/1111/home-left" - * AdUnit.ortb2Imp.ext.data.adserver.name="gam" - * AdUnit.ortb2Imp.ext.data.adserver.adslot="/1111/home" - * AdUnit.ortb2Imp.ext.data.pbadslot="/1111/home-left" + * AdUnit.ortb2Imp.ext.gpid="/1111/home-left" + * AdUnit.ortb2Imp.ext.data.adserver.name="gam" + * AdUnit.ortb2Imp.ext.data.adserver.adslot="/1111/home" + * AdUnit.ortb2Imp.ext.data.pbadslot="/1111/home-left" * **Prebid Server Adapters** - will see the OpenRTB as: - * imp[].ext.gpid - * imp[].ext.data.adserver.name - * imp[].ext.data.adserver.adslot - * imp[].ext.data.pbadslot + * imp[].ext.gpid + * imp[].ext.data.adserver.name + * imp[].ext.data.adserver.adslot + * imp[].ext.data.pbadslot {: .alert.alert-info :} The Prebid Ad Slot didn't get broad adoption, so it's likely that @@ -56,20 +57,21 @@ Optional initialization parameters: | mcmEnabled | no | boolean | Removes extra network IDs when Multiple Customer Management is active. Default is false. | true | For example: -``` + +```javascript pbjs.setConfig({ gptPreAuction: { - enabled: true, // enabled by default - useDefaultPreAuction: false, - customPreAuction: function(adUnit, adServerAdSlot) { - ... - return "customPbAdSlot"; - }, - customGptSlotMatching: function(gptSlotObj) { - ... - return true; // or false - }, - mcmEnabled: true + enabled: true, // enabled by default + useDefaultPreAuction: false, + customPreAuction: function(adUnit, adServerAdSlot) { + ... + return "customPbAdSlot"; + }, + customGptSlotMatching: function(gptSlotObj) { + ... + return true; // or false + }, + mcmEnabled: true } }); ``` @@ -78,15 +80,15 @@ pbjs.setConfig({ When this module is turned on, it uses the BEFORE_REQUEST_BIDS event to insert functionality that: -- loops through each adunit in the auction -- maps the PBJS adunit to the GPT slot using the same algorithm as setTargetingForGPTAsync including customGptSlotMatching +* loops through each adunit in the auction +* maps the PBJS adunit to the GPT slot using the same algorithm as setTargetingForGPTAsync including customGptSlotMatching ### Defining the AdServer name and adslot If GPT slot matching succeeds: -- it sets the Adunit ortb2Imp.ext.data.adserver.name to 'gam' -- it copies the resulting GPT slot name to ortb2Imp.ext.data.adserver.adslot +* it sets the Adunit ortb2Imp.ext.data.adserver.name to 'gam' +* it copies the resulting GPT slot name to ortb2Imp.ext.data.adserver.adslot ### Defining PbAdSlot and GPID @@ -107,20 +109,20 @@ Here's what the module does to define these values: 1. Otherwise, if the AdUnit.code matched one or more GAM AdSlots, use that for both PbAdSlot and GPID 1. Otherwise use the AdUnit.code for PbAdSlot. - ## Example customPbAdSlot function {: .alert.alert-info :} In PBJS 6.5 and later, we recommend using the useDefaultPreAuction flag or the customPreAuction function. The following customPbAdSlot function will work for many publishers. Assumptions: -- AdUnits have been registered with [pbjs.addAdUnits](/dev-docs/publisher-api-reference/addAdUnits.html). -- AdUnit.code is either the GPT slot name or the div-id. -- The site has unique (non-random) div-ids. + +* AdUnits have been registered with [pbjs.addAdUnits](/dev-docs/publisher-api-reference/addAdUnits.html). +* AdUnit.code is either the GPT slot name or the div-id. +* The site has unique (non-random) div-ids. If either of these isn't the case, you'll need to supply your own function. -``` +```javascript // Use adunit.ortb2Imp.ext.data.pbadslot if it exists. // compare adunit.code to find a single matching slot in GPT // if there is a single slot match, just use that slot name @@ -128,39 +130,40 @@ If either of these isn't the case, you'll need to supply your own function. pbjs.setConfig({ gptPreAuction: { - enabled: true, // enabled by default - customPbAdSlot: function(adUnitCode, adServerAdSlot) { - // get adunit object - au=pbjs.adUnits.filter(au => au.code==adUnitCode); - if (au.length==0) { - return; - } - - // use pbadslot if supplied - if (au[0].ort2bImp && au[0].ort2bImp.ext && au[0].ort2bImp.ext.data && au[0].ort2bImp.ext.data.pbadslot) { - return au[0].ort2bImp.ext.data.pbadslot; - } - - // confirm that GPT is set up - if (!(googletag && googletag.apiReady)) { - return; - } - // find all GPT slots with this name - var gptSlots = googletag.pubads().getSlots().filter(function(gpt) { - return gpt.getAdUnitPath() == adServerAdSlot; - }); - if (gptSlots.length==0) { - return; // should never happen - } - if (gptSlots.length==1) { - return adServerAdSlot; - } - // else the adunit code must be div id. append it. - return adServerAdSlot+"#"+adUnitCode; - } - }); -}; + enabled: true, // enabled by default + customPbAdSlot: function(adUnitCode, adServerAdSlot) { + // get adunit object + au=pbjs.adUnits.filter(au => au.code==adUnitCode); + if (au.length==0) { + return; + } + + // use pbadslot if supplied + if (au[0].ort2bImp && au[0].ort2bImp.ext && au[0].ort2bImp.ext.data && au[0].ort2bImp.ext.data.pbadslot) { + return au[0].ort2bImp.ext.data.pbadslot; + } + + // confirm that GPT is set up + if (!(googletag && googletag.apiReady)) { + return; + } + // find all GPT slots with this name + var gptSlots = googletag.pubads().getSlots().filter(function(gpt) { + return gpt.getAdUnitPath() == adServerAdSlot; + }); + if (gptSlots.length==0) { + return; // should never happen + } + if (gptSlots.length==1) { + return adServerAdSlot; + } + // else the adunit code must be div id. append it. + return adServerAdSlot+"#"+adUnitCode; + } + } +}); ``` # Further Reading -- [Prebid Ad Slot and GPID](/features/pbAdSlot.html) + +* [Prebid Ad Slot and GPID](/features/pbAdSlot.html) diff --git a/dev-docs/modules/greenbidsRtdProvider.md b/dev-docs/modules/greenbidsRtdProvider.md new file mode 100644 index 0000000000..c45bbbec54 --- /dev/null +++ b/dev-docs/modules/greenbidsRtdProvider.md @@ -0,0 +1,73 @@ +--- +layout: page_v2 +title: Greenbids Realtime Module +display_name: Greenbids Realtime Module +description: The Greenbids RTD adapter allows to dynamically filter calls to SSP to reduce outgoing call to the programmatics chain, reducing ad serving carbon impact +page_type: module +module_type: rtd +module_code : greenbidsRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Greenbids Realtime Module + +{:.no_toc} + +* TOC +{:toc} + +## Overview + +The Greenbids RTD adapter allows to dynamically filter calls to SSP to reduce outgoing call to the programmatics chain, reducing ad serving carbon impact + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` object. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `name` | required | Real time data module name | `'greenbidsRtdProvider'` | `string` | +| `waitForIt` | required (mandatory true value) | Tells prebid auction to wait for the result of this module | `'true'` | `boolean` | +| `params` | required | | | `Object` | +| `params.pbuid` | required | The client site id provided by Greenbids. | `'TEST_FROM_GREENBIDS'` | `string` | +| `params.timeout` | optional (default 200) | Maximum amount of milliseconds allowed for module to finish working (has to be <= to the realTimeData.auctionDelay property) | `200` | `number` | + +### Example + +```javascript +const greenbidsDataProvider = { + name: 'greenbidsRtdProvider', + waitForIt: true, + params: { + pbuid: 'TEST_FROM_GREENBIDS', + timeout: 200 + } +}; +pbjs.setConfig({ + realTimeData: { + auctionDelay: 200, + dataProviders: [greenbidsDataProvider] + } +}); +``` + +## Integration + +To install the module, follow these instructions: + +### Step 1: Contact Greenbids to get a pbuid and account + +### Step 2: Integrate the Greenbids Analytics Adapter (see prebid Analytics modules) + +### Step 3: Prepare the base Prebid file + +* Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Greenbids Realtime Module* module + +* Option 2: From the command line, run `gulp build --modules=greenbidsRtdProvider,...` + +### Step 4: Set configuration + +Enable Greenbids Real Time Module using `pbjs.setConfig`. Example is provided in Configuration section. diff --git a/dev-docs/modules/growthCodeRtdProvider.md b/dev-docs/modules/growthCodeRtdProvider.md new file mode 100644 index 0000000000..161f654780 --- /dev/null +++ b/dev-docs/modules/growthCodeRtdProvider.md @@ -0,0 +1,64 @@ +--- +layout: page_v2 +title: GrowthCode Real-time Data Submodule +display_name: GrowthCode Real-time Data Submodule +description: GrowthCode Real-time Data Submodule +page_type: module +module_type: rtd +module_code : growthCodeRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# GrowthCode Real-time Data Submodule + +{:.no_toc} + +* TOC +{:toc} + +The [GrowthCode](https://growthcode.io) real-time data module in Prebid enables publishers to fully +leverage the potential of their first-party audiences and contextual data. +With an integrated cookieless GrowthCode identity, this module offers real-time +contextual and audience segmentation capabilities that can seamlessly +integrate into your existing Prebid deployment, making it easy to maximize +your advertising strategies. + +## Building Prebid with GrowthCode Support + +Compile the GrowthCode RTD module into your Prebid build: + +`gulp build --modules=userId,rtdModule,growthCodeRtdProvider,appnexusBidAdapter` + +Please visit [growthcode.io](https://growthcode.io) for more information. + +```javascript +pbjs.setConfig({ + // ... + realTimeData: { + auctionDelay: 200, + dataProviders: [ + { + name: 'growthCodeRtd', + waitForIt: true, + params: { + pid: 'TEST01', + } + } + ] + } + // ... +}); +``` + +### Parameter Descriptions for the GrowthCode Configuration Section + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Notes | +|:---------------------------------|:--------|:--------------------------------------------------------------------------|:----------------------------| +| name | String | Real time data module name | Always 'growthCodeRtd' | +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| params | Object | | | +| params.pid | String | This is the Parter ID value obtained from GrowthCode | `TEST01` | +| params.url | String | Custom URL for server | Optional | diff --git a/dev-docs/modules/hadronRtdProvider.md b/dev-docs/modules/hadronRtdProvider.md index dd7afdd3ae..7e54c02e89 100644 --- a/dev-docs/modules/hadronRtdProvider.md +++ b/dev-docs/modules/hadronRtdProvider.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # Audigent Hadron Real-time Data Submodule + {:.no_toc} * TOC @@ -32,10 +33,9 @@ Users, devices, content, cohorts and other features are identified and utilized to augment every bid request with targeted, first-party data-derived segments before being submitted to supply-side platforms. Enriching the bid request with robust first-party audience and contextual data, Audigent's Hadron RTD module -helps optimize targeting and header-bidding performance. For more information, +helps optimize targeting and header-bidding performance. For more information, please visit https://audigent.com or contact our Prebid integration team at -prebid@audigent.com. - +. ## Publisher Usage @@ -47,12 +47,12 @@ Add the Hadron RTD provider to your Prebid config. In this example we will confi publisher 1234 to retrieve segments from Audigent. See the "Parameter Descriptions" below for more detailed information of the configuration parameters. Please work with your Audigent Prebid support team -(prebid@audigent.com) on which version of Prebid.js supports different bidder +() on which version of Prebid.js supports different bidder and segment configurations. -``` -pbjs.setConfig( - ... +```javascript +pbjs.setConfig({ + // ... realTimeData: { auctionDelay: auctionDelay, dataProviders: [ @@ -61,15 +61,13 @@ pbjs.setConfig( waitForIt: true, params: { segmentCache: false, - requestParams: { - publisherId: 1234 - } + partnerId: 1234 } } ] } - ... -} + // ... +}); ``` **Config Syntax details:** @@ -82,7 +80,7 @@ pbjs.setConfig( | params | Object | | | | params.handleRtd | Function | A passable RTD handler that allows custom adunit and ortb2 logic to be configured. The function signature is (bidConfig, rtd, rtdConfig, pbConfig) => {}. | Optional | | params.segmentCache | Boolean | This parameter tells the Hadron RTD module to attempt reading segments from a local storage cache instead of always requesting them from the Audigent server. | Optional. Defaults to false. | -| params.requestParams | Object | Publisher partner specific configuration options, such as optional publisher id and other segment query related metadata to be submitted to Audigent's backend with each request. Contact prebid@audigent.com for more information. | Optional | +| params.partnerId | Number | This is the Audigent Partner ID obtained from Audigent. | Required | | params.hadronIdUrl | String | Parameter to specify alternate hadronid endpoint url. | Optional | ## Publisher Customized RTD Handling @@ -96,9 +94,9 @@ optional handleRtd parameter and provide your custom RTD handling logic there. Please see the following example, which provides a function to modify bids for a bid adapter called adBuzz and perform custom logic on bidder parameters. -``` -pbjs.setConfig( - ... +```javascript +pbjs.setConfig({ + // ... realTimeData: { auctionDelay: auctionDelay, dataProviders: [ @@ -119,20 +117,18 @@ pbjs.setConfig( } }, segmentCache: false, - requestParams: { - publisherId: 1234 - } + partnerId: 1234 } } ] } - ... -} + // ... +}); ``` The handleRtd function can also be used to configure custom ortb2 data processing. Please see the examples available in the hadronRtdProvider_spec.js -tests and work with your Audigent Prebid integration team (prebid@audigent.com) +tests and work with your Audigent Prebid integration team () on how to best configure your own Hadron RTD & Open RTB data handlers. ## Testing @@ -144,7 +140,3 @@ To view an example of available segments returned by Audigent's backends: and then point your browser at: `http://localhost:9999/integrationExamples/gpt/hadronRtdProvider_example.html` - - - - diff --git a/dev-docs/modules/haloRtdProvider.md b/dev-docs/modules/haloRtdProvider.md index 3728bb185d..f1811a6e29 100644 --- a/dev-docs/modules/haloRtdProvider.md +++ b/dev-docs/modules/haloRtdProvider.md @@ -12,8 +12,9 @@ sidebarType : 1 --- # Audigent Halo Real-time Data Submodule + Audigent Halo has been rebranded as Audigent Hadron. Please review the updated -docs here: +docs here: [Audigent Hadron Real-time Data Submodule](/dev-docs/modules/hadronRtdProvider.html) diff --git a/dev-docs/modules/iasRtdProvider.md b/dev-docs/modules/iasRtdProvider.md index 99dae5c16a..39ea54a48a 100644 --- a/dev-docs/modules/iasRtdProvider.md +++ b/dev-docs/modules/iasRtdProvider.md @@ -19,13 +19,13 @@ Integral Ad Science(IAS) Real Time Data Module. Please contact [Integral Ad Scie ## Integration -1) Compile Integral Ad Science(IAS) RTD Provider into your Prebid build: +1. Compile Integral Ad Science(IAS) RTD Provider into your Prebid build: -``` -`gulp build --modules=iasBidAdapter,iasRtdProvider`... -``` + ```bash + gulp build --modules=iasBidAdapter,iasRtdProvider + ``` -2) Use `setConfig` to instruct Prebid.js to initialize the IAS module, as specified below. +2. Use `setConfig` to instruct Prebid.js to initialize the IAS module, as specified below. ## Configuration @@ -34,19 +34,27 @@ This module is configured as part of the `realTimeData.dataProviders` object. Configuration example for using RTD module with the `ias` provider: ```javascript - pbjs.setConfig({ - realTimeData: { - dataProviders: [ - { - name: 'ias', - waitForIt: true, - params: { - pubId: '1234', +pbjs.setConfig({ + realTimeData: { + dataProviders: [ + { + name: 'ias', + waitForIt: true, + params: { + pubId: '1234', + keyMappings: { + 'id': 'ias_id' + }, + pageUrl: 'https://integralads.com/test', + adUnitPath: { + 'one-div-id': '/012345/ad/unit/path' } } - ] - } -``` + } + ] + } +}); +``` Parameters details: @@ -54,3 +62,6 @@ Parameters details: | Name | Type | Scope | Description | | :------------ | :------------ | :------- | :------- | | pubId | string | required | IAS publisher ID | +| keyMappings | object | optional | map from the default IAS key-value ids to any necessary custom key-value id | +| pageUrl | string | optional | URL of the external page (e.g. when prebid is called from inside an iframe) that IAS needs to classify | +| adUnitPath | object | optional | map from the ad slot ids to their ad unit paths | diff --git a/dev-docs/modules/idLibrary.md b/dev-docs/modules/idLibrary.md index 5874353f8e..f30dfa34ef 100644 --- a/dev-docs/modules/idLibrary.md +++ b/dev-docs/modules/idLibrary.md @@ -3,7 +3,7 @@ layout: page_v2 page_type: module title: ID Import Library description: Retrieve user ids deployed on your site, and return them to a configurable endpoint for ID Graphing. -module_code : currency +module_code : idImportLibrary display_name : ID Import Library enable_download : true sidebarType : 1 @@ -13,9 +13,10 @@ Maintainer: eng-dmp@magnite.com # ID Import Library + {:.no_toc} -The ID Import Library module gathers and generates a map of identities present on the page. The primary usecase for this adapter is for Publishers who have included multiple UserId subadapters in their prebid.js implementation, and want to store the resulting user ids serverside for modeling or graphing purposes. The ID Library module, anchors the response of `refreshUserIds()` to a persistant identifier (md5 encrypted) and returns an map of uids. This map of uids comes in the form of a POST message in JSON format and must be output to a publisher configured endpoint. +The ID Import Library module gathers and generates a map of identities present on the page. The primary usecase for this adapter is for Publishers who have included multiple UserId subadapters in their prebid.js implementation, and want to store the resulting user ids serverside for modeling or graphing purposes. The ID Library module, anchors the response of `refreshUserIds()` to a persistant identifier (md5 encrypted) and returns an map of uids. This map of uids comes in the form of a POST message in JSON format and must be output to a publisher configured endpoint. The module attempts to extract a persistant identifier in the following ways: @@ -28,7 +29,6 @@ To get started, add the module to your Prebid.js wrapper. From the command line: {: .alert.alert-info :} gulp build --modules=idImportLibrary - ## Application Flow In the idLibrary module, the persistant id is fetched from the page and synced with the user ids as follows: @@ -39,11 +39,10 @@ In the idLibrary module, the persistant id is fetched from the page and synced w 1. Otherwise if no valid value is found, add a listener on the element 1. Once the listener finds a valid value, go on to step 5. 1. Else, scan the values of all text and email input elements on the page. If one of them has a valid persistent ID value, we found it. Go on to step 5. -1. Else, scan the whole body tag for a valid persistent ID value. If one is found go on to step 5. This step is off by default, as it can lead to false postives. For example if a publisher has embedded customerservice@acme.com this value would be captured by the full body scan and anchored to the user id values present on the page. Turning on this feature should be done with care. +1. Else, scan the whole body tag for a valid persistent ID value. If one is found go on to step 5. This step is off by default, as it can lead to false postives. For example if a publisher has embedded this value would be captured by the full body scan and anchored to the user id values present on the page. Turning on this feature should be done with care. 1. If a valid persistent ID value has been found, then MD5 hash it, combine it with user IDs from the user ID module and POST to the specified endpoint. - -## Configuration: +## Configuration {: .table .table-bordered .table-striped } | Param | Required | Description | @@ -62,7 +61,7 @@ Please note, A full scan (Step 4 above) of the body element is configured on by idImportLibrary:{ url: 'url', target: 'username', - debounce: 250 + debounce: 250 } }); ``` @@ -80,15 +79,15 @@ After the data is collected, it will be POSTed to the configured URL in this for ```json { - "hid":"5dd72a98c8146bafa84313fc15eb27c2", - "uids": - { - "id5id":"ID5-ZHMOQ7afBOa_gZxzTSelo5KFcVwCQgM7d-BUkWtjAA", - "sharedid": - { - "id":"01EE77EKRHXEZVJYMSQVRJ9536", - "third":"01EE77EKRHXEZVJYMSQVRJ9536" - } - } + "hid":"5dd72a98c8146bafa84313fc15eb27c2", + "uids": + { + "id5id":"ID5-ZHMOQ7afBOa_gZxzTSelo5KFcVwCQgM7d-BUkWtjAA", + "sharedid": + { + "id":"01EE77EKRHXEZVJYMSQVRJ9536", + "third":"01EE77EKRHXEZVJYMSQVRJ9536" + } + } } ``` diff --git a/dev-docs/modules/idWardRtdProvider.md b/dev-docs/modules/idWardRtdProvider.md new file mode 100644 index 0000000000..642ae36ddd --- /dev/null +++ b/dev-docs/modules/idWardRtdProvider.md @@ -0,0 +1,67 @@ +--- +layout: page_v2 +title: ID Ward Real Time Data Provider Module +display_name: ID Ward Real Time Data Provider Module +description: ID Ward Real Time Data Provider Module +page_type: module +module_type: rtd +module_code : idWardRtdProvider +enable_download : false +vendor_specific: true +sidebarType : 1 +--- + +> **Warning!** +> +> The **idWardRtdProvider** module has been renamed to [anonymisedRtdProvider](/dev-docs/modules/anonymisedRtdProvider.html) in light of the company's rebranding. +> **idWardRtdProvider** module is maintained for backward compatibility until the next major Prebid release. +> +> Please use anonymisedRtdProvider instead of idWardRtdProvider in your Prebid integration. +> + +# ID Ward Real Time Data Provider Module + +ID Ward is a data anonymization technology for privacy-preserving advertising. Publishers and advertisers are able to target and retarget custom audience segments covering 100% of consented audiences. +ID Ward’s Real-time Data Provider automatically obtains segment IDs from the ID Ward on-domain script (via `localStorage`) and passes them to the bid-stream. + +## Publisher Usage + +1. Build the idWardRtd module into the Prebid.js package with: + + ```bash + gulp build --modules=idWardRtdProvider,... + ``` + +2. Use `setConfig` to instruct Prebid.js to initilaize the idWardRtdProvider module, as specified below. + +### Configuration + +```javascript + pbjs.setConfig({ + realTimeData: { + dataProviders: [ + { + name: "idWard", + waitForIt: true, + params: { + cohortStorageKey: "cohort_ids", + segtax: , + } + } + ] + } + }); +``` + +Please note that idWardRtdProvider should be integrated into the publisher website along with the [ID Ward Pixel](https://publishers-web.id-ward.com/pixel-integration). +Please reach out to Id Ward representative() if you have any questions or need further help to integrate Prebid, idWardRtdProvider, and Id Ward Pixel + +**Config Syntax details:** + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Id Ward Rtd module name | 'idWard' always| +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| cohortStorageKey | String | the `localStorage` key, under which Id Ward Pixel stores the segment IDs | 'cohort_ids' always | +| segtax | Integer | the taxonomy for Id Ward | Getting this value is in progress, once done this will become optional | diff --git a/dev-docs/modules/imRtdProvider.md b/dev-docs/modules/imRtdProvider.md new file mode 100644 index 0000000000..0173f7974e --- /dev/null +++ b/dev-docs/modules/imRtdProvider.md @@ -0,0 +1,73 @@ +--- +layout: page_v2 +title: Intimate Merger Real time Data Provider +display_name: Intimate Merger Real-time Data Submodule +description: Intimate Merger Real-time Data Submodule +page_type: module +module_type: rtd +module_code : imRtdProvider +enable_download : true +sidebarType : 1 +--- + +# Intimate Merger Real time Data Provider + +{:.no_toc} + +* TOC +{:toc} + +This module reads segments from [Intimate Merger](https://corp.intimatemerger.com/) audience data platform and attaches them as targeting keys to bid requests. + +The audience data platform performs segmentation even in environments where 3rd party cookies are not available, but curretly only available in Japan. + +## Usage + +Add it to your Prebid.js package with: + +`gulp build --modules=rtdModule,imRtdProvider` + +## Publisher Customized RTD Handling + +The following configuration parameters are available: + +```javascript +pbjs.setConfig({ + // ... + realTimeData: { + auctionDelay: 5000, + dataProviders: [ + { + name: "im", + waitForIt: true, + params: { + cid: 5126, // Set your Intimate Merger Customer ID here for production + setGptKeyValues: true + } + } + ] + } + // ... +}): +``` + +## Parameters + +{: .table .table-bordered .table-striped } +| Param under dataProviders | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `"im"` | +| waitForIt | Optional | Boolean | Required to ensure that the auction is delayed until prefetch is complete. Defaults to false but recommended to true | `true` | +| params | Required | Object | Details of module params. | | +| params.cid | Required | Number | This is the Customer ID value obtained via Intimate Merger. | `5126` | +| params.setGptKeyValues | Optional | Boolean | This is set targeting for GPT/GAM. Default setting is true. | `true` | + +## Testing + +First, make sure to add the Intimate Merger submodule to your Prebid.js package with: + +`gulp serve --modules=rtdModule,imRtdProvider` + +and then point your browser at: + +`http://localhost:9999/integrationExamples/gpt/imRtdProvider_example.html` diff --git a/dev-docs/modules/index.md b/dev-docs/modules/index.md index 4b62546f54..952f2c0a61 100644 --- a/dev-docs/modules/index.md +++ b/dev-docs/modules/index.md @@ -10,9 +10,9 @@ sidebarType: 1 The core of Prebid.js contains only the foundational code needed for header bidding. Any functionality that could be considered an add-on is part of a module. These are the major categories: -- [Bidder adapters](/dev-docs/bidders.html) -- [Analytics adapters](/overview/analytics.html) -- Any other extensible functionality - documented on this page +* [Bidder adapters](/dev-docs/bidders.html) +* [Analytics adapters](/overview/analytics.html) +* Any other extensible functionality - documented on this page * TOC {:toc} @@ -68,6 +68,7 @@ than others. See [the realTimeData setConfig](/dev-docs/publisher-api-reference/ ## Vendor-Specific Modules + These modules may require accounts with a service provider. @@ -90,7 +91,7 @@ These modules may require accounts with a service provider. ## Further Reading -+ [Source code of all modules](https://github.com/prebid/Prebid.js/tree/master/modules) -+ [How to add a Bid Adapter](/dev-docs/bidder-adaptor.html) -+ [How to add an Analytics Adapter](/dev-docs/integrate-with-the-prebid-analytics-api.html) -+ [How to add a Real Time Data Submodule](/dev-docs/add-rtd-submodule.html) +* [Source code of all modules](https://github.com/prebid/Prebid.js/tree/master/modules) +* [How to add a Bid Adapter](/dev-docs/bidder-adaptor.html) +* [How to add an Analytics Adapter](/dev-docs/integrate-with-the-prebid-analytics-api.html) +* [How to add a Real Time Data Submodule](/dev-docs/add-rtd-submodule.html) diff --git a/dev-docs/modules/instreamTracking.md b/dev-docs/modules/instreamTracking.md index 1e2c16f128..c0bbe124ed 100644 --- a/dev-docs/modules/instreamTracking.md +++ b/dev-docs/modules/instreamTracking.md @@ -10,6 +10,7 @@ sidebarType : 1 --- # Instream Video Ads Tracking + {:.no_toc} * TOC @@ -33,51 +34,53 @@ This module uses `window.performance.getEntriesByType('resource')` to check the | `instreamTracking.pollingFreq` | Optional | Integer |The frequency of polling. Default: `500`ms | | `instreamTracking.urlPattern` | Optional | RegExp | Regex for cache url patterns, to avoid false positives. | -#### Basic Example -{% highlight js %} +### Basic Example + +```javascript pbjs.setConfig({ 'instreamTracking': { enabled: true, } }); -{% endhighlight %} +``` -#### Example with urlPattern +### Example with urlPattern While checking for URLs having `videoCacheKey`, there are chances of false positives. To avoid those cases, we can set `instreamTracking.urlPattern: /REGEX_PATTERN/`. -{% highlight js %} +```javascript pbjs.setConfig({ 'instreamTracking': { enabled: true, urlPattern: /(prebid\.adnxs\.com\/pbc\/v1\/cache\.*)|(search\.spotxchange\.com\/ad\/vast\.html\?key=\.*)/ } }); -{% endhighlight %} +``` ## Intergation To install the module, follow these instructions: -#### Step 1: Prepare the base Prebid file +### Step 1: Prepare the base Prebid file -- Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Instream Tracking* module +* Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Instream Tracking* module -- Option 2: From the command line, run `gulp build --modules=instreamTracking,...` +* Option 2: From the command line, run `gulp build --modules=instreamTracking,...` -#### Step 2: Set configuration +### Step 2: Set configuration Enable `instreamTracking` using `pbjs.setConfig` -{% highlight js %} +```javascript pbjs.setConfig({ 'instreamTracking': { enabled: true, } }); -{% endhighlight %} +``` ## Further Reading + ​ [Prebid.js for Video]({{site.baseurl}}/prebid-video/video-overview.html) [Client-side Caching of VAST XML]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html#setConfig-vast-cache) diff --git a/dev-docs/modules/intersectionRtdProvider.md b/dev-docs/modules/intersectionRtdProvider.md index a4381b8e92..a7d5d69ea0 100644 --- a/dev-docs/modules/intersectionRtdProvider.md +++ b/dev-docs/modules/intersectionRtdProvider.md @@ -11,6 +11,7 @@ sidebarType : 1 --- # Intersection Module + {:.no_toc} * TOC @@ -23,35 +24,36 @@ The Intersection module provides intersection for ad slots on the page using Implementation works like this: - 1) Build the Intersection module into the Prebid.js package with: +1. Build the Intersection module into the Prebid.js package with: -``` -gulp build --modules=intersectionRtdProvider&... -``` + ```bash + gulp build --modules=intersectionRtdProvider&... + ``` -2) Use `setConfig` to instruct the browser to obtain the intersection data +2. Use `setConfig` to instruct the browser to obtain the intersection data ## Configuration This module is configured as part of the `realTimeData.dataProviders` object: -``` - pbjs.setConfig({ - "realTimeData": { - auctionDelay: 100, - dataProviders:[{ - "name": "intersection", - "waitForIt": true - }] - } - }); +```javascript +pbjs.setConfig({ + "realTimeData": { + auctionDelay: 100, + dataProviders:[{ + "name": "intersection", + "waitForIt": true + }] + } +}); ``` ## Output For each bidder, the module adds intersection in a JSON format. Example: -``` + +```javascript { "intersection":{ 'boundingClientRect': { @@ -72,4 +74,3 @@ Example: } } ``` - diff --git a/dev-docs/modules/jwplayerRtdProvider.md b/dev-docs/modules/jwplayerRtdProvider.md index 346e354e93..dacdf35035 100644 --- a/dev-docs/modules/jwplayerRtdProvider.md +++ b/dev-docs/modules/jwplayerRtdProvider.md @@ -12,6 +12,7 @@ sidebarType : 1 --- # JW Player RTD Provider + {:.no_toc} * TOC @@ -19,74 +20,81 @@ sidebarType : 1 ## Overview -The JW Player RTD module passes contextual and performance based information about individual video impression opportunities to bid adapters in order to increase monetization. +The JW Player RTD module passes contextual and performance based information about individual video impression opportunities to bid adapters in order to increase monetization. To use this module, you'll need to work with [JW Player](https://www.jwplayer.com/video-monetization/) to get an account and discuss the best integration path. -## Implementation for Publishers: +## Implementation for Publishers -1) Compile the JW Player RTD Provider into your Prebid build: +1. Compile the JW Player RTD Provider into your Prebid build: -`gulp build --modules=jwplayerRtdProvider` + ```bash + gulp build --modules=jwplayerRtdProvider + ``` -2) Publishers must register JW Player as a Real Time Data provider by using `setConfig` to load a Prebid Config containing a `realTimeData.dataProviders` array: +2. Publishers must register JW Player as a Real Time Data provider by using `setConfig` to load a Prebid Config containing a `realTimeData.dataProviders` array: -```javascript -pbjs.setConfig({ - ..., - realTimeData: { - auctionDelay: 100, - dataProviders: [{ - name: "jwplayer", - waitForIt: true, - params: { - mediaIDs: ['abc', 'def', 'ghi', 'jkl'] + ```javascript + pbjs.setConfig({ + ..., + realTimeData: { + auctionDelay: 100, + dataProviders: [{ + name: "jwplayer", + waitForIt: true, + params: { + mediaIDs: ['abc', 'def', 'ghi', 'jkl'] + } + }] + } + }); + ``` + +3. Optionally, if you would like to prefetch the targeting information for certain media, you must include the media IDs in `params.mediaIDs`, as displayed above. You must also set `waitForIt` to `true` and make sure that a value is set to `realTimeData.auctionDelay`. + + `waitForIt` is required to ensure the auction waits for the prefetching of the relvant targeting information to complete. It signals to Prebid that you allow the module to delay the auction if necessary. + Setting an `auctionDelay` in the `realTimeData` object is required to ensure the auction waits for prefetching to complete. The `auctionDelay` is the max time in ms that the auction will wait for the requested targeting information. + + **Note:** Though prefetch is optional, we highly recommend enabling it to ensure that the targeting information is available before bids are requested. + + **Config Syntax details:** + + {: .table .table-bordered .table-striped } + | Name |Type | Description | Notes | + | :------------ | :------------ | :------------ |:------------ | + | name | String | Real time data module name | Always 'jwplayer' | + | waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | + | params | Object | | | + | params.mediaIDs | Array of Strings | Media Ids for prefetching | Optional | + | params.overrideContentId | String enum: 'always', 'whenEmpty' or 'never' | Determines when the module should update the oRTB site.content.id | Defaults to 'always' | + | params.overrideContentUrl | String enum: 'always', 'whenEmpty' or 'never' | Determines when the module should update the oRTB site.content.url | Defaults to 'whenEmpty' | + | params.overrideContentTitle | String enum: 'always', 'whenEmpty' or 'never' | Determines when the module should update the oRTB site.content.title | Defaults to 'whenEmpty' | + | params.overrideContentDescription | String enum: 'always', 'whenEmpty' or 'never' | Determines when the module should update the oRTB site.content.ext.description | Defaults to 'whenEmpty' | + +4. Include the content's media ID and/or the player's ID in the matching AdUnit's `fpd.context.data.jwTargeting` before calling `addAdUnits`: + + ```javascript + const adUnit = { + code: '/19968336/prebid_native_example_1', + ..., + ortb2Imp: { + ext: { + data: { + jwTargeting: { + // Note: the following Ids are placeholders and should be replaced with your Ids. + playerDivId: 'abcd', + mediaID: '1234' + } } - }] - } -}); -``` - -3) Optionally, if you would like to prefetch the targeting information for certain media, you must include the media IDs in `params.mediaIDs`, as displayed above. You must also set `waitForIt` to `true` and make sure that a value is set to `realTimeData.auctionDelay`. - -`waitForIt` is required to ensure the auction waits for the prefetching of the relvant targeting information to complete. It signals to Prebid that you allow the module to delay the auction if necessary. -Setting an `auctionDelay` in the `realTimeData` object is required to ensure the auction waits for prefetching to complete. The `auctionDelay` is the max time in ms that the auction will wait for the requested targeting information. - -**Note:** Though prefetch is optional, we highly recommend enabling it to ensure that the targeting information is available before bids are requested. - -**Config Syntax details:** - -{: .table .table-bordered .table-striped } -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| name | String | Real time data module name | Always 'jwplayer' | -| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | -| params | Object | | | -| params.mediaIDs | Array of Strings | Media Ids for prefetching | Optional | + } + } + }; -4) Include the content's media ID and/or the player's ID in the matching AdUnit's `fpd.context.data.jwTargeting` before calling `addAdUnits`: + pbjs.que.push(function() { + pbjs.addAdUnits([adUnit]); + pbjs.requestBids({...}); + }); + ``` -```javascript - const adUnit = { - code: '/19968336/prebid_native_example_1', - ..., - ortb2Imp: { - ext: { - data: { - jwTargeting: { - // Note: the following Ids are placeholders and should be replaced with your Ids. - playerID: 'abcd', - mediaID: '1234' - } - } - } - } - }; - - pbjs.que.push(function() { - pbjs.addAdUnits([adUnit]); - pbjs.requestBids({...}); - }); -``` **Note**: You may also include `jwTargeting` information in the prebid config's `ortb2.site.ext.data`. Information provided in the adUnit will always supersede the information in the config; use the config to set fallback information or information that applies to all adUnits. **AdUnit Syntax details:** @@ -96,40 +104,53 @@ Setting an `auctionDelay` in the `realTimeData` object is required to ensure the | :------------ | :------------ | :------------ |:------------ | | ortb2Imp.ext.data.jwTargeting | Object | | | | ortb2Imp.ext.data.jwTargeting.mediaID | String | Media Id of the content associated to the Ad Unit | Optional but highly recommended | -| ortb2Imp.ext.data.jwTargeting.playerID | String | the ID of the HTML div element used when instantiating the JW Player instance that will render the content associated with the Ad Unit | Optional but recommended. You can retrieve this ID by calling `player.id`, where player is the JW Player instance variable. | +| ortb2Imp.ext.data.jwTargeting.playerDivId | String | the ID of the HTML div element used when instantiating the JW Player instance that will render the content associated with the Ad Unit | Optional but recommended. You can retrieve this ID by calling `player.id`, where player is the JW Player instance variable. | +| ortb2Imp.ext.data.jwTargeting.playerID | String | Deprecated as of 8.40.0 - use playerDivId instead | | -## Implementation for Bid Adapters: +## Implementation for Bid Adapters This section contains guidelines for bid adapters that are working with JW Player to utilize the additional targeting. Those bidders should implement the `buildRequests` function. When it is called, the `bidRequests` param will be an array of bids. Each bidRequest for which targeting information was found will conform to the following object structure: -```json +```javascript { - adUnitCode: 'xyz', - bidId: 'abc', - ..., - ortb2: { - site: { - content: { - id: 'jw_abc123', - data: [{ - name: 'jwplayer', + adUnitCode: 'xyz', + bidId: 'abc', + ..., + ortb2: { + site: { + content: { + id: 'jw_abc123', + title: 'media title', + url: 'https:www.cdn.com/media.mp4', + data: [ + { + name: 'jwplayer.com', ext: { - segtax: 502 + segtax: 502, + cids: ['abc123'] }, - segment: [{ - id: '123' - }, { - id: '456' - }] - }] + segment: [ + { + id: '123' + }, + { + id: '456' + } + ] + } + ], + ext: { + description: 'media description' } } } + } } ``` + Each bid for which targeting information was found will have a ortb2 param conforming to the [oRTB v2 object structure](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). The `ortb2` object will contain our proprietaty targeting segments in a format compliant with the [IAB's segment taxonomy structure](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/segtax.md). The content's ID can be obtained in the `bid.ortb2.site.content.id` property path and the targeting segments can be found in `bid.ortb2.site.content.data.segment`. @@ -141,21 +162,25 @@ The content's ID can be obtained in the `bid.ortb2.site.content.id` property pat | :------------ | :------------ | :------------ |:------------ | | ortb2.site.content | Object | | | | ortb2.site.content.id | String | Unique identifier for the specific media asset | | +| ortb2.site.content.url | String | URL for the specific media asset | | +| ortb2.site.content.title | String | The title of the media content | | +| ortb2.site.content.ext.description | String | The description of the media content | | | ortb2.site.content.data | Array | Contains segment taxonomy objects | | -| ortb2.site.content.data[index].name | String | the `jwplayer` string indicating the provider name | | +| ortb2.site.content.data[index].name | String | the `jwplayer.com` string indicating the provider name | | | ortb2.site.content.data[index].ext.segtax | Integer | the `502` value is the unique identifier for JW Player's proprietary taxonomy | | +| ortb2.site.content.data[index].ext.cids | Array | List of extended content ids as defined in [oRTB's community extensions](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/extended-content-ids.md#example---content-id-and-seller-defined-context). | | | ortb2.site.content.data[index].segment | Array | Contains the segment taxonomy values as an object | | | ortb2.site.content.data[index].segment[index].id | String | String representation of the data segment value | | ## Example To view an example: - -- in the Prebid repo, run in your cli: + +* in the Prebid repo, run in your cli: `gulp serve --modules=jwplayerRtdProvider` -- in your browser, navigate to: +* in your browser, navigate to: `http://localhost:9999/integrationExamples/gpt/jwplayerRtdProvider_example.html` diff --git a/dev-docs/modules/jwplayerVideoProvider.md b/dev-docs/modules/jwplayerVideoProvider.md new file mode 100644 index 0000000000..ddcf76572a --- /dev/null +++ b/dev-docs/modules/jwplayerVideoProvider.md @@ -0,0 +1,25 @@ +--- +layout: page_v2 +page_type: module +title: Module - JW Player Video Submodule +description: Allows Prebid to integrate directly with JW Player video players. +module_code : jwplayerVideoProvider +display_name : JW Player Video Provider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# JW Player Video Provider + +The JW Player Video Provider is a submodule of the Prebid Video Module. + +The JW Player Vendor Code for the Video Module is `1`. + +For information on how to use the Video Module with JW Player please visit the [docs]({{site.github.url}}/prebid-video/video-module.html). + +## Additional Information + +- If you would like to further customize your JW Player experience, please visit our [Developer docs](https://docs.jwplayer.com/players/docs/jw8-overview). +- To sign up for a developer account: [Developer sign up](https://info.jwplayer.com/sign-up/?utm_source=developer&utm_medium=CTA). +- To learn more [about us](https://www.jwplayer.com/). diff --git a/dev-docs/modules/konduit.md b/dev-docs/modules/konduit.md index f9bb831eea..720ce52d48 100644 --- a/dev-docs/modules/konduit.md +++ b/dev-docs/modules/konduit.md @@ -11,13 +11,14 @@ sidebarType : 1 --- # Konduit Accelerate Module + {:.no_toc} The Konduit Accelerate module applies the [Konduit](https://konduitvideo.com/) video acceleration optimization to a publisher’s existing Prebid setup. This optimization provides publishers with tools to monetize previously lost revenue and drive higher fill rates on their video inventory. To install the module, follow these instructions: -### Step 1: Prepare the base Prebid file +## Step 1: Prepare the base Prebid file Build your Prebid.js package in one of two ways: @@ -26,8 +27,7 @@ Build your Prebid.js package in one of two ways: - From the command line, run `gulp build --modules=konduitWrapper,...` - -### Step 2: Implement module code on page +## Step 2: Implement module code on page - Add konduitId as config using `setConfig` prebid method (`pbjs.setConfig({ konduit: { konduitId: your_konduit_id } })`) @@ -48,14 +48,16 @@ Build your Prebid.js package in one of two ways: Konduit Accelerate module respects the Prebid `enableSendAllBids` flag and supports both ‘Send All Bids’ and ‘Use only the winning bid’ scenarios. Prebid set the `enableSendAllBids` flag to true by default and it can be explicitly disabled in Prebid config if needed. + ```javascript pbjs.setConfig({ enableSendAllBids: false }); ``` -Please refer to [Publisher API Reference (Send All Bids)](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) for more information on the Send All Bids settings. -### Step 3: Configure Google Ad Manager (GAM) +Please refer to [Publisher API Reference (Send All Bids)](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) for more information on the Send All Bids settings. + +## Step 3: Configure Google Ad Manager (GAM) In order for Konduit’s module to be completely integrated, line item creatives need to be adjusted in GAM. Please contact [support@konduit.me](mailto:support@konduit.me) for assistance. @@ -84,10 +86,9 @@ Note that the creative URL contains a few custom macros that allow Konduit platf | k_cache_key_BIDDERCODE | %%PATTERN:k_cache_key_rubicon%% | The macro is passing a cache key so that Konduit platform is able to fetch a bidder tag for processing. This macro should be used in a ‘send all bids’ mode. | Refer to the following documentation for more information on Google Ad Manager setup: -[Step By Step Guide to Google Ad Manager Setup](https://prebid.org/adops/step-by-step.html) -[Send all bids to the ad server - Ad Ops setup](https://prebid.org/adops/send-all-bids-adops.html) +[Step By Step Guide to Google Ad Manager Setup](/adops/step-by-step.html) -### Sample Code +## Sample Code We recommended using the Konduit module function call in the `bidsBackHandler` callback function. @@ -119,8 +120,8 @@ pbjs.que.push(function() { }); }); ``` -​ -## Further Reading -​ -[Getting Started Example]({{site.baseurl}}/dev-docs/getting-started.html) -[Prebid.js for Video]({{site.baseurl}}/prebid-video/video-overview.html) + +# Further Reading + +- [Getting Started Example]({{site.baseurl}}/dev-docs/getting-started.html) +- [Prebid.js for Video]({{site.baseurl}}/prebid-video/video-overview.html) diff --git a/dev-docs/modules/mass.md b/dev-docs/modules/mass.md index cdacac886a..6515d3e2d8 100644 --- a/dev-docs/modules/mass.md +++ b/dev-docs/modules/mass.md @@ -10,6 +10,7 @@ sidebarType : 1 --- # MASS Module + {:.no_toc} * TOC @@ -17,20 +18,22 @@ sidebarType : 1 ## Overview +{: .alert.alert-warning :} +This module does not exist in PBJS 8.0 or later. + This module enables the MASS protocol for Prebid. To use it, you'll need to work with a MASS enabled provider. -This module scans incoming bids for the presence of a "mass" flag being set to -true in the bid meta or a publisher specified DealID pattern and uses +This module scans incoming bids for the presence of a "mass" flag being set to +true in the bid meta or a publisher specified DealID pattern and uses external resources to decypher and process the MASS:// URI found within the ad markup. This modules is designed to work with MASS enabled Exchanges and DSP's. -This module only loads external JavaScript resources if the publisher ad server has -selected a MASS enabled bid as a winner. - -Find out more [here](https://massplatform.net). +This module only loads external JavaScript resources if the publisher ad server has +selected a MASS enabled bid as a winner. {: .alert.alert-warning :} + ## Disclosure This module loads external JavaScript to render creatives @@ -43,11 +46,10 @@ You can specify your own `dealIdPattern` and `renderUrl` by adding one or more e Build the MASS module into the Prebid.js package with: -``` +```bash gulp build --modules=mass,... ``` - ## Module Configuration ```js @@ -71,6 +73,7 @@ pbjs.que.push(function() { ### Configuration Parameters +{: .table .table-bordered .table-striped } |Name |Type |Description |Notes | | :------------ | :------------ | :------------ |:------------ | |enabled | Boolean |Enable/disable the module |Defaults to `true` | @@ -142,43 +145,48 @@ pbjs.que.push(function() { There are two options to view the integration example: ### Option 1 - Your own development environment + To view the integration example: - -1) Build Prebid using the following required options -``` -gulp build --modules=ixBidAdapter,mass -``` +1. Build Prebid using the following required options -2) Use a http server with a valid hostname to access its content. It is not advised to run the bid simulation using localhost or 127.0.0.1 + ```bash + gulp build --modules=ixBidAdapter,mass + ``` -``` -http://hostname/integrationExamples/mass/index.html -``` +2. Use a http server with a valid hostname to access its content. It is not advised to run the bid simulation using localhost or 127.0.0.1 -### Option 2 - Hosted online -Mass Platform Limited hosts an official integration and demo page that can be accessed using the following link: https://demo.massplatform.net/ix/prebid/ + ```text + http://hostname/integrationExamples/mass/index.html + ``` ## Testing MASS -Testing requires valid bids to be returned to Prebid. To assist with this process, we recommend you use the MASS Bid Simulation tool found at https://github.com/massplatform/bidsim. Your Exchange partner might be able to assist you with other specialist tools and browser plugins to achieve similar resuls. -The instructions below assume that you have followed the installation instructions for the MASS Bidsim tool found at https://github.com/massplatform/bidsim/blob/master/README.md. +Testing requires valid bids to be returned to Prebid. To assist with this process, we recommend you use the MASS Bid Simulation tool found at . Your Exchange partner might be able to assist you with other specialist tools and browser plugins to achieve similar resuls. + +The instructions below assume that you have followed the installation instructions for the MASS Bidsim tool found at . ### Testing using MASS compliant tags + The bidsim tool ships with working DSP example tags that can be found under the bidsim/tags folder. A quick way to test the Integration test page in combination with the official bootloader is to use the following command: -``` + +```bash node bidsim --inject --bid 2000 --width 300 --height 250 --dealid 'MASS' --tag "tags/inskin-housead-desktop.js" -o https://demo.massplatform.net/ix/prebid ``` + ### For third-party technology companies + Third-parties that wish to integrate with the official MASS bootloader can get started by running the following command: -``` + +```bash node bidsim --inject --bid 2000 --width 300 --height 250 --dealid 'MASS' --tag "tags/test.js" -o https://demo.massplatform.net/ix/prebid ``` -Explanation: The tags/test.js tag calls a reference endpoint for developers that can be accessed here: https://demo.massplatform.net/reference/endpoint.js. +Explanation: The tags/test.js tag calls a reference endpoint for developers that can be accessed here: . When running the above command to invoke this reference endpoint, you will see all the params that MASS collected and passed onto your endpoint. This includes inputs, parsed inputs, tag parameters and MASS/Provider specific configurations. ### Testing on live sites + Any sites that have been MASS configured will work with the Bidsim tool. This is a convenient way to test whether your publisher ad server and slot is correctly configured. diff --git a/dev-docs/modules/mediafilterRtdProvider.md b/dev-docs/modules/mediafilterRtdProvider.md new file mode 100644 index 0000000000..3020d971f9 --- /dev/null +++ b/dev-docs/modules/mediafilterRtdProvider.md @@ -0,0 +1,49 @@ +--- +layout: page_v2 +title: The Media Trust Real-Time Ad Defense +display_name: The Media Trust Real-Time Ad Defense +description: Stop malware, redirects, scams, offensive ad content, heavy ads, and more from ruining your audience's experience. +page_type: module +module_type: rtd +module_code : mediafilterRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# The Media Trust Real-Time Ad Defense + +## Overview + +As malvertising, scams, and controversial and offensive ad content proliferate across the digital media ecosystem, publishers need advanced controls to both shield audiences from malware attacks and ensure quality site experience. Via a speedy script, The Media Trust empowers publisher Ad/Revenue Operations teams to block malware, high-risk ad platforms, heavy ads, ads with sensitive or objectionable content, and custom lists (e.g., competitors)—all in real-time. Customizable replacement code calls for a new ad to ensure impressions are still monetized. + +{: .alert.alert-warning :} +To start using this module, please contact [The Media Trust](https://mediatrust.com/how-we-help/media-filter/) to get a script and configuration hash for module configuration. + +## Integration + +1. Build Prebid bundle with The Media Filter module included. + + ```bash + gulp build --modules=mediafilterRtdProvider + ``` + +2. Include the bundled script in your application. + +## Configuration + +Add configuration entry to `realTimeData.dataProviders` for The Media Filter module. + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: 'mediafilter', + params: { + // Replace with the configuration hash provided by your sales rep + configurationHash: '' + } + }] + } +}); +``` diff --git a/dev-docs/modules/medianetRtdProvider.md b/dev-docs/modules/medianetRtdProvider.md index fac7f1cf1c..2576d8af7a 100644 --- a/dev-docs/modules/medianetRtdProvider.md +++ b/dev-docs/modules/medianetRtdProvider.md @@ -12,9 +12,10 @@ sidebarType : 1 --- # Media.net Realtime Module + {:.no_toc} -* TOC +* TOC {:toc} ## Overview @@ -25,8 +26,7 @@ The module currently provisions Media.net's Intelligent Refresh configured by th Intelligent Refresh (IR) module lets publisher refresh their ad inventory without affecting page experience of visitors through configured criteria. The module optionally provides tracking of refresh inventory and appropriate targeting in GAM. Publisher configured criteria is fetched via an external JS payload. -{: .alert.alert-warning :} -Disclosure: This module loads external code that is not open source and has not been reviewed by Prebid.org. +{% include dev-docs/loads-external-javascript.md %} ## Configuration @@ -35,11 +35,11 @@ This module is configured as part of the `realTimeData.dataProviders` object. {: .table .table-bordered .table-striped } | Name | Scope | Description | Example | Type | |------------|----------|----------------------------------------|---------------|----------| -| `name ` | required | Real time data module name | `'medianet'` | `string` | +| `name` | required | Real time data module name | `'medianet'` | `string` | | `params` | required | | | `Object` | | `params.cid` | required | The customer id is provided by Media.net. | `'8CUX0H51C'` | `string` | -#### Basic Example +### Basic Example ```javascript pbjs.setConfig({ @@ -89,15 +89,16 @@ var targeting = { ``` ## Integration + To install the module, follow these instructions: -#### Step 1: Prepare the base Prebid file +### Step 1: Prepare the base Prebid file -- Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Media.net Realtime Module* module +* Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Media.net Realtime Module* module -- Option 2: From the command line, run `gulp build --modules=medianetRtdProvider,...` +* Option 2: From the command line, run `gulp build --modules=medianetRtdProvider,...` -#### Step 2: Set configuration +### Step 2: Set configuration Enable Media.net Real Time Module using `pbjs.setConfig` @@ -113,4 +114,3 @@ pbjs.setConfig({ } }); ``` - diff --git a/dev-docs/modules/mgidRtdProvider.md b/dev-docs/modules/mgidRtdProvider.md new file mode 100644 index 0000000000..547de867f8 --- /dev/null +++ b/dev-docs/modules/mgidRtdProvider.md @@ -0,0 +1,64 @@ +--- +layout: page_v2 +title: Mgid Realtime Module +display_name: Mgid Realtime Module +description: Mgid RTD module allows you to enrich bid data with contextual and audience signals, based on IAB taxonomies. +page_type: module +module_type: rtd +module_code : mgidRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Mgid Realtime Module + +{:.no_toc} + +* TOC +{:toc} + +## Overview + +Mgid RTD module allows you to enrich bid data with contextual and audience signals, based on IAB taxonomies. + +## Configuration + +This module is configured as part of the `realTimeData.dataProviders` object. + +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `name` | required | Real time data module name | `'mgid'` | `string` | +| `params` | required | | | `Object` | +| `params.clientSiteId` | required | The client site id provided by Mgid. | `'123456'` | `string` | +| `params.timeout` | optional | Maximum amount of milliseconds allowed for module to finish working | `1000` | `number` | + +### Example + +```javascript +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: 'mgid', + params: { + clientSiteId: '123456' + } + }] + } +}); +``` + +## Integration + +To install the module, follow these instructions: + +### Step 1: Prepare the base Prebid file + +* Option 1: Use Prebid [Download](/download.html) page to build the prebid package. Ensure that you do check *Mgid Realtime Module* module + +* Option 2: From the command line, run `gulp build --modules=mgidRtdProvider,...` + +### Step 2: Set configuration + +Enable Mgid Real Time Module using `pbjs.setConfig`. Example is provided in Configuration section. diff --git a/dev-docs/modules/multibid.md b/dev-docs/modules/multibid.md index e9ae46f0cc..8a463451ef 100644 --- a/dev-docs/modules/multibid.md +++ b/dev-docs/modules/multibid.md @@ -10,6 +10,7 @@ sidebarType : 1 --- # MultiBid Module + {:.no_toc} * TOC @@ -25,31 +26,31 @@ highest bid will be considered for sending to the ad server. ## Use Cases -- Allows a bidder to provide bids on both outstream and banner. -- Supports the ability of one bidder to provide multiple video bids for the fallback scenario. -- Allows some bids to be blocked in ad server targeting logic while allowing other bids from the same bidder to be considered. +* Allows a bidder to provide bids on both outstream and banner. +* Supports the ability of one bidder to provide multiple video bids for the fallback scenario. +* Allows some bids to be blocked in ad server targeting logic while allowing other bids from the same bidder to be considered. There are two specific actions enabled by this module: -1) It tells bidders how many bids will be considered. If [useBidCache](https://docs.prebid.org/dev-docs/publisher-api-reference.html#setConfig-Use-Bid-Cache) is on, more than one bid response per adapter can be registered. (Note that this is the case even without this module, but bid adapters might not know they can supply extra bids without the `multibid` config.) +1. It tells bidders how many bids will be considered. If [useBidCache](https://docs.prebid.org/dev-docs/publisher-api-reference.html#setConfig-Use-Bid-Cache) is on, more than one bid response per adapter can be registered. (Note that this is the case even without this module, but bid adapters might not know they can supply extra bids without the `multibid` config.) -2) It expands the number of ad server targeting values that can go to the ad server. +2. It expands the number of ad server targeting values that can go to the ad server. Here's an example configuration: -``` +```javascript pbjs.setConfig({ multibid: [{ bidder: "bidderA", // bidderA can supply up to two bids maxBids: 2, - // the second bid will go to the ad server as hb_pb_bidA2 + // the second bid will go to the ad server as hb_pb_bidA2 targetBiddercodePrefix: "bidA" },{ bidder: "bidderB", // bidderB can supply up to three bids maxBids: 3, - // additional bids will be passed as hb_pb_bidB2 and hb_pb_bidB3 + // additional bids will be passed as hb_pb_bidB2 and hb_pb_bidB3 targetBiddercodePrefix: "bidB" },{ bidders: ["bidderC","bidderD"] @@ -80,7 +81,7 @@ become subject to the `maxBids` limit. The MultiBid module is not included with Prebid.js by default. To get this behavior, you must include the module in the build: -``` +```bash gulp build --modules=multibid,exampleBidAdapter ``` @@ -89,10 +90,9 @@ gulp build --modules=multibid,exampleBidAdapter Publishers don't need to set up more line items in the ad server unless they want to optimize a scenario where the primary bid might not match special targeting. Example scenarios include: -- The publisher has set up special blocking on header bidding line items. For example: hb_adomin_bidderA not in "advA, advB, advC". In this case, the primary bid may be skipped over, so creating line items for the secondary bids could make sense. -- There's ad targeting logic that could exclude outstream bids on certain ad units for certain bidders. For example: AdUnit="abc" and hb_format_bidderA not in "video". In this case, the bidder can return a banner bid as well as video. -- The ad server supports video fallbacks, in which case multiple video bids from the same bidder can be part of the fallback list. - +* The publisher has set up special blocking on header bidding line items. For example: hb_adomin_bidderA not in "advA, advB, advC". In this case, the primary bid may be skipped over, so creating line items for the secondary bids could make sense. +* There's ad targeting logic that could exclude outstream bids on certain ad units for certain bidders. For example: AdUnit="abc" and hb_format_bidderA not in "video". In this case, the bidder can return a banner bid as well as video. +* The ad server supports video fallbacks, in which case multiple video bids from the same bidder can be part of the fallback list. ## Bid Adapter Interface @@ -104,4 +104,4 @@ array returned from the `interpretResponse` function. ## Related Topics -- [MultiBid in the Prebid Server /openrtb2/auction endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#multibid-pbs-java-only) +* [MultiBid in the Prebid Server /openrtb2/auction endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#multibid) diff --git a/dev-docs/modules/nativeRendering.md b/dev-docs/modules/nativeRendering.md new file mode 100644 index 0000000000..c597a3552c --- /dev/null +++ b/dev-docs/modules/nativeRendering.md @@ -0,0 +1,22 @@ +--- +layout: page_v2 +page_type: module +title: Module - Native rendering +description: Render native bids with renderAd or dynamic creatives +module_code : nativeRendering +display_name : Native Rendering +enable_download : true +sidebarType : 1 +--- + +# Native rendering module + +This module enables rendering of native ads through [pbjs.renderAd](/dev-docs/publisher-api-reference/renderAd.html) or [dynamic creatives](/adops/js-dynamic-creative.html). + +There's no configuration necessary except for installing the module; once included, you may use those rendering methods for native bids. If _not_ included, rendering native ads is only supported through [Prebid Universal Creative](/overview/prebid-universal-creative.html). + +## Further reading + +- [renderAd reference](/dev-docs/publisher-api-reference/renderAd.html) +- [Prebid.js dynamic creatives](/adops/js-dynamic-creative.html) +- [Prebid Universal Creative](/overview/prebid-universal-creative.html) diff --git a/dev-docs/modules/neuwoRtdProvider.md b/dev-docs/modules/neuwoRtdProvider.md new file mode 100644 index 0000000000..667f469371 --- /dev/null +++ b/dev-docs/modules/neuwoRtdProvider.md @@ -0,0 +1,57 @@ +--- +layout: page_v2 +title: Neuwo Real-Time Data Module +display_name: Neuwo Real-Time Data Module +description: Enrich bids using neuwo.ai +page_type: module +module_type: rtd +module_code : neuwoRtdProvider +enable_download : true +sidebarType : 1 +--- + +# Neuwo Real-Time Data Module + +## Overview + +The Neuwo AI RTD module is an advanced AI solution for real-time data processing in the field of contextual targeting and advertising. With its cutting-edge algorithms, it allows advertisers to target their audiences with the highest level of precision based on context, while also delivering a seamless user experience. + +The module provides advertisers with valuable insights and real-time contextual bidding capabilities. Whether you're a seasoned advertising professional or just starting out, Neuwo AI RTD module is the ultimate tool for contextual targeting and advertising. + +The benefit of Neuwo AI RTD module is that it provides an alternative solution for advertisers to target their audiences and deliver relevant advertisements, as the widespread use of cookies for tracking and targeting is becoming increasingly limited. + +The RTD module uses cutting-edge algorithms to process real-time data, allowing advertisers to target their audiences based on contextual information, such as segments, IAB Tiers and brand safety. The RTD module is designed to be flexible and scalable, making it an ideal solution for advertisers looking to stay ahead of the curve in the post-cookie era. + +Generate your token at: [neuwo.ai/generatetoken/] + +## Configuration + +| Name | Scope | Description | Example | Type | +|------------|----------|----------------------------------------|---------------|----------| +| `name` | required | Handle of the module used in real-time data providers; for this, use 'NeuwoRTDModule' | 'NeuwoRTDModule' | static | +| `params.publicToken` | required | Your neuwo.ai public token | `neu23-te45-idkf-44aa` (format example) | `string` | +| `params.apiUrl` | required | Your neuwo.ai API url | `https://some-api-url.neuwo.ai/a/b/c` (format example) | `string` | + +```javascript +const neuwoDataProvider = { + name: 'NeuwoRTDModule', + params: { + publicToken: '', + apiUrl: '' + } +} +pbjs.setConfig({realTimeData: { dataProviders: [ neuwoDataProvider ]}}) +``` + +## Installation + +### Step 1: Install Prebid.js + +- Option 1: Use Prebid [Download](/download.html) page to build the Prebid.js package + - Include Neuwo Real-Time Data Module + +- Option 2: Include `neuwoRtdProvider` in build: `gulp build --modules=rtdModule,neuwoRtdProvider,...` + +### Step 2: Set configuration + +Enable Neuwo Real-Time Data Module using `pbjs.setConfig` in a related Javascript context. Command example is provided in Configuration section. diff --git a/dev-docs/modules/oneKeyRtdProvider.md b/dev-docs/modules/oneKeyRtdProvider.md new file mode 100644 index 0000000000..6ab216354a --- /dev/null +++ b/dev-docs/modules/oneKeyRtdProvider.md @@ -0,0 +1,148 @@ +--- +layout: page_v2 +title: OneKey RTD Module +display_name: OneKey RTD Module +description: OneKey Real Time Data Module +page_type: module +module_type: rtd +module_code : oneKeyRtdProvider +enable_download : false +vendor_specific: true +sidebarType : 1 +--- + +# OneKey Data Provider + +{:.no_toc} + +* TOC +{:toc} + +## Overview + +The OneKey real-time data module in Prebid has been built so that publishers +can quickly and easily setup the OneKey Addressability Framework. +This module is used along with the oneKeyIdSystem to pass OneKey data to your partners. +Both modules are required. This module will pass transmission requests to your partners +while the oneKeyIdSystem will pass the oneKeyData. + +Background information: + +* [OneKey-Network/addressability-framework](https://github.com/OneKey-Network/addressability-framework) +* [OneKey-Network/OneKey-implementation](https://github.com/OneKey-Network/OneKey-implementation) + +## Implementation for Publishers + +### Integration + +1. Compile the OneKey RTD Provider and the OneKey UserID sub-module into your Prebid build. + + ```bash + gulp build --modules=rtdModule,oneKeyRtdProvider + ``` + +2. Publishers must register OneKey RTD Provider as a Real Time Data provider by using `setConfig` +to load a Prebid Config containing a `realTimeData.dataProviders` array: + + ```javascript + pbjs.setConfig({ + ..., + realTimeData: { + auctionDelay: 100, + dataProviders: [ + { + name: 'oneKey', + waitForIt: true + } + ] + } + }); + ``` + +3. Configure the OneKey RTD Provider with the bidders that are part of the OneKey community. If there is no bidders specified, the RTD provider +will share OneKey data with all adapters. + +⚠️ This module works with a User Id sub-module. Both must be configured. See the [OneKey Id Sub-Module](/dev-docs/modules/userId.html#onekey-ids--preferences). + +### Parameters + +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Real time data module name | Always 'oneKey' | +| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false | +| params | Object | | Optional | +| params.bidders | Array | List of bidders to restrict the data to. | Optional | + +## Implementation for Bidders + +### Bidder Requests + +The data will provided to the bidders using the `ortb2` object. +The following is an example of the format of the data: + +```json +"user": { + "ext": { + "paf": { + "transmission": { + "seed": { + "version": "0.1", + "transaction_ids": ["06df6992-691c-4342-bbb0-66d2a005d5b1", "d2cd0aa7-8810-478c-bd15-fb5bfa8138b8"], + "publisher": "cmp.pafdemopublisher.com", + "source": { + "domain": "cmp.pafdemopublisher.com", + "timestamp": 1649712888, + "signature": "turzZlXh9IqD5Rjwh4vWR78pKLrVsmwQrGr6fgw8TPgQVJSC8K3HvkypTV7lm3UaCi+Zzjl+9sd7Hrv87gdI8w==" + } + } + } + } + } +} +``` + +```json +"ortb2Imp": { + "ext": { + "data": { + "paf": { + "transaction_id": "52d23fed-4f50-4c17-b07a-c458143e9d09" + } + } + } +} +``` + +### Bidder Responses + +Bidders who are part of the OneKey Addressability Framework and receive OneKey +transmissions are required to return transmission responses as outlined in +[OneKey-Network/addressability-framework](https://github.com/OneKey-Network/addressability-framework). Transmission responses should be appended to bids +along with the releveant content_id using the meta.paf field. The paf-lib will +be responsible for collecting all of the transmission responses. + +Below is an example of setting a transmission response: + +```javascript +bid.meta.paf = { + content_id: "90141190-26fe-497c-acee-4d2b649c2112", + transmission: { + version: "0.1", + contents: [ + { + transaction_id: "f55a401d-e8bb-4de1-a3d2-fa95619393e8", + content_id: "90141190-26fe-497c-acee-4d2b649c2112" + } + ], + status: "success", + details: "", + receiver: "dsp1.com", + source: { + domain: "dsp1.com", + timestamp: 1639589531, + signature: "d01c6e83f14b4f057c2a2a86d320e2454fc0c60df4645518d993b5f40019d24c" + }, + children: [] + } +} +``` diff --git a/dev-docs/modules/optimeraRtdProvider.md b/dev-docs/modules/optimeraRtdProvider.md index 351febd353..8f816eab25 100644 --- a/dev-docs/modules/optimeraRtdProvider.md +++ b/dev-docs/modules/optimeraRtdProvider.md @@ -11,7 +11,7 @@ vendor_specific: true sidebarType : 1 --- -# Optimera Real Time Date Module +# Optimera Real Time Data Module # Overview @@ -19,15 +19,15 @@ Optimera Real Time Data Module. Provides targeting for ad requests from data col ## Integration -1) Compile the Optimera RTD Provider into your Prebid build: +1. Compile the Optimera RTD Provider into your Prebid build: -``` -`gulp build --modules=rtdModule,optimeraRtdProvider`... -``` + ```bash + gulp build --modules=rtdModule,optimeraRtdProvider + ``` -Note: You must include rtdModule in the build list. + Note: You must include `rtdModule` in the build list. -2) Use `setConfig` to instruct Prebid.js to initialize the optimera module, as specified below. +2. Use `setConfig` to instruct Prebid.js to initialize the optimera module, as specified below. ## Configuration @@ -36,21 +36,23 @@ This module is configured as part of the `realTimeData.dataProviders` object. Configuration example for using RTD module with the `optimeraRTD` provider: ```javascript - pbjs.setConfig({ - realTimeData: { - dataProviders: [ - { - name: 'optimeraRTD', - waitForIt: true, - params: { - clientID: '9999', - optimeraKeyName: 'optimera', - device: 'de' - } +pbjs.setConfig({ + realTimeData: { + dataProviders: [ + { + name: 'optimeraRTD', + waitForIt: true, + params: { + clientID: '9999', + optimeraKeyName: 'optimera', + device: 'de', + apiVersion: 'v0', } - ] - } -``` + } + ] + } +}) +``` ## Migration From the Optimera Bidder Adapter @@ -69,21 +71,22 @@ Contact Optimera to get assistance with the params. | clientID | string | required | Optimera Client ID | | optimeraKeyName | string | optional | GAM key name for Optimera. If migrating from the Optimera bidder adapter this will default to hb_deal_optimera and can be ommitted from the configuration. | | device | string | optional | Device type code for mobile, tablet, or desktop. Either mo, tb, de | +| apiVersion | string | optional | Optimera API Versions. Either v0, or v1. ** Note: v1 wll need to be enabled specifically for your account, otherwise use v0. ## Example To view an integration example: - -1) in your cli run: -``` -gulp serve --modules=appnexusBidAdapter,optimeraRtdProvider` -``` +1. in your cli run: -2) in your browser, navigate to: + ```bash + gulp serve --modules=appnexusBidAdapter,optimeraRtdProvider` + ``` -``` -http://localhost:9999/integrationExamples/gpt/optimeraRtdProvider_example.html -``` +2. in your browser, navigate to: + + ```text + http://localhost:9999/integrationExamples/gpt/optimeraRtdProvider_example.html + ``` You will be able to see targeting set for each ad request with the 'optimera' key name. diff --git a/dev-docs/modules/oxxionRtdProvide.md b/dev-docs/modules/oxxionRtdProvide.md new file mode 100644 index 0000000000..646160121c --- /dev/null +++ b/dev-docs/modules/oxxionRtdProvide.md @@ -0,0 +1,74 @@ +--- +layout: page_v2 +title: oxxion Real Time Data Provider +display_name: oxxion Rtd +description: oxxion Real-time Vast Impression Tracking +page_type: module +module_type: rtd +module_code : oxxionRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# oxxion Rtd + +## Overview + +Module Name: Oxxion Rtd Provider +Module Type: Rtd Provider +Maintainer: + +## Oxxion Real-Time-Data submodule + +Oxxion helps you to understand how your prebid stack performs. +This Rtd module purpose is to filter bidders requested. + +## Integration + +Make sure to have the following modules listed while building prebid : `rtdModule,oxxionRtdProvider` +`rtdModule` is required to activate real-time-data submodules. +For example : + +```bash +gulp build --modules=schain,priceFloors,currency,consentManagement,appnexusBidAdapter,rubiconBidAdapter,rtdModule,oxxionRtdProvider +``` + +Then add the oxxion Rtd module to your prebid configuration : + +```javascript +pbjs.setConfig( + ... + realTimeData: { + auctionDelay: 300, + dataProviders: [ + { + name: "oxxionRtd", + waitForIt: true, + params: { + domain: "test.endpoint", + threshold: false, + samplingRate: 10, + } + } + ] + } + ... +) +``` + +## setConfig Parameters General + +{: .table .table-bordered .table-striped } +| Name | Type | Description | +|:---------------------------------|:---------|:------------------------------------------------------------------------------------------------------------| +| domain | String | This string identifies yourself in Oxxion's systems and is provided to you by your Oxxion representative. | + +## setConfig Parameters for bidder filtering + +{: .table .table-bordered .table-striped } +| Name | Type | Description | +|:---------------------------------|:-----------|:------------------------------------------------------------------------------------------------------------| +| threshold | Float/Bool | False or minimum expected bid rate to call a bidder (ex: 1.0 for 1% bid rate). | +| samplingRate | Integer | Percentage of request not meeting the criterias to run anyway in order to check for any change. | +| bidders | Array | Optional: If set, filtering will only be applied to bidders listed. diff --git a/dev-docs/modules/paapi.md b/dev-docs/modules/paapi.md new file mode 100644 index 0000000000..8a47f9402e --- /dev/null +++ b/dev-docs/modules/paapi.md @@ -0,0 +1,182 @@ +--- +layout: page_v2 +page_type: module +title: Module - PAAPI +description: Protected Audience API +module_code : paapi +display_name : PAAPI +enable_download : true +sidebarType : 1 +--- + +# PAAPI module + +This module allows Prebid.js to support PAAPI, formerly known as [FLEDGE](https://github.com/WICG/turtledove/blob/main/FLEDGE.md). + +This document covers the steps necessary for publishers to enable PAAPI on their inventory. It also describes +the changes Bid Adapters need to implement in order to support PAAPI. + +A related module, [fledgeForGpt](/dev-docs/modules/fledgeForGpt.html), adds support specifically for GPT's [component auctions](https://developers.google.com/publisher-tag/reference#googletag.config.componentauctionconfig). + +## Publisher Integration + +To use PAAPI, publishers must: + +- include this module in their Prebid.js bundle + + ```bash + gulp build --modules=paapi,... + ``` + +- enable PAAPI, globally or by ad unit, through [configuration](#config) +- manage the PAAPI auctions. This can be delegated to GPT with the [fledgeForGpt module](/dev-docs/modules/fledgeForGpt.html); homegrown solutions are possible with [getPAAPIConfig](/dev-docs/publisher-api-reference/getPAAPIConfig.html), but out of scope for this document. + + + +### Module Configuration + +This module exposes the following settings: + +{: .table .table-bordered .table-striped } +|Name |Type |Description |Notes | +| ------------ | ------------ | ------------ |------------ | +|enabled | Boolean |Enable/disable the module |Defaults to `false` | +|bidders | Array[String] |Optional list of bidders |Defaults to all bidders | +|defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1 | + +As noted above, PAAPI support is disabled by default. To enable it, set the `enabled` value to `true` for this module and configure `defaultForSlots` to be `1` (meaning _Client-side auction_). +using the `setConfig` method of Prebid.js: + +```js +pbjs.que.push(function() { + pbjs.setConfig({ + paapi: { + enabled: true, + defaultForSlots: 1 + } + }); +}); +``` + +Optionally, PAAPI support can be limited to specific bidders: + +```js +pbjs.que.push(function() { + pbjs.setConfig({ + paapi: { + enabled: true, + defaultForSlots: 1, + bidders: ['bidderA', 'bidderB'] + } + }); +}); +``` + +### Bidder Configuration + +This module adds the following setting for bidders: + +{: .table .table-bordered .table-striped } +|Name |Type |Description |Notes | +| ------------ | ------------ | ------------ |------------ | +| fledgeEnabled | Boolean | Enable/disable a bidder to participate in FLEDGE | Defaults to `false` | +|defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1| + +In addition to enabling PAAPI at the module level, individual bidders can also be enabled. This allows publishers to +selectively test with one or more bidders as they desire. To enable one or more bidders, use the `setBidderConfig` method +of Prebid.js: + +```js +pbjs.setBidderConfig({ + bidders: ["bidderA"], + config: { + fledgeEnabled: true, + defaultForSlots: 1 + } +}); +``` + +### AdUnit Configuration + +All adunits can be opted-in to PAAPI in the global config via the `defaultForSlots` parameter. +If needed, adunits can be configured individually by setting an attribute of the `ortb2Imp` object for that +adunit. This attribute will take precedence over `defaultForSlots` setting. + +{: .table .table-bordered .table-striped } +|Name |Type |Description |Notes | +| ------------ | ------------ | ------------ |------------ | +| ortb2Imp.ext.ae | Integer | Auction Environment: 1 indicates PAAPI eligible, 0 indicates it is not | Absence indicates this is not PAAPI eligible | + +The `ae` field stands for Auction Environment and was chosen to be consistent with the field that GAM passes to bidders +in their Open Bidding and Exchange Bidding APIs. More details on that can be found +[here](https://github.com/google/ads-privacy/tree/master/proposals/fledge-rtb#bid-request-changes-indicating-interest-group-auction-support) +In practice, this looks as follows: + +```js +pbjs.addAdUnits({ + code: "my-adunit-div", + // other config here + ortb2Imp: { + ext: { + ae: 1 + } + } +}); +``` + +## Bid Adapter Integration + +Chrome has enabled a two-tier auction in PAAPI. This allows multiple sellers (frequently SSPs) to act on behalf of the publisher with +a single entity serving as the final decision maker. In their [current approach](https://github.com/google/ads-privacy/tree/master/proposals/fledge-multiple-seller-testing), +GPT has opted to run the final auction layer while allowing other SSPs/sellers to participate as +[Component Auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) which feed their +bids to the final layer. To learn more about Component Auctions, go [here](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#24-scoring-bids-in-component-auctions). + +The PAAPI auction, including Component Auctions, are configured via an `AuctionConfig` object that defines the parameters of the auction for a given +seller. This module enables PAAPI support by allowing bid adaptors to return `AuctionConfig` objects in addition to bids. If a bid adaptor returns an +`AuctionConfig` object, Prebid.js will make it available through [`getPAAPIConfig`](/dev-docs/publisher-api-reference/getPAAPIConfig.html), as well as other PAAPI modules such as [fledgeForGpt](/dev-docs/modules/fledgeForGpt.html). + +Modifying a bid adapter to support PAAPI is a straightforward process and consists of the following steps: + +1. Detecting when a bid request is PAAPI eligible +2. Responding with AuctionConfig + +PAAPI eligibility is made available to bid adapters' [`buildRequests`](/dev-docs/bidder-adaptor.html#building-the-request) method through the `ortb2Imp.ext.ae` property of bid requests; it is set to `1` when the browser supports PAAPI and publisher configuration has enabled it as described above. Bid adapters +who wish to participate should read this flag and pass it to their server. + +When a bid request is PAAPI enabled, a bid adapter can return a tuple consisting of bids and AuctionConfig objects rather than just a list of bids: + +```js +function interpretResponse(resp, req) { + // Load the bids from the response - this is adapter specific + const bids = parseBids(resp); + + // Load the auctionConfigs from the response - also adapter specific + const fledgeAuctionConfigs = parseAuctionConfigs(resp); + + if (fledgeAuctionConfigs) { + // Return a tuple of bids and auctionConfigs. It is possible that bids could be null. + return {bids, fledgeAuctionConfigs}; + } else { + return bids; + } +} +``` + +An AuctionConfig must be associated with an adunit and auction, and this is accomplished using the value in the `bidId` field from the objects in the +`validBidRequests` array passed to the `buildRequests` function - see [here](/dev-docs/bidder-adaptor.html#ad-unit-params-in-the-validbidrequests-array) +for more details. This means that the AuctionConfig objects returned from `interpretResponse` must contain a `bidId` field whose value corresponds to +the request it should be associated with. This may raise the question: why isn't the AuctionConfig object returned as part of the bid? The +answer is that it's possible to participate in the PAAPI auction without returning a contextual bid. + +An example of this can be seen in the OpenX bid adapter [here](https://github.com/prebid/Prebid.js/blob/master/modules/openxBidAdapter.js) or RTB House bid adapter [here](https://github.com/prebid/Prebid.js/blob/master/modules/rtbhouseBidAdapter.js). + +Other than the addition of the `bidId` field, the `AuctionConfig` object should adhere to the requirements set forth in PAAPI. The details of creating an +`AuctionConfig` object are beyond the scope of this document. + +## Related Reading + +- [fledgeForGpt module](/dev-docs/modules/fledgeForGpt.html) +- [Protected Audience API (PAAPI)](https://github.com/WICG/turtledove/blob/main/FLEDGE.md), formerly FLEDGE +- [Component Auctions](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) +- [getPAAPIConfig](/dev-docs/publisher-api-reference/getPAAPIConfig.html) diff --git a/dev-docs/modules/permutiveRtdProvider.md b/dev-docs/modules/permutiveRtdProvider.md index 0983fe4d8a..b09e2f0dba 100644 --- a/dev-docs/modules/permutiveRtdProvider.md +++ b/dev-docs/modules/permutiveRtdProvider.md @@ -12,23 +12,29 @@ sidebarType : 1 --- # Permutive RTD Provider + {:.no_toc} * TOC {:toc} -## Overview +## Prebid Config for Permutive RTD Module + This module reads cohorts from Permutive and attaches them as targeting keys to bid requests. -## Usage +### _Permutive Real-time Data Submodule_ + +#### Usage + Compile the Permutive RTD module into your Prebid build: -``` + +```bash gulp build --modules=rtdModule,permutiveRtdProvider ``` > Note that the global RTD module, `rtdModule`, is a prerequisite of the Permutive RTD module. -You then need to enable the Permutive RTD in your Prebid configuration, using the below format: +You then need to enable the Permutive RTD in your Prebid configuration. Below is an example of the format: ```javascript pbjs.setConfig({ @@ -47,30 +53,127 @@ pbjs.setConfig({ }) ``` -## Supported Bidders -The Permutive RTD module sets Audience Connector cohorts as bidder-specific `ortb2.user.data` first-party data, following the Prebid `ortb2` convention, for any bidder included in `acBidders`. The module also supports bidder-specific data locations per ad unit (custom parameters) for the below bidders: +#### Parameters + +The parameters below provide configurability for general behaviours of the RTD submodule, +as well as enabling settings for specific use cases mentioned above (e.g. acbidders). + +## Parameters {: .table .table-bordered .table-striped } -| Bidder | ID | Custom Cohorts | Audience Connector | -| ----------- | ---------- | -------------------- | ------------------ | -| Xandr | `appnexus` | Yes | Yes | -| Magnite | `rubicon` | Yes | No | -| Ozone | `ozone` | No | Yes | +| Name | Type | Description | Default | +| ---------------------- | -------------------- | --------------------------------------------------------------------------------------------- | ------------------ | +| name | String | This should always be `permutive` | - | +| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | +| params | Object | | - | +| params.acBidders | String[] | An array of bidder codes to share cohorts with in certain versions of Prebid, see below | `[]` | +| params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` | -Key-values details for custom parameters: -* **Custom Cohorts:** The module configuration will automatically reflect the SSP integrations (_Activations_) you have enabled in your Permutive dashboard. Any additional bidders you want to pass data to will need to be configured. Permutive cohorts will be sent in the permutive key-value. +### Context -* **Audience Connector:** You'll need to define which bidders should receive Audience Connector cohorts. You need to include the `ID` of any bidder in the `acBidders` array. Audience Connector cohorts will be sent in the `p_standard` key-value. +Permutive is not listed as a TCF vendor as all data collection is on behalf of the publisher and based on consent the publisher has received from the user. +Rather than through the TCF framework, this consent is provided to Permutive when the user gives the relevant permissions on the publisher website which allow the Permutive SDK to run. +This means that if GDPR enforcement is configured _and_ the user consent isn’t given for Permutive to fire, no cohorts will populate. +As Prebid utilizes TCF vendor consent, for the Permutive RTD module to load, Permutive needs to be labeled within the Vendor Exceptions +### Instructions -## Parameters +1. Publisher enables rules within Prebid GDPR module +2. Label Permutive as an exception, as shown below. -{: .table .table-bordered .table-striped } -| Name | Type | Description | Default | -| ----------------- | -------------------- | ------------------ | ------------------ | -| name | String | This should always be `permutive` | - | -| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | -| params | Object | | - | -| params.acBidders | String[] | An array of bidders which should receive Audience Connector cohorts. | `[]` | -| params.maxSegs | Integer | Maximum number of cohorts to be included in either the `permutive` or `p_standard` key-value. | `500` | +```javascript +[ + { + purpose: 'storage', + enforcePurpose: true, + enforceVendor: true, + vendorExceptions: ["permutive"] + }, + { + purpose: 'basicAds', + enforcePurpose: true, + enforceVendor: true, + vendorExceptions: [] + } +] +``` + +Before making any updates to this configuration, please ensure that this approach aligns with internal policies and current regulations regarding consent. + +## Cohort Activation with Permutive RTD Module + +**Note**: Publishers must be enabled on the above Permutive RTD Submodule to enable Standard Cohorts. + +### _Enabling Publisher Cohorts_ + +#### Standard Cohorts + +The Permutive RTD module sets Standard Cohort IDs as bidder-specific ortb2.user.data first-party data, following the Prebid ortb2 convention. Cohorts will be sent in the `p_standard` key-value. + +For Prebid versions below 7.29.0, populate the acbidders config in the Permutive RTD with an array of bidder codes with whom you wish to share Standard Cohorts with. You also need to permission the bidders by communicating the bidder list to the Permutive team at . + +For Prebid versions 7.29.0 and above, do not populate bidder codes in acbidders for the purpose of sharing Standard Cohorts (Note: there may be other business needs that require you to populate acbidders for Prebid versions 7.29.0+, see Advertiser Cohorts below). To share Standard Cohorts with bidders in Prebid versions 7.29.0 and above, communicate the bidder list to the Permutive team at . + +#### _Bidder Specific Requirements for Standard Cohorts_ + +For PubMatic or OpenX: Please ensure you are using Prebid.js 7.13 (or later) +For Xandr: Please ensure you are using Prebid.js 7.29 (or later) +For Equativ: Please ensure you are using Prebid.js 7.26 (or later) + +#### Custom Cohorts + +The Permutive RTD module also supports passing any of the **Custom** Cohorts created in the dashboard to some SSP partners for targeting +e.g. setting up publisher deals. For these activations, cohort IDs are set in bidder-specific locations per ad unit (custom parameters). + +Currently, bidders with known support for custom cohort targeting are: + +* Xandr +* Magnite + +When enabling the respective Activation for a cohort in Permutive, this module will automatically attach that cohort ID to the bid request. +There is no need to enable individual bidders in the module configuration, it will automatically reflect which SSP integrations you have enabled in your Permutive dashboard. +Permutive cohorts will be sent in the permutive key-value. + +### _Enabling Advertiser Cohorts_ + +If you are connecting to an Advertiser seat within Permutive to share Advertiser Cohorts, populate the acbidders config in the Permutive RTD with an array of bidder codes with whom you wish to share Advertiser Cohorts with. + +### _Managing acbidders_ + +If your business needs require you to populate acbidders with bidder codes based on the criteria above, there are **two** ways to manage it. + +#### Option 1 - Automated + +If you are using Prebid.js v7.13.0+, bidders may be added to or removed from the acbidders config directly within the Permutive Dashboard. + +**Permutive can do this on your behalf**. Simply contact your Permutive CSM with on cc, +indicating which bidders you would like added. + +Or, a publisher may do this themselves within the Permutive Dashboard using the below instructions. + +##### Create Integration + +In order to manage acbidders via the Permutive dashboard, it is necessary to first enable the Prebid integration via the integrations page (settings). + +![Alt text](/assets/images/dev-docs/modules/permutiveRtdProvider-integration-create.png?raw=true "Permutive Prebid integration - create") + +**Note on Revenue Insights:** The prebid integration includes a feature for revenue insights, +which is not required for the purpose of updating acbidders config. +Please see [this document](https://support.permutive.com/hc/en-us/articles/360019044079-Revenue-Insights) for more information about revenue insights. + +##### Update acbidders + +The input for the “Data Provider config” is a multi-input free text. A valid “bidder code” needs to be entered in order to enable Standard or Advertiser Cohorts to be passed to the desired partner. The [prebid Bidders page](https://docs.prebid.org/dev-docs/bidders.html) contains instructions and a link to a list of possible bidder codes. + +![Alt text](/assets/images/dev-docs/modules/permutiveRtdProvider-integration-update.png?raw=true "Permutive Prebid integration - update") + +Bidders can be added or removed from acbidders using this feature, however, this will not impact any bidders that have been applied using the manual method below. + +#### Option 2 - Manual + +As a secondary option, bidders may be added manually. + +To do so, define which bidders should receive Standard or Advertiser Cohorts by +including the _bidder code_ of any bidder in the `acBidders` array. +**Note:** If you ever need to remove a manually-added bidder, the bidder will also need to be removed manually. diff --git a/dev-docs/modules/prebidServer.md b/dev-docs/modules/prebidServer.md new file mode 100644 index 0000000000..22bb4c6737 --- /dev/null +++ b/dev-docs/modules/prebidServer.md @@ -0,0 +1,283 @@ +--- +layout: page_v2 +title: Module - Prebid Server Adapter +display_name: Prebid Server Adapter +description: Server-to-Server header bidding +page_type: module +module_code : prebidServerBidAdapter +enable_download : true +vendor_specific: false +sidebarType : 1 +--- + +# Prebid Server Adapter +{: .no_toc} + +- TOC +{:toc } + +## Overview + +The Prebid Server Adapter is a meta-adapter. It's not an actual bidder, but +rather a way to get a batch of bids from other bidders with one request. +A request for the set of auctions is sent to Prebid Server, which performs +all the auctions server-to-server (S2S), responding in time for Prebid.js to +send the results to the ad server. This lightens the performance load on the user's device. + +### Prebid Server Adapter Video Overview + +
      + +Video notes: + +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) +- [Prebid Managed Services](https://prebid.org/managed-services/) +- [Header Bidding with Prebid](/overview/intro.html) +- [Transcript of this video overview](/dev-docs/pbsBidAdapter-video-overview.html) + +## Configuration + +Here's an example config enabling the AppNexus Prebid Server: + +```javascript +pbjs.setConfig({ + s2sConfig: { + accountId : '12345', + bidders : ['appnexus','pubmatic', 'rubicon'], + defaultVendor: 'appnexus', + timeout: 300 + } +}); +``` + +To use multiple prebid servers, just define `s2sConfig` as an array. +The same bidder cannot be set in both configs. For example: + +```javascript +pbjs.setConfig({ + s2sConfig: [ + { + name: "pbs-appnexus", + accountId: '12345', + bidders: ['appnexus','pubmatic'], + defaultVendor: 'appnexus', + timeout: 300, + }, + { + name: "pbs-rubicon", + accountId: '678910', + bidders: ['rubicon'], + defaultVendor: 'rubicon', + timeout: 300, + }, + ], +}); +``` + +There are many configuration options for s2sConfig: + +{: .table .table-bordered .table-striped } +| Attribute | Scope | Type | Description | +|------------+---------+---------+---------------------------------------------------------------| +| `accountId` | Required | String | Your Prebid Server account ID. This is obtained from whoever's hosting your Prebid Server. | +| `name` | Optional | String | A handle for this configuration, used to reference a specific server (when multiple are present) from [ad unit configuration](/dev-docs/adunit-reference.html#stored-imp) | +| `bidders` | Optional | Array of Strings | Which bidders auctions should take place on the server side | +| `allowUnknownBidderCodes` | Optional | Boolean | Allow Prebid Server to bid on behalf of bidders that are not explicitly listed in the adUnit. See important [note](#allowUnknownBidderCodes) below. Defaults to `false`. | +| `defaultVendor` | Optional | String | Automatically includes all following options in the config with vendor's default values. Individual properties can be overridden by including them in the config along with this setting. See the Additional Notes below for more information. | +| `enabled` | Optional | Boolean | Enables this s2sConfig block - defaults to `false` | +| `timeout` | Optional | Integer | Number of milliseconds allowed for the server-side auctions. This should be approximately 200ms-300ms less than your Prebid.js timeout to allow for all bids to be returned in a timely manner. Defaults to 1000ms. | +| `adapter` | Required | String | Adapter to use to connect to Prebid Server. Defaults to 'prebidServer' | +| `endpoint` | Required | URL or Object | Defines the auction endpoint for the Prebid Server cluster. See table below for object config properties. | +| `syncEndpoint` | Required | URL or Object | Defines the cookie_sync endpoint for the Prebid Server cluster. See table below for object config properties. | +| `userSyncLimit` | Optional | Integer | Max number of userSync URLs that can be executed by Prebid Server cookie_sync per request. If not defined, PBS will execute all userSync URLs included in the request. | +| `syncTimeout` | Optional | Integer | Maximum number of milliseconds allowed for each server-side userSync to load. Default is 1000. | +| `syncUrlModifier` | Optional | Object | Function to modify a bidder's sync url before the actual call to the sync endpoint. Bidder must be enabled for s2sConfig. | +| `coopSync` | Optional | Boolean | Whether or not PBS is allowed to perform "cooperative syncing" for bidders not on this page. Publishers help each other improve match rates by allowing this. Default is true. | +| `defaultTtl` | Optional | Integer | Configures the default TTL in the Prebid Server adapter to use when Prebid Server does not return a bid TTL - 60 if not set | +| `adapterOptions` | Optional | Object | Arguments will be added to resulting OpenRTB payload to Prebid Server in every impression object at request.imp[].ext.BIDDER. See the example above. | +| `extPrebid` | Optional | Object | Arguments will be added to resulting OpenRTB payload to Prebid Server in request.ext.prebid. See the examples below. | + +If `endpoint` and `syncEndpoint` are objects, these are the supported properties: + +{: .table .table-bordered .table-striped } +| Attribute | Scope | Type | Description | +|------------+---------+---------+---------------------------------------------------------------| +| p1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for non-consent requests or users who grant consent. | +| noP1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for users who do not grant consent. (This is useful for a server configured to not accept any cookies to ensure compliance regulations.) | + +**Notes on s2sConfig properties** + +- Currently supported vendors are: appnexus, openx, and rubicon +- When using `defaultVendor` option, `accountId` still needs to be defined. +- If `bidders` is omitted, only adUnits that also omit bidders will be sent to Prebid Server. See the [stored impressions](#stored-imp) example below. +- If the `s2sConfig` timeout is not specified, Prebid Server will utilize a configured default for `tmax`. +- When using the `endpoint` or `syncEndpoint` object configs, you should define both properties. If either property is not defined, Prebid Server requests for that type of user will not be made. If you do not need to distinguish endpoints for consent reasons, you can simply define the same URL value in both fields or use the String version of the field (which is configured to use defined URL for all users). +- When `allowUnknownBidderCodes` is `true`, bidders that have not been explicitly requested in [`adUnit.bids`](../adunit-reference.html#adunitbids) may take part in the auction. This can break custom logic that relies on the availability of a bid request object for any given bid. Known scenarios where custom code won't get the request when there's an "unknown bidder": + - There will not be a [`bidRequested`](/dev-docs/publisher-api-reference/getEvents.html) event. + - In the [MASS custom renderers](/dev-docs/modules/mass.html#configuration-parameters) module, `payload.bidRequest` will be undefined. + - In the [Price Floors module](/dev-docs/modules/floors.html), custom schema functions will see the bidRequest object as undefined. + +Additional options for `s2sConfig` may be enabled by including the [Server-to-Server testing module]({{site.baseurl}}/dev-docs/modules/s2sTesting.html). + +**Passing the Referrer to Server Side Adapters** + +- Setting `extPrebid.origreferrer` will be recognized by some server-side adapters as the referring URL for the current page. + +**Emitting SeatNonBid Data** + +- Prebid Server can be instructed to return additional [SeatNonBid](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#seat-non-bid) information about why bidders might not have bid on certain adunits. You can get this extra information by setting `extPrebid.returnallbidstatus` equal to `true`. Note that client-side analytics adapters can receive this data by listening to the `seatNonBid` event. + +## Bid Params + +Bid params are sourced from the adapter configurations set for client side. These do not need to change for Prebid Server. + +{: .alert.alert-warning :} +**Errors in bidder parameters will cause Prebid Server to reject the +entire request.** The Prebid Server philosophy is to avoid silent failures -- +we assume you will test changes, and that it will be easier to notice a +4xx error coming from the server than a silent failure where it skips just +the bad parameter. + +## Examples + +### Defining endpoints + +s2sConfig example with the endpoint attributes defined instead of using the 'defaultVendor' approach: + +```javascript +pbjs.setConfig({ + s2sConfig: [{ + accountId: '1001', + bidders: ['bidderA', 'bidderB'], + endpoint: 'https://mypbs.example.com/path', + syncEndpoint: 'https://mypbs.example.com/path', + timeout: 300 + }] +}) +``` + +A similar example with the endpoint attributes defined as objects: + +```javascript +pbjs.setConfig({ + s2sConfig: [{ + accountId: '1001', + bidders: ['bidderA', 'bidderB'], + endpoint: { + p1Consent: 'https://mypbs.example.com/path', + noP1Consent: 'https://mypbs2.example.com/path' + }, + syncEndpoint: { + p1Consent: 'https://mypbs.example.com/path', + noP1Consent: 'https://mypbs2.example.com/path' + }, + timeout: 300 + }] +}) +``` + +### Server-Side Aliases + +You may want to run a particular bidder on the client for banner, but that same bidder on the +server for video. You would do this by setting a **server-side** alias. For example: + +```javascript +pbjs.setConfig({ + s2sConfig: [{ + accountId: '1', + bidders: ['tripleliftVideo'], + defaultVendor: 'appnexus', + timeout: 500, + extPrebid: { + aliases: { + tripleliftVideo: tripleLift + } + } + }] +}) +``` + +Here's how it works: + +1. Video ad units are coded with the dynamic alias. e.g. tripleliftVideo +1. The s2sConfig.bidders array contains 'tripleliftVideo' telling Prebid.js to direct bids for that code to the server +1. Finally, the extPrebid.aliases line tells Prebid Server to route the 'tripleliftVideo' biddercode to the 'triplelift' server-side adapter. + +### Video via s2sConfig + +Supporting video through the Server-to-Server route can be done by providing a couple of extra arguments on the `extPrebid` object. e.g. + +```javascript +pbjs.setConfig({ + s2sConfig: [{ + accountId: '1001', + bidders: ['rubicon', 'pubmatic'], + defaultVendor: 'rubicon', + timeout: 250, + extPrebid: { + cache: { + vastxml: {returnCreative: false} + }, + targeting: { + pricegranularity: {"ranges": [{"max": 40.00, "increment": 1.00}]} + } + } + }] +}) +``` + + + +### Stored impressions + +Prebid Server stored [requests](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-requests) can be requested through the adUnit `ortb2Imp` property. This is useful to move the list of bidders and parameters from the page to blocks of JSON stored on the server. For these cases, it's not necessary to specify `bids`: + +```javascript +pbjs.addAdUnits([{ + code: 'example-stored-request', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + ortb2Imp: { + ext: { + prebid: { + storedrequest: { + id: 'your-stored-request-id' + } + } + } + } +}]) +``` + +### Stored responses + +For debugging purposes, it can be useful to have a page that retrieves a static value rather than running an actual auction. +For this you can use PBS [stored responses](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-responses). +Here's an example: + +```javascript +pbjs.addAdUnits([{ + code: 'example-stored-response', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + ortb2Imp: { + ext: { + prebid: { + storedauctionresponse: { + id: 'your-stored-response-id' + } + } + } + } +}]) +``` + +## Related Reading + +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) diff --git a/dev-docs/modules/pubCommonId.md b/dev-docs/modules/pubCommonId.md index 455e89bb38..80f706b182 100644 --- a/dev-docs/modules/pubCommonId.md +++ b/dev-docs/modules/pubCommonId.md @@ -12,9 +12,10 @@ sidebarType : 1 # Publisher Common ID Module + {:.no_toc} -This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It's lightweight and self contained. Adapters that support Publisher Common ID will be able to pick up the user ID and return it for additional server-side cross device tracking. +This module stores a unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It's lightweight and self contained. Adapters that support Publisher Common ID will be able to pick up the user ID and return it for additional server-side cross device tracking. ## Page integration @@ -33,33 +34,32 @@ Add a pubcid object in the setConfig() call. Example: Changing ID expiration to 1 year -{% highlight js %} +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; pbjs.que.push(function() { pbjs.setConfig({pubcid: {expInterval: 525600}}); pbjs.addAdUnits(adUnits); }); -{% endhighlight %} +``` ### User Opt-Out -Users must be allowed to opt out of targeted advertising. When implementing this module, you are required to place a link in your privacy policy or elsewhere on your website which allows the user to implement this opt-out. User opt-out is supported by setting the `_pubcid_optout` as a cookie in the publisher’s domain, or in local storage. When this flag is set, then Publisher Common ID is neither read nor updated, and it will not be made available to any adapters. The opt-out must also delete the Publisher Common ID value (shown in [example](../../examples/modules/pub_common_id_optout.html)). +Users must be allowed to opt out of targeted advertising. When implementing this module, you are required to place a link in your privacy policy or elsewhere on your website which allows the user to implement this opt-out. User opt-out is supported by setting the `_pubcid_optout` as a cookie in the publisher’s domain, or in local storage. When this flag is set, then Publisher Common ID is neither read nor updated, and it will not be made available to any adapters. The opt-out must also delete the Publisher Common ID value. * Opt-In - `_pubcid_optout` flag is not present or set to 0 * Opt-Out - `_pubcid_optout` flag is set to 1 - ### Build the package - + #### Step 1: Bundle the module code Follow the basic build instructions on the GitHub repo's main README. To include the module, an additional option must be added to the the gulp build command: - -{% highlight bash %} + +```bash gulp build --modules=pubCommonId,bidAdapter1,bidAdapter2 -{% endhighlight %} - +``` + #### Step 2: Publish the package(s) to the CDN After testing, get your javascript file(s) out to your Content Delivery Network (CDN) as normal. @@ -68,9 +68,9 @@ Note that there are more dynamic ways of combining these components for publishe ## Adapter integration -Adapters should look for `bid.crumbs.pubcid` in buildRequests() method. +Adapters should look for `bid.crumbs.pubcid` in buildRequests() method. -{% highlight js %} +```javascript [ { "bidder":"appnexus", @@ -88,14 +88,11 @@ Adapters should look for `bid.crumbs.pubcid` in buildRequests() method. "auctionId":"a1a98ab2-97c9-4f42-970e-6e03040559f2" } ] -{% endhighlight %} - +``` ## Technical Details -- The ID is UUID v4 and stored as a cookie and a local storage item called `_pubcid` in the page's domain. -- This module hooks into the pbjs.requestBids() method. When invoked, it retrieves the id from cookie and local storage, updates the expiration time, and decorates the adUnits objects. A new id will be created if one doesn't exist already. -- The id stored as cookie takes precedence over local storage. -- Beware that if prebid.js is included in an ad server frame, then the ID would have ad server domain instead. - - +* The ID is UUID v4 and stored as a cookie and a local storage item called `_pubcid` in the page's domain. +* This module hooks into the pbjs.requestBids() method. When invoked, it retrieves the id from cookie and local storage, updates the expiration time, and decorates the adUnits objects. A new id will be created if one doesn't exist already. +* The id stored as cookie takes precedence over local storage. +* Beware that if prebid.js is included in an ad server frame, then the ID would have ad server domain instead. diff --git a/dev-docs/modules/pubxaiRtdProvider.md b/dev-docs/modules/pubxaiRtdProvider.md new file mode 100644 index 0000000000..26a0f84923 --- /dev/null +++ b/dev-docs/modules/pubxaiRtdProvider.md @@ -0,0 +1,79 @@ +--- +layout: page_v2 +title: Pubx.ai RTD Provider +display_name: Pubx.ai RTD Module +description: RTD module for Prebid provided by Pubx.ai to set dynamic floors +page_type: module +module_type: rtd +module_code: pubxaiRtdProvider +enable_download: true +vendor_specific: true +sidebarType: 1 +--- + +# Pubx.ai RTD Module + +{:.no_toc} + +* TOC +{:toc} + +## Description + +This RTD module, provided by Pubx.ai, sets dynamic floors for Prebid auctions. + +## Integration + +Ensure that the following modules are listed when building Prebid: `priceFloors`. +For example: + +```shell +gulp build --modules=priceFloors +``` + +To compile the RTD module into your Prebid build: + +```shell +gulp build --modules=rtdModule,pubxaiRtdProvider +``` + +## Configuration + +To use the Pubx.ai RTD module, add `realTimeData` with the parameters mentioned below to the Prebid config. + +```js +const AUCTION_DELAY = 100; +pbjs.setConfig({ + // rest of the config + ..., + realTimeData: { + auctionDelay: AUCTION_DELAY, + dataProviders: { + name: "pubxai", + waitForIt: true, + params: { + pubxId: ``, + endpoint: ``, // (optional) + floorMin: ``, // (optional) + enforcement: ``, // (optional) + data: `` // (optional) + } + } + } + // rest of the config + ..., +}); +``` + +## Parameters + +| Name | Type | Description | Default | +| :----------------- | :------ | :------------------------------------------------------------- | :------------------------- | +| name | String | Name of the real-time data module | Always `pubxai` | +| waitForIt | Boolean | Should be `true` if an `auctionDelay` is defined (optional) | `false` | +| params | Object | | | +| params.pubxId | String | Publisher ID | | +| params.endpoint | String | URL to retrieve floor data (optional) | `https://floor.pbxai.com/` | +| params.floorMin | Number | Minimum CPM floor (optional) | `None` | +| params.enforcement | Object | Enforcement behavior within the Price Floors Module (optional) | `None` | +| params.data | Object | Default floor data provided by pubX.ai (optional) | `None` | diff --git a/dev-docs/modules/qortexRtdProvider.md b/dev-docs/modules/qortexRtdProvider.md new file mode 100644 index 0000000000..189d492345 --- /dev/null +++ b/dev-docs/modules/qortexRtdProvider.md @@ -0,0 +1,73 @@ +--- +layout: page_v2 +title: Qortex Realtime Data Module +display_name: Qortex RTD Module +description: Appends contextual segments to the bidding object based on the content of a page +page_type: module +module_type: rtd +module_code : qortexRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Qortex Real-time Data Submodule + +{:.no_toc} + +* TOC +{:toc} + +## Overview + +The Qortex RTD module appends contextual segments to the bidding object based on the content of a page using the Qortex API. + +Upon load, the Qortex context API will analyze the bidder page (video, text, image, etc.) and will return a [Content object](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=26). The module will then merge that object into the appropriate bidders' `ortb2.site.content`, which can be used by prebid adapters that use `site.content` data. + +## Build + +```SH +gulp build --modules="rtdModule,qortexRtdProvider,qortexBidAdapter,..." +``` + +> `rtdModule` is a required module to use Qortex RTD module. + +## Configuration + +Please refer to [Prebid Documentation](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-realTimeData) on RTD module configuration for details on required and optional parameters of `realTimeData` + +When configuring Qortex as a data provider, refer to the template below to add the necessary information to ensure the proper connection is made. + +### RTD Module Setup + +```javascript +pbjs.setConfig({ + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: 'qortex', + waitForIt: true, + params: { + groupId: 'ABC123', //required + bidders: ['qortex', 'adapter2'], //optional (see below) + tagConfig: { // optional, please reach out to your account manager for configuration reccommendation + videoContainer: 'string', + htmlContainer: 'string', + attachToTop: 'string', + esm6Mod: 'string', + continuousLoad: 'string' + } + } + }] + } +}); +``` + +### Paramter Details + +{: .table .table-bordered .table-striped } +| Name |Type | Description |Required | Notes | +| :--------------- | :------------ | :------------------------------------------------------------------ |:---------|:------------ | +| `groupId` | String | The Qortex groupId linked to the publisher | Yes | Your account manager can provide this information for you if needed, it is required for any type integration and access to Qortex services | +| `bidders` | Array of Strings | this is a list containing the bidder code of the prebid adapters you would like this module to impact | No | If this parameter is included, `ortb2.site.content` will be updated *only* for adapters in this array. If this parameter is omitted, the RTD module will default to updating `ortb2.site.content` on *all* bid adapters being used on the page| +| `tagConfig` | Object | The config settings that could be used to initialize the Qortex integration on your page | No | A preconfigured object for this step will be provided to you by the Qortex team. The RTD module will only carry out this process if a valid tagConfig is provided. diff --git a/dev-docs/modules/raynRtdProvider.md b/dev-docs/modules/raynRtdProvider.md new file mode 100644 index 0000000000..81cbcd02bf --- /dev/null +++ b/dev-docs/modules/raynRtdProvider.md @@ -0,0 +1,120 @@ +--- +layout: page_v2 +title: Rayn RTD Provider +display_name: Rayn Real Time Data Module +description: Rayn Real Time Data module appends privacy preserving enhanced contextual categories and audiences. Moments matter. +page_type: module +module_type: rtd +module_code: raynRtdProvider +enable_download: true +vendor_specific: true +sidebarType: 1 +--- + +# Rayn Real-time Data Submodule + +Rayn is a privacy preserving, data platform. We turn content into context, into audiences. For Personalisation, Monetisation and Insights. This module reads contextual categories and audience cohorts from RaynJS (via localStorage) and passes them to the bid-stream. + +For best results, we recommend that you deploy RaynJS on your properties, as instructed in the Rayn implementation guide. RaynJS will ensure that your auctions contain Rayn data. Please reach out to [support@rayn.io](mailto:support@rayn.io) if you have any questions. + +## Integration + +To install the module, follow these instructions: + +Step 1: Prepare the base Prebid file +Compile the Rayn RTD module (`raynRtdProvider`) into your Prebid build along with the parent RTD Module (`rtdModule`). From the command line, run gulp build `gulp build --modules=rtdModule,raynRtdProvider` + +Step 2: Set configuration +Enable Rayn RTD Module using pbjs.setConfig. Example is provided in the Configuration section. See the **Parameter Description** for more detailed information of the configuration parameters. + +### Configuration + +This module is configured as part of the realTimeData.dataProviders object. + +Example format: + +```js +pbjs.setConfig( + // ... + realTimeData: { + auctionDelay: 1000, + dataProviders: [ + { + name: "rayn", + waitForIt: true, + params: { + bidders: ["appnexus", "pubmatic"], + integration: { + iabAudienceCategories: { + v1_1: { + tier: 6, + enabled: true, + }, + }, + iabContentCategories: { + v3_0: { + tier: 4, + enabled: true, + }, + v2_2: { + tier: 4, + enabled: true, + }, + }, + } + } + } + ] + } + // ... +} +``` + +## Parameter Description + +The parameters below provide configurability for general behaviours of the RTD submodule, as well as enabling settings for specific use cases mentioned above (e.g. tiers and bidders). + +### Parameters + +{: .table .table-bordered .table-striped } +| Name | Type | Description | Notes | +| :---------------------------------------------------- | :-------- | :----------------------------------------------------------------------------------- | :---- | +| name | `String` | RTD sub module name | Always "rayn" | +| waitForIt | `Boolean` | Required to ensure that the auction is delayed for the module to respond | Optional. Defaults to false but recommended to true | +| params | `Object` | || +| params.bidders | `Array` | Bidders with which to share context and segment information | Optional. In case no bidder is specified Rayn will append data for all bidders | +| params.integration | `Object` | Controls which IAB taxonomy should be used and up to which category tier | Optional. In case it's not defined, all supported IAB taxonomies and all category tiers will be used | +| params.integration.iabAudienceCategories | `Object` | || +| params.integration.iabAudienceCategories.v1_1 | `Object` | || +| params.integration.iabAudienceCategories.v1_1.enabled | `Boolean` | Controls if IAB Audience Taxonomy v1.1 will be used | Optional. Enabled by default | +| params.integration.iabAudienceCategories.v1_1.tier | `Number` | Controls up to which IAB Audience Taxonomy v1.1 Category tier will be used | Optional. Tier 6 by default | +| params.integration.iabContentCategories | `Object` | || +| params.integration.iabContentCategories.v3_0 | `Object` | || +| params.integration.iabContentCategories.v3_0.enabled | `Boolean` | Controls if IAB Content Taxonomy v3.0 will be used | Optional. Enabled by default | +| params.integration.iabContentCategories.v3_0.tier | `Number` | Controls up to which IAB Content Taxonomy v3.0 Category tier will be used | Optional. Tier 4 by default | +| params.integration.iabContentCategories.v2_2 | `Object` | || +| params.integration.iabContentCategories.v2_2.enabled | `Boolean` | Controls if IAB Content Taxonomy v2.2 will be used | Optional. Enabled by default | +| params.integration.iabContentCategories.v2_2.tier | `Number` | Controls up to which IAB Content Taxonomy v2.2 Category tier will be used | Optional. Tier 4 by default | + +Please note that raynRtdProvider should be integrated into the website along with RaynJS. + +## Testing + +To view an example of the on page setup: + +```bash +gulp serve-fast --modules=rtdModule,raynRtdProvider,appnexusBidAdapter +``` + +Then in your browser access: [http://localhost:9999/integrationExamples/gpt/raynRtdProvider_example.html](http://localhost:9999/integrationExamples/gpt/raynRtdProvider_example.html) + +Run the unit tests, just on the Rayn RTD module test file: + +```bash +gulp test --file "test/spec/modules/raynRtdProvider_spec.js" +``` + +## Support + +If you require further assistance or are interested in discussing the module functionality please reach out to [support@rayn.io](mailto:support@rayn.io). +You are also able to find more examples and other integration routes on the Rayn documentation site. diff --git a/dev-docs/modules/reconciliationRtdProvider.md b/dev-docs/modules/reconciliationRtdProvider.md index 47ff52d92e..c85eb2436c 100644 --- a/dev-docs/modules/reconciliationRtdProvider.md +++ b/dev-docs/modules/reconciliationRtdProvider.md @@ -12,6 +12,7 @@ sidebarType: 1 --- # Reconciliation SDK Module + {:.no_toc} * TOC @@ -20,59 +21,58 @@ sidebarType: 1 ## Overview The purpose of Reconciliation Real Time Data Provider is to allow publishers to collect supply chain structure information and vendor-specific impression IDs from ad creative suppliers. It reports the data to the Reconciliation Service, allowing publishers, advertisers and other supply chain participants to match and reconcile ad server, SSP, DSP and verification system log file records. -Reconciliation SDK was created as part of TAG DLT initiative ([https://www.tagtoday.net/pressreleases/dlt_9_7_2020](https://www.tagtoday.net/pressreleases/dlt_9_7_2020)). +Reconciliation SDK was created as part of TAG DLT initiative ([www.tagtoday.net/pressreleases/dlt_9_7_2020](https://www.tagtoday.net/pressreleases/dlt_9_7_2020)). TAG recently led a twelve-month, cross-industry pilot in the UK that evaluated the feasibility and benefits of using Distributed Ledger Technology (DLT) to increase trust and transparency in digital advertising. -More information: https://www.tagtoday.net/brand-safety#dltnetwork -Contact us: consultation@tagtoday.net +More information: +Contact us: Implementation works like this: -1) Build the Reconciliation module into the Prebid.js package with: +1. Build the Reconciliation module into the Prebid.js package with: -``` -gulp build --modules=reconciliationRtdProvider&... -``` + ```bash + gulp build --modules=reconciliationRtdProvider&... + ``` -2) Use `setConfig` to pass parameters to module +2. Use `setConfig` to pass parameters to module ## Configuration This module is configured as part of the `realTimeData.dataProviders` object: +```javascript +pbjs.setConfig({ + "realTimeData": { + dataProviders:[{ + name: "reconciliation", + params: { + publisherMemberId: "test_prebid_publisher", + allowAccess: true, //optional - false by default + } + }] + } +}); ``` - pbjs.setConfig({ - "realTimeData": { - dataProviders:[{ - name: "reconciliation", - params: { - publisherMemberId: "test_prebid_publisher", - allowAccess: true, //optional - false by default - } - }] - } - }); -``` Syntax details: {: .table .table-bordered .table-striped } | Name |Type | Description | Notes | | :------------ | :------------ | :------------ |:------------ | -| name | String | Real time data module name | Always 'reconciliation' | +| name | String | Real time data module name | Always 'reconciliation' | | params | Object | | | | params.publisherMemberId |String |Unique Publisher ID| | | params.allowAccess |Boolean |Share AdUnit IDs with advertiser Reconciliation Tags| Optional. Default to `false`| - - ## Output For each ad slot, the module returns custom targeting values used to match impressions (publisher-adserver-advertiser). The module also tracks AdUnit initialization and impressions ('impression' message is sent by the Reconciliation Tag in ad markup). Custom targetings example: -``` + +```json { "slotA":{ "RSDK_AUID": "/slotA-Unit", @@ -84,4 +84,3 @@ Custom targetings example: } } ``` - diff --git a/dev-docs/modules/relevadRtdProvider.md b/dev-docs/modules/relevadRtdProvider.md new file mode 100644 index 0000000000..9d33922dec --- /dev/null +++ b/dev-docs/modules/relevadRtdProvider.md @@ -0,0 +1,112 @@ +--- +layout: page_v2 +title: Relevad RTD Provider +display_name: Relevad RTD Provider +description: Contextual Categories and Segments, cookieless and privacy-first. +page_type: module +module_type: rtd +module_code : relevadRtdProvider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Relevad RTD Provider + +Relevad is a contextual semantic analytics company. Our privacy-first, cookieless contextual categorization, segmentation, and keyword generation platform is designed to help publishers and advertisers optimize targeting and increase ad inventory yield. + +This real-time data processing module provides quality contextual IAB categories and segments to prebid.js auction bidders. Every category and segment comes with a score measuring its relevance to the publisher’s web page. Publishers may configure their preferred minimum score setting with the module parameter “minscore”. Relevad service does not use browser cookies and is fully GDPR compliant. + +{:.no_toc} + +* TOC +{:toc} + +## Usage + +Compile the Relevad RTD module (`relevaddRtdProvider`) into your Prebid build, along with the parent RTD Module (`rtdModule`): + +`gulp build --modules=rtdModule,relevadRtdProvider` + +Next we configure the module, via `pbjs.setConfig`. See the **Parameter Descriptions** below for more detailed information of the configuration parameters. + +```javascript +pbjs.setConfig({ + //... + realTimeData: { + auctionDelay: 1000, + dataProviders: [ + { + name: "RelevadRTDModule", + waitForIt: true, + params: { + partnerId: your_partner_id, // Your Relevad partner id. + setgpt: true, // Target or not google GAM/GPT on your page. + minscore: 30, // Minimum relevancy score (0-100). If absent, defaults to 30. + + // The list of bidders to target with Relevad categories and segments. If absent or empty, target all bidders. + bidders: [ + { bidder: "appnexus", // Bidder name + adUnitCodes: ['adUnit-1','adUnit-2'], // List of adUnit codes to target. If absent or empty, target all ad units. + minscore: 70, // Minimum relevancy score for this bidder (0-100). If absent, defaults to the global minscore. + }, + ... + ] + } + } + ] + } + // ... +}); +``` + +## Parameter Descriptions + +{: .table .table-bordered .table-striped } + +| Name | Type | Description | Notes | +| :----------------- | :--------- | :----------------------------------------------------------- | :----------------------------------------------------------- | +| name | String | Relevad RTD module name | Mandatory, must be **RelevadRTDModule** | +| waitForIt | Boolean | Whether to delay auction for the RTD module response | Optional. Defaults to false.We recommend setting it to true. Relevad RTD service is very fast. | +| params | Object | | Relevad RTD module configuration | +| params.partnerid | String | Relevad Partner ID, required to enable the service | Mandatory | +| params.publisherid | String | Relevad publisher id | Mandatory | +| params.apikey | String | Relevad API key | Mandatory | +| param.actualUrl | String | Your page URL. When present, will be categorized instead of the browser-provided URL | Optional, defaults to the browser-providedURL | +| params.setgpt | Boolean | Target or not Google GPT/GAM when it is configured on your page | Optional, defaults to true. | +| params.minscore | Integer | Minimum categorization relevancy score in the range of 0-100. Our categories and segments come with their relevancy scores. We’ll send to the bidders only categories and segments with the scores higher than the minscore. | Optional, defaults to 30 | +| params.bidders | Dictionary | Bidders with which to share category and segment information | Optional. If empty or absent, target all bidders. | + +### Bidder-specific configuration. Every bidder may have these configuration parameters + +| Name | Type | Description | Notes | +| :---------- | :--------------- | :----------------------------------------------------------- | :------------------------------------------------------- | +| bidder | String | Bidder name | Mandatory. Example: “appnexus” | +| adUnitCodes | Array of Strings | List of specific AdUnit codes you with to target | Optional. If empty or absent, all ad units are targeted. | +| minscore | Integer | Bidder-specific minimum categorization relevancy score (0, 100) | Optional, defaults to global minscore above. | + +If you do not have your own `partnerid, publisherid, apikey` please reach out to [info@relevad.com](mailto:info@relevad.com). + +## Testing + +To view an example of the on page setup required: + +```bash +gulp serve-fast --modules=rtdModule,relevadRtdProvider +``` + +Then in your browser access: + +```text +http://localhost:9999/integrationExamples/gpt/relevadRtdProvider_example.html +``` + +Run the unit tests for Relevad RTD module: + +```bash +gulp test --file "test/spec/modules/relevadRtdProvider_spec.js" +``` + +## Support + +If you require further assistance or are interested in discussing the module functionality please reach out to [anna@relevad.com](mailto:anna@relevad,com). diff --git a/dev-docs/modules/s2sTesting.md b/dev-docs/modules/s2sTesting.md index a772ee0df3..e227acf841 100644 --- a/dev-docs/modules/s2sTesting.md +++ b/dev-docs/modules/s2sTesting.md @@ -9,8 +9,6 @@ enable_download : true sidebarType : 1 --- - - # Prebid JS Module: Server-to-Server Testing This module allows publishers the chance to ramp-up on [Prebid Server](/prebid-server/overview/prebid-server-overview.html), @@ -24,8 +22,8 @@ additional options for controlling how requests are sent: The package is built by specifying the `s2sTesting` module on the build command. For example: -``` -gulp build --modules=rubiconBidAdapter,appnexusAstBidAdapter,prebidServerBidAdapter,s2sTesting +```bash +gulp build --modules= ... , prebidServerBidAdapter,s2sTesting ``` The expectation is the Server-to-Server Testing module will used for a limited period. @@ -35,27 +33,34 @@ period is complete, regardless of outcome, A/B testing would be turned off and this module no longer included in the PrebidJS build. ## Features + With the Server-to-Server Testing module, the following enhancements are provided: New 'bidderControl' options in s2sConfig. E.g. -``` -pbjs.setConfig( +```javascript +pbjs.setConfig({ s2sConfig: { - bidders: [ "rubicon", "appnexus" ], + bidders: [ "bidderA", "bidderB" ], enabled: true, + defaultVendor: 'vendor1', testing: true, testServerOnly: false, bidderControl: { - "rubicon": { + "bidderA": { bidSource: {server:10, client:90}, includeSourceKvp: true }, - "appnexus": { + "bidderB": { bidSource: {server: 25, client:75}, includeSourceKvp: true } } + }, + // needed since PBJS 5.0 to generate the hb_source key + targetingControls: { + addTargetingKeys: ['SOURCE'] + } }); ``` @@ -66,27 +71,28 @@ The `testing: true` attribute is required to enable the bidderControl and bidSource features. This shouldn't be confused with the `enabled: true` flag which enables the entire server-to-server feature. -When 'includeSourceKvp' is specified in s2sConfig, the system will log an +When 'includeSourceKvp' is specified in s2sConfig and the appropriate [addTargetingKeys targetingControl](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) is added, the system will log an additional Key Value Pair (KVP) to the ad server. This will allow reporting to confirm the ratio of client-vs-server administered requests, as well as more advanced reporting. -``` +```javascript hb_source_BIDDER=client ``` + OR -``` +```javascript hb_source_BIDDER=s2s ``` There's also a new `bidSource` option in AdUnits that overrides the global bidSource. E.g. -``` +```javascript AdUnit={ [...] bids=[{ - bidder: "rubicon", + bidder: "bidderA", bidSource: {client:50, server:50} // precedence over s2sConfig.bidderControl [...] }] @@ -95,14 +101,13 @@ AdUnit={ ## Analysis -Determining the success of the test is up to each publisher, but +Determining the success of the test is up to each publisher, but keep in mind the various data sources you may have access to: * Ad Server reports - the additional `hb_source` key value pair can be used to confirm some elements on the performance. * Prebid Analytics Adapter - if you're already monitoring header bidding, those reports should be monitored for impacts in key metrics from the A/B test. * Bidder data - SSPs should be able to provide data about cookie match rates and general performance during the test period. - ## Usage Examples ### 1. Global A/B Test @@ -113,22 +118,28 @@ I don't want to modify AdUnits because that's time consuming in the CMS.* Example S2S Config defining that 10% of Rubicon requests and 100% of AppNexus requests go through the server: -``` -pbjs.setConfig( +```javascript +pbjs.setConfig({ s2sConfig: { account: "PREBID-SERVER-ACCOUNT", - bidders: [ "rubicon", "appnexus" ], + bidders: [ "bidderA", "bidderB" ], + defaultVendor: 'vendor1', enabled: true, testing: true, bidderControl: { - "rubicon": { + "bidderA": { bidSource: {client:90, server:10}, includeSourceKvp: true } } + }, + targetingControls: { + addTargetingKeys: ['SOURCE'] + } }); ``` -The additional hb_source_rubicon KVP will be sent to the ad server for additional reporting. + +The additional hb_source_bidderA KVP will be sent to the ad server for additional reporting. ### 2. A/B Test for one AdUnit @@ -136,40 +147,47 @@ The additional hb_source_rubicon KVP will be sent to the ad server for additiona approach and the client approach so we can gauge the impact of Prebid Server, but we want to do this on a small number of AdUnits.* -Example S2S Config defining that the client route is the default path for the rubicon adapter: +Example S2S Config defining that the client route is the default path for bidderA: -``` -pbjs.setConfig( +```javascript +pbjs.setConfig({ s2sConfig: { account: "PREBID-SERVER-ACCOUNT", - bidders: [ "rubicon", "appnexus" ], + bidders: [ "bidderA", "bidderB" ], + defaultVendor: 'vendor1', enabled: true, testing: true, bidderControl: { - rubicon: { + bidderA: { bidSource: {client:100}, includeSourceKvp: true } } + }, + targetingControls: { + addTargetingKeys: ['SOURCE'] + } }); ``` + And then changes to override one particular AdUnit for server testing: -``` +```javascript AdUnit={ [...] bids=[{ - bidder: "rubicon", + bidder: "bidderA", bidSource: {server:25, client:75} [...] }] } ``` -Requests will go to the Rubicon Exchange on the server path 25% of the time -and the client path the rest of the time. The additional hb_source_rubicon + +Requests will go to bidderA on the server path 25% of the time +and the client path the rest of the time. The additional hb_source_bidderA KVP will be sent to the ad server for additional reporting. -### 3. A/B Test isolating the server +### 3. A/B Test isolating the server *As a Publisher, I want to get metrics on the difference between a 'pure server' approach and a mixed client-server approach so we can gauge the impact of Prebid Server running alone, without any client requests. I'll use the `testServerOnly: true` flag to suppress all client requests whenever the 'A/B test group' results in a server request.* @@ -180,44 +198,51 @@ For best results, all bidders/bids in the 'A/B test group' should be configured Example S2S Config defining that 5% of the time all bid requests will go 'server' and 95% of the time a mix of 'server' and 'client': -``` -pbjs.setConfig( +```javascript +pbjs.setConfig({ s2sConfig: { account: "PREBID-SERVER-ACCOUNT", - bidders: [ "rubicon", "criteo" ], + bidders: [ "bidderA", "bidderB" ], + defaultVendor: 'vendor1', enabled: true, testing: true, testServerOnly: true, bidderControl: { - rubicon: { + bidderA: { bidSource: {client:95, server 5}, includeSourceKvp: true }, - criteo: { + bidderB: { bidSource: {client:95, server 5}, includeSourceKvp: true } } + }, + targetingControls: { + addTargetingKeys: ['SOURCE'] + } }); AdUnit={ [...] bids=[{ - bidder: "index", + bidder: "bidderA", [...] },{ - bidder: "rubicon", + bidder: "bidderB", [...] },{ - bidder: "criteo", + bidder: "bidderC", [...] }] } ``` -5% of the time rubicon, and criteo will use s2s bid requests while index does not bid, and the other 95% of the time rubicon, criteo, and index use client bid requests. + +5% of the time bidderA and bidderB will use s2s bid requests while bidderC does not bid, and the other 95% of the time all bidders use client bid requests. Addtional details: -- If a bidder is always 100% server-side -- i.e. doesn't have either `s2sConfig.bidderControl` or `AdUnit.bids[].bidSource`, then it will not affect `testServerOnly`. i.e. It's going on the server path will not exclude client side adapters. + +* If a bidder is always 100% server-side -- i.e. doesn't have either `s2sConfig.bidderControl` or `AdUnit.bids[].bidSource`, then it will not affect `testServerOnly`. i.e. It's going on the server path will not exclude client side adapters. ### 4. Turn on Test KVP, but no server requests @@ -226,26 +251,29 @@ other use cases above. I'll use the test KVP to confirm relative responses, so would like to have the `hb_source` test KVP coming in even on pages where the server test isn't running.* -Example S2S Config defining that client is the default path for the rubicon adapter: +Example S2S Config defining that client is the default path for bidderA: -``` -pbjs.setConfig( +```javascript +pbjs.setConfig({ s2sConfig: { ... enabled: false, testing: true, bidderControl: { - "rubicon": { - "bidSource": {client:100}, + bidderA: { + bidSource: {client:100}, includeSourceKvp: true } } + }, + targetingControls: { + addTargetingKeys: ['SOURCE'] + } }); ``` -The test KVP hb_source_rubicon on this page will always sent with the value "client". -## Further Reading - -+ [Prebid Server](/prebid-server/overview/prebid-server-overview.html) +The test KVP hb_source_bidderA on this page will always sent with the value "client". +## Further Reading +* [Prebid Server](/prebid-server/overview/prebid-server-overview.html) diff --git a/dev-docs/modules/schain.md b/dev-docs/modules/schain.md index 4534f4840b..562d1f5b8c 100644 --- a/dev-docs/modules/schain.md +++ b/dev-docs/modules/schain.md @@ -10,6 +10,7 @@ sidebarType : 1 --- # Supply Chain Object Module + {:.no_toc} * TOC @@ -19,16 +20,17 @@ Service Providers who manage Prebid wrappers on behalf of multiple publishers an Two modes are supported: -- **Global Supply Chains** +* **Global Supply Chains** Use this configuration when the Prebid.js implementation is managed by an entity that needs to add an SChain node to every bid request. i.e. payments flow through this entity for all traffic. -- **Bidder-Specific Supply Chains** +* **Bidder-Specific Supply Chains** Use this configuration when one or more bid adapters is an entity (such as a reseller) that requires an SChain node, but other adapters do not require the node. e.g. payments flow through a bidder that doesn't add its own schain node. ## How to Use the Module First, build the schain module into your Prebid.js package: -``` + +```bash gulp build --modules=schain,... ``` @@ -38,7 +40,7 @@ The module performs validations on the schain data provided and makes it availab Call `setConfig` with the `schain` object to be used: -{% highlight js %} +```javascript pbjs.setConfig({ "schain": { "validation": "strict", @@ -55,13 +57,13 @@ pbjs.setConfig({ } } }); -{% endhighlight %} +``` ### Bidder-Specific Supply Chains This method uses the `pbjs.setBidderConfig` function, with a syntax similar to the global scenario above. -{% highlight js %} +```javascript pbjs.setBidderConfig({ "bidders": ['bidderA'], // can list more bidders here if they share the same config "config": { @@ -81,7 +83,7 @@ pbjs.setBidderConfig({ } } }); -{% endhighlight%} +``` You can find more information about the `pbjs.setBidderConfig` function in the [Publisher API Reference]({{site.baseurl}}/dev-docs/publisher-api-reference/setBidderConfig.html). @@ -124,5 +126,5 @@ $(function(){ ## Further Reading -- [IAB OpenRTB SupplyChain Object Specification](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md) -- [Sellers.json Specification](https://iabtechlab.com/sellers-json/) +* [IAB OpenRTB SupplyChain Object Specification](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/supplychainobject.md) +* [Sellers.json Specification](https://iabtechlab.com/sellers-json/) diff --git a/dev-docs/modules/sirdataRtdProvider.md b/dev-docs/modules/sirdataRtdProvider.md index 68a07237f2..860e5952e3 100644 --- a/dev-docs/modules/sirdataRtdProvider.md +++ b/dev-docs/modules/sirdataRtdProvider.md @@ -11,13 +11,14 @@ vendor_specific: true sidebarType : 1 --- -# Sirdata RTD Segmentation Module +# Sirdata RTD/SDA Module + {:.no_toc} * TOC {:toc} -Sirdata provides a disruptive API that allows publishers and curating SSPs to leverage its cutting-edge contextualization technology and its audience segments based on cookies and consent or without cookies nor consent, even in Europe! +Sirdata provides a disruptive API that allows publishers and curating SSPs to leverage its cutting-edge contextualization technology and its audience segments based on cookies and consent or without cookies nor consent, even in Europe! User-based segments and page-level automatic contextual categories will be attached to bid request objects sent to different SSPs in order to optimize targeting. @@ -27,7 +28,9 @@ User's country and choice management are included in the module, so it's 100% co ORTB2 compliant and FPD support for Prebid versions < 4.29 -Please contact prebid@sirdata.com for more information. +Now supports Seller Defined Audience ! + +Please contact for more information. ## Publisher Usage @@ -41,15 +44,15 @@ Add the Sirdata RTD provider to your Prebid config. `actualUrl` MUST be set with actual location of parent page if prebid.js is loaded in an iframe (eg. postbid). It can be left blank ('') or removed otherwize. -`partnerId` and `key` should be provided by your partnering SSP or get one and your dedicated taxonomy from Sirdata (prebid@sirdata.com). Segments ids (user-centric) and category ids (page-centric) will be provided salted and hashed : you can use them with a dedicated and private matching table. +`partnerId` and `key` should be provided by your partnering SSP or get one and your dedicated taxonomy from Sirdata (). Segments ids (user-centric) and category ids (page-centric) will be provided salted and hashed : you can use them with a dedicated and private matching table. -Should you want to allow a SSP or a partner to curate your media and operate cross-publishers campaigns with our data, please ask Sirdata (prebid@sirdata.com) to whitelist him it in your account. +Should you want to allow a SSP or a partner to curate your media and operate cross-publishers campaigns with our data, please ask Sirdata () to whitelist him it in your account. #### Minimal configuration -``` -pbjs.setConfig( - ... +```javascript +pbjs.setConfig({ + // ... realTimeData: { auctionDelay: 1000, dataProviders: [ @@ -57,21 +60,21 @@ pbjs.setConfig( name: "SirdataRTDModule", waitForIt: true, params: { - partnerId: 1, + partnerId: 1, key: 1, } } ] } - ... -} + // ... +}); ``` #### Advanced configuration -``` -pbjs.setConfig( - ... +```javascript +pbjs.setConfig({ + // ... realTimeData: { auctionDelay: 1000, dataProviders: [ @@ -93,13 +96,17 @@ pbjs.setConfig( bidder: 'ix', sizeLimit: 1200 //specific to Index Exchange, contextualMinRelevancyScore: 50, //Min score to filter contextual category for curation in the bidder (0-100 scale) + },{ + bidder: 'smartadserver' + },{ + bidder: 'proxistore' }] } } ] } - ... -} + // ... +}); ``` ### Parameter Descriptions for the Sirdata Configuration Section @@ -109,8 +116,8 @@ pbjs.setConfig( | name | String | Real time data module name | Mandatory. Always 'SirdataRTDModule' | | waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true | | params | Object | | Optional | -| params.partnerId | Integer | Partner ID, required to get results and provided by Sirdata. Use 1 for tests and get one running at prebid@sirdata.com | Mandatory. Defaults 1. | -| params.key | Integer | Key linked to Partner ID, required to get results and provided by Sirdata. Use 1 for tests and get one running at prebid@sirdata.com | Mandatory. Defaults 1. | +| params.partnerId | Integer | Partner ID, required to get results and provided by Sirdata. Use 1 for tests and get one running at | Mandatory. Defaults 1. | +| params.key | Integer | Key linked to Partner ID, required to get results and provided by Sirdata. Use 1 for tests and get one running at | Mandatory. Defaults 1. | | params.setGptKeyValues | Boolean | This parameter Sirdata to set Targeting for GPT/GAM | Optional. Defaults to true. | | params.contextualMinRelevancyScore | Integer | Min score to keep filter category in the bidders (0-100 scale). Optional. Defaults to 30. | | params.bidders | Object | Dictionary of bidders you would like to supply Sirdata data for. | Optional. In case no bidder is specified Sirdata will atend to ad data custom and ortb2 to all bidders, adUnits & Globalconfig | @@ -121,42 +128,81 @@ Bidders can receive common setting : | bidder | String | Bidder name | Mandatory if params.bidders are specified | | adUnitCodes | Array of String | Use if you want to limit data injection to specified adUnits for the bidder | Optional. Default is false and data shared with the bidder isn't filtered | | customFunction | Function | Use it to override the way data is shared with a bidder | Optional. Default is false | -| curationId | String | Specify the curation ID of the bidder. Provided by Sirdata, request it at prebid@sirdata.com | Optional. Default curation ids are specified for main bidders | +| curationId | String | Specify the curation ID of the bidder. Provided by Sirdata, request it at | Optional. Default curation ids are specified for main bidders | | contextualMinRelevancyScore | Integer | Min score to filter contextual categories for curation in the bidder (0-100 scale). Optional. Defaults to 30 or global params.contextualMinRelevancyScore if exits. | | sizeLimit | Integer | used only for bidder 'ix' to limit the size of the get parameter in Index Exchange ad call | Optional. Default is 1000 | - ### Overriding data sharing function As indicated above, it is possible to provide your own bid augmentation functions. This is useful if you know a bid adapter's API supports segment fields which aren't specifically being added to request objects in the Prebid bid adapter. Please see the following example, which provides a function to modify bids for a bid adapter called ix and overrides the appnexus. - -``` data Object format for usage in this kind of function : + +```json { - "segments":[111111,222222], - "contextual_categories":{"333333":100}, - "shared_taxonomy":{ - "27446":{ //CurationId - "segments":[444444,555555], - "contextual_categories":{"666666":100} - } - } + "segments": [ + 111111, + 222222 + ], + "segtaxid": null, + "cattaxid": null, + "contextual_categories": { + "333333": 100 + }, + "shared_taxonomy": { + "27440": { + "segments": [ + 444444, + 555555 + ], + "segtaxid": 552, + "cattaxid": 553, + "contextual_categories": { + "666666": 100 + } + } + }, + "global_taxonomy": { + "9998": { + "segments": [ + 123, + 234 + ], + "segtaxid": 4, + "cattaxid": 7, + "contextual_categories": { + "345": 100, + "456": 100 + } + }, + "9999": { + "segments": [ + 12345, + 23456 + ], + "segtaxid": 550, + "cattaxid": 551, + "contextual_categories": { + "34567": 100, + "45678": 100 + } + } + } } ``` -``` +```javascript function overrideAppnexus (adUnit, segmentsArray, dataObject, bid) { - for (var i = 0; i < segmentsArray.length; i++) { + for (var i = 0; i < segmentsArray.length; i++) { if (segmentsArray[i]) { bid.params.user.segments.push(segmentsArray[i]); } } } -pbjs.setConfig( - ... +pbjs.setConfig({ + // ... realTimeData: { auctionDelay: 1000, dataProviders: [ @@ -164,11 +210,11 @@ pbjs.setConfig( name: "SirdataRTDModule", waitForIt: true, params: { - partnerId: 1, + partnerId: 1, key: 1, - setGptKeyValues: true, - contextualMinRelevancyScore: 50, //Min score to keep contextual category in the bidders (0-100 scale) - actualUrl: actual_url, //top location url, for contextual categories + setGptKeyValues: true, + contextualMinRelevancyScore: 50, //Min score to keep contextual category in the bidders (0-100 scale) + actualUrl: actual_url, //top location url, for contextual categories bidders: [{ bidder: 'appnexus', customFunction: overrideAppnexus, @@ -185,15 +231,17 @@ pbjs.setConfig( ] } ... -} +}); ``` ### Testing To view an example of available segments returned by Sirdata's backends: -`gulp serve --modules=rtdModule,sirdataRtdProvider,appnexusBidAdapter` +```bash +gulp serve --modules=rtdModule,sirdataRtdProvider,appnexusBidAdapter +``` and then point your browser at: -`http://localhost:9999/integrationExamples/gpt/sirdataRtdProvider_example.html` +[http://localhost:9999/integrationExamples/gpt/sirdataRtdProvider_example.html] diff --git a/dev-docs/modules/sizeMapping.md b/dev-docs/modules/sizeMapping.md new file mode 100644 index 0000000000..8aa2172c13 --- /dev/null +++ b/dev-docs/modules/sizeMapping.md @@ -0,0 +1,210 @@ +--- +layout: page_v2 +page_type: module +title: Module - Size Mapping +description: Display Responsive AdUnits in demanding page environments. +module_code: sizeMapping +display_name: Size Mapping +enable_download: true +sidebarType: 1 +--- + +# Size Mapping Module + +{: .no_toc } + +* TOC +{: toc } + +## Overview + +The size mapping module enables the global `sizeConfig` configuration which, together with labels, allows for responsive ad units. + +{% capture tip-choosing %} +As of Prebid.js 3.11.0, the [Advanced SizeMapping module](/dev-docs/modules/sizeMappingV2.html) provides an alternate way to handle responsive AdUnits. +You should consider using that module if any of these scenarios are true: +{::nomarkdown} +
        +
      • You need to work with video or native AdUnits
      • +
      • The site needs to alter different AdUnits at different screen widths; e.g., the left-nav changes sizes at 600 pixels, but the footer's size behavior changes at 620 pixels.
      • +
      • The site needs to alter different mediaTypes at different screen widths; e.g., the banner size ranges are 0-400px, 401-700px, and 701+px, but the native ads appear at 500px.
      • +
      • Some bidders or mediaTypes should be included (or removed) at different overlapping size ranges.
      • +
      +
      +{:/} +If, on the other hand, you're only working with the banner mediaType and the AdUnits all change behavior together at the same viewport width, then the built-in sizeConfig feature is appropriate. +{% endcapture %} +{% include alerts/alert_tip.html content=tip-choosing %} + + + +## Configure Responsive Ads + +The `sizeConfig` object passed to `pbjs.setConfig` provides a global way to describe types of devices and screens using [CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries). See below for an explanation of the feature and examples showing how to use it. + + + +### How Size Config Works for Banners + +* Before `requestBids` sends bid requests to adapters, it will evaluate and pick the appropriate label(s) based on the `sizeConfig.mediaQuery` and device properties. Once it determines the active label(s), it will then filter the `adUnit.bids` array based on the `labels` defined and whether the `banner` mediaType was included. Ad units that include a `banner` mediaType that don't match the label definition are dropped. +* The required `sizeConfig.mediaQuery` property allows [CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries). The queries are tested using the [`window.matchMedia`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) API. +* If a label conditional (e.g. `labelAny`) doesn't exist on an ad unit, it is automatically included in all requests for bids. +* If multiple rules match, the sizes will be filtered to the intersection of all matching rules' `sizeConfig.sizesSupported` arrays. +* The `adUnit.mediaTypes.banner.sizes` selected will be filtered based on the `sizesSupported` of the matched `sizeConfig`. So the `adUnit.mediaTypes.banner.sizes` is a subset of the sizes defined from the resulting intersection of `sizesSupported` sizes and `adUnit.mediaTypes.banner.sizes`. (Note: size config will also operate on `adUnit.sizes`, however `adUnit.sizes` is deprecated in favor of `adUnit.mediaTypes`) + +### Note on sizeConfig and different mediaTypes + +The sizeConfig logic only applies to `adUnits`/`bids` that include the `banner` `mediaType` (regardless of whether the request is single or multi-format). + +For example, if a request contained the `banner` and `video` `mediaTypes` and it failed the label check, then the entire adUnit/bid would be dropped (including the `video` part of the request). However if the same request passed the label check, then the `adUnit.mediaTypes.banner.sizes` would be filtered as per the matching sizeConfig and the multi-format request would proceed as normal. + +If the ad unit does not include `banner` `mediaType` at all, then the sizeConfig logic will not influence that ad Unit; it will automatically be passed into the auction. + + + +### Size Config Example + +To set size configuration rules, pass in `sizeConfig` as follows: + +```javascript + +pbjs.setConfig({ + sizeConfig: [{ + 'mediaQuery': '(min-width: 1600px)', + 'sizesSupported': [ + [1000, 300], + [970, 90], + [728, 90], + [300, 250] + ], + 'labels': ['desktop-hd'] + }, { + 'mediaQuery': '(min-width: 1200px)', + 'sizesSupported': [ + [970, 90], + [728, 90], + [300, 250] + ], + 'labels': ['desktop'] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet'] + }, { + 'mediaQuery': '(min-width: 0px)', + 'sizesSupported': [ + [300, 250], + [300, 100] + ], + 'labels': ['phone'] + }] +}); + +``` + +## Labels + +There are two parts to defining responsive and conditional ad units with labels: + +1. Defining the labels +2. Defining the conditional ad unit targeting for the labels + +Labels may be defined in two ways: + +1. Through [`sizeConfig`](#configure-responsive-ads) +2. As an argument to [`pbjs.requestBids`](/dev-docs/publisher-api-reference/requestBids.html) + +```javascript +pbjs.requestBids({labels: []}); +``` + +Labels may be targeted in the AdUnit structure by two conditional operators: `labelAny` and `labelAll`. + +With the `labelAny` operator, just one label has to match for the condition to be true. In the example below, either A or B can be defined in the label array to activate the bid or ad unit: + +```javascript +labelAny: ["A", "B"] +``` + +With the `labelAll` conditional, every element of the target array must match an element of the label array in +order for the condition to be true. In the example below, both A and B must be defined in the label array to activate the bid or ad unit: + +```javascript +labelAll: ["A", "B"] +``` + +{: .alert.alert-warning :} +Only one conditional may be specified on a given AdUnit or bid -- if both `labelAny` and `labelAll` are specified, only the first one will be utilized and an error will be logged to the console. It is allowable for an AdUnit to have one condition and a bid to have another. + +{: .alert.alert-warning :} +If either `labeAny` or `labelAll` values is an empty array, it evaluates to `true`. + +{: .alert.alert-warning :} +It is important to note that labels do not act as filters for sizeConfig. In the example above, using a screen of 1600px wide and `labelAll:["desktop"]` will *not* filter out sizes defined in the `desktop-hd` sizeConfig. Labels in sizeConfig are only used for selecting or de-selecting AdUnits and AdUnit.bids. + +Label targeting on the ad unit looks like the following: + +```javascript +pbjs.addAdUnits([{ + code: "ad-slot-1", + mediaTypes: { + banner: { + sizes: [ + [970, 90], + [728, 90], + [300, 250], + [300, 100] + ] + } + }, + labelAny: ["visitor-uk"] + /* The full set of bids, not all of which are relevant on all devices */ + bids: [{ + bidder: "pulsepoint", + /* Labels flag this bid as relevant only on these screen sizes. */ + labelAny: ["desktop", "tablet"], + params: { + "cf": "728X90", + "cp": 123456, + "ct": 123456 + } + }, + { + bidder: "pulsepoint", + labelAny: ["desktop", "phone"], + params: { + "cf": "300x250", + "cp": 123456, + "ct": 123456 + } + }, + { + bidder: "sovrn", + labelAny: ["desktop", "tablet"], + params: { + "tagid": "123456" + } + }, + { + bidder: "sovrn", + labelAny: ["phone"], + params: { + "tagid": "111111" + } + } + ] +}]); + +``` + +See [Conditional Ad Units]({{site.baseurl}}/dev-docs/conditional-ad-units.html) for additional use cases around labels. + + + +## Further Reading + +* [Advanced size mapping](/dev-docs/modules/sizeMappingV2.html) +* [Conditional Ad Units](/dev-docs/conditional-ad-units.html) diff --git a/dev-docs/modules/sizeMappingV2.md b/dev-docs/modules/sizeMappingV2.md index d5c52b2218..22b1bf8bde 100644 --- a/dev-docs/modules/sizeMappingV2.md +++ b/dev-docs/modules/sizeMappingV2.md @@ -1,7 +1,7 @@ --- layout: page_v2 page_type: module -title: Module - Size Mapping +title: Module - Advanced Size Mapping description: Display Responsive AdUnits in demanding page environments. module_code: sizeMappingV2 display_name: Advanced Size Mapping @@ -10,6 +10,7 @@ sidebarType: 1 --- # Advanced Size Mapping Module + {: .no_toc } * TOC @@ -19,10 +20,10 @@ sidebarType: 1 The Advanced Size Mapping module enables configuration of responsive ad units with more flexibility than the [core `sizeConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) feature. It detects the browser viewport dimensions, and based on that, applies a series of checks on the ad unit to determine: - - which banner sizes should be active - - what the playerSize is for a video media type - - whether the native media type should be active - - whether a particular bidder should participate in the auction +* which banner sizes should be active +* what the playerSize is for a video media type +* whether the native media type should be active +* whether a particular bidder should participate in the auction The module can act on all three media types, **banner**, **video**, and **native**, and can be used to control their behavior. It can also activate/deactivate a particular bidder based on some checks.
      @@ -42,6 +43,8 @@ It's meant for publishers that have complex site designs. You should use this mo If, on the other hand, the AdUnits, bidders, and mediaTypes all change behavior together at the same viewport width, then the built-in [`sizeConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) feature will work. + +Note that the Prebid Server bid adapter does not currently support the scenario where an adUnit has multiple mediaTypes, with different bidders set to different relevantMediaTypes for the same screen size. {% endcapture %} {% include alerts/alert_tip.html content=tip-choosing %} @@ -49,11 +52,11 @@ then the built-in [`sizeConfig`](/dev-docs/publisher-api-reference/setConfig.htm If you've used [`sizeConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Configure-Responsive-Ads) in Prebid.js before, read this section to learn about the differences. If you haven't used sizeConfig before, you can skip to the next section. -- The biggest change to size mapping is the introduction of **AdUnit** and **Bidder** level sizeConfig declarations. Instead of defining a global sizeConfig object configured in [`pbjs.setConfig`](/dev-docs/publisher-api-reference/setConfig.html#module_pbjs.setConfig), each Ad Unit and Bidder can define and control their own set of sizeConfig rules. This process makes it easier to reason which sizes should be active for the current viewport size in complex scenarios. +* The biggest change to size mapping is the introduction of **AdUnit** and **Bidder** level sizeConfig declarations. Instead of defining a global sizeConfig object configured in [`pbjs.setConfig`](/dev-docs/publisher-api-reference/setConfig.html#module_pbjs.setConfig), each Ad Unit and Bidder can define and control their own set of sizeConfig rules. This process makes it easier to reason which sizes should be active for the current viewport size in complex scenarios. -- A **sizeConfig** parameter may be specified on the AdUnit mediaType or a bidder. In these scenarios, the syntax is a little different than with the global configuration. Here's an example for a sizeConfig object for banner media type: +* A **sizeConfig** parameter may be specified on the AdUnit mediaType or a bidder. In these scenarios, the syntax is a little different than with the global configuration. Here's an example for a sizeConfig object for banner media type: -{% highlight js %} +```javascript mediaTypes: { banner: { sizeConfig: [ @@ -62,17 +65,17 @@ If you've used [`sizeConfig`](/dev-docs/publisher-api-reference/setConfig.html#s ]; } } -{% endhighlight %} +``` -- **Labels** aren't defined in AdUnit sizeConfig objects. Instead of funneling viewport sizes into a small number of labeled scenarios, the Advanced Size Mapping approach allows each AdUnit and Bidder to define separate size buckets. Labels are still an effective way to do other tasks such as filtering AdUnits and Bidders based on their geo location. For more details on Labels, visit [Conditional Ad Units](/dev-docs/conditional-ad-units.html). +* **Labels** aren't defined in AdUnit sizeConfig objects. Instead of funneling viewport sizes into a small number of labeled scenarios, the Advanced Size Mapping approach allows each AdUnit and Bidder to define separate size buckets. Labels are still an effective way to do other tasks such as filtering AdUnits and Bidders based on their geo location. For more details on Labels, visit [Conditional Ad Units](/dev-docs/conditional-ad-units.html). -- Likewise, **mediaQuery** is not used in AdUnit sizeConfig objects. Instead, an array of size buckets is defined by just the `minViewPort` property. Only one size bucket activates based on viewport size. +* Likewise, **mediaQuery** is not used in AdUnit sizeConfig objects. Instead, an array of size buckets is defined by just the `minViewPort` property. Only one size bucket activates based on viewport size. It may be useful to compare the globally-configured sizeConfig with the AdUnit-level sizeConfig. [Here is an example](/dev-docs/publisher-api-reference/setConfig.html#sizeConfig-Example) using global sizeConfig. Here's that same example using Advanced Size Mapping: -{% highlight js %} +```javascript const adUnit = { code: "ad-slot-1", mediaTypes: { @@ -86,7 +89,7 @@ Here's that same example using Advanced Size Mapping: } } } -{% endhighlight %} +``` Note the tradeoff here: If you're specifying duplicate sizeConfigs on every AdUnit, you might be better off using the global sizeConfig approach. But if the global approach isn't flexible enough for your site design, the AdUnit-level approach is the right way to go. @@ -116,14 +119,13 @@ What happens as a result of each active size bucket changes based on the media t | mediaTypes.native | active | `true` | Indicates whether Native mediaTypes should be active or not for this size bucket in this AdUnit. | | bids.bidder | relevantMediaTypes | `['banner', 'video', 'native']` or `['none']` | An array that defines a list of mediaTypes that a bidder will bid on for this size bucket in this AdUnit. Set to ['none'] if no mediaType of this size bucket. | - ### Examples #### An AdUnit with Banner Media Type, Bidder-Level sizeConfig, and Labels Note that the labels are assumed to be passed in via [`pbjs.requestBids()`](/dev-docs/publisher-api-reference.html#module_pbjs.requestBids). -{% highlight js%} +```javascript { code: 'ad-code-1', mediaTypes: { @@ -155,31 +157,34 @@ Note that the labels are assumed to be passed in via [`pbjs.requestBids()`](/dev ] }] } -{% endhighlight %} +``` Here are two requests and how they would be handled in this scenario: I. A request originating in the US, viewport size: `[1400px, 800px]` -- Steps for **bidderA**: + +* Steps for **bidderA**: 1. AdUnit passes label check. 2. Size bucket `[1200, 0]` gets activated. Sizes: `[[970, 400], [300, 200], [300, 250]]` are active at AdUnit level. 3. BidderA passes label check. 4. Request for Banner media type sent to bidderA with sizes: `[[970, 400], [300, 200], [300, 250]]` -- Steps for **bidderB**: +* Steps for **bidderB**: 1. AdUnit passes label check. 2. Size bucket `[1200, 0]` gets activated. Sizes: `[[970, 400], [300, 200], [300, 250]]` are active at AdUnit level. 3. At the Bidder level, size bucket, `[1200, 0]` gets activated. Relevant media types is set to `none`. This deactivates the bidder. 4. No bid request is sent for bidderB. II. A request originating in the UK, viewport size: `[1700px, 900px]` -- Steps for both bidders: + +* Steps for both bidders: 1. AdUnit passes label check. 2. Size bucket `[1600, 0]` gets activated. Sizes is `[]`, and an empty array indicates no sizes for the current viewport, which disables the Ad Unit. 3. No request will be sent to either bidder. #### Example of a Multi-Format AdUnit with Bidder-Level sizeConfig -{% highlight js%} + +```javascript { code: 'ad-code-2', mediaTypes: { @@ -191,7 +196,7 @@ II. A request originating in the UK, viewport size: `[1700px, 900px]` }, video: { context: 'instream', - ... other video params ... + ... other video params ... sizeConfig: [ { minViewPort: [0, 0], playerSize: [] }, { minViewPort: [1200, 0], playerSize: [640, 400]} @@ -227,23 +232,25 @@ II. A request originating in the UK, viewport size: `[1700px, 900px]` ] }] } -{% endhighlight %} +``` Here are two requests and how they would be handled in this scenario: I. A mobile device with viewport size: `[460px, 300px]` -- Steps for both bidders: + +* Steps for both bidders: 1. Size bucket `[0, 0]` activates for all three media types. Banner is deactivated due to `sizes: []`. Video is deactivated since `playerSize: []`. Native is deactivated since `active: false`. 2. Since no media type is active, the AdUnit is deactivated. 3. No request is sent for either bidder, even though bidderB's minViewPort would have allowed video or native. II. A tablet with viewport size: `[1100px, 980px]` -- Steps for **bidderA**: + +* Steps for **bidderA**: 1. Size bucket `[900, 0]` activates for banner media type, so the associated sizes are active. Size bucket `[0, 0]` activates for video media type. Its associated property is `playerSize: []`, so the video media type gets disabled. Size bucket `[600, 0]` activates for native media type. Its associated property is `active: true`, which keeps native media type active at the AdUnit level. 2. At the Bidder level, size bucket `[700, 0]` activates. Associated property `relevantMediaTypes` is set to `['banner']`. 3. Only the banner media type is sent to bidderA even though native was activated at the AdUnit level. -- Steps for **bidderB**: +* Steps for **bidderB**: 1. The AdUnit-level activations are the same as for bidderA. 2. At the level of bidderB, size bucket `[400, 0]` activates. Associated property `relevantMediaTypes` is set to `['native', 'video']`. Since video media type is already disabled at the AdUnit level, request for video won't be sent to the bidder. 3. Only a request for native media type is sent to bidderB. @@ -252,11 +259,11 @@ II. A tablet with viewport size: `[1100px, 980px]` Follow the basic build instructions in the GitHub Prebid.js repo's main [README](https://github.com/prebid/Prebid.js/blob/master/README.md). To include the Advanced Size Mapping module, the `sizeMappingV2` module must be added to the **gulp build** command: -{% highlight bash %} +```bash gulp build --modules=sizeMappingV2,bidAdapter1,bidAdapter2 -{% endhighlight %} +``` ## Further Reading -- [Global sizeConfig](/dev-docs/publisher-api-reference.html#setConfig-Configure-Responsive-Ads) -- [Conditional Ad Units](/dev-docs/conditional-ad-units.html) +* [Global sizeConfig](/dev-docs/modules/sizeMapping.html) +* [Conditional Ad Units](/dev-docs/conditional-ad-units.html) diff --git a/dev-docs/modules/timeoutRtdProvider.md b/dev-docs/modules/timeoutRtdProvider.md index 7830eb7b40..5e0aa25c54 100644 --- a/dev-docs/modules/timeoutRtdProvider.md +++ b/dev-docs/modules/timeoutRtdProvider.md @@ -11,26 +11,30 @@ sidebarType : 1 --- ## Overview -The timeout RTD module enables publishers to set rules that determine the timeout based on -certain features. It supports rules dynamically retrieved from a timeout provider as well as rules + +The timeout RTD module enables publishers to set rules that determine the timeout based on +certain features. It supports rules dynamically retrieved from a timeout provider as well as rules set directly via configuration. -Build the timeout RTD module into the Prebid.js package with: -``` +Build the timeout RTD module into the Prebid.js package with: + +```bash gulp build --modules=timeoutRtdProvider,rtdModule... ``` ## Configuration -The module is configured in the realTimeData.dataProviders object. The module will override -`bidderTimeout` in the pbjs config. + +The module is configured in the realTimeData.dataProviders object. The module will override +`bidderTimeout` in the pbjs config. ### Timeout Data Provider interface -The timeout RTD module provides an interface of dynamically fetching timeout rules from -a data provider just before the auction begins. The endpoint url is set in the config just as in + +The timeout RTD module provides an interface of dynamically fetching timeout rules from +a data provider just before the auction begins. The endpoint url is set in the config just as in the example below, and the timeout data will be used when making bid requests. - -``` + +```javascript pbjs.setConfig({ - ... + // ... "realTimeData": { "dataProviders": [{ "name": 'timeout', @@ -45,18 +49,19 @@ pbjs.setConfig({ // This value below will be modified by the timeout RTD module if it successfully // fetches the timeout data. "bidderTimeout": 1500, - ... + // ... }); ``` -Sample Endpoint Response: -``` +Sample Endpoint Response: + +```json { "rules": { "includesVideo": { "true": 200, "false": 50 - }, + }, "numAdUnits" : { "1-5": 100, "6-10": 200, @@ -73,34 +78,39 @@ Sample Endpoint Response: "fast": 50, "unknown": 10 }, + } } ``` -### Rule Handling: -The rules retrieved from the endpoint will be used to add time to the `bidderTimeout` based on certain features such as +### Rule Handling + +The rules retrieved from the endpoint will be used to add time to the `bidderTimeout` based on certain features such as the user's deviceType, connection speed, etc. These rules can also be configured statically on page via a `rules` object. -Note that the timeout Module will ignore the static rules if an endpoint url is provided. The timeout rules follow the +Note that the timeout Module will ignore the static rules if an endpoint url is provided. The timeout rules follow the format: -``` + +```javascript { '': { '': } } ``` + See bottom of page for examples. Currently supported features: |Name |Description | Keys | Example | :------------ | :------------ | :------------ |:------------ | -| includesVideo | Adds time to the timeout based on whether there is a video ad unit in the auction or not | 'true'/'false'| { "true": 200, "false": 50 } | +| includesVideo | Adds time to the timeout based on whether there is a video ad unit in the auction or not | 'true'/'false'| { "true": 200, "false": 50 } | | numAdUnits | Adds time based on the number of ad units. Ranges in the format `'lowerbound-upperbound` are accepted. This range is inclusive | numbers or number ranges | {"1": 50, "2-5": 100, "6-10": 200} | | deviceType | Adds time based on device type| 2, 4, or 5| {"2": 50, "4": 100} | | connectionSpeed | Adds time based on connection speed. `connectionSpeed` defaults to 'unknown' if connection speed cannot be determined | slow, medium, fast, or unknown | { "slow": 200} | If there are multiple rules set, all of them would be used and any that apply will be added to the base timeout. For example, if the rules object contains: -``` + +```javascript { "includesVideo": { "true": 200, @@ -112,12 +122,14 @@ If there are multiple rules set, all of them would be used and any that apply wi } } ``` + and there are 3 ad units in the auction, all of which are banner, then the timeout to be added will be 150 milliseconds (50 for `includesVideo[false]` + 100 for `numAdUnits['1-3']`). Full example: -``` + +```javascript pbjs.setConfig({ - ... + // ... "realTimeData": { "dataProviders": [{ "name": 'timeout', @@ -145,15 +157,16 @@ pbjs.setConfig({ } } } - ]} + }] } - ... + // ... // The timeout RTD module will add time to `bidderTimeout` based on the rules set above. "bidderTimeout": 1500, +}) ``` ## Timeout Providers {: .table } | Partner | Contact | About | -| OpenX | [apollo@openx.com](mailto:apollo@openx.com) | Dynamic timeout optimization and more | \ No newline at end of file +| OpenX | [apollo@openx.com](mailto:apollo@openx.com) | Dynamic timeout optimization and more | diff --git a/dev-docs/modules/topicsFpdModule.md b/dev-docs/modules/topicsFpdModule.md new file mode 100644 index 0000000000..30eff8b5e0 --- /dev/null +++ b/dev-docs/modules/topicsFpdModule.md @@ -0,0 +1,83 @@ +--- +layout: page_v2 +page_type: module +title: Module - topicsFpdModule +description: how to get topics data using Topics API +module_code : topicsFpdModule +display_name : Topics FPD Module +enable_download : true +sidebarType : 1 +--- + +# Topics First Party Data (FPD) Module + +This module is use to call the Topics API (document.browsingTopics()) which will fetch the first party domain as well third party domain(Iframe) topics data which will be sent onto user.data in bid stream. + +To learn more about topics in general, visit [googles blog "Get to know the new Topics API for Privacy Sandbox"](https://blog.google/products/chrome/get-know-new-topics-api-privacy-sandbox/). + +This document covers the steps necessary for publishers to enable Topics Data on their inventory. It also describes +the configuration needed to override topics Iframe Default implementation + +## Publisher Integration + +Publishers wishing to enable must compile Prebid.js with support for this module. +This is accomplished by adding the `topicsFpdModule` module to the list of modules they are already using: + +```bash +gulp build --modules=topicsFpdModule,... +``` + +# Description + +The intent of the Topics API is to provide callers (including third-party ad-tech or advertising providers on the page that run script) with coarse-grained advertising topics that the page visitor might currently be interested in. + +Topics Module(topicsFpdModule) should be included in prebid final package to call topics API. +Module topicsFpdModule helps to call the Topics API which will send topics data in bid stream (onto user.data) + +```javascript +try { + if ('browsingTopics' in document && document.featurePolicy.allowsFeature('browsing-topics')) { + topics = document.browsingTopics(); + } +} catch (e) { + console.error('Could not call topics API', e); +} +``` + +# Topics Iframe Configuration + +Topics iframe implementation is the enhancements of existing module under topicsFpdModule.js where different bidders will call the topic API under their domain to fetch the topics for respective domain and the segment data will be part of ORTB request under user.data object. Default config is maintained in the module itself. + +Below are the configuration which can be used to configure and override the default config maintained in the module. + +```javascript +pbjs.setConfig({ + userSync: { + // ..., + topics: { + maxTopicCaller: 3, // SSP rotation + bidders: [{ + bidder: 'pubmatic', + iframeURL: 'https://ads.pubmatic.com/AdServer/js/topics/topics_frame.html', + expiry: 7 // Configurable expiry days + },{ + bidder: 'appnexus', + iframeURL: 'https://appnexus.com:8080/topics/fpd/topic.html', // dummy URL + expiry: 7 // Configurable expiry days + }] + } + // ... + } +}) +``` + +## Topics Config Descriptions + +{: .table .table-bordered .table-striped } +| Field | Required? | Type | Description | +| --- | --- | --- | --- | +| topics.maxTopicCaller | no | integer | Defines the maximum numbers of Bidders Iframe which needs to be loaded on the publisher page. Default is 1 which is hardcoded in Module. Eg: topics.maxTopicCaller is set to 3. If there are 10 bidders configured along with their iframe URLS, random 3 bidders iframe URL is loaded which will call TOPICS API. If topics.maxTopicCaller is set to 0, it will load random 1(default) bidder iframe atleast. | +| topics.bidders | no | Array of objects | Array of topics callers with the iframe locations and other necessary informations like bidder(Bidder code) and expiry. Default Array of topics in the module itself.| +| topics.bidders[].bidder | yes | string | Bidder Code of the bidder(SSP). | +| topics.bidders[].iframeURL | yes | string | URL which is hosted on bidder/SSP/third-party domains which will call Topics API. | +| topics.bidders[].expiry | no | integer | Max number of days where Topics data will be persist. If Data is stored for more than mentioned expiry day, it will be deleted from storage. Default is 21 days which is hardcoded in Module. | diff --git a/dev-docs/modules/userId.md b/dev-docs/modules/userId.md index c0c11f60a8..3025b6e144 100644 --- a/dev-docs/modules/userId.md +++ b/dev-docs/modules/userId.md @@ -25,19 +25,17 @@ The User ID module supports multiple ways of establishing pseudonymous IDs for u 1. The publisher builds Prebid.js by specifying one or more ID sub-modules they would like to include. e.g. "gulp build --modules=____IdSystem". You also need to add the `userId` module to your Prebid.js distribution. 1. The page defines User ID configuration in `pbjs.setConfig()` 1. When `setConfig()` is called, and if the user has consented to storing IDs locally, the module is invoked to call the URL if needed - 1. If the relevant local storage is present, the module doesn't call the URL and instead parses the scheme-dependent format, injecting the resulting ID into `bidRequest.userId`. - 1. If GDPR applies, the consent signal from the CMP is hashed and stored in a cookie called `_pbjs_userid_consent_data`. This is required so that ID sub-modules may be called to refresh their ID if the user's consent preferences have changed from the previous page, and ensures cached IDs are no longer used if consent is withdrawn. + 1. If the relevant local storage is present or the value of the id is specified in the configuration, the module doesn't call the URL and instead parses the scheme-dependent format, injecting the resulting ID into `bidRequest.userId`. + 1. If GDPR applies, the consent signal from the CMP is hashed and stored in a cookie called `_pbjs_userid_consent_data`. Real-time consent is obtained from the CMP and compared to this value; if the user id is in storage and consent has not changed, the call to the id module may be suppressed to save network traffic. This functionality is provided so that ID sub-modules may be called to refresh their ID if the user's consent preferences have changed from the previous page, for example, the encryption of an id may need to change if the id provider learns it now has consent to share the id with a new DSP. If this value is suppressed by the strictStorageEnforcement, the id call will not be suppressed from refreshing for this reason but may be suppressed by other enforcement settings. 1. An object containing one or more IDs (`bidRequest.userId`) is made available to Prebid.js adapters and Prebid Server S2S adapters. 1. In addition to `bidRequest.userId`, `bidRequest.userIdAsEids` is made available to Prebid.js adapters and Prebid Server S2S adapters. `bidRequest.userIdAsEids` has userIds in ORTB EIDS format. +1. The page can call [pbjs.getUserIds()](/dev-docs/publisher-api-reference/getUserIds.html), [pbjs.getUserIdsAsEids()](/dev-docs/publisher-api-reference/getUserIdsAsEids.html), or [pbjs.getUserIdsAsync()](/dev-docs/publisher-api-reference/getUserIdsAsync.html). {: .alert.alert-info :} -Note that User IDs aren't needed in the mobile app world because device ID is available in those ad serving scenarios. +Note that User IDs aren't as popular in the mobile app world because device ID is available in those ad serving scenarios. {: .alert.alert-info :} -Note that not all bidder adapters support all forms of user ID. See the tables below for a list of which bidders support which ID schemes. - -{: .alert.alert-info :} -As of Prebid 4.0, this module will attempt storage in the main domain of the publisher's website instead of a subdomain, unless this behavior is overriden by a submodule. +Not all bidder adapters support all forms of user ID. See the tables below for a list of which bidders support which ID schemes. ## User ID, GDPR, Permissions, and Opt-Out @@ -59,45 +57,53 @@ Without third-party cookies, mechanisms like the [NAI](https://optout.networkadv Publishers that want to do this should design their workflow and then set `_pbjs_id_optout` cookie or HTML5 local storage. For instance: -- read from an in-page javascript variable and set `_pbjs_id_optout` to any value. -- call an in-page function and use the results to create a `_pbjs_id_optout` cookie with any value. - +* read from an in-page javascript variable and set `_pbjs_id_optout` to any value. +* call an in-page function and use the results to create a `_pbjs_id_optout` cookie with any value. ## Basic Configuration By including this module and one or more of the sub-modules, a number of new options become available in `setConfig()`, -under the `userSync` object as attributes of the `userIds` array -of sub-objects. In addition, publishers using Google AdManager may want to sync one of the identifiers as their Google PPID for frequency capping or reporting. -The PPID has strict rules; refer to [Google AdManager documentation](https://support.google.com/admanager/answer/2880055?hl=en) for them. +under the `userSync` object as attributes of the `userIds` array of sub-objects. + +The `value` parameter can be used to indicate an identifier the publisher has obtained via a direct integration with that identity provider that the publisher wishes to make available to Prebid.js bidders. + +Publishers using Google AdManager may want to sync one of the identifiers as their Google PPID for frequency capping or reporting. +The PPID in GAM (which is unrelated to the PPID UserId Submodule) has strict rules; refer to [Google AdManager documentation](https://support.google.com/admanager/answer/2880055?hl=en) for them. Please note, Prebid uses a [GPT command](https://developers.google.com/publisher-tag/reference#googletag.PubAdsService) to sync identifiers for publisher convenience. It doesn't currently work for instream video requests, as Prebid typically interacts with the player, which in turn may interact with IMA. IMA does has a [similar method](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/reference/js/google.ima.ImaSdkSettings#setPpid) as GPT, but IMA does not gather this ID from GPT. {: .table .table-bordered .table-striped } | Param under userSync | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | -| ppid | Optional | String | Must be a source from the pbjs.getUserIdsAsEids() array | `"pubcid.org"` | +| ppid | Optional | String | Must be a source from the [pbjs.getUserIdsAsEids()](#getUserIdsAsEids) array | `"pubcid.org"` | The table below has the options that are common across ID systems. See the sections below for specific configuration needed by each system and examples. +{% assign userid_pages = site.pages | where: "layout", "userid" | sort_natural: "title" %} + +{% assign name_string = "" %} +{% assign count = 0 %} + {: .table .table-bordered .table-striped } | Param under userSync.userIds[] | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | -| name | Required | String | May be: `"admixerId"`, `"adtelligentId"`, `"akamaiDAPId"`, `"amxId"`, `"britepoolId"`, `"criteo"`, `"fabrickId"`, `"flocId"`, `"hadronId"`, `"id5id"`, `identityLink`, `"idx"`, `"intentIqId"`, `"liveIntentId"`, `"lotamePanoramaId"`, `"merkleId"`, `"naveggId"`, `"mwOpenLinkId"`, `"netId"`, `"novatiqId"`, `"parrableId"`, `"quantcastId"`, `"pubProvidedId"`, `"sharedId"`, `"tapadId"`, `"unifiedId"`,`"uid2"`, `"verizonMediaId"`, `"zeotapIdPlus"` | `"unifiedId"` +| name | Required | String | May be any of the following values: {% for page in userid_pages -%}{% if count == 1 %}{{ name_string │ append: ", " -}}{% endif %}{% assign count = 1 %}`"{{ name_string │ append: name_string -}}{{ name_string │ append: page.useridmodule -}}"`{% endfor %} | `"unifiedId"` | | params | Based on User ID sub-module | Object | | | | bidders | Optional | Array of Strings | An array of bidder codes to which this user ID may be sent. | `['bidderA', 'bidderB']` | -| storage | Optional | Object | The publisher can specify some kind of local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. This is not needed when `value` is specified or the ID system is managing its own storage | | -| storage.type | Required | String | Must be either `"cookie"` or `"html5"`. This is where the results of the user ID will be stored. | `"cookie"` | +| storage | Optional | Object | The publisher can specify some kind of local storage in which to store the results of the call to get the user ID. This can be cookie, HTML5 storage or both. This is not needed when `value` is specified or the ID system is managing its own storage | | +| storage.type | Required | String | Must be `"cookie"`, `"html5"` or `"cookie&html5"`. This is where the results of the user ID will be stored. | `"cookie"` | | storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"_unifiedId"` | | storage.expires | Strongly Recommended | Integer | How long (in days) the user ID information will be stored. If this parameter isn't specified, session cookies are used in cookie-mode, and local storage mode will create new IDs on every page. | `365` | -| storage.refreshInSeconds | Optional | Integer | The amount of time (in seconds) the user ID should be cached in storage before calling the provider again to retrieve a potentially updated value for their user ID. If set, this value should equate to a time period less than the number of days defined in `storage.expires`. By default the ID will not be refreshed until it expires. -| value | Optional | Object | Used only if the page has a separate mechanism for storing a User ID. The value is an object containing the values to be sent to the adapters. | `{"tdid": "1111", "pubcid": {2222}, "IDP": "IDP-2233", "id5id": {"uid": "ID5-12345"}}` | - +| storage.refreshInSeconds | Optional | Integer | The amount of time (in seconds) the user ID should be cached in storage before calling the provider again to retrieve a potentially updated value for their user ID. If set, this value should equate to a time period less than the number of days defined in `storage.expires`. By default the ID will not be refreshed until it expires. | `30` | +| value | Optional | Object | Used only if the page has a separate mechanism for storing a User ID. The value is an object containing the values to be sent to the adapters. | `{"tdid": "1111", "IDP": "IDP-2233", "id5id": {"uid": "ID5-12345"}}` | ## Permissions + Publishers can control which user ids are shared with the bid adapters they choose to work with by using the bidders array. The bidders array is part of the User id module config, publisher may choose to send an id to some bidders but not all, the default behavior is that each user id go to all bid adapters the publisher is working with. Use the optional `bidders` parameter to define an array of bidder codes to which this user ID may be sent. In this example the SharedID sub adapter is only allowed to be sent to the Rubicon adapter. -``` + +```javascript userIds: [ { name: "sharedId", @@ -116,11 +122,13 @@ userIds: [ } ] ``` + The Rubicon bid adapter would then receive -``` + +```javascript { "bidder": "rubicon", - ... + // ... "userId": { "sharedid": { "id": "01*******", @@ -141,2129 +149,264 @@ The Rubicon bid adapter would then receive ] } ], - ... + // ... } ``` -## User ID Sub-Modules - -### AkamaiDAPId - -The Akamai Data Activation Platform (DAP) is a privacy-first system that protects end-user privacy by only allowing them to be targeted as part of a larger cohort. DAP views hiding individuals in large cohorts as the best mechanism to prevent unauthorized tracking. - -The integration of DAP into Prebid.JS consists of creating a UserID plugin that interacts with the DAP API. The UserID module tokenizes the end-user identity into an ephemeral, secure pseudonymization called a dapId. The dapId is then supplied to the bid-stream where the SSP partner looks up cohort membership for that token, and supplies the cohorts to the rest of the bid-stream. +## Prebid multiple identifiers populated by user id submodule -In this system, no end-user identifier is supplied to the bid-stream, only cohorts. This is a foundational privacy principal DAP is built upon. +It is possible for a user id submodule to populate several identifiers including identifiers that could also be populated by other user id submodules leading to collisions. In such cases of id collisions, it is possible to add a configurable prioritization to the core user id module. This will allow publishers to specify which user id submodule has priority for populating the identifier over other user id submodules. -#### AkamaiDAPId Configuration - -First, make sure to add the DAP submodule to your Prebid.js package with: - -``` -gulp build --modules=akamaiDAPIdSystem,userId -``` +This can be configured inside the `userSync` object in the following manner: -The following configuration parameters are available: +Let's say that the UID2 token populated by the trade desk user id submodule has the value 'uid2_value' and the UID2 token populated by Liveintent user id module has the value 'liveIntentUid2_value' (The actual identifiers populated in this case should be one and the same however the values are written differently in order to help the reader understand the source from which the identifiers get picked up from) ```javascript -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'akamaiDAPId', - params: { - apiHostname: '', - domain: 'your-domain.com', - type: 'email' | 'mobile' | ... | 'dap-signature:1.0.0', - identity: ‘your@email.com’ | ‘6175551234' | ..., - apiVersion: 'v1' | 'x1', - attributes: '{ "cohorts": [ "3:14400", "5:14400", "7:0" ],"first_name": "...","last_name": "..." }' - }, - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules +"userSync": { + "idPriority": { + "uid2": ['liveIntentId', 'uid2'] + } } -}); -``` -In order to make use of v1 APIs, "apiVersion" needs to explicitly mention 'v1'. The "apiVersion" defaults to x1 if not specified. -"attributes" can be configured in x1 API only and not v1 APIs. Please ensure that the "attributes" value is in same format as shown above. - -Contact Prebid@akamai.com(Akamai account rep) for apiHostname. - - -### AdmixerID - -Admixer ID, provided by [Admixer] (https://admixer.com/), is a universal ID solution that doesn't rely on 3rd party cookies and helps publishers and advertisers to recognize users across various browsers and environments. Our sub adapter takes deterministic signals like email and phone as input and returns an anonymous id that unlocks access to a wide range of Admixer's demand sources, amplifying audience segmentation, targeting and measurement. -The Admixer privacy policy is at https://admixer.com/privacy/ - -Add Admixer ID module to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=admixerIdSystem - -#### AdmixerID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"admixerId"` | `"admixerId"` | -| params | Required | Object | Details for admixer initialization. | | -| params.pid | Optional | String | id provided by admixer | "458frgde-djd7-3ert-gyhu-12fghy76dnmko" | -| params.e | Optional | String | The hashed email address of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha256. | "3d400b57e069c993babea0bd9efa79e5dc698e16c042686569faae20391fd7ea" | -| params.p | Optional | String | The hashed phone number of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha256. | "05de6c07eb3ea4bce45adca4e0182e771d80fbb99e12401416ca84ddf94c3eb9" | - -#### AdmixerID Examples - -1) Individual params may be set for the Admixer ID Submodule. - -{% highlight javascript %} - pbjs.setConfig({ - userSync: { - userIds: [{ - name: "admixerId", - storage: { - name: "admixerId", - type: "cookie", - expires: 30 - }, - params: { - pid: "4D393FAC-B6BB-4E19-8396-0A4813607316", // example id - e: "3d400b57e069c993babea0bd9efa79e5dc698e16c042686569faae20391fd7ea", // example hashed email (sha256) - p: "05de6c07eb3ea4bce45adca4e0182e771d80fbb99e12401416ca84ddf94c3eb9" //example hashed phone (sha256) - } - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules - } - }); -{% endhighlight %} - -### Adtelligent - -The [Adtelligent](https://adtelligent.com) ID system is a unique per-session user identifier for providing high quality DMP data for advertisers - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=userId,adtelligentIdSystem - -#### Adtelligent Configuration - -adtelligentIdSystem adapter doesn't require any configuration or storage params. The adapter performs asynchronously and to achieve better performance it is recommended to set the `storage` object `refreshInSeconds` to a short period, such as ten minutes. At the end of the set storage refresh the adapter will refresh its configuration. - -#### Adtelligent Example - -{% highlight javascript %} - pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'adtelligent' - }] - } - }); -{% endhighlight %} - -Example with a short storage for ~10 minutes and refresh in 5 minutes: - -{% highlight javascript %} - pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'adtelligent', - storage: { - type: "html5", - name: "adt_id", - expires:0.003, - refreshInSeconds: 60 * 5 - } - }] - } - }); -{% endhighlight %} - -### AMX RTB ID - -The AMX RTB ID is a first-party identifier designed for publishers using the AMX RTB adapter. For more information please contact [prebid@amxrtb.com](prebid@amxrtb.com) - -#### AMX RTB ID Configuration - -First, add the AMX RTB ID module to your Prebid.js build: - -```shell -gulp build --modules=userId,amxIdSystem ``` -Then configure the amxId in your `userSync` configuration: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'amxId', - storage: { - name: 'amxId', - type: 'html5', - expires: 14, - } - }] - } -}); -``` - -This will add a `userId.amxId` property to all bidRequests. This will be read by the AMX RTB bid adapter, and any other adapters that support EIDs: +The corresponding user id object and the eids array will look like this: ```javascript { - amxId: '3ca11058-ecbc-419f-bda7-b52fe7baf02a' + // ... + "userId": { + "uid2": { + "id": "liveIntentUid2_value_98*******" + } + }, + "userIdAsEids": [ + { + "source": "uidapi.com", + "uids": [ + { + "id": "liveIntentUid2_value_98*******", + "atype": 3, + "ext": { + "provider": "liveintent.com" + } + } + ] + } + ], + // ... } ``` -### BritePool +## User ID Sub-Modules -The [BritePool](https://britepool.com) ID is a persistent identifier that enables identity resolution for people-based marketing in the cookieless world. Every BritePool ID is associated with a real identity. As a result, publishers, SSPs and DSPs that integrate with BritePool, or automated -integration partners (such as PubMatic), are able to maximize revenues without cookies. As addressable individuals visit publisher websites and mobile apps, the BritePool IDs associated with these identities are passed into the bidstream; enabling advertisers to transact against these BritePool ID's and publishers to maximize the revenues associated with their inventory and audience. The BritePool ID combines consumer privacy with easy, rapid integration for publishers and does not significantly increase the computing resources required of DSPs and SSPs. +{% assign userid_pages = site.pages | where: "layout", "userid" | sort_natural: "title" %} -Add it to your Prebid.js package with: +{% for page in userid_pages %} +
    • {{page.title}}
    • +{% endfor %} -{: .alert.alert-info :} -gulp build --modules=britepoolIdSystem +## Bidder Adapter Implementation -#### BritePool Registration +If your ID structure is complicated, it is helpful to add tests for `pbjs.getUserIds()`, `pbjs.getUserIdsAsEids()` and `pbjs.getUserIdsAsync()`. -Please reach out to [prebid@britepool.com](mailto:prebid@britepool.com) and request your `api_key`. +To add a custom data type for the response of `pbjs.getUserIdsAsEids()`, see other examples within the `createEidsArray` method in [/modules/userId/eid.js](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.js). -The BritePool privacy policy is at [https://britepool.com/services-privacy-notice/](https://britepool.com/services-privacy-notice/). +### Prebid.js Adapters -#### BritePool Configuration +Bidders that want to support the User ID module in Prebid.js need to update their bidder adapter to read the indicated bidRequest attributes and pass them to their endpoint. {: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"britepoolId"` | `"britepoolId"` | -| params | Required | Object | Details for britepool initialization. | | -| params.api_key | Required | String | BritePool API Key provided by BritePool | "458frgde-djd7-3ert-gyhu-12fghy76dnmko" | -| params.url | Optional | String | BritePool API url | "https://sandbox-api.britepool.com/v1/britepool/id" | -| params.identifier | Required | String | Where identifier in the params object is the key name. At least one identifier is required. Available Identifiers `aaid` `dtid` `idfa` `ilid` `luid` `mmid` `msid` `mwid` `rida` `ssid` `hash` | `params.ssid` `params.aaid` | - -#### BritePool Examples - -1) Individual params may be set for the BritePool User ID Submodule. At least one identifier must be set in the params. - -{% highlight javascript %} - pbjs.setConfig({ - userSync: { - userIds: [{ - name: "britepoolId", - storage: { - name: "britepoolid", - type: "cookie", - expires: 30 - }, - params: { - url: "https://sandbox-api.britepool.com/v1/britepool/id", // optional. used for testing - api_key: "xxx", // provided by britepool - hash: "yyyy", // example identifier - ssid: "r894hvfnviurfincdejkencjcv" // example identifier - } - }], - syncDelay: 3000 // 3 seconds after the first auction - } - }); -{% endhighlight %} - -### Criteo ID for Exchanges - -Criteo is the leading advertising platform for the Open Internet. The Criteo ID for Exchanges module enables publishers to access Criteo’s unique demand - more than 20.000 advertisers & brands - to monetize their exchange inventory with an optimal take rate across all browsing environments. -Note that direct access to that demand is also available through [Criteo Direct Bidder](https://www.criteo.com/products/criteo-direct-bidder/), in which case this module is unnecessary. - -The Criteo privacy policy is at [https://www.criteo.com/privacy/](https://www.criteo.com/privacy/). - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=criteoIdSystem - -#### Criteo ID Configuration - -The Criteo ID module does not require any configuration parameters. It should work as-is provided that bidders use it in their adapters. -When calling Criteo RTB, partners should forward this id in the field `user.ext.prebid_criteoid`. +| ID System Name | ID System Host | Prebid.js Attr: bidRequest.userId. | EID Source | Example Value | +| --- | --- | --- | --- | --- | --- | +| 33Across ID | 33Across | 33acrossId | 33across.com | "1111" | +| Admixer ID | Admixer | admixerId | admixer.net | "1111" | +| adQuery QiD | adQuery | qid | adquery.io | "p9v2dpnuckkzhuc..." | +| Adriver ID | Adriver | adriverId | adriver.ru | "1111" | +| Adtelligent ID | Adtelligent | adtelligentId | adtelligent.com | `"1111"` | +| AMX ID | AMX | amxId | amxdt.net | "3ca11058-..." | +| BritePool ID | BritePool | britepoolid | britepool.com | "1111" | +| AudienceOne ID | DAC | dacId | dac.co.jp | {"id": "1111"} | +| DeepIntent ID | Deep Intent | deepintentId | deepintent.com | "1111" | +| DMD ID | DMD | dmdId | hcn.health | "1111" | +| Czech Ad ID | czechAdId | czechAdId | czechadid.cz | "1111" | +| CriteoID | Criteo | criteoId | criteo.com | "1111" | +| Fabrick ID | Neustar | fabrickId | neustar.biz | "1111" | +| FLoC ID | n/a | flocId | | | +| GrowthCode ID | GrowthCode | growthCodeId | growthcode.io | "1111" | +| Hadron ID | Audigent | hadronId | audigent.com | {"hadronId":"user-hadron-id", "auSeg":["segment1", "segment2"]} | +| ID+ | Zeotap | IDP | zeotap.com | "1111" | +| ID5 ID | ID5 | id5id | id5-sync.com | {uid: "1111", ext: { linkType: 2, abTestingControlGroup: false } } | +| IdentityLink | LiveRamp | idl_env | liveramp.com | "1111" | +| Intent IQ ID | Intent IQ | intentiqid | intentiq.com | "1111" | +| Kinesso ID | Kinesso | kpuid | kpuid.com | "1111" | +| LiveIntent ID | Live Intent | lipb.lipbid | liveintent.com | "1111" | +| Lotame Panorama ID | Lotame | lotamePanoramaId | crwdcntrl.net | "e4b9..." | +| MediaWallah OpenLink ID | MediaWallah | mwOpenLinkId | mediawallahscript.com | "1111" | +| merkleID | Merkle | merkleId | merkleinc.com | "1111" | +| naveggId | Navegg | naveggId | navegg.com | "1111" | +| netID | netID | netId | netid.de | "fH5A..." | +| Novatiq ID | Novatiq | novatiqId | novatiq.com | "1111" | +| Parrable ID | Parrable | parrableId | parrable.com | {"eid":"01.15946..."} | +| Publisher Link ID | n/a | publinkId | epsilon.com | | +| PubProvided ID | n/a | pubProvidedId | publisher domain | "1111" | +| Quantcast ID | n/a | quantcastId | quantcast.com | "1111" | +| Tapad ID | Tapad | tapadId | tapad.com | "1111" | +| Teads ID | Teads | teadsId | teads.com | "1111" | +| SharedID (PBJS 5.x) | n/a | pubcid | pubcid.org | "1111" | +| SharedID (PBJS 4.x)| Prebid | sharedid | sharedid.org | {"id":"01EAJWWN...", "third":"01EAJ..."} | +| Unified ID | Trade Desk | tdid | adserver.org | "1111" | +| ConnectID | Yahoo | connectId | yahoo.com | {"connectId": "72d04af6..."} | +| FreePass ID | FreePass | freepassId | | "1111" | +| UtiqMtp ID | Utiq | utiqMtpId | utiq-mtp.com | "1111" | -{: .alert.alert-info :} -NOTE: For optimal performance, the Criteo Id module should be called at every opportunity. It embeds its own optimal caching mechanism. It's best not to use `params.storage` with this module as it may only lower the performances. If you are using multiple id systems, however, you may use it for the other id systems that supports it. +For example, the adapter code might do something like: -#### Criteo ID Example +```javascript + if (bidRequest.userId && bidRequest.userId.sharedid) { + url+="&pubcid="+bidRequest.userId.sharedid; + } +``` -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "criteo", - }] - } -}); -{% endhighlight %} +### Prebid Server Adapters -### Deepintent DPES ID by Deepintent +Bidders that want to support the User ID module in Prebid Server need to update their server-side bid adapter to read the desired OpenRTB 'user.ext.eids.source' object and forward the relevant values to their endpoint. -The DeepIntent Healthcare Marketing Platform is the first and only DSP that combines real-world health data, premium partnerships, and custom integrations to reach patients and providers across any device. DeepIntent empowers publishers to maximize their inventory, collaborate and transact directly with advertisers, and grow their business in a safe, controlled, transparent, and privacy-compliant way. Our publisher partners sell inventory on every channel via real-time bidding or conducting one-to-one trading with hundreds of the country’s leading healthcare brands and agencies. +See the [Prebid.js EIDs javascript source](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.js) for the definitive list of user EID sources. -DeepIntent’s DPES ID is a shared user identifier built for healthcare marketers and publishers integrated within DeepIntent’s Healthcare Marketplace. The DPES ID lets users protect and manage their privacy throughout the advertising value chain. User data written and associated with the DPES ID is not stored on DeepIntent’s servers. Instead, this data is stored in a decentralized way on a user’s browser. Users can still opt out of the ads by navigating to https://option.deepintent.com/adchoices + +### Exporting User IDs -#### Deepintent DPES ID Registration +If you need to export the user IDs stored by Prebid User ID module, the `getUserIds()` function will return an object formatted the same as bidRequest.userId. -DPES ID is free to use and requires a simple registration with DeepIntent. Please reach out to DeepIntent’s Publisher Development team at prebid@deepintent.com to learn more and get started. Once a publisher registers with DeepIntent’s platform, DeepIntent will provide a simple code snippet to be integrated with the publisher’s website. This code snippet will capture and store information per the publisher’s end user agreement. The DPES User ID module uses the DPES ID by passing it within the DeepIntent Prebid adapter. +```javascript +pbjs.getUserIds() // returns object like bidRequest.userId. e.g. {"pubcid":"1111", "tdid":"2222"} +``` -#### Deepintent DPES ID Configuration + -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module: `"deepintentId"` | `"deepintentId"` | -| storage | Required | Object | Storage settings for how the User Id module will cache the Deepintent ID locally | | -| storage.type | Required | String | This is where the results of the user ID will be stored. Deepintent`"html5"` or `"cookie"`. | `"html5"` | -| storage.name | Optional | String | The name of the local storage where the user ID will be stored. Deepintent | `"_dpes_id"` | -| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. Deepintent recommends `90`. | `90` | +You can use `getUserIdsAsEids()` to get the user IDs stored by Prebid User ID module in ORTB Eids format. Refer [eids.md](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.md) for output format. -#### Deepintent DPES ID Examples +```javascript +pbjs.getUserIdsAsEids() // returns userIds in ORTB Eids format. e.g. +[ + { + source: 'pubcid.org', + uids: [{ + id: 'some-random-id-value', + atype: 1 + }] + }, -1) Publisher stores the hashed identity from healthcare identity in cookie -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'deepintentId', - storage: { - type: 'cookie', // "html5" is the required storage type option is "html5" - name: '_dpes_id', - expires: 90 // storage lasts for 90 days, optional if storage type is html5 - } - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules - } -}); -{% endhighlight %} + { + source: 'adserver.org', + uids: [{ + id: 'some-random-id-value', + atype: 1, + ext: { + rtiPartner: 'TDID' + } + }] + }, -2) Publisher stores the hashed identity from healthcare identity in localstorage -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'deepintentId', - storage: { - type: 'html5' // "html5" is the required storage type option is "html5" - name: '_dpes_id' - } - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + { + source: 'id5-sync.com', + uids: [{ + id: 'ID5-12345', + atype: 1, + ext: { + linkType: 2, + abTestingControlGroup: false + } + }] } -}); -{% endhighlight %} - -### DMD ID by DMD Marketing Corp - -DMD is the preeminent supplier of US-based healthcare professional (HCP) identity data to the pharmaceutical, health system and medical publishing industries. DMD is the only data provider that has acquired its deterministic identity data through a fully consented, first-party, opt-in process. DMD’s privacy policy that can be found at [Privacy Policy](https://hcn.health/privacy-policy). - -For assistance setting up your module, please contact us at prebid@dmdconnects.com - -Add the DMD ID to your Prebid.js Package with: - -{: .alert.alert-info :} -gulp build --modules=userId,dmdIdSystem - -#### DMD ID Registration - -Please reach out to [prebid@dmdconnects.com](mailto:prebid@dmdconnects.com) to request your `api_key` - -#### DMD ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of Module | `"dmdId"` | -| storage | Required | Object | | -| storage.name | Required | String | `dmd-dgid` | -| params | Required | Object | Container of all module params. | | -| params.api_key | Required | String | This is your `api_key` as provided by DMD Marketing Corp. | `3fdbe297-3690-4f5c-9e11-ee9186a6d77c` | - -#### DMD ID Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'dmdId', - params: { - api_key: '3fdbe297-3690-4f5c-9e11-ee9186a6d77c' // provided to you by DMD - } - }] - } -}); -{% endhighlight %} - -### Fabrick ID by Neustar - -[Neustar Fabrick™](https://www.home.neustar/fabrick) is a unified identity ecosystem that powers connections between brands, publishers, and consumers to accelerate marketing performance across online and offline channels. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=fabrickIdSystem - -#### Fabrick Registration - -Please reach out to [FabrickIntegrations@team.neustar](mailto:FabrickIntegrations@team.neustar) to request your `apiKey`. - -#### Fabrick Configuration +] +``` -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `"fabrickId"` | -| params | Required | Object | Container of all module params. | | -| params.apiKey | Required | String | This is your apiKey as provided by Neustar. | | -| params.e | | String | This is a hashed email address used to link a user to their Fabrick ID. | | -| params.p | | String | This is a hashed phone number used to link a user to their Fabrick ID. | | -| params.i4 | | String | This is an IPv4 address used to link a user to their Fabrick ID. | | -| params.i6 | | String | This is an IPv6 address used to link a user to their Fabrick ID. | | -| params.m | | String | This is a mobile advertising ID (IDFA/AAID) used to link a user to their Fabrick ID. | | -| params.ia | | String | This is an identifier for advertising (IFA) used to link a user to their Fabrick ID. | | -| params.iv | | String | This is an identifier for vendors (IFV) used to link a user to their Fabrick ID. | | - -#### Fabrick Examples - -1) Publisher passes an apiKey and hashed email address and elects to store the Fabrick ID envelope in a cookie. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'fabrickId', - params: { - apiKey: '123456789', // provided to you by Neustar - e: '31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66' // example hashed email address (sha256) - }, - storage: { - name: 'pbjs_fabrickId', - type: 'cookie', - expires: 7 - } - }] - } -}); -{% endhighlight %} + -2) Publisher passes an apiKey and hashed email address and elects to store the fabrickId envelope in HTML5 localStorage. +`pbjs.getUserIds()` and `pbjs.getUserIdsAsEids()` may return only some IDs, or none at all, if they are called before all ID providers have had a chance to initialize - depending on [`auctionDelay` and/or `syncDelay`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-ConfigureUserSyncing-UserSyncProperties), that may need to wait until an auction has completed. +To access the complete set of IDs, you may use `getUserIdsAsync`, which returns a promise that is guaranteed to resolve only once all IDs are available: -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'fabrickId', - params: { - apiKey: '123456789', // provided to you by Neustar - e: '31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66' // example hashed email address (sha256) - }, - storage: { - type: "html5", - name: "pbjs_fabrickId", - expires: 7 - } - }] - } +```javascript +pbjs.getUserIdsAsync().then(function (userIds) { + // all IDs are available here: + pbjs.getUserIds() // same as the `userIds` argument + pbjs.getUserIdsAsEids() }); -{% endhighlight %} - -### FLoC ID - -The [Federated Learning of Cohorts (FLoC)](https://web.dev/floc/) system provides a privacy-preserving mechanism for interest-based ad selection. As a user moves around the web, their browser uses the FLoC algorithm to work out an "interest cohort", which will be the same for thousands of browsers with a similar recent browsing history. The user's browser is associated with one interest cohort at a time and recalculates its cohort periodically (currently once every seven days during this initial origin trial) on the user's device, without sharing individual browsing data with the browser vendor or anyone else. +``` -There are two important things to note when using the FLoC Userid Sub adapter. +## ID Providers -1. Unlike other user id subadapters FLoC ids cannot be stored in a cookie or Local Storage. FLoC ids change periodically and should always be fetched from the FLoC API +If you're an ID provider that wants to get on this page: -2. The function `(getGlobal()).getUserIds` returns `userId.flocId.id=value` into the bid request **NOT** `userid.userIdAsEids`. +* Fork Prebid.js and write a sub-module similar to one of the *IdSystem modules already in the [modules](https://github.com/prebid/Prebid.js/tree/master/modules) folder. +* Add your *IdSystem name into the modules/.submodules.json file +* Follow all the guidelines in the [contribution page](https://github.com/prebid/Prebid.js/blob/master/CONTRIBUTING.md). +* Submit a Pull Request against the [Prebid.js repository](https://github.com/prebid/Prebid.js). +* Fork the prebid.org [documentation repository](https://github.com/prebid/prebid.github.io), modify /dev-docs/modules/userId.md, /download.md, and submit a documentation Pull Request. -To include the FLoC user id module use: + -`$ gulp build --modules=flocIdSystem` +## ESP Configurations -{: .alert.alert-info :} -Note: FLoC is still in a trial period. [How to take part in the FLoC origin trial](https://developer.chrome.com/blog/floc/). During the trial, a token is -required. Publishers may get their own token or use sharedid's token if they choose. Use this without the line breaks: -A3dHTSoNUMjjERBLlrvJSelNnwWUCwVQhZ5tNQ+sll7y+LkPPVZXtB77u2y7CweRIxiYaGw -GXNlW1/dFp8VMEgIAAAB+eyJvcmlnaW4iOiJodHRwczovL3NoYXJlZGlkLm9yZzo0NDMiLC -JmZWF0dXJlIjoiSW50ZXJlc3RDb2hvcnRBUEkiLCJleHBpcnkiOjE2MjYyMjA3OTksImlzU -3ViZG9tYWluIjp0cnVlLCJpc1RoaXJkUGFydHkiOnRydWV9 +Google now supports Encrypted Signals for Publishers(ESP), a program that allows publishers can explicitly share encrypted signals on bid requests with third-party bidders. User ID modules now support code which will register the signal sources and encrypted signals are created and are sent to GAM request in a3p parameter. 'encryptedSignal' configuration under userSync Module will help to configure signal sources. +Please find more details [Share encrypted signals with bidders (Beta)](https://support.google.com/admanager/answer/10488752?hl=en). -#### FLoC ID Configuration +Alternatively, GAM can now pull IDs from Prebid for UserId submodules that [register with GAM](https://services.google.com/fb/forms/encryptedsignalsforpublishers-signalcollectorform/) For those registered submodules, publishers can [select Prebid UserID module (Beta) under "Signal collection deployment."](https://support.google.com/admanager/answer/10488752?hl=en). Publishers selecting this option should not also select those identifiers in the `encryptedSignalSources.sources.source` array. {: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | +| Param under userSync | Scope | Type | Description | Example | | --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `"flocId"` | -| params | Required | Object | Container of all module params. | | -| params.token | Required | String | This is your apiKey as provided by Chrome. This value is required during the origin trial phase but will be optional once the origin trial ends. Publishers may use sharedid's registered token if they choose. | `A3dHTSo...`| - -#### FLoC Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "flocId", - params: { - "token": "Registered token" // see above for sharedId's FLoC token - } - }], - syncDelay: 3000 // 3 seconds after the first auction - } -}); -{% endhighlight %} - -### Hadron ID from Audigent - -Audigent is a next-generation data management platform and a first-of-a-kind "data agency" containing some of the most exclusive content-consuming audiences across desktop, mobile and social platforms. Our HadronId module allows for user id resolution and Audigent user data segmentation to be retrieved for users across the web. For assistance setting up your module please contact us at [prebid@audigent.com](mailto:prebid@audigent.com). - -#### HadronId Configuration -Add the Hadron ID system to your Prebid.js package with: +| encryptedSignalSources | Optional | Object | Publisher can specify the ESP config by adding encryptedSignal Object under userSync Object | | +| encryptedSignalSources.sources | Required | Object | An array of Object consisting of a sources list and encryption flag | Check below config as an example | +| encryptedSignalSources.sources.source | Required | Array | An array of sources for which signals needs to be registered | `['sharedid.org','criteo.com']` | +| encryptedSignalSources.sources.encrypt | Required | Boolean | Should be set to false by default. Please find below note | `true` or `false` | +| encryptedSignalSources.sources.customFunc | Required | function | This function will be defined for custom sources only and called which will return the custom data set from the page | Check below config as an example | +| encryptedSignalSources.registerDelay | Optional | Integer | The amount of time (in milliseconds) after which registering of signals will happen. Default value 0 is considered if 'registerDelay' is not provided. | `3000` | {: .alert.alert-info :} -gulp build --modules=userId,hadronIdSystem - -Add HadronId to the userSync configuration. - -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'hadronId', - storage: { - name: 'hadronId', - type: 'html5' - } - }] - } -}); -``` - -The `request.userId.hadronId` will contain the Audigent HadronId: -``` -{ - "hadronId": "0201chpvai07jv2yg08xizqr0bwpa1w0evvmq014d2ykn0b5oe" -} -``` -The following configuration parameters are available: - -{: .table .table-bordered .table-striped } -| Param under usersync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the HadronID module - `"hadronId"` | `"hadronId"` | -| params | Optional | Object | Used to store params for the HadronId system | -| params.url | Optional | String | Set an alternate GET url for HadronId with this parameter | -| params.urlArg | Optional | Object | Optional url parameter for params.url | - -### ID+ - -ID+, powered by zeotap, enables the marketing ecosystem to overcome challenges posed by the demise of identifiers and a fast-changing regulatory landscape. ID+ is an open invitation to the entire industry to build the future of identity together. - -This sub-module enables the user’s ID+ to be available in the bid request. - -More information on ID+ can be found here: [https://idplus.io/](https://idplus.io/) - -Add it to your Prebid.js package with: +**NOTE:** +For eids encryption (encryptedSignalSources.encrypt) set to true is not recommended unless downstream is informed of the changes. {: .alert.alert-info :} -gulp build --modules=zeotapIdPlusIdSystem +**NOTE:** +Publishers enabling passing eids/signal through ESP should reach out to SSPs integrated through OB to make sure to take any additional steps needed to ensure impact on 3p cookie based transaction is handled and impact is minimal. -#### ID+ Registration +ESP Configuration Example: -You can set up your ID+ account by contacting our support team at [support.idplus@zeotap.com](mailto:support.idplus@zeotap.com) or via [https://idplus.io/contact-us](https://idplus.io/contact-us.html) and we will get back to you. - -ID+ is covered under zeotap privacy policy: [Zeotap Privacy Policy](https://zeotap.com/website-privacy-policy). - -#### ID+ Example - -{% highlight javascript %} +```javascript pbjs.setConfig({ userSync: { - userIds: [{ - name: "zeotapIdPlus" - }] + ..., + encryptedSignalSources: { + "sources": [{ + source: ['sharedid.org', 'criteo.com', 'id5-sync.com', 'pubcid.org', 'audigent.com'], + encrypt: false + }, { + source: ['pubmatic.com'], + customFunc: () => { + return '{"keywords":["tech","auto"]}'; + }, + encrypt: true + }, { + source: ['segment.com'], + customFunc: () => { + return '[{ "id": "1", "value": "seg1" },{ "id": "2", "value": "seg2" }]'; + }, + encrypt: true + }], + "registerDelay": 3000 + }, + .... } -}); -{% endhighlight %} - - -### ID5 Universal ID - -The ID5 ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 ID and detailed integration docs, please visit [our documentation](https://support.id5.io/portal/en/kb/articles/prebid-js-user-id-module). - - -#### ID5 ID Registration +}) -The ID5 ID is free to use, but requires a simple registration with ID5. Please visit [our website](https://id5.io/solutions/#publishers) to sign up and request your ID5 Partner Number to get started. - -The ID5 privacy policy is at [https://id5.io/platform-privacy-policy](https://id5.io/platform-privacy-policy). - -#### ID5 ID Configuration - -First, make sure to add the ID5 submodule to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=id5IdSystem,userId - -The following configuration parameters are available: - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` | -| params | Required | Object | Details for the ID5 ID. | | -| params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` | -| params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://support.id5.io/portal/en/kb/articles/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` | -| params.abTesting | Optional | Object | Allows publishers to easily run an A/B Test. If enabled and the user is in the Control Group, the ID5 ID will NOT be exposed to bid adapters for that request | Disabled by default | -| params.abTesting.enabled | Optional | Boolean | Set this to `true` to turn on this feature | `true` or `false` | -| params.abTesting.controlGroupPct | Optional | Number | Must be a number between `0.0` and `1.0` (inclusive) and is used to determine the percentage of requests that fall into the control group (and thus not exposing the ID5 ID). For example, a value of `0.20` will result in 20% of requests without an ID5 ID and 80% with an ID. | `0.1` | - -{: .alert.alert-info :} -**NOTE:** The ID5 ID that is delivered to Prebid will be encrypted by ID5 with a rotating key to avoid unauthorized usage and to enforce privacy requirements. Therefore, we strongly recommend setting `storage.refreshInSeconds` to `8` hours (`8*3600` seconds) or less to ensure all demand partners receive an ID that has been encrypted with the latest key, has up-to-date privacy signals, and allows them to transact against it. - -##### A Note on A/B Testing - -Publishers may want to test the value of the ID5 ID with their downstream partners. While there are various ways to do this, A/B testing is a standard approach. Instead of publishers manually enabling or disabling the ID5 User ID Module based on their control group settings (which leads to fewer calls to ID5, reducing our ability to recognize the user), we have baked this in to our module directly. - -To turn on A/B Testing, simply edit the configuration (see above table) to enable it and set what percentage of users you would like to set for the control group. The control group is the set of user where an ID5 ID will not be exposed in to bid adapters or in the various user id functions available on the `pbjs` global. An additional value of `ext.abTestingControlGroup` will be set to `true` or `false` that can be used to inform reporting systems that the user was in the control group or not. It's important to note that the control group is user based, and not request based. In other words, from one page view to another, a user will always be in or out of the control group. - -#### ID5 Universal ID Examples - -{: .alert.alert-warning :} -**ATTENTION:** As of Prebid.js v4.14.0, ID5 requires `storage.type` to be `"html5"` and `storage.name` to be `"id5id"`. Using other values will display a warning today, but in an upcoming release, it will prevent the ID5 module from loading. This change is to ensure the ID5 module in Prebid.js interoperates properly with the [ID5 API](https://github.com/id5io/id5-api.js) and to reduce the size of publishers' first-party cookies that are sent to their web servers. If you have any questions, please reach out to us at [prebid@id5.io](mailto:prebid@id5.io). - -Publisher wants to retrieve the ID5 ID through Prebid.js - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'id5Id', - params: { - partner: 173, // change to the Partner Number you received from ID5 - pd: 'MT1iNTBjY...', // optional, see table above for a link to how to generate this - abTesting: { // optional - enabled: true, // false by default - controlGroupPct: 0.1 // valid values are 0.0 - 1.0 (inclusive) - } - }, - storage: { - type: 'html5', // "html5" is the required storage type - name: 'id5id', // "id5id" is the required storage name - expires: 90, // storage lasts for 90 days - refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh - } - }], - auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules - } -}); -{% endhighlight %} - -### IDx - -IDx, a universal ID solution provided by [Retargetly](https://retargetly.com), is the evolution of digital identifiers for the Latin American region. Through a proprietary identity graph, it allows publishers, advertisers, and ad tech platforms to recognize users across domains and devices even where third party cookies aren't available. - -The IDx platform is designed with privacy at its core and allows for nearly every conceivable digital use case including but not limited to audience targeting, retargeting, frequency management, personalization, and total reach reporting. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=idxIdSystem - -#### IDx Registration - -If you are a publisher or an advertiser, then IDx is free to use but requires a simple registration process. To do this, please send an email to [idx-partners@retargetly.com](mailto:idx-partners@retargetly.com) to request your IDx Partner ID. - -We may ask for some basic information from you before approving your request. For more information on IDx, please visit [retargetly.com/idx](http://retargetly.com/idx). - -#### IDx Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"idx"` | `"idx"` | - -#### IDx Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "idx" - }] - } -}); -{% endhighlight %} - -### IM-UID by Intimate Merger - -IM-UID, provided by [Intimate Merger](https://corp.intimatemerger.com/), is a universal identifier that designed for publishers, platforms and advertisers to perform segmentation and targeting even in environments where 3rd party cookies are not available. IM-UID is currently only available in Japan. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=imuIdSystem - -#### IM-UID Registration - -Please visit [https://lp.intimatemerger.com/im-uid](https://lp.intimatemerger.com/im-uid) and request your Customer ID to get started. - -The Intimate Merger privacy policy is at https://corp.intimatemerger.com/privacypolicy/ - -#### IM-UID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `"imuid"` | -| params | Required | Object | Details of module params. | | -| params.cid | Required | Number | This is the Customer ID value obtained via Intimate Merger. | `5126` | -| params.url | Optional | String | Use this to change the default endpoint URL. | `"https://example.com/some/api"` | - -#### IM-UID Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "imuid", - params: { - cid: 5126 // Set your Intimate Merger Customer ID here for production - } - }] - } -}); -{% endhighlight %} - -### Intent IQ ID - -Intent IQ’s universal ID with its unparalleled coverage of over 80% of ad inventory, protects publishers’ ability to rely on advertising as their main revenue source while preserving user privacy in a third party cookieless world. - -The universal ID is an Intent IQ generated alphanumeric characters ID representing a person. This ID is not matched with personal information and remains anonymous to Intent IQ. - -Intent IQ universal ID enables partners - publishers, SSPs, DSPs, DMPs and advertisers to support, in a privacy-friendly way, and on a person level, core elements of the advertising business model - - -- Targeting across sites and devices -- Frequency capping -- Attribution measurement across sites and devices - -Intent IQ's universal ID works across IP addresses and user-agent changes. - -Intent IQ's universal ID truly stands out in the coverage and accuracy it provides. Intent IQ's universal ID covers over 80% of ad inventory with 90% accuracy. By contrast, third-party cookies offer 56% coverage and log-in solutions offer coverage of less than 20%. - - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=intentIqIdSystem - -#### Intent IQ ID Registration - -You can set up Intent IQ ID by contacting our operations team at [Intent IQ Contact Us](https://www.intentiq.com/contact-us) and getting your partner id. - -The Intent IQ ID privacy is covered under the [Intent IQ Privacy Policy](https://www.intentiq.com/technology-privacy-policy). - -#### Intent IQ ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"intentIqId"` | `"intentIqId"` | -| params | Required for IntentIqId | Object | Details for IntentIqId initialization. | | -| params.partner | Required | String | This is the partner ID value obtained from registering with IntentIQ. | `"1177538"` | -| params.pcid | Optional | String | This is the partner cookie ID, it is a dynamic value attached to the request. | `"g3hC52b"` | -| params.pai | Optional | String | This is the partner customer ID / advertiser ID, it is a dynamic value attached to the request. | `"advertiser1"` | - -{: .alert.alert-info :} -**NOTE:** The Intent IQ ID is encrypted with a key that changes every several hours. Demand partners utilize the latest key to decrypt the ID and use it. Therefore, to enable demand partners have an ID they can use, we highly recommend calling Intent IQ every 4 hours by setting storage.refreshInSeconds to 4 hours (4*3600 seconds) - -#### Intent IQ ID Examples - -1) Publisher has a partner ID from Intent IQ and cookies. - -{: .alert.alert-warning :} -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "intentIqId", - params: { - partner: 123456 // valid partner id - }, - storage: { - type: "cookie", - name: "intentIqId", // create a cookie with this name - expires: 60, // cookie can last for 60 days - refreshInSeconds: 4*3600 // refresh ID every 4 hours to ensure it's fresh -} - }], - syncDelay: 3000 // 3 seconds after the first auction - } -}); -{% endhighlight %} - -2) Publisher supports Intent IQ and HTML5 local storage. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "intentIqId", - params: { - partner: 123456 // valid partner id - }, - storage: { - type: "html5", - name: "intentIqId", // set localstorage with this name - expires: 60, - refreshInSeconds: 4*3600 // refresh ID every 4 hours to ensure it's fresh - } - }], - syncDelay: 3000 - } -}); -{% endhighlight %} - - -3) Publisher supports IntentIQ and HTML5 local storage with extra dynamic params such as 'pcid' and 'pai'. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "intentIqId", - params: { - partner: 123456 // valid partner id - pcid: PCID_VARIABLE // string value, dynamically loaded into a variable before setting the configuration - pai: PAI_VARIABLE // string value, dynamically loaded into a variable before setting the configuration - }, - storage: { - type: "html5", - name: "intentIqId", // set localstorage with this name - expires: 60 - } - }], - syncDelay: 3000 - } -}); -{% endhighlight %} - -### Kinesso ID - -Kinesso ID solution is a new approach to persistent cross domain authentication. - -#### How it works - -The Kinesso identity solution creates a persistent cross domain authenticated user id that is then used to link users with their interest signals (commonly known as segments). The Kinesso user ID (knsso) is never broadcast into the bid stream. Instead it is sent to a server side data store, merged with accompanying data from the Prebid Id Library and shipped to Kinesso. All data is encrypted at rest and in transit so your identifiers are never stored or transmitted in an insecure manner. - -The Kinesso ID sub adapter sets two cookies, one as a third party cookie and the other as a first party cookie in the publisher's domain. These cookies are merged with the user's hashed email address (when present) server side and sent to Kinesso. The combined output looks like this: - -{: .table .table-bordered .table-striped } -| kpuid | knsso | hid | account_id | created on | -| --- | --- | --- | --- | --- | -| `` | `` | `` | `` | `` | - -Kinesso will then attach these users to deals ids that they will target in the ORTB bid stream by brands and agencies represented by IPG. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=kinessoIdSystem - -#### Kinesso ID Registration - -You can set up Kinesso ID sub adapter by contacting Kinesso at prebid@kinesso.com - -The Kinesso ID privacy policy is covered under the [Kinesso Privacy Notice](https://kinesso.com/privacy-policy/). Please note, at present the Kinesso ID module is not meant for use inside the EEA. - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'kpuid'` | -| params | Required | Object | Details for KinessoId initialization | | -| params.accountid | Required | Int | Your SSP Account Id | 123 | - -### LiveIntent nonID - -LiveIntent offers audience resolution by leveraging our next-generation identity solutions. The LiveIntent identity graph is built around a people-based set of data that is authenticated daily through active engagements with email newsletters and media across the web. The LiveIntent nonID is a user identifier tied to an active, encrypted email in our graph and functions in cookie-challenged environments and browsers. - -There are two ways to build your Prebid.js package to include the LiveIntent nonID: -* The standard version which allows publishers to include the module with full functionalities, like hashing email addresses and identity resolution -* The minimal version, which allows publishers to deploy a smaller bundle with minimal features, including identity resolution. - -Add the **full** LiveIntent Identity module to your Prebid.js package with: -{: .alert.alert-info :} -gulp build --modules=userId,liveIntentIdSystem - -Add the **minimal** LiveIntent Identity module to your Prebid.js package with: -{: .alert.alert-info :} -LiveConnectMode=minimal gulp build --modules=liveIntentIdSystem - -The `request.userId.lipb` object would look like: -``` -{ - "lipbid": "T7JiRRvsRAmh88", - "segments": ["999"] -} -``` - -The adapters can be implemented to use the lipbid as the identifier and segments to which that identifier is associated with. To enable identity resolution for a specific publisher, LiveIntent builds a model on the backend with data collected via an additional call issued on each page load. - -#### LiveIntent ID Registration - -Please register with us if you’re not already a LiveIntent customer: [https://www.liveintent.com/prebid-registration/](https://www.liveintent.com/prebid-registration/) - -LiveIntent’s privacy policies for the services rendered can be found at [https://www.liveintent.com/services-privacy-policy/](https://www.liveintent.com/services-privacy-policy/) - -#### How does LiveIntent ID work - -The LiveIntent ID sub-module resolves the identity of audiences by connecting impression opportunities to a stable identifier - the nonID. In order to provide resolution one or more first-party cookies are used to create a stable identifier. - -How does LiveIntent ID sub-module decide, which first-party cookies to use: -1. By default LiveIntent ID sub-module generates its own first-party identifier on the publisher’s domain. Publishers have the option to disable the cookie generation when configuring the LiveIntent ID sub-module. -2. A publisher can also define in the configuration which additional first-party cookies should be used. These can be used in a combination with the LiveIntent first-party cookie. - -The LiveIntent ID sub-module sends the defined identifiers to the identity graph, which processes them and creates a nonID. The parameters being sent are described [here](https://github.com/liveintent-berlin/live-connect/blob/HEAD/COLLECTOR_PARAMS.md) - -For the identity resolution the LiveIntent ID sub-module makes a request to LiveIntent’s identity resolution API, which returns a nonID and the audience segment(s) a user belongs to. The nonID and the segment ID are then exposed by the Prebid User ID Module to Prebid adapters to be sent out in a bid request. An SSP can then make the impression opportunity available to any buyers targeting the segment. - -The first-party cookie generation and identity resolution functionality is provided by the LiveConnect JS library, included within the LiveIntent ID sub-module. LiveIntent has created a shared library that is open source, available at [https://www.npmjs.com/package/live-connect-js](https://www.npmjs.com/package/live-connect-js). - -The LiveIntent ID sub-module follows the standard Prebid.js initialization based on the GDPR consumer opt-out choices. With regard to CCPA, the LiveConnect JS receives a us_privacy string from the Prebid US Privacy Consent Management Module and respects opt-outs. - - -#### LiveIntent ID configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'liveIntentId'` | -| params | Required | Object | Container of all module params. || -| params.publisherId |Optional| String | The unique identifier for each publisher (for existing LiveIntent customers)|`'12432415'`| -| params.ajaxTimeout |Optional| Number |This configuration parameter defines the maximum duration of a call to the IdentityResolution endpoint. By default, 1000 milliseconds.|`1000`| -| params.partner | Optional| String |The name of the partner whose data will be returned in the response.|`'prebid'`| -| params.identifiersToResolve |Optional| Array[String] |Used to send additional identifiers in the request for LiveIntent to resolve against the LiveIntent ID.|`['my-id']`| -| params.emailHash |Optional| String |The hashed email address of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha2.|`1a79a4d60de6718e8e5b326e338ae533`| -| params.url | Optional| String |Use this to change the default endpoint URL if you can call the LiveIntent Identity Exchange within your own domain.|`'https://idx.my-domain.com'`| -| params.liCollectConfig |Optional| Object |Container of all collector params.|| -| params.liCollectConfig.fpiStorageStrategy |Optional| String |This parameter defines whether the first party identifiers that LiveConnect creates and updates are stored in a cookie jar, or in local storage. If nothing is set, default behaviour would be `cookie`. Allowed values: [`cookie`, `ls`, `none`]|`'cookie'`| -| params.liCollectConfig.fpiExpirationDays |Optional| Number |The expiration time of an identifier created and updated by LiveConnect.By default, 730 days.|`729`| -| params.liCollectConfig.collectorUrl |Optional| String |The parameter defines where the signal pixels are pointing to. The params and paths will be defined subsequently. If the parameter is not set, LiveConnect will by default emit the signal towards `https://rp.liadm.com`.|`'https://rp.liadm.com'`| -| params.liCollectConfig.appId |Optional| String |LiveIntent's media business entity application id.|`'a-0012'`| -| storage | Required | Object | This object defines where and for how long the results of the call to get a user ID will be stored. | | -| storage.type | Required | String | This parameter defines where the resolved user ID will be stored (either `'cookie'` or `'html5'` localstorage).| `'cookie'` | -| storage.name | Required | String | The name of the cookie or html5 localstorage where the resolved user ID will be stored. | `'pbjs_li_nonid'` | -| storage.expires | Recommended | Integer | How long (in days) the user ID information will be stored. The recommended value is `1` | `1` | - -#### LiveIntent ID examples - -1. To receive the LiveIntent ID, the setup looks like this. -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "liveIntentId", - params: { - publisherId: "9896876" - }, - storage: { - type: “cookie”, - name: “pbjs_li_nonid”, //create a cookie with this name - expires: 1 // cookie is stored for 1 day - } - }] - } -}) -``` - -2. If you are passing additional identifiers that you want to resolve to the LiveIntent ID, add those under the `identifiersToResolve` array in the configuration parameters. -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "liveIntentId", - params: { - publisherId: "9896876", - identifiersToResolve: ["my-own-cookie"] - }, - storage: { - type: “cookie”, - name: “pbjs_li_nonid”, //create a cookie with this name - expires: 1 // cookie is stored for 1 day - } - }] - } -}) -``` - -3. If all the supported configuration params are passed, then the setup looks like this. -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "liveIntentId", - params: { - publisherId: "9896876", - identifiersToResolve: ["my-own-cookie"], - url: "https://publisher.liveintent.com/idex", - partner: "prebid", - ajaxTimeout: 1000, - liCollectConfig: { - fpiStorageStrategy: "cookie", - fpiExpirationDays: 730, - collectorUrl: "https://rp.liadm.com", - appId: "a-0012" - } - }, - storage: { - type: “cookie”, - name: “pbjs_li_nonid”, //create a cookie with this name - expires: 1 // cookie is stored for 1 day - } - }] - } -}) -``` - -### Lotame Panorama ID - -[Lotame Panorama](https://www.lotame.com/panorama/) is a suite of data-enrichment solutions for digital advertising that empowers marketers, agencies, publishers and media companies to transform consumer personas into addressable audiences. At the heart of Lotame Panorama is the Panorama ID, a people-based identifier powered by deterministic and probabilistic data, available across the cookie-challenged web and all browsers. - -Lotame’s Panorama ID module sends information from the request to its identity graph in order to successfully generate a Panorama ID. For more information on how the Panorama ID works, please visit [https://www.lotame.com/panorama/id/](https://www.lotame.com/panorama/id/). - -**Ease of Implementation**: Deployment of the Lotame Panorama ID module has been optimized for ease by not requiring any registration to utilize. Simply add the generic module to start producing the Panorama ID across your inventory. Clients who would like the advantage of additional options can register to receive their own client ID. Reach out to prebid@lotame.com to learn more about the optional registration. - -Lotame's privacy policy related to the Panorama ID and the collection of data and how data is used is available at [https://www.lotame.com/about-lotame/privacy/lotames-products-services-privacy-policy/](https://www.lotame.com/about-lotame/privacy/lotames-products-services-privacy-policy/). Consult with your legal counsel to determine the appropriate user disclosures with respect to use of the Lotame Panorama ID module. - -If you have any questions about Panorama ID, please reach out by emailing [prebid@lotame.com](mailto:prebid@lotame.com). - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=lotamePanoramaIdSystem - -#### Lotame Panorama ID Configuration - -The Lotame Panorama ID module does not require any configuration parameters. It should work as-is provided that bidders use it in their adapters. - -{: .alert.alert-info :} -NOTE: For optimal performance, the Lotame Panorama Id module should be called at every opportunity. It is best not to use `params.storage` with this module as the module has its own optimal caching mechanism. - -#### Lotame Panorama ID Example - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of the module | "lotamePanoramaId" | -| params | Optional | Object | Configuration options for the Lotame Panorama ID Module | | -| params.clientId | Optional | String | The Lotame Panorama Client ID | "1001" | - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "lotamePanoramaId", - params: { - clientId: "Optional - See your Lotame Representative" - } - }] - } -}); -{% endhighlight %} - -### MediaWallah OpenLinkID - -MediaWallah's openLink is an anonymous person based ID that enables buyers and sellers of media to connect a person and their devices across the web and mobile apps. openLink facilities the buying of media between DSPs, SSPs and publishers. - -Add support for MediaWallah OpenLinkID to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=userId,mwOpenLinkIdSystem - -#### MediaWallah OpenLinkID Registration - -MediaWallah requires the creation of an accountId a partnerId in order to take advantage of openLink. Please contact your partner resource to get these Ids provisioned. - -#### MediaWallah OpenLinkID Configuration - -
      -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'mwOpenLinkId'` | -| params | Required | Object | Details for mwOLID syncing. || -| params.accountId | Required | String | The MediaWallah assigned Account Id | `1000` | -| params.partnerId | Required | String | The MediaWallah assign partner Id |`'1001'`| -| params.uid | Optional | String | Your unique Id for the user or browser. Used for matching. | `'u-123xyz'` | -{: .table .table-bordered .table-striped } -
      - -#### MediaWallah OpenLinkID Examples - -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'mwOpenLinkId', - params: { - accountId: '1000', - partnerId: '1001', - uid: 'u-123xyz' - } - }] - } -}) -``` - -### Merkle ID - -[Merkury by Merkle](https://merkury.merkleinc.com/contact) enables marketers, media owners, and publishers to own, build, and control a cookie-less Private Identity Graph. Merkury uses an organization’s first-party CRM data and valuable interactions such as logins, outbound email campaigns and media reach to create and grow a universe of person-based IDs for cross-channel targeting, personalization, measurement and more. - -#### Merkury by Merkle ID Examples - -Publisher stores Merkury by Merkle in local storage for 30 days - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'merkleId', - params: { - vendor:'example_vendor', - sv_cid:'example_cid', - sv_pubid:'example_pubid', - sv_domain:'example.com' - }, - storage: { - type: 'html5', - name: 'merkleId', - expires: 30 - } - }] - } -}); -{% endhighlight %} - -### Navegg ID - -[Navegg](https://www.navegg.com) enables publishers, advertisers and agencies to use their own first party data together to activate media in a cookie-less way across several Ad Tech platforms. Navegg has one of the largest data networks in Latin America which also allows the enhancement of data with unique categories. - -#### Navegg ID Examples - -Publisher stores NaveggId in local storage and/or 1st party cookies - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'naveggId' - }] - } -}); -{% endhighlight %} - -### netID - -The [European netID Foundation (EnID)](https://developerzone.netid.de/index.html) aims to establish with the netID an independent European alternative in the digital market for Demand and Supply side. With the netID Single-Sign-On, the EnID established an open standard for consumer logins for services of Buyers and Brands, that also includes user-centric consent management capabilities that results in a standardized, EU-GDPR compliant, IAB TCF aware, cross-device enabled Advertising Identifier, which can be leveraged by publishers and advertisers (and vendors supporting them) to efficiently deliver targeted advertising through programmatic systems to already more than 38 million Europeans on mobile and desktop devices. - -The EnID is a non-profit organization which is open to any contributing party on both, the demand and supply side to make identity work for consumers as well as the advertising ecosystem. - -#### netID Examples - -1) Publisher stores netID via his own logic - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "netId", - value: { - "netId":"fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg" - } - }] - } -}); -{% endhighlight %} - -### NextRoll ID - -NextRoll is an industry-leading marketing technology and data stack that fuels growth for businesses of all kinds. Our technology powers two multi-million dollar high-growth businesses: AdRoll and RollWorks. The NextRoll ID is a cookieless identifier built from NextRoll’s proprietary identity graph. Publishers, ad tech platforms, and NextRoll’s brands (AdRoll and RollWorks) leverage the NextRoll ID to access unique demand in cookieless environments. The NextRoll ID respects user privacy preferences and enables users to opt out through multiple web based mechanisms found in [Section 8 of NextRoll’s Privacy Policy](https://nextroll.com/privacy#service-8). - -#### NextRoll ID Registration - -To sign up for a Partner ID please contact your NextRoll representative or send an email to [publishers@nextroll.com](mailto:publishers@nextroll.com). - -#### NextRoll ID Configuration - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=nextrollIdSystem - -Enable the module in configuration, with your Partner ID: - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "nextrollId", - params: { - partnerId: 'YOUR_PARTNER_ID' - } - }] - } -}); -{% endhighlight %} - -### Novatiq Hyper ID - -The [Novatiq](https://www.novatiq.com) proprietary dynamic Hyper ID is a unique, non sequential and single use identifier for marketing activation. Our in network solution matches verification requests to telco network IDs safely and securely inside telecom infrastructure. The Novatiq Hyper ID can be used for identity validation and as a secured 1st party data delivery mechanism. - -#### Novatiq Hyper ID Configuration - -Enable by adding the Novatiq submodule to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=novatiqIdSystem,userId - - -Module activation and configuration: - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'novatiq', - params: { - // change to the Partner Number you received from Novatiq - sourceid '1a3' - } - } - }], - // 50ms maximum auction delay, applies to all userId modules - auctionDelay: 50 - } -}); -{% endhighlight %} - -#### Parameters for the Novatiq Module - -
      -| Param | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | Module identification: `"novatiq"` | `"novatiq"` | -| params | Required | Object | Configuration specifications for the Novatiq module. | | -| params.sourceid | Required | String | This is the Novatiq Partner Number obtained via Novatiq registration. | `1a3` | -{: .table .table-bordered .table-striped } -
      - - -### Novatiq Hyper ID with Prebid SharedID support -You can make use of the Prebid.js SharedId module as follows. - -#### Novatiq Hyper ID Configuration - -Enable by adding the Novatiq and SharedId submodule to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=novatiqIdSystem,userId,pubCommonId - -Module activation and configuration: - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: "pubCommonId", - storage: { - type: "cookie", - // optional: will default to _pubcid if left blank - name: "demo_pubcid", - - // expires in 1 years - expires: 365 - }, - bidders: [ 'adtarget' ] - }, - { - name: 'novatiq', - params: { - // change to the Partner Number you received from Novatiq - sourceid '1a3', - - // Use the sharedID module - useSharedId: true, - - // optional: will default to _pubcid if left blank. - // If not left blank must match "name" in the the module above - sharedIdName: 'demo_pubcid' - } - } - }], - // 50ms maximum auction delay, applies to all userId modules - auctionDelay: 50 - } -}); -{% endhighlight %} - -#### Parameters for the Novatiq Module - -
      -| Param | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | Module identification: `"novatiq"` | `"novatiq"` | -| params | Required | Object | Configuration specifications for the Novatiq module. | | -| params.sourceid | Required | String | The Novatiq Partner Number obtained via Novatiq | `1a3` | -| params.useSharedId | Optional | Boolean | Use the sharedID module if it's activated. | `true` | -| params.sharedIdName | Optional | String | Same as the SharedID "name" parameter
      Defaults to "_pubcid" | `"demo_pubcid"` | -{: .table .table-bordered .table-striped } -
      - -#### Parameters for the SharedID Module - -
      -| Param | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | Module identification: `"pubCommonId"` | `"pubCommonId"` | -| params | Required | Object | Configuration specifications for the SharedID module. | | | -| params.storage | Required | Object | | | -| params.storage.type | Required | String | Storage type, Set to `"cookie"` | `"cookie"` | -| params.storage.name | Optional | String | Storage cookie name. If this is changed must match sharedIdName
      in the Novatiq module | `"demo_pubcid"` || -| params.storage.expires | Required | integer | Time to expire | `365` | -{: .table .table-bordered .table-striped } -
      - -If you have any questions, please reach out to us at [prebid@novatiq.com](mailto:prebid@novatiq.com) - -### Parrable ID - -The Parrable ID is a Full Device Identifier that can be used to identify a device across different browsers and webviews on a single device including browsers that have third party cookie restrictions. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=parrableIdSystem - -#### Parrable ID Registration - -Please contact Parrable to obtain a Parrable Partner Client ID and/or use the Parrable Partner Client ID provided by the vendor for each Parrable-aware bid adapter you will be using. Note that if you are working with multiple Parrable-aware bid adapters you may use multiple Parrable Partner Client IDs. - -The Parrable privacy policy as at [https://www.parrable.com/privacy-policy/](https://www.parrable.com/privacy-policy/). - -#### Parrable ID Configuration - -In addition to the parameters documented above in the Basic Configuration section the following Parrable specific configuration is required: - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| params | Required | Object | Details for the Parrable ID. | | -| params.partners | Required | Array[String] | A list of one or more Parrable Partner Client IDs for the Parrable-aware bid adapters you are using. Please obtain Parrable Partner Client IDs from them and/or obtain your own. | `[ '30182847-e426-4ff9-b2b5-9ca1324ea09b' ]` | -| params.timezoneFilter | Optional | Object | Configures a timezone or timezone offset filter | | -| params.timezoneFilter.allowedZones | Optional | Array[String] | description | `[ 'America/Anchorage' ]` | -| params.timezoneFilter.allowedOffsets | Optional | Array[Number] | description | `[ -4 ]` | -| params.timezoneFilter.blockedZones | Optional | Array[String] | description | `[ 'America/New_York' ]` | -| params.timezoneFilter.blockedOffsets | Optional | Array[Number] | description | `[ -5 ]` | - - -{: .alert.alert-info :} -NOTE: The Parrable ID that is delivered to Prebid is encrypted by Parrable with a time-based key and updated frequently in the browser to enforce consumer privacy requirements and thus will be different on every page view, even for the same user. - -The Parrable ID system manages a cookie with the name of `_parrable_id` containing the ID and optout states of the user. -This cookie is used also by standalone Parrable integrations outside of Prebid. -It is for this reason that the cookie name is not configurable for the Parrable ID system. - -#### Timezone and Timezone Offset Filtering - -The Parrable ID system enables a publisher to configure lists of **allowed** timezones (eg. `Europe/Dublin`) and/or timezone offsets (eg. `-4`) as well as a lists of **blocked** timezones and timezone offsets. - -- With no configuration (`params.timezoneFilter` not set, or all of the lists are empty) all impressions are permitted. -- With only allow lists configured a browser must match either a timezone or timezone offset for it to not be filtered. -- With only block lists configured an impression will be filtered only if it is from a browser matching a blocked timezone or timezone offset. -- An impression from a browser that matches any allowed timezone or timezone offset, but does not match a blocked timezone or timezone offset will engage in the Parrable ID syncronization process. -- If a browser has a stored Parrable ID then it will not be filtered even if the browser is in a timezone or timezone offset that is blocked. - -All configured timezones should follow the `TZ database name` column from the [IANA tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) - -#### Parrable ID Examples - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: `'parrableId'`, - params: { - partners: [ - '30182847-e426-4ff9-b2b5-9ca1324ea09b', - 'b07cf20d-8b55-4cd7-9e84-d804ed66b644' - ], // change to the Parrable Partner Client ID(s) you received from the Parrable Partners you are using - timezoneFilter: { - allowedZones: ['America/New_York', 'Europe/Madrid'] - } - } - }], - syncDelay: 1000 - } -}); -{% endhighlight %} - -### Publisher Link -Publisher Link, provided by [Epsilon](https://www.epsilon.com/us), is a cross-device identity solution that activates publisher first-party, authenticated -data to improve audience identification and increase bid opportunities, specifically designed for sites with authenticated -traffic. Publisher first-party authenticated data and a user's unique encrypted ID is linked to an existing people-based -Epsilon CORE ID. By utilizing Publisher Link, publishers are able to reap the benefits of Epsilon's CORE ID. - -#### Publisher Link Registration -Please contact [Epsilon](mailto:PublisherSupport@Epsilon.com) to sign up. - -The Epsilon privacy is covered in the [Epsilon Privacy Policy](https://www.epsilon.com/us/privacy-policy). - -The Publisher Link opt-out is included [here](https://www.epsilon.com/privacy/dms/opt-out/email) - -#### Publisher Link Configuration - -In addition to the parameters documented above in the Basic Configuration section the following Publisher Link specific configuration is available: - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'publinkId'` | -| params | Required | Object | Customized parameters. | | -| params.e | Required | String | Hashed email address of the user. Supports MD5 and SHA256. | `'7D320454942620664D96EF78ED4E3A2A'` | -| params.site_id | Required | String | Site ID provided by Epsilon. | `'123456'` | -| params.api_key | Required | String | API key provided by Epsilon. | `'00000000-0000-0000-0000-00000000000'` - -#### Publisher Link Examples -```javascript - pbjs.setConfig({ - userSync: { - userIds: [{ - name: "publinkId", - storage: { - name: "pbjs_publink", - type: "cookie", - expires: 30 - }, - params: { - e: "7D320454942620664D96EF78ED4E3A2A", // example hashed email (md5) - site_id: "123456", - api_key: "00000000-0000-0000-0000-00000000000" - } - }] - } - }); -``` - -### RampID - -RampID, formerly known as IdentityLink, provided by [LiveRamp](https://liveramp.com) is a single person-based identifier which allows marketers, platforms and publishers to perform personalized segmentation, targeting and measurement use cases that require a consistent, cross-channel view of the user in anonymous spaces. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=identityLinkIdSystem - -#### RampID Registration - -Please sign up through our [Console](https://launch.liveramp.com) platform and request a `placementId`. - -The RampID privacy policy is at [https://liveramp.com/privacy/service-privacy-policy/](https://liveramp.com/privacy/service-privacy-policy/). - -#### RampID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"identityLink"` | `"identityLink"` | -| params | Required for Id Link | Object | Details for RampID initialization. | | -| params.pid | This parameter is required for RampID | String | This is the placementId, value needed for obtaining user’s RampID envelope -| params.notUse3P | This parameter is not required for RampID | Boolean | Property for choosing should 3P Liveramp envelope endpoint be fired or not, in order to get RampID envelope - -#### RampID Examples - -1) Publisher passes a placement ID and elects to store the RampID envelope in a cookie. Make sure that the expiration time of the cookie is similar to what is set in ATS. - - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "identityLink", - params: { - pid: '999', // Set your real RampID placement ID here - // notUse3P: true/false // If you do not want to use 3P endpoint to retrieve the envelope. If you do not set this property to true, 3P endpoint will be fired. By default this property is undefined and 3P request will be fired. - }, - storage: { - type: "cookie", - name: "idl_env", // "idl_env" is the required storage name - expires: 15 // RampID envelope can last for 15 days - } - }], - syncDelay: 3000 // 3 seconds after the first auction - } -}); -{% endhighlight %} - -2) Publisher passes a placement ID and elects to store the RampID envelope in HTML5 localStorage. Make sure that the expiration time for localstorage is similar to what is set in ATS. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "identityLink", - params: { - pid: '999', // Set your real RampID placement ID here - // notUse3P: true/false // If you do not want to use 3P endpoint to retrieve the envelope. If you do not set this property to true, 3P endpoint will be fired. By default this property is undefined and 3P request will be fired. - }, - storage: { - type: "html5", - name: "idl_env", // "idl_env" is the required storage name - expires: 15 // RampID envelope can last for 15 days - } - }], - syncDelay: 3000 - } -}); -{% endhighlight %} - -### SharedID - -This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support SharedId will be able to pick up the user ID and return it for additional server-side cross device tracking. - -There is no special registration or configuration for SharedID. Each publisher's privacy policy should take -SharedID into account. Prebid recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page. For more information check out Prebid's dedicated [identity page](/identity/sharedid.html) - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=sharedIdSystem - -#### SharedID ID Configuration - -In addition to the parameters documented above in the Basic Configuration section the following SharedID specific configuration is available: - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'pubCommonId'` | -| params | Optional | Object | Customized parameters | | -| params.create | Optional | Boolean | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` | -| params.pixelUrl | Optional | String | For publisher server support only. Where to call out to for a server cookie -- see [Prebid Identity](/identity/sharedid.html) for more information. | `/wp-json/pubcid/v1/extend/` -| params.extend | Optional | Boolean | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `false` | -| storage | Required | Object | The publisher must specify some kind of local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | -| storage.expires | Integer | Required | How long the user ID information will be stored. | `365` | -| storage.name | String | Required | The name of the cookie or html5 local storage where the user ID will be stored. | `_pubcid` -| storage.type | String | Required | This is where the results of the user ID will be stored. Must be either: Must be either: "cookie" or "html5". For server side implementations, which have the best identifier life and revenue impact, this must be a cookie. | `cookie` - -#### SharedID Examples - -1) Publisher supports SharedID and first party domain cookie storage - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "pubCommonId", - storage: { - type: "cookie", - name: `"_pubcid"`, // create a cookie with this name - expires: 365 // expires in 1 years - } - }] - } -}); -{% endhighlight %} - -2) Publisher supports both UnifiedID and SharedID and first party domain cookie storage - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "unifiedId", - params: { - partner: "myTtdPid" - }, - storage: { - type: "cookie", - name: "pbjs-unifiedid", // create a cookie with this name - expires: 60 - } - },{ - name: "pubCommonId", - params: { - pixelUrl: "/wp-json/pubcid/v1/extend/" - }, - storage: { - type: "cookie", - name: `"_pubcid"`, // create a cookie with this name - expires: 180 - } - }], - syncDelay: 5000 // 5 seconds after the first bidRequest() - } -}); -{% endhighlight %} - -3) Publisher supports SharedID and first party domain cookie storage initiated by a first party server - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "pubCommonId", - params: { - pixelUrl: "/wp-json/pubcid/v1/extend/" //pixelUrl should be specified when the server plugin is used - }, - storage: { - type: "cookie", - name: `"_pubcid"`, // create a cookie with this name - expires: 365 // expires in 1 years - } - }] - } -}); -{% endhighlight %} - -### Trustpid - -Trustpid generates unique tokens, enabling improved efficiency in programmatic advertising while safeguarding transparency and control for end customers via `trustpid.com`. A website visitor’s Trustpid is generated based on network identifiers provided by network operators and requires explicit user consent. - -Trustpid is also the brand name of the service, which is provided by Vodafone Sales and Services Limited (“VSSL”). - -#### Trustpid configuration - -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of the module | `"trustpid"` -| params | Required | Object | Object with configuration parameters for trustpid User Id submodule | - | -| params.maxDelayTime | Required | Integer | Max amount of time (in seconds) before looking into storage for data | 2500 | -| bidders | Required | Array of Strings | An array of bidder codes to which this user ID may be sent. Currently required and supporting AdformOpenRTB | `['adf']` | -| storage | Required | Object | Local storage configuration object | - | -| storage.type | Required | String | Type of the storage that would be used to store user ID. Must be `"html5"` to utilise HTML5 local storage. | `"html5"` | -| storage.name | Required | String | The name of the key in local storage where the user ID will be stored. | `"trustpid"` | -| storage.expires | Required | Integer | How long (in days) the user ID information will be stored. For safety reasons, this information is required.| `1` | - -Configuration example: - -```javascript -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: "trustpid", - params: { - maxDelayTime: 2500, - }, - bidders: ["adf"], - storage: { - type: "html5", - name: "trustpid", - expires: 1, - }, - }], - syncDelay: 3000, - auctionDelay: 3000 - } -}); -``` - -#### Truspid onboarding - -If you wish to find out more about Trustpid, please contact onboarding@trustpid.com - -### PubProvided ID - -The PubProvided Id module allows publishers to set and pass a first party user id into the bid stream. This module has several unique characteristics: - -1. The module supports a user defined function, that generates an eids-style object: - -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "pubProvidedId", - params: { - eidsFunction: getIdsFn // any function that exists in the page - } - }] - } -}); -``` - -Or, the eids values can be passed directly into the `setConfig` call: -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "pubProvidedId", - params: { - eids: [{ - source: "domain.com", - uids: [{ - id: "value read from cookie or local storage", - atype: 1, - ext: { - stype: "ppuid" - } - - }] - }, { - source: "3rdpartyprovided.com", - uids: [{ - id: "value read from cookie or local storage", - atype: 3, - ext: { - stype: "dmp" - } - }] - }] - } - }] - } -}); -``` - -In either case, bid adapters will receive the eid values after consent is validated. - -2. This design allows for the setting of any number of uuids in the eids object. Publishers may work with multiple ID providers and nest their own id within the same eids object. The opportunity to link a 1st party uuid and a 3rd party generated UUID presents publishers with a unique ability to address their users in a way demand sources will understand. - -3. Finally, this module allows publishers to broadcast their user id, derived from in-house tech, directly to buyers within the confines of existing compliance (CCPA & GDPR) frameworks. - -4. The `eids.uids.ext.stype` "source-type" extension helps downstream entities know what do with the data. Currently defined values are: - -- dmp - this uid comes from the in-page dmp named in eids.source -- ppuid - this uid comes from the publisher named in eids.source -- other - for setting other id origin signals please use the [adCOM!](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#object--extended-identifier-uids-) `atype` spec - -5. Bid adapters listening for "userIds.pubProvidedId" will not receive a string, please use the userIdAsEids value/function to return the userid as a string. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=pubProvidedId - - -#### PubProvided Configuration - -{: .table .table-bordered .table-striped } -| Params under usersync.userIds[]| Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the ID module | `"PubProvided"` | -| params | Optional | Object | Details for syncing. | | -| params.eidsFunction | Optional | function | any function that exists in the page | getIdsFn() | -| uids.atype | optional | int | ADCOM - Type of user agent the match is from | `"1"` | -| uids.ext.stype | Optional | String | Description of how the id was generated and by whom ('ppuid','DMP','other') | `DMP` | - -### Quantcast ID - -The Prebid Quantcast ID module stores a Quantcast ID in a first party cookie. The ID is then made available in the bid request. The ID from the cookie added in the bidstream allows Quantcast to more accurately bid on publisher inventories without third party cookies, which can result in better monetization across publisher sites from Quantcast. And, it’s free to use! For easier integration, you can work with one of our SSP partners, like PubMatic, who can facilitate the legal process as well as the software integration for you. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=userId,quantcastIdSystem - -Quantcast’s privacy policies for the services rendered can be found at - https://www.quantcast.com/privacy/ - -Publishers deploying the module are responsible for ensuring legally required notices and choices for users. - -The Quantcast ID module will only perform any action and return an ID in situations where: -1. the publisher has not set a ‘coppa' flag on the prebid configuration on their site (see [pbjs.setConfig.coppa](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa)) -2. there is not a IAB us-privacy string indicating the digital property has provided user notice and the user has made a choice to opt out of sale -3. if GDPR applies, an IAB TCF v2 string exists indicating that Quantcast does not have consent for purpose 1 (cookies, device identifiers, or other information can be stored or accessed on your device for the purposes presented to you), or an established legal basis (by default legitimate interest) for purpose 10 (your data can be used to improve existing systems and software, and to develop new products). - -#### Quantcast ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"quantcastId"` | `"quantcastId"` | -| params | Optional | Object | Details for Quantcast initialization. | | -| params.ClientID | Optional | String | Optional parameter for Quantcast prebid managed service partners. The parameter is not required for websites with Quantcast Measure tag. Reach out to Quantcast for ClientID if you are not an existing Quantcast prebid managed service partner: quantcast-idsupport@quantcast.com | | - - -#### Quantcast ID Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "quantcastId" - }] - } -}); -{% endhighlight %} - - - -### Tapad ID - -Tapad's ID module provides access to a universal identifier that publishers, ad tech platforms and advertisers can use for data collection and collation without reliance on third-party cookies. -Tapad's ID module is free to use and promotes collaboration across the industry by facilitating interoperability between DSPs, SSPs and publishers. - -To register as an authorized user of the Tapad ID module, or for more information, documentation and access to Tapad’s Terms and Conditions please contact [prebid@tapad.com](mailto:prebid@tapad.com). - -Tapad’s Privacy landing page containing links to region-specific Privacy Notices may be found here: [https://tapad.com/privacy.html](https://tapad.com/privacy.html). - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=userId,tapadIdSystem - -#### Tapad ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"tapadId"` | `"tapadId"` | -| params | Required | Object | Details for Tapad initialization. | | -| params.company_id | Required | Number | Tapad Company Id provided by Tapad | 1234567890 | - -#### Tapad ID Example - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [ - { - name: "tapadId", - params: { - companyId: 1234567890 - }, - storage: { - type: "cookie", - name: "tapad_id", - expires: 1 - } - } - ] - } -}); -{% endhighlight %} - -### Unified ID - -The Unified ID solution is provided by adsrvr.org and the Trade Desk. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=unifiedIdSystem - -#### Unified ID Registration - -You can set up Unified ID in one of these ways: - -- Register with The Trade Desk from their [Unified ID page](https://www.thetradedesk.com/industry-initiatives/unified-id-solution). -- Utilize a [managed services](https://prebid.org/product-suite/managed-services/) company who can do this for you. - -The Unified ID privacy is covered under the [TradeDesk Services Privacy Policy](https://www.thetradedesk.com/general/privacy). - -#### Unified ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | `"unifiedId"` | `"unifiedId"` | -| params | Required for UnifiedId | Object | Details for UnifiedId initialization. | | -| params.partner | Either this or url required for UnifiedId | String | This is the partner ID value obtained from registering with The Trade Desk or working with a Prebid.js managed services provider. | `"myTtdPid"` | -| params.url | Required for UnifiedId if not using TradeDesk | String | If specified for UnifiedId, overrides the default Trade Desk URL. | "https://unifiedid.org/somepath?args" | -| value | Optional | Object | Used only if the page has a separate mechanism for storing the Unified ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"tdid": "D6885E90-2A7A-4E0F-87CB-7734ED1B99A3"}` | - -#### Unified ID Examples - -1) Publisher has a partner ID with The Trade Desk, and is using the default endpoint for Unified ID. - -{: .alert.alert-warning :} -Bug: The default URL did not support HTTPS in Prebid.js 2.10-2.14. So instead of using -the 'partner' parameter, it's best to supply the Trade Desk URL as shown in this example. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "unifiedId", - params: { - url: "//match.adsrvr.org/track/rid?ttd_pid=MyTtidPid&fmt=json" - }, - storage: { - type: "cookie", - name: "pbjs-unifiedid", // create a cookie with this name - expires: 60 // cookie can last for 60 days - } - }], - syncDelay: 3000 // 3 seconds after the first auction - } -}); -{% endhighlight %} - -2) Publisher supports UnifiedID with a vendor other than Trade Desk and HTML5 local storage. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "unifiedId", - params: { - url: "URL_TO_UNIFIED_ID_SERVER" - }, - storage: { - type: "html5", - name: "pbjs-unifiedid", // set localstorage with this name - expires: 60 - } - }], - syncDelay: 3000 - } -}); -{% endhighlight %} - -3) Publisher has integrated with UnifiedID on their own and wants to pass the UnifiedID directly through to Prebid.js. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "unifiedId", - value: {"tdid": "D6885E90-2A7A-4E0F-87CB-7734ED1B99A3"} - }] - } -}); -{% endhighlight %} - -### Unified ID 2.0 - -Unified ID 2 is an email based id solution that is owned and operated by the prebid community. Unified ID 2, relies on user consent before an id can be added to the bid stream. Consent can be gathered by SSO providers who have integrated against the UID 2 framework, or Publishers own login & consent mechaninism. - -Add it to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=uid2IdSystem - -#### Unified ID Registration - -You can set up Unified ID 2 in one of these ways: - -- Include the module to your pb.js wrapper, no registration is required -- Utilize a [managed services](https://prebid.org/product-suite/managed-services/) company who can do this for you. - -Each publisher’s privacy policy should take UnifiedId 2 into account - -#### Unified ID 2 Configuration - -{: .table .table-bordered .table-striped } -The below parameters apply only to the UID 2.0 User ID Module integration. - -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | ID value for the UID20 module - `"uid2"` | `"uid2"` | -| value | Optional | Object | Used only if the page has a separate mechanism for storing the UID 2.O ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"uid2": { "id": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}}` | - -#### Unified ID 2 Example - -Publisher has a integrated with an SSO provider that sets a cookie called __uid2_advertising_token when user consent is granted. - -{% highlight javascript %} -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'uid2' - }] - } -}); -{% endhighlight %} - - -### Yahoo ConnectID - -Yahoo ConnectID is a person based ID and does not depend on 3rd party cookies. It enables ad tech platforms to recognize and match users consistently across the open web. Built on top of Yahoo’s robust and proprietary ID Graph it delivers a higher find rate of audiences on publishers’ sites user targeting that respects privacy. - -Verizon Media ConnectID honors privacy choices from the [Yahoo Privacy Dashboard](https://legal.yahoo.com/us/en/yahoo/privacy/dashboard/index.html) as well as global privacy acts. - -Add support for Yahoo ConnectID to your Prebid.js package with: - -{: .alert.alert-info :} -gulp build --modules=userId,connectIdSystem - -#### Yahoo ConnectID Registration - -A Yahoo supplied publisher specific pixel Id is required. Please reach out to your account manager for assistance with setup. - -#### Yahoo ConnectID Configuration - -
      -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of this module. | `'connectId'` | -| params | Required | Object | Container of all module params. || -| params.pixelId | Required | Number | The Yahoo supplied publisher specific pixel Id | `8976` | -| params.he | Required | String | The SHA-256 hashed user email address |`'ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4'`| -| storage | Required | Object | Defines where and for how long the results of the call to get a user ID will be stored. | | -| storage.type | Required | String | Defines where the resolved user ID will be stored (either `'cookie'` or `'html5'` localstorage).| `'html5'` | -| storage.name | Required | String | The name of the cookie or html5 localstorage where the resolved user ID will be stored. | `'connectId'` | -| storage.expires | Recommended | Integer | How long (in days) the user ID information will be stored. The recommended value is `15` | `15` | -{: .table .table-bordered .table-striped } -
      - -#### Yahoo ConnectID Examples - -``` -pbjs.setConfig({ - userSync: { - userIds: [{ - name: "connectId", - params: { - pixelId: 8976, - he: "ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4" - }, - storage: { - type: "html5", - name: "connectId", - expires: 15 - } - }] - } -}) -``` - -## Adapters Supporting the User ID Sub-Modules - -{% assign bidder_pages = site.pages | where: "layout", "bidder" %} - -
      - -{% for item in bidder_pages %} -{% if item.userIds != nil %} - -{% endif %} -{% endfor %} -
      BidderIDs Supported
      {{item.biddercode}}{{item.userIds}}
      - -## Bidder Adapter Implementation - -### Prebid.js Adapters - -Bidders that want to support the User ID module in Prebid.js, need to update their bidder adapter to read the indicated bidRequest attributes and pass them to their endpoint. - -{: .table .table-bordered .table-striped } -| ID System Name | ID System Host | Prebid.js Attr: bidRequest.userId. | EID Source | Example Value | -| --- | --- | --- | --- | --- | --- | --- | -| Admixer ID | Admixer | admixerId | admixer.net | "1111" | -| Adtelligent ID | Adtelligent | bidRequest.userId.adtelligentId | `"1111"` | -| Akamai DAP ID | Akamai DAP | dapId | akamai.com | "eyJhbGciOiJka....YIsj7"| -| AMX RTB ID | AMX RTB | amxId | amxrtb.com | "3ca11058-..." | -| BritePool ID | BritePool | britepoolid | britepool.com | "1111" | -| DeepIntent ID | Deep Intent | deepintentId | deepintent.com | "1111" | -| DMD ID | DMD | dmdId | hcn.health | "1111" | -| CriteoID | Criteo | criteoId | criteo.com | "1111" | -| Fabrick ID | Neustar | fabrickId | neustar.biz | "1111" | -| FLoC ID | n/a | flocId | | | -| Hadron ID | Audigent | hadronId | audigent.com | {"hadronId":"user-hadron-id", "auSeg":["segment1", "segment2"]} | -| ID+ | Zeotap | IDP | zeotap.com | "1111" | -| ID5 ID | ID5 | id5id | id5-sync.com | {uid: "1111", ext: { linkType: 2, abTestingControlGroup: false } } | -| IdentityLink | LiveRamp | idl_env | liveramp.com | "1111" | -| Intent IQ ID | Intent IQ | intentiqid | intentiq.com | "1111" | -| Kinesso ID | Kinesso | kpuid | kpuid.com | "1111" | -| LiveIntent ID | Live Intent | lipb.lipbid | liveintent.com | "1111" | -| Lotame Panorama ID | Lotame | lotamePanoramaId | crwdcntrl.net | "e4b9..." | -| MediaWallah OpenLink ID | MediaWallah | mwOpenLinkId | mediawallahscript.com | "1111" | -| merkleID | Merkle | merkleId | merkleinc.com | "1111" | -| naveggId | Navegg | naveggId | navegg.com | "1111" | -| netID | netID | netId | netid.de | "fH5A..." | -| NextRoll ID | NextRoll | nextrollId | nextroll.com | "bf3Ka.../SjP/zpVGr09voA" | -| Novatiq ID | Novatiq | novatiqId | novatiq.com | "1111" | -| Parrable ID | Parrable | parrableId | parrable.com | {"eid":"01.15946..."} | -| Publisher Link ID | n/a | publinkId | epsilon.com | | -| PubProvided ID | n/a | pubProvidedId | publisher domain | "1111" | -| Quantcast ID | n/a | quantcastId | quantcast.com | "1111" | -| Tapad ID | Tapad | tapadId | tapad.com | "1111" | -| SharedID (PBJS 5.x) | n/a | pubcid | pubcid.org | "1111" | -| SharedID (PBJS 4.x)| Prebid | sharedid | sharedid.org | {"id":"01EAJWWN...", "third":"01EAJ..."} | -| Unified ID | Trade Desk | tdid | adserver.org | "1111" | -| ConnectID | Yahoo | connectId | yahoo.com | "72d04af6..." | - -For example, the adapter code might do something like: - -{% highlight javascript %} - if (bidRequest.userId && bidRequest.userId.sharedid) { - url+="&pubcid="+bidRequest.userId.sharedid; - } -{% endhighlight %} - -### Prebid Server Adapters - -Bidders that want to support the User ID module in Prebid Server, need to update their server-side bid adapter to read the desired OpenRTB 'user.ext.eids.source' object and forward the relevant values to their endpoint. - -See the [Prebid.js EIDs javascript source](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.js) for the definitive list of user EID sources. - -### Exporting User IDs - -If you need to export the user IDs stored by Prebid User ID module, the `getUserIds()` function will return an object formatted the same as bidRequest.userId. - -``` -pbjs.getUserIds() // returns object like bidRequest.userId. e.g. {"pubcid":"1111", "tdid":"2222"} -``` - -You can use [`getUserIdsAsEids()`](/dev-docs/publisher-api-reference/getUserIds.html) to get the user IDs stored by Prebid User ID module in ORTB Eids format. Refer [eids.md](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.md) for output format. -``` -pbjs.getUserIdsAsEids() // returns userIds in ORTB Eids format. e.g. -[ - { - source: 'pubcid.org', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }, - - { - source: 'adserver.org', - uids: [{ - id: 'some-random-id-value', - atype: 1, - ext: { - rtiPartner: 'TDID' - } - }] - }, - - { - source: 'id5-sync.com', - uids: [{ - id: 'ID5-12345', - atype: 1, - ext: { - linkType: 2, - abTestingControlGroup: false - } - }] - } -] ``` -## ID Providers - -If you're an ID provider that wants to get on this page: - -- Fork Prebid.js and write a sub-module similar to one of the *IdSystem modules already in the [modules](https://github.com/prebid/Prebid.js/tree/master/modules) folder. -- Add your *IdSystem name into the modules/.submodules.json file -- Follow all the guidelines in the [contribution page](https://github.com/prebid/Prebid.js/blob/master/CONTRIBUTING.md). -- Submit a Pull Request against the [Prebid.js repository](https://github.com/prebid/Prebid.js). -- Fork the prebid.org [documentation repository](https://github.com/prebid/prebid.github.io), modify /dev-docs/modules/userId.md, /download.md, and submit a documentation Pull Request. - - - -## Passing UserIds to Google Ad Manager for targeting - -User IDs from Prebid User ID module can be passed to GAM for targeting in Google Ad Manager or could be passed ahead to Google Open Bidding using ```userIdTargeting``` module. Note Google deprecated the ability to pass key values, including identifiers, to OB partners and then later began a closed beta to resume it with details non-public (see https://developers.google.com/authorized-buyers/rtb/request-guide ). More details on the user id module can be found [here](https://github.com/prebid/Prebid.js/blob/master/modules/userIdTargeting.md). In short, you just need to add the optional userIdTargeting sub-module into your `gulp build` command and the additional `userIdTargeting` config becomes available. +This will have no effect until you call the `registerSignalSources` API. This method must be called +**after** the `pbjs.setConfig` and `gpt.js` has loaded. See [API reference for `registerSignalSources`](/dev-docs/publisher-api-reference/registerSignalSources.html) ## Further Reading diff --git a/dev-docs/modules/userid-submodules/33across.md b/dev-docs/modules/userid-submodules/33across.md new file mode 100644 index 0000000000..903bc2a9df --- /dev/null +++ b/dev-docs/modules/userid-submodules/33across.md @@ -0,0 +1,56 @@ +--- +layout: userid +title: 33Across ID +description: 33Across ID User ID sub-module +useridmodule: 33acrossIdSystem +--- + + +The 33Across User ID sub-module is a way for publishers to monetize their cookieless inventory across multiple supply-side platforms via Prebid.JS. The sub-module provides publishers with addressability for their open marketplace cookieless inventory and access to cookieless demand. The 33Across User ID sub-module utilizes Lexicon technology to connect Publishers to Demand partners via proprietary technologies in a probabilistic and privacy-safe manner. Please contact [PrebidUIM@33across.com](mailto:PrebidUIM@33across.com) to get your authorization process started. + +For Lexicon, we only support US/CAN/AUS/JP. + +## 33Across ID Configuration + +Please make sure to add the 33across user ID sub-module to your Prebid.js package with: + +```shell +gulp build --modules=33acrossIdSystem,userId +``` + +The following configuration parameters are available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this sub-module | `"33acrossId"` | +| params ||| Details for the sub-module initialization || +| params.pid | Required | String | Partner ID (PID) | Please reach out to [PrebidUIM@33across.com](mailto:PrebidUIM@33across.com) and request your PID | +| params.storeFpid | Optional | Boolean | Indicates whether a supplemental first-party ID may be stored to improve addressability | `false` (default) or `true` | +| storage ||||| +| storage.name | Required | String | The name of the cookie or html5 local storage key | `"33acrossId"` (recommended) | +| storage.type | Required | String | This is where the 33across user ID will be stored | `"html5"` (recommended) or `"cookie"` | +| storage.expires | Strongly Recommended | Number | How long (in days) the user ID information will be stored | `30` (recommended) | +| storage.refreshInSeconds | Strongly Recommended | Number | How many seconds until the ID is refreshed | `8 * 3600` (recommended) | + +## 33Across ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "33acrossId", + params: { + pid: "0010b00002GYU4eBAH", // Example ID + storeFpid: true + }, + storage: { + name: "33acrossId", + type: "html5", + expires: 30, + refreshInSeconds: 8 * 3600 + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/admixer.md b/dev-docs/modules/userid-submodules/admixer.md new file mode 100644 index 0000000000..1ceb62cafb --- /dev/null +++ b/dev-docs/modules/userid-submodules/admixer.md @@ -0,0 +1,52 @@ +--- +layout: userid +title: AdmixerID +description: AdmixerID User ID sub-module +useridmodule: admixerIdSystem +--- + + +Admixer ID, provided by [Admixer](https://admixer.com/), is a universal ID solution that doesn't rely on 3rd party cookies and helps publishers and advertisers to recognize users across various browsers and environments. Our sub adapter takes deterministic signals like email and phone as input and returns an anonymous id that unlocks access to a wide range of Admixer's demand sources, amplifying audience segmentation, targeting and measurement. + +The Admixer privacy policy is at + +Add Admixer ID module to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=admixerIdSystem + +## AdmixerID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"admixerId"` | `"admixerId"` | +| params | Required | Object | Details for admixer initialization. | | +| params.pid | Optional | String | id provided by admixer | "458frgde-djd7-3ert-gyhu-12fghy76dnmko" | +| params.e | Optional | String | The hashed email address of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha256. | "3d400b57e069c993babea0bd9efa79e5dc698e16c042686569faae20391fd7ea" | +| params.p | Optional | String | The hashed phone number of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha256. | "05de6c07eb3ea4bce45adca4e0182e771d80fbb99e12401416ca84ddf94c3eb9" | + +## AdmixerID Examples + +### Individual params may be set for the Admixer ID Submodule + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "admixerId", + storage: { + name: "admixerId", + type: "cookie", + expires: 30 + }, + params: { + pid: "4D393FAC-B6BB-4E19-8396-0A4813607316", // example id + e: "3d400b57e069c993babea0bd9efa79e5dc698e16c042686569faae20391fd7ea", // example hashed email (sha256) + p: "05de6c07eb3ea4bce45adca4e0182e771d80fbb99e12401416ca84ddf94c3eb9" //example hashed phone (sha256) + } + }], + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/adquery.md b/dev-docs/modules/userid-submodules/adquery.md new file mode 100644 index 0000000000..df509d54ea --- /dev/null +++ b/dev-docs/modules/userid-submodules/adquery.md @@ -0,0 +1,42 @@ +--- +layout: userid +title: adQuery QiD +description: adQuery QiD User ID sub-module +useridmodule: adqueryIdSystem +--- + + +The adQuery QiD is a first-party identifier designed for publishers using the Adquery adapter. For more information please contact [prebid@adquery.io](mailto:prebid@adquery.io) + +## adQuery QiD Configuration + +First, add the adQuery QiD module to your Prebid.js build: + +```shell +gulp build --modules=userId,adqueryIdSystem +``` + +Then configure the qui in your `userSync` configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'qid', + storage: { + name: 'qid', + type: 'html5', + expires: 365, + } + }] + } +}); +``` + +This will add a `userId.qid` property to all bidRequests. This will be read by the Adquery bid adapter, and any other adapters that support EIDs: + +```javascript +{ + qid: 'p9v2dpnuckkzhuc92i' +} +``` diff --git a/dev-docs/modules/userid-submodules/adriver.md b/dev-docs/modules/userid-submodules/adriver.md new file mode 100644 index 0000000000..e1f6b48b7f --- /dev/null +++ b/dev-docs/modules/userid-submodules/adriver.md @@ -0,0 +1,25 @@ +--- +layout: userid +title: Adriver ID +description: Adriver ID User ID sub-module +useridmodule: adriverId +--- + +## Adriver ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module: `"adriverId"` | `"adriverId"` | + +## Adriver ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "adriverId" + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/adtelligent.md b/dev-docs/modules/userid-submodules/adtelligent.md new file mode 100644 index 0000000000..ac210e75fd --- /dev/null +++ b/dev-docs/modules/userid-submodules/adtelligent.md @@ -0,0 +1,48 @@ +--- +layout: userid +title: Adtelligent +description: Adtelligent User ID sub-module +useridmodule: adtelligentIdSystem +--- + + +The [Adtelligent](https://adtelligent.com) ID system is a unique per-session user identifier for providing high quality DMP data for advertisers + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=userId,adtelligentIdSystem + +## Adtelligent Configuration + +adtelligentIdSystem adapter doesn't require any configuration or storage params. The adapter performs asynchronously and to achieve better performance it is recommended to set the `storage` object `refreshInSeconds` to a short period, such as ten minutes. At the end of the set storage refresh the adapter will refresh its configuration. + +## Adtelligent Example + +```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'adtelligent' + }] + } + }); +``` + +Example with a short storage for ~10 minutes and refresh in 5 minutes: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'adtelligent', + storage: { + type: "html5", + name: "adt_id", + expires:0.003, + refreshInSeconds: 60 * 5 + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/amxrtb.md b/dev-docs/modules/userid-submodules/amxrtb.md new file mode 100644 index 0000000000..8ab6d0eef4 --- /dev/null +++ b/dev-docs/modules/userid-submodules/amxrtb.md @@ -0,0 +1,42 @@ +--- +layout: userid +title: AMX ID +description: AMX ID User ID sub-module +useridmodule: amxIdSystem +--- + + +The AMX ID is a first-party identifier designed for publishers using the AMX RTB adapter. For more information please contact [info@amxdt.net](mailto:info@amxdt.net) + +## AMX ID Configuration + +First, add the AMX ID module to your Prebid.js build: + +```shell +gulp build --modules=userId,amxIdSystem +``` + +Then configure the amxId in your `userSync` configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'amxId', + storage: { + name: 'amxId', + type: 'html5', + expires: 14, + } + }] + } +}); +``` + +This will add a `userId.amxId` property to all bidRequests: + +```javascript +{ + amxId: '3ca11058-ecbc-419f-bda7-b52fe7baf02a' +} +``` diff --git a/dev-docs/modules/userid-submodules/audienceone.md b/dev-docs/modules/userid-submodules/audienceone.md new file mode 100644 index 0000000000..74d8d5bfee --- /dev/null +++ b/dev-docs/modules/userid-submodules/audienceone.md @@ -0,0 +1,39 @@ +--- +layout: userid +title: AudienceOne ID by DAC +description: AudienceOne ID by DAC User ID sub-module +useridmodule: dacIdSystem +--- + + +AudienceOne ID, provided by [D.A.Consortium Inc.](https://www.dac.co.jp/), is ID for ad targeting by using 1st party cookie. +Please visit [solutions.dac.co.jp/audienceone](https://solutions.dac.co.jp/audienceone) and request your Owner ID to get started. + +Add the AudienceOne ID to your Prebid.js Package with: + +{: .alert.alert-info :} +gulp build --modules=dacIdSystem + +## AudienceOne ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module | `"dacId"` | +| params | Required | Object | Details of module params. | | +| params.oid | Required | String | This is the Owner ID value obtained via D.A.Consortium Inc. | `"55h67qm4ck37vyz5"` | + +## AudienceOne ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'dacId', + params: { + 'oid': '55h67qm4ck37vyz5' // Set your AudienceOne Owner ID here + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/britepool.md b/dev-docs/modules/userid-submodules/britepool.md new file mode 100644 index 0000000000..1ad65a74ff --- /dev/null +++ b/dev-docs/modules/userid-submodules/britepool.md @@ -0,0 +1,58 @@ +--- +layout: userid +title: BritePool +description: BritePool User ID sub-module +useridmodule: britepoolIdSystem +--- + +{: .alert.alert-warning :} +britepool is probably a defunct User ID system, as britepool.com is now an e-commerce site. + +The BritePool ID is a persistent identifier that enables identity resolution for people-based marketing in the cookieless world. Every BritePool ID is associated with a real identity. As a result, publishers, SSPs and DSPs that integrate with BritePool, or automated +integration partners (such as PubMatic), are able to maximize revenues without cookies. As addressable individuals visit publisher websites and mobile apps, the BritePool IDs associated with these identities are passed into the bidstream; enabling advertisers to transact against these BritePool ID's and publishers to maximize the revenues associated with their inventory and audience. The BritePool ID combines consumer privacy with easy, rapid integration for publishers and does not significantly increase the computing resources required of DSPs and SSPs. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=britepoolIdSystem + +## BritePool Registration + +Please reach out to [prebid@britepool.com](mailto:prebid@britepool.com) and request your `api_key`. + +## BritePool Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"britepoolId"` | `"britepoolId"` | +| params | Required | Object | Details for britepool initialization. | | +| params.api_key | Required | String | BritePool API Key provided by BritePool | "458frgde-djd7-3ert-gyhu-12fghy76dnmko" | +| params.url | Optional | String | BritePool API url | "URL" | +| params.identifier | Required | String | Where identifier in the params object is the key name. At least one identifier is required. Available Identifiers `aaid` `dtid` `idfa` `ilid` `luid` `mmid` `msid` `mwid` `rida` `ssid` `hash` | `params.ssid` `params.aaid` | + +## BritePool Examples + +### Individual params may be set for the BritePool User ID Submodule. At least one identifier must be set in the params + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "britepoolId", + storage: { + name: "britepoolid", + type: "cookie", + expires: 30 + }, + params: { + url: "URL", // optional. used for testing + api_key: "xxx", // provided by britepool + hash: "yyyy", // example identifier + ssid: "r894hvfnviurfincdejkencjcv" // example identifier + } + }], + syncDelay: 3000 // 3 seconds after the first auction + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/cpexid.md b/dev-docs/modules/userid-submodules/cpexid.md new file mode 100644 index 0000000000..ee9a48fa42 --- /dev/null +++ b/dev-docs/modules/userid-submodules/cpexid.md @@ -0,0 +1,30 @@ +--- +layout: userid +title: Czech Ad ID (czechAdId) +description: Czech Ad ID (czechAdId) User ID sub-module +useridmodule: czechAdIdSystem +--- + +Czech Ad ID is a joint project of publishers of the [CPEx alliance](https://www.cpex.cz/) and [Seznam.cz](https://www.seznam.cz). It is a deterministic user ID that offers cross-domain and cross-device identification. For more information see [czechadid.cz](https://www.czechadid.cz)). + +{: .alert.alert-info :} +gulp build --modules=czechAdIdSystem + +## czechAdId Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module | `"czechAdId"` | + +## czechAdId Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'czechAdId' + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/criteo.md b/dev-docs/modules/userid-submodules/criteo.md new file mode 100644 index 0000000000..8e48b94ce2 --- /dev/null +++ b/dev-docs/modules/userid-submodules/criteo.md @@ -0,0 +1,36 @@ +--- +layout: userid +title: Criteo ID for Exchanges +description: Criteo ID for Exchanges User ID sub-module +useridmodule: criteoIdSystem +--- + + +Criteo is the leading advertising platform for the Open Internet. The Criteo ID for Exchanges module enables publishers to access Criteo’s unique demand - more than 20.000 advertisers & brands - to monetize their exchange inventory with an optimal take rate across all browsing environments. +Note that direct access to that demand is also available through [Criteo Direct Bidder](https://www.criteo.com/products/criteo-direct-bidder/), in which case this module is unnecessary. + +The Criteo privacy policy is at [www.criteo.com/privacy/](https://www.criteo.com/privacy/). + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=criteoIdSystem + +## Criteo ID Configuration + +The Criteo ID module does not require any configuration parameters. It should work as-is provided that bidders use it in their adapters. + +{: .alert.alert-info :} +NOTE: For optimal performance, the Criteo Id module should be called at every opportunity. It embeds its own optimal caching mechanism. It's best not to use `params.storage` with this module as it may only lower the performances. If you are using multiple id systems, however, you may use it for the other id systems that supports it. + +## Criteo ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "criteo", + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/deepintent.md b/dev-docs/modules/userid-submodules/deepintent.md new file mode 100644 index 0000000000..6a56d887d6 --- /dev/null +++ b/dev-docs/modules/userid-submodules/deepintent.md @@ -0,0 +1,63 @@ +--- +layout: userid +title: Deepintent +description: Deepintent User ID sub-module +useridmodule: deepintentIdSystem +--- + + +The DeepIntent Healthcare Marketing Platform is the first and only DSP that combines real-world health data, premium partnerships, and custom integrations to reach patients and providers across any device. DeepIntent empowers publishers to maximize their inventory, collaborate and transact directly with advertisers, and grow their business in a safe, controlled, transparent, and privacy-compliant way. Our publisher partners sell inventory on every channel via real-time bidding or conducting one-to-one trading with hundreds of the country’s leading healthcare brands and agencies. + +DeepIntent’s DPES ID is a shared user identifier built for healthcare marketers and publishers integrated within DeepIntent’s Healthcare Marketplace. The DPES ID lets users protect and manage their privacy throughout the advertising value chain. User data written and associated with the DPES ID is not stored on DeepIntent’s servers. Instead, this data is stored in a decentralized way on a user’s browser. Users can still opt out of the ads by navigating to + +## Deepintent DPES ID Registration + +DPES ID is free to use and requires a simple registration with DeepIntent. Please reach out to DeepIntent’s Publisher Development team at to learn more and get started. Once a publisher registers with DeepIntent’s platform, DeepIntent will provide a simple code snippet to be integrated with the publisher’s website. This code snippet will capture and store information per the publisher’s end user agreement. The DPES User ID module uses the DPES ID by passing it within the DeepIntent Prebid adapter. + +## Deepintent DPES ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module: `"deepintentId"` | `"deepintentId"` | +| storage | Required | Object | Storage settings for how the User Id module will cache the Deepintent ID locally | | +| storage.type | Required | String | This is where the results of the user ID will be stored. Deepintent`"html5"` or `"cookie"`. | `"html5"` | +| storage.name | Optional | String | The name of the local storage where the user ID will be stored. Deepintent | `"_dpes_id"` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. Deepintent recommends `90`. | `90` | + +## Deepintent DPES ID Examples + +1. Publisher stores the hashed identity from healthcare identity in cookie + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'deepintentId', + storage: { + type: 'cookie', // "html5" is the required storage type option is "html5" + name: '_dpes_id', + expires: 90 // storage lasts for 90 days, optional if storage type is html5 + } + }], + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + } + }); + ``` + +2. Publisher stores the hashed identity from healthcare identity in localstorage + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'deepintentId', + storage: { + type: 'html5' // "html5" is the required storage type option is "html5" + name: '_dpes_id' + } + }], + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + } + }); + ``` diff --git a/dev-docs/modules/userid-submodules/dmd.md b/dev-docs/modules/userid-submodules/dmd.md new file mode 100644 index 0000000000..7e932dc0c0 --- /dev/null +++ b/dev-docs/modules/userid-submodules/dmd.md @@ -0,0 +1,46 @@ +--- +layout: userid +title: DMD ID by DMD Marketing Corp +description: DMD ID by DMD Marketing Corp User ID sub-module +useridmodule: dmdIdSystem +--- + + +DMD is the preeminent supplier of US-based healthcare professional (HCP) identity data to the pharmaceutical, health system and medical publishing industries. DMD is the only data provider that has acquired its deterministic identity data through a fully consented, first-party, opt-in process. DMD’s privacy policy that can be found at [Privacy Policy](https://hcn.health/privacy-policy). + +For assistance setting up your module, please contact us at + +Add the DMD ID to your Prebid.js Package with: + +{: .alert.alert-info :} +gulp build --modules=userId,dmdIdSystem + +## DMD ID Registration + +Please reach out to [prebid@dmdconnects.com](mailto:prebid@dmdconnects.com) to request your `api_key` + +## DMD ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of Module | `"dmdId"` | +| storage | Required | Object | | +| storage.name | Required | String | `dmd-dgid` | +| params | Required | Object | Container of all module params. | | +| params.api_key | Required | String | This is your `api_key` as provided by DMD Marketing Corp. | `3fdbe297-3690-4f5c-9e11-ee9186a6d77c` | + +## DMD ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'dmdId', + params: { + api_key: '3fdbe297-3690-4f5c-9e11-ee9186a6d77c' // provided to you by DMD + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/euid.md b/dev-docs/modules/userid-submodules/euid.md new file mode 100644 index 0000000000..7e279c9cf1 --- /dev/null +++ b/dev-docs/modules/userid-submodules/euid.md @@ -0,0 +1,187 @@ +--- +layout: userid +title: European Unified ID +description: European Unified ID User ID sub-module +useridmodule: euidIdSystem +--- + +European Unified ID (EUID) is an open-source identity solution built for the open internet and based on the Unified ID 2.0 solution. It leverages encrypted email data to provide a privacy-conscious, secure, and accurate identity standard designed to meet market requirements in Europe and the UK. + +EUID relies on user consent before an ID can be added to the bid stream. Consent can be gathered by SSO providers who have integrated against the EUID framework, or through a publisher's own login and consent mechanism. + +To add EUID to your Prebid.js package, run the following: + +{: .alert.alert-info :} +gulp build --modules=euidIdSystem + +## European Unified ID Registration + +European Unified ID is still in the pre-release phase. To obtain an EUID publisher account, get in touch with your UID2 account contact. + +Each publisher’s privacy policy should take European Unified ID into account. + +## European Unified ID Tokens + +EUID tokens are generated on the server side by making an API call to an EUID operator using details provided when you receive EUID publisher access. This API returns a JSON data structure with multiple values, including an advertising token and a refresh token. For full functionality, provide the entire object in one of these ways: + +- JSON-encoded as a cookie. +- Included in the configuration object. + +For examples, see [European Unified ID Examples](#european-unified-id-examples). + +The following sample is fictitious, but shows what the token response object looks like: + +```javascript +{ + "advertising_token": "...", + "refresh_token": "...", + "identity_expires": 1633643601000, + "refresh_from": 1633643001000, + "refresh_expires": 1636322000000, + "refresh_response_key": "wR5t6HKMfJ2r4J7fEGX9Gw==" +} +``` + +When this full data structure is provided, the module automatically refreshes the token periodically, as long as the refresh token hasn't expired. + +## Client Refresh mode + +This is the recommended mode for most scenarios. In this mode, the full response body from the EUID Token Generate or Token Refresh endpoint must be provided to the module. As long as the refresh token remains valid, the module will refresh the advertising token as needed. + +To configure the module to use this mode, you must **either**: + +1. Set `params.euidCookie` to the name of the cookie which contains the response body as a JSON string, **or** +2. Set `params.euidToken` to the response body as a JavaScript object. + +### Client refresh cookie example + +In this example, the cookie is called `euid_pub_cookie`. + +Cookie: + +```javascript +euid_pub_cookie={"advertising_token":"...advertising token...","refresh_token":"...refresh token...","identity_expires":1684741472161,"refresh_from":1684741425653,"refresh_expires":1684784643668,"refresh_response_key":"...response key..."} +``` + +Configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid', + params: { + euidCookie: 'euid_pub_cookie' + } + }] + } +}); +``` + +### Client refresh euidToken example + +Configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid', + params: { + euidToken: { + 'advertising_token': '...advertising token...', + 'refresh_token': '...refresh token...', + // etc. - see the Sample Token below for contents of this object + } + } + }] + } +}); +``` + +## European Unified ID Server-Only Mode + +There is a server-only mode where the value of the advertising token can be provided either directly (see the `value` parameter in the [European Unified ID Configuration](#european-unified-id-configuration) section) or via a cookie. In this mode, no attempt is made to automatically refresh the token. + +### Cookie-based server-only mode + +To use the cookie-based server-only mode, set a cookie named `__euid_advertising_token` to the value of the advertising token only, as shown in this fictitious example: + +Cookie: `__euid_advertising_token=eb33b0cb8d354722b9c01a31d4064888` + +Configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid' + }] + } +}); +``` + +### Configuration-based server-only mode + +To use the configuration-based server-only mode, set the value directly in the configuration of the module, as shown in this fictitious example: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid' + value: { + 'euid': { + 'id': 'eb33b0cb8d354722b9c01a31d4064888' + } + } + }] + } +}); +``` + +## European Unified ID Configuration + +The following parameters apply only to the European Unified ID module integration. + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the EUID module - `"euid"` | `"euid"` | +| value | Optional, Server only | Object | An object containing the value for the advertising token. | See the example above. | +| params.euidToken | Optional, Client refresh | Object | The initial EUID token. This should be `body` element of the decrypted response from a call to the `/token/generate` or `/token/refresh` endpoint. | See the sample token above. | +| params.euidCookie | Optional, Client refresh | String | The name of a cookie which holds the initial EUID token, set by the server. The cookie should contain JSON in the same format as the euidToken param. **If euidToken is supplied, this param is ignored.** | See the sample token above. | +| params.euidApiBase | Optional, Client refresh | String | Overrides the default EUID API endpoint. | `"https://prod.euid.eu"` _(default)_| +| params.storage | Optional, Client refresh | String | Specify whether to use `cookie` or `localStorage` for module-internal storage. It is recommended to not provide this and allow the module to use the default. | `localStorage` _(default)_ | + +## European Unified ID Examples + +In the following example, the publisher has set a cookie called `euid_identity` containing the EUID token generation response object: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid', + params: { + euidServerCookie: 'euid_identity' + } + }] + } +}); +``` + +In the following example, the publisher has retrieved a server-generated EUID response, and it is currently stored in the JavaScript variable `euidIdentity`: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'euid', + params: { + euidToken: euidIdentity + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/fabrick.md b/dev-docs/modules/userid-submodules/fabrick.md new file mode 100644 index 0000000000..582ed44926 --- /dev/null +++ b/dev-docs/modules/userid-submodules/fabrick.md @@ -0,0 +1,88 @@ +--- +layout: userid +title: Fabrick ID by Neustar +description: Fabrick ID by Neustar User ID sub-module +useridmodule: fabrickIdSystem +--- + + +[Neustar Fabrick™](https://www.home.neustar/fabrick) is a unified identity ecosystem that powers connections between brands, publishers, and consumers to accelerate marketing performance across online and offline channels. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=fabrickIdSystem + +## Fabrick Registration + +Please reach out to [FabrickIntegrations@team.neustar](mailto:FabrickIntegrations@team.neustar) to request your `apiKey`. + +## Fabrick Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `"fabrickId"` | +| params | Required | Object | Container of all module params. | | +| params.apiKey | Required | String | This is your apiKey as provided by Neustar. | | +| params.e | | String | This is a hashed email address used to link a user to their Fabrick ID. | | +| params.p | | String | This is a hashed phone number used to link a user to their Fabrick ID. | | +| params.i4 | | String | This is an IPv4 address used to link a user to their Fabrick ID. | | +| params.i6 | | String | This is an IPv6 address used to link a user to their Fabrick ID. | | +| params.m | | String | This is a mobile advertising ID (IDFA/AAID) used to link a user to their Fabrick ID. | | +| params.ia | | String | This is an identifier for advertising (IFA) used to link a user to their Fabrick ID. | | +| params.iv | | String | This is an identifier for vendors (IFV) used to link a user to their Fabrick ID. | | +| params.1pd | | String | This is partner or advertiser’s 1st party user ID (e.g. a Customer ID/CUSTID) other than a 1st party cookie ID. Length allowed: 255 characters. Characters allowed: (A-Z a-z), digits (0-9), '-' '_' '/' ':' '=' '.'. Characters not allowed: '>' '<' '*' '+' '&' '@' '#' '!' '%' '$' '(' ')' '?' ';' '\|' '\' '{' '}' '[' ']'. | | +| params.u | | String | This is the page_url - the url which the user is currently browsing. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | +| params.f | | String | This is the referrer_url - the url which the user visited prior to landing on the page_url. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | +| params.ifa_type | | String | This denotes the source of the IFA. Please refer to [IAB IFA Guidelines](https://iabtechlab.com/wp-content/uploads/2018/12/OTT-IFA-guidelines.final_Dec2018.pdf) for recommended values and additional details. | | +| params.lmt | | Boolean | Possible values are '0' or '1'. A value of '1' indicates that a user has requested that ad tracking and measurement be disabled. If a value of '1' is being passed, the real IFA must not be sent via the 'ia' parameter – a 'synthetic' or 'session' IFA can be sent. Please refer to [IAB IFA Guidelines](https://iabtechlab.com/wp-content/uploads/2018/12/OTT-IFA-guidelines.final_Dec2018.pdf) for recommended values and additional details. | | +| params.1pc | | String | This is partner or advertiser’s 1st party cookie ID. Length allowed: 255 characters. Characters allowed: (A-Z a-z), digits (0-9), '-' '_' '/' ':' '=' '.'. Characters not allowed: '>' '<' '*' '+' '&' '@' '#' '!' '%' '$' '(' ')' '?' ';' '\|' '\' '{' '}' '[' ']'. | | +| params.iab1 | | String | This is IAB Tech Lab’s Content Taxonomy v3.0  Tier 1 category. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | +| params.iab2 | | String | This is IAB Tech Lab’s Content Taxonomy v3.0  Tier 2 category. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | +| params.iab3 | | String | This is IAB Tech Lab’s Content Taxonomy v3.0 Tier 3 category. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | +| params.iab4 | | String | This is IAB Tech Lab’s Content Taxonomy v3.0 Tier 4 category. Note: Encoding is required for any character outside of alphabets (A-Z a-z), digits (0-9), hyphen (-), underscore (_) tilde (~), and dot (.). | | + +## Fabrick Examples + +1. Publisher passes an apiKey and hashed email address and elects to store the Fabrick ID envelope in a cookie. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'fabrickId', + params: { + apiKey: '123456789', // provided to you by Neustar + e: '31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66' // example hashed email address (sha256) + }, + storage: { + name: 'pbjs_fabrickId', + type: 'cookie', + expires: 7 + } + }] + } + }); + ``` + +2. Publisher passes an apiKey and hashed email address and elects to store the fabrickId envelope in HTML5 localStorage. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'fabrickId', + params: { + apiKey: '123456789', // provided to you by Neustar + e: '31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66' // example hashed email address (sha256) + }, + storage: { + type: "html5", + name: "pbjs_fabrickId", + expires: 7 + } + }] + } + }); + ``` diff --git a/dev-docs/modules/userid-submodules/floc.md b/dev-docs/modules/userid-submodules/floc.md new file mode 100644 index 0000000000..a7b31a3e56 --- /dev/null +++ b/dev-docs/modules/userid-submodules/floc.md @@ -0,0 +1,30 @@ +--- +layout: userid +title: FLoC ID +description: FLoC ID User ID sub-module +useridmodule: flocIdSystem +enable_download: false +--- + +{: .alert.alert-warning :} +This module was removed in Prebid.js 7.0 + +The [Federated Learning of Cohorts (FLoC)](https://web.dev/floc/) system provides a privacy-preserving mechanism for interest-based ad selection. As a user moves around the web, their browser uses the FLoC algorithm to work out an "interest cohort", which will be the same for thousands of browsers with a similar recent browsing history. The user's browser is associated with one interest cohort at a time and recalculates its cohort periodically (currently once every seven days during this initial origin trial) on the user's device, without sharing individual browsing data with the browser vendor or anyone else. + +There are two important things to note when using the FLoC Userid Sub adapter. + +1. Unlike other user id subadapters FLoC ids cannot be stored in a cookie or Local Storage. FLoC ids change periodically and should always be fetched from the FLoC API + +2. The function `(getGlobal()).getUserIds` returns `userId.flocId.id=value` into the bid request **NOT** `userid.userIdAsEids`. + +To include the FLoC user id module use: + +`$ gulp build --modules=flocIdSystem` + +{: .alert.alert-info :} +Note: FLoC is still in a trial period. [How to take part in the FLoC origin trial](https://developer.chrome.com/blog/floc/). During the trial, a token is +required. Publishers may get their own token or use sharedid's token if they choose. Use this without the line breaks: +A3dHTSoNUMjjERBLlrvJSelNnwWUCwVQhZ5tNQ+sll7y+LkPPVZXtB77u2y7CweRIxiYaGw +GXNlW1/dFp8VMEgIAAAB+eyJvcmlnaW4iOiJodHRwczovL3NoYXJlZGlkLm9yZzo0NDMiLC +JmZWF0dXJlIjoiSW50ZXJlc3RDb2hvcnRBUEkiLCJleHBpcnkiOjE2MjYyMjA3OTksImlzU +3ViZG9tYWluIjp0cnVlLCJpc1RoaXJkUGFydHkiOnRydWV9 diff --git a/dev-docs/modules/userid-submodules/freepass.md b/dev-docs/modules/userid-submodules/freepass.md new file mode 100644 index 0000000000..9c829ee064 --- /dev/null +++ b/dev-docs/modules/userid-submodules/freepass.md @@ -0,0 +1,47 @@ +--- +layout: userid +title: FreePass ID +description: FreePass User ID sub-module +useridmodule: freepassIdSystem +--- + +[FreePass](https://freepass-login.com/introduction.html) is a common authentication service operated by Freebit Co., Ltd. Users with a FreePass account do not need to create a new account to use partner services. + +Please contact FreePass before using this ID at [fp-hbidding@freebit.net](mailto:fp-hbidding@freebit.net) + +## FreePass ID Configuration + +Please make sure to add the FreePass user ID sub-module to your Prebid.js package with: + +```shell +gulp build --modules=freepassIdSystem,userId +``` + +The following configuration parameters are available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +|--------------------------------|----------|--------|------------------------------------------------------|----------------| +| name | Required | String | The name of this module | `"freepassId"` | +| freepassData | Optional | Object | FreePass data | `{}` | +| freepassData.commonId | Optional | String | Common ID obtained from FreePass | `"abcd1234"` | +| freepassData.userIp | Optional | String | User IP obtained in cooperation with partner service | `"127.0.0.1"` | + +Usage example: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'freepassId', + storage: { name: '_freepassId', type: 'cookie', expires: 30 }, + params: { + freepassData: { + commonId: 'fpcommonid123', + userIp: '127.0.0.1' + } + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/ftrack.md b/dev-docs/modules/userid-submodules/ftrack.md new file mode 100644 index 0000000000..89b636c898 --- /dev/null +++ b/dev-docs/modules/userid-submodules/ftrack.md @@ -0,0 +1,58 @@ +--- +layout: userid +title: FTrack ID from Flashtalking By Mediaocean +description: FTrack ID from Flashtalking By Mediaocean User ID sub-module +useridmodule: ftrackIdSystem +--- + + +The FTrack Identity Framework (["FTrack"](https://www.flashtalking.com/identity-framework#FTrack)) User ID Module allows publishers to take advantage of Flashtalking's FTrack ID during the bidding process. + +Flashtalking’s cookieless tracking technology uses probabilistic device recognition to derive a privacy-friendly persistent ID for each device. + +Questions? Comments? Bugs? Praise? Please contact FlashTalking's Prebid Support at [prebid-support@flashtalking.com](mailto:prebid-support@flashtalking.com) + +Complete information available on the Flashtalking [privacy policy page](https://www.flashtalking.com/privacypolicy). + +## FTrack ID from Flashtalking By Mediaocean Configuration + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'FTrack', + params: { + url: 'https://d9.flashtalking.com/d9core', // required, if not populated ftrack will not run + ids: { + 'device id': true, + 'single device id': true, + 'household id': true + } + }, + storage: { + type: 'html5', // "html5" is the required storage type + name: 'FTrackId', // "FTrackId" is the required storage name + expires: 90, // storage lasts for 90 days + refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh + } + }], + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + } +}); +``` + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| :-- | :-- | :-- | :-- | :-- | +| name | Required | String | The name of this module: `"FTrack"` | `"FTrack"` | +| params | Required | Object | The IDs available, if not populated then the defaults "Device ID" and "Single Device ID" will be returned | | +| params.url | Required | String | The URL for the ftrack library reference. If not populated, ftrack will not run. | '' | +| params.ids | Optional | Object | The ftrack IDs available, if not populated then the defaults "Device ID" and "Single Device ID" will be returned | | +| params.ids['device id'] | Optional | Boolean | Should ftrack return "device id". Set to `true` to return it. If set to `undefined` or `false`, ftrack will not return "device id". Default is `false` | `true` | +| params.ids['single device id'] | Optional | Boolean | Should ftrack return "single device id". Set to `true` to return it. If set to `undefined` or `false`, ftrack will not return "single device id". Default is `false` | `true` | +| params.ids['household id'] | Optional; _Requires pairing with either "device id" or "single device id"_ | Boolean | __1.__ Should ftrack return "household id". Set to `true` to attempt to return it. If set to `undefined` or `false`, ftrack will not return "household id". Default is `false`. __2.__ _This will only return "household id" if value of this field is `true` __AND__ "household id" is defined on the device._ __3.__ _"household id" requires either "device id" or "single device id" to be also set to `true`, otherwise ftrack will not return "household id"._ | `true` | +| storage | Required | Object | Storage settings for how the User ID module will cache the FTrack ID locally | | +| storage.type | Required | String | This is where the results of the user ID will be stored. FTrack __requires__ `"html5"`. | `"html5"` | +| storage.name | Required | String | The name of the local storage where the user ID will be stored. FTrack __requires__ `"FTrackId"`. | `"FTrackId"` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. FTrack recommends `90`. | `90` | +| storage.refreshInSeconds | Optional | Integer | How many seconds until the FTrack ID will be refreshed. FTrack strongly recommends 8 hours between refreshes | `8*3600` | diff --git a/dev-docs/modules/userid-submodules/gravito.md b/dev-docs/modules/userid-submodules/gravito.md new file mode 100644 index 0000000000..dfb57b3020 --- /dev/null +++ b/dev-docs/modules/userid-submodules/gravito.md @@ -0,0 +1,34 @@ +--- +layout: userid +title: GRAVITO ID by Gravito Ltd. +description: GRAVITO ID by Gravito Ltd. User ID sub-module +useridmodule: gravitoIdSystem +--- + + +Gravito ID, provided by [Gravito Ltd.](https://gravito.net), is ID for ad targeting by using 1st party cookie. +Please contact Gravito Ltd. for using this ID. + +Add the Gravito ID to your Prebid.js Package with: + +{: .alert.alert-info :} +gulp build --modules=gravitoIdSystem + +## Gravito ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module | `"gravitompId"` | + +## Gravito ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'gravitompId' + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/growthcode.md b/dev-docs/modules/userid-submodules/growthcode.md new file mode 100644 index 0000000000..8add06f7cf --- /dev/null +++ b/dev-docs/modules/userid-submodules/growthcode.md @@ -0,0 +1,73 @@ +--- +layout: userid +title: GrowthCode +description: GrowthCode User ID sub-module +useridmodule: growthCodeIdSystem +--- + + +[GrowthCode](https://growthcode.io/) offers scaled infrastructure-as-a-service +to empower independent publishers to harness data and take control of +identity and audience while rapidly aligning to industry changes and +margin pressure. + +## GrowthCode Configuration + +First, make sure to add the GrowthCode submodule to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=growthCodeIdSystem,userId + +The following configuration parameters are available: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'growthCodeId', + params: { + customerEids: 'customerEids', + } + }] + } +}); +``` + +The following configuration parameters are available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +|--------------------------------|----------|--------|------------------------------------------------------------------------|-----------------| +| name | Required | String | The name of this module. | `"growthCodeId"` | +| params | Required | Object | Details of module params. | | +| params.customerEids | Optional | String | Name of the variable name where the customer EID information is stored | | + +### Sample Eids +Below is an example of the EIDs stored in Local Store (customerEids) + +```json +[ + { + "source":"domain.com", + "uids":[ + { + "id":"8212212191539393121", + "ext":{ + "stype":"ppuid" + } + } + ] + }, + { + "source":"example.com", + "uids":[ + { + "id":"e06e9e5a-273c-46f8-aace-6f62cf13ea71", + "ext":{ + "stype":"ppuid" + } + } + ] + } +] +``` diff --git a/dev-docs/modules/userid-submodules/hadron.md b/dev-docs/modules/userid-submodules/hadron.md new file mode 100644 index 0000000000..3f067c944a --- /dev/null +++ b/dev-docs/modules/userid-submodules/hadron.md @@ -0,0 +1,54 @@ +--- +layout: userid +title: Hadron ID from Audigent +description: Hadron ID from Audigent User ID sub-module +useridmodule: hadronIdSystem +--- + + +Audigent is a next-generation data management platform and a first-of-a-kind "data agency" containing some of the most exclusive content-consuming audiences across desktop, mobile and social platforms. Our HadronId module allows for user id resolution and Audigent user data segmentation to be retrieved for users across the web. For assistance setting up your module please contact us at [prebid@audigent.com](mailto:prebid@audigent.com). + +## HadronId Configuration + +Add the Hadron ID system to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=userId,hadronIdSystem + +Add HadronId to the userSync configuration. + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'hadronId', + storage: { + name: 'hadronId', + type: 'html5' + }, + params: { + partnerId: 1234 + } + }] + } +}); +``` + +The `request.userId.hadronId` will contain the Audigent HadronId: + +```json +{ + "hadronId": "0201chpvai07jv2yg08xizqr0bwpa1w0evvmq014d2ykn0b5oe" +} +``` + +The following configuration parameters are available: + +{: .table .table-bordered .table-striped } +| Param under usersync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the HadronID module - `"hadronId"` | `"hadronId"` | +| params | Optional | Object | Used to store params for the HadronId system | +| params.url | Optional | String | Set an alternate GET url for HadronId with this parameter | +| params.urlArg | Optional | Object | Optional url parameter for params.url | +| params.partnerId | Required | Number | This is the Audigent Partner ID obtained from Audigent. | diff --git a/dev-docs/modules/userid-submodules/id5.md b/dev-docs/modules/userid-submodules/id5.md new file mode 100644 index 0000000000..ac2d6455d2 --- /dev/null +++ b/dev-docs/modules/userid-submodules/id5.md @@ -0,0 +1,82 @@ +--- +layout: userid +title: ID5 ID +description: ID5 ID User ID sub-module +useridmodule: id5IdSystem +--- + + +The ID5 ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 ID and detailed integration docs, please visit [our documentation](https://wiki.id5.io/en/identitycloud/retrieve-id5-ids/prebid-user-id-module/id5-prebid-user-id-module). + +## ID5 ID Registration + +The ID5 ID is free to use, but requires a simple registration with ID5. Please visit [our website](https://id5.io/solutions/#publishers) to sign up and request your ID5 Partner Number to get started. + +The ID5 privacy policy is at [id5.io/platform-privacy-policy](https://id5.io/platform-privacy-policy). + +## ID5 ID Configuration + +First, make sure to add the ID5 submodule to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=id5IdSystem,userId + +The following configuration parameters are available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` | +| params | Required | Object | Details for the ID5 ID. | | +| params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` | +| params.externalModuleUrl | Optional | String | URL to the external ID5 module. Highly recommended for the best integration possible. | `https://cdn.id5-sync.com/api/1.0/id5PrebidModule.js` | +| params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://wiki.id5.io/en/identitycloud/retrieve-id5-ids/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` | +| params.abTesting | Optional | Object | Allows publishers to easily run an A/B Test. If enabled and the user is in the Control Group, the ID5 ID will NOT be exposed to bid adapters for that request | Disabled by default | +| params.abTesting.enabled | Optional | Boolean | Set this to `true` to turn on this feature | `true` or `false` | +| params.abTesting.controlGroupPct | Optional | Number | Must be a number between `0.0` and `1.0` (inclusive) and is used to determine the percentage of requests that fall into the control group (and thus not exposing the ID5 ID). For example, a value of `0.20` will result in 20% of requests without an ID5 ID and 80% with an ID. | `0.1` | +| params.disableExtensions | Optional | Boolean | Set this to `true` to force turn off extensions call. Default `false` | `true` or `false` | + +{: .alert.alert-info :} +**NOTE:** The ID5 ID that is delivered to Prebid will be encrypted by ID5 with a rotating key to avoid unauthorized usage and to enforce privacy requirements. Therefore, we strongly recommend setting `storage.refreshInSeconds` to `8` hours (`8*3600` seconds) or less to ensure all demand partners receive an ID that has been encrypted with the latest key, has up-to-date privacy signals, and allows them to transact against it. + +### A Note on A/B Testing + +Publishers may want to test the value of the ID5 ID with their downstream partners. While there are various ways to do this, A/B testing is a standard approach. Instead of publishers manually enabling or disabling the ID5 User ID Module based on their control group settings (which leads to fewer calls to ID5, reducing our ability to recognize the user), we have baked this in to our module directly. + +To turn on A/B Testing, simply edit the configuration (see above table) to enable it and set what percentage of users you would like to set for the control group. The control group is the set of user where an ID5 ID will not be exposed in to bid adapters or in the various user id functions available on the `pbjs` global. An additional value of `ext.abTestingControlGroup` will be set to `true` or `false` that can be used to inform reporting systems that the user was in the control group or not. It's important to note that the control group is user based, and not request based. In other words, from one page view to another, a user will always be in or out of the control group. + +### A Note on Using Multiple Wrappers +If you or your monetization partners are deploying multiple Prebid wrappers on your websites, you should make sure you add the ID5 ID User ID module to *every* wrapper. Only the bidders configured in the Prebid wrapper where the ID5 ID User ID module is installed and configured will be able to pick up the ID5 ID. Bidders from other Prebid instances will not be able to pick up the ID5 ID. + +## ID5 ID Examples + +Publisher wants to retrieve the ID5 ID through Prebid.js + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'id5Id', + params: { + partner: 173, // change to the Partner Number you received from ID5 + externalModuleUrl: 'https://cdn.id5-sync.com/api/1.0/id5PrebidModule.js', + pd: 'MT1iNTBjY...', // optional, see table above for a link to how to generate this + abTesting: { // optional + enabled: true, // false by default + controlGroupPct: 0.1 // valid values are 0.0 - 1.0 (inclusive) + } + }, + storage: { + type: 'html5', // "html5" is the required storage type + name: 'id5id', // "id5id" is the required storage name + expires: 90, // storage lasts for 90 days + refreshInSeconds: 8*3600 // refresh ID every 8 hours to ensure it's fresh + } + }], + auctionDelay: 50 // 50ms maximum auction delay, applies to all userId modules + } +}); +``` + +{: .alert.alert-warning :} +**ATTENTION:** As of Prebid.js v4.14.0, ID5 requires `storage.type` to be `"html5"` and `storage.name` to be `"id5id"`. Using other values will display a warning today, but in an upcoming release, it will prevent the ID5 module from loading. This change is to ensure the ID5 module in Prebid.js interoperates properly with the [ID5 API](https://github.com/id5io/id5-api.js) and to reduce the size of publishers' first-party cookies that are sent to their web servers. For the same reasons it is very important as of Prebid.js v8.33.0 to provide the `externalModuleUrl` parameter and set it to the latest available module version at `https://cdn.id5-sync.com/api/1.0/id5PrebidModule.js`. If you have any questions, please reach out to us at [prebid@id5.io](mailto:prebid@id5.io). diff --git a/dev-docs/modules/userid-submodules/idplus.md b/dev-docs/modules/userid-submodules/idplus.md new file mode 100644 index 0000000000..9175f7f31e --- /dev/null +++ b/dev-docs/modules/userid-submodules/idplus.md @@ -0,0 +1,36 @@ +--- +layout: userid +title: ID+ +description: ID+ User ID sub-module +useridmodule: zeotapIdPlusIdSystem +--- + + +ID+, powered by zeotap, enables the marketing ecosystem to overcome challenges posed by the demise of identifiers and a fast-changing regulatory landscape. ID+ is an open invitation to the entire industry to build the future of identity together. + +This sub-module enables the user’s ID+ to be available in the bid request. + +More information on ID+ can be found here: [idplus.io](https://idplus.io/) + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=zeotapIdPlusIdSystem + +## ID+ Registration + +You can set up your ID+ account by contacting our support team at [support.idplus@zeotap.com](mailto:support.idplus@zeotap.com) or via [idplus.io/contact-us](https://idplus.io/contact-us.html) and we will get back to you. + +ID+ is covered under zeotap privacy policy: [Zeotap Privacy Policy](https://zeotap.com/website-privacy-policy). + +## ID+ Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "zeotapIdPlus" + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/idx.md b/dev-docs/modules/userid-submodules/idx.md new file mode 100644 index 0000000000..433876c6e4 --- /dev/null +++ b/dev-docs/modules/userid-submodules/idx.md @@ -0,0 +1,41 @@ +--- +layout: userid +title: IDx +description: IDx User ID sub-module +useridmodule: idxIdSystem +--- + + +IDx, a universal ID solution provided by [Retargetly](https://retargetly.com), is the evolution of digital identifiers for the Latin American region. Through a proprietary identity graph, it allows publishers, advertisers, and ad tech platforms to recognize users across domains and devices even where third party cookies aren't available. + +The IDx platform is designed with privacy at its core and allows for nearly every conceivable digital use case including but not limited to audience targeting, retargeting, frequency management, personalization, and total reach reporting. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=idxIdSystem + +## IDx Registration + +If you are a publisher or an advertiser, then IDx is free to use but requires a simple registration process. To do this, please send an email to [idx-partners@retargetly.com](mailto:idx-partners@retargetly.com) to request your IDx Partner ID. + +We may ask for some basic information from you before approving your request. For more information on IDx, please visit [retargetly.com](https://retargetly.com/). + +## IDx Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"idx"` | `"idx"` | + +## IDx Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "idx" + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/imuid.md b/dev-docs/modules/userid-submodules/imuid.md new file mode 100644 index 0000000000..56fb116ec2 --- /dev/null +++ b/dev-docs/modules/userid-submodules/imuid.md @@ -0,0 +1,44 @@ +--- +layout: userid +title: IM-UID by Intimate Merger +description: IM-UID by Intimate Merger User ID sub-module +useridmodule: imuIdSystem +--- + +IM-UID, provided by [Intimate Merger](https://corp.intimatemerger.com/), is a universal identifier that designed for publishers, platforms and advertisers to perform segmentation and targeting even in environments where 3rd party cookies are not available. IM-UID is currently only available in Japan. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=imuIdSystem + +## IM-UID Registration + +Please visit [lp.intimatemerger.com/im-uid](https://lp.intimatemerger.com/im-uid) and request your Customer ID to get started. + +The Intimate Merger privacy policy is at + +## IM-UID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `"imuid"` | +| params | Required | Object | Details of module params. | | +| params.cid | Required | Number | This is the Customer ID value obtained via Intimate Merger. | `5126` | +| params.url | Optional | String | Use this to change the default endpoint URL. | `"https://example.com/some/api"` | + +## IM-UID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "imuid", + params: { + cid: 5126 // Set your Intimate Merger Customer ID here for production + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/intentiq.md b/dev-docs/modules/userid-submodules/intentiq.md new file mode 100644 index 0000000000..e99228ef2a --- /dev/null +++ b/dev-docs/modules/userid-submodules/intentiq.md @@ -0,0 +1,91 @@ +--- +layout: userid +title: Intent IQ ID +description: Intent IQ ID User ID sub-module +useridmodule: intentIqIdSystem +--- + +# Intent IQ Universal ID module + +By leveraging the Intent IQ identity graph, our module helps publishers, SSPs, and DSPs overcome the challenges of monetizing cookie-less inventory and preparing for a future without 3rd-party cookies. Our solution implements 1st-party data clustering and provides Intent IQ person IDs with over 90% coverage and unmatched accuracy in supported countries while remaining privacy-friendly and CCPA compliant. This results in increased CPMs, higher fill rates, and, ultimately, lifting overall revenue + +# All you need is a few basic steps to start using our solution + +## Registration + +Navigate to [our portal](https://www.intentiq.com/) and contact our team for partner ID. +check our [documentation](https://pbmodule.documents.intentiq.com/) to get more information about our solution and how utilze it's full potential + +## Integration + +{: .alert.alert-info :} +gulp build –modules=intentIqIdSystem + +We recommend including the Intent IQ Analytics adapter module for improved visibility + +## Configuration + +### Parameters + +Please find below list of parameters that could be used in configuring Intent IQ Universal ID module + +{: .table .table-bordered .table-striped } + +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| ------------------------------ | -------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- | +| name | Required | String | The name of this module: "intentIqId" | `"intentIqId"` | +| params | Required | Object | Details for IntentIqId initialization. | | +| params.partner | Required | Number | This is the partner ID value obtained from registering with IntentIQ. | `1177538` | +| params.percentage | Required | Number | This a percentage value for our A/B testing group distribution. The values supposed to be in range of 0 to 100. We suggest to set it to 95 percent for optimal balance ofbetween prefromance and preceision. | `95` | +| params.pcid | Optional | String | This is the partner cookie ID, it is a dynamic value attached to the request. | `"g3hC52b"` | +| params.pai | Optional | String | This is the partner customer ID / advertiser ID, it is a dynamic value attached to the request. | `"advertiser1"` | +| params.enableCookieStorage | Optional | Boolean | This is a parameter allowing to enable or disable cookie storage. Defaults to false. | `"true"` | + +### Configuration example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: "intentIqId", + params: { + partner: 123456, // valid partner id + percentage: 95, + enableCookieStorage: true + }, + storage: { + type: "html5", + name: "intentIqId", // set localstorage with this name + expires: 60, + refreshInSeconds: 4 * 3600, // refresh ID every 4 hours to ensure it's fresh + }, + }, + ], + syncDelay: 3000, + }, +}); +``` + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "intentIqId", + params: { + partner: 123456 // valid partner id + pcid: PCID_VARIABLE, // string value, dynamically loaded into a variable before setting the configuration + pai: PAI_VARIABLE , // string value, dynamically loaded into a variable before setting the configuration + percentage: 95, + enableCookieStorage: false + }, + storage: { + type: "html5", + name: "intentIqId", // set localstorage with this name + expires: 60 + } + }], + syncDelay: 3000 + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/just.md b/dev-docs/modules/userid-submodules/just.md new file mode 100644 index 0000000000..31a4beddd9 --- /dev/null +++ b/dev-docs/modules/userid-submodules/just.md @@ -0,0 +1,63 @@ +--- +layout: userid +title: Just ID +description: Just ID User ID sub-module +useridmodule: justIdSystem +--- + + +[Justtag Group](https://www.justtag.com/en) is a European, privacy focused DMP and segment provider. Having a leading position in Poland and growing presence in the CEE region, we created Just ID - an alternative ID solution, designed to respect users’ privacy choices which doesn’t rely on 3rd party cookies. Our aim is to help Publishers and Advertisers to recognize users across various environments and enable ad-tech market players with a smooth transition into post 3rd party cookie era. + +## Just ID Modes + +- **BASIC** - In this mode we rely on Justtag library that already exists on publisher page. Typicaly that library expose global variable called `__atm` + +- **COMBINED** - Just ID generation process may differ between various cases depends on publishers. This mode combines our js library with prebid for ease of integration + +If you have any questions about Just ID, please reach out by emailing [prebid@justtag.com](mailto:prebid@justtag.com). + +## Just ID Configuration + +{: .table .table-bordered .table-striped } +| Param under usersync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID of the module - `'justId'` | `'justId'` | +| params | Optional | Object | Details for Just ID syncing. | | +| params.mode | Optional | String | Mode in which the module works. Available Modes: `'COMBINED'`, `'BASIC'`(default) | `'COMBINED'` | +| params.atmVarName | Optional | String | Name of global object property that point to Justtag ATM Library. Defaults to `'__atm'` | `'__atm'` | +| params.url | Optional | String | API Url, **required** in `COMBINED` mode | `'https://id.nsaudience.pl/getId.js'` | +| params.partner | Optional | String | This is the Justtag Partner Id which may be required in some custom integrations with Justtag | `'some-publisher'` | + +## Just ID Example + +ex. 1. Mode `COMBINED` + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'justId', + params: { + mode: 'COMBINED', + url: 'https://id.nsaudience.pl/getId.js' + } + }] + } +}); +``` + +ex. 2. Mode `BASIC` + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'justId' + }] + } +}); +``` + +## Just ID Disclosure + +This module in `COMBINED` mode loads external JavaScript to generate optimal quality user ID. It is possible to retrieve user ID, without loading additional script by this module in `BASIC` mode. diff --git a/dev-docs/modules/userid-submodules/kinesso.md b/dev-docs/modules/userid-submodules/kinesso.md new file mode 100644 index 0000000000..0253366081 --- /dev/null +++ b/dev-docs/modules/userid-submodules/kinesso.md @@ -0,0 +1,40 @@ +--- +layout: userid +title: Kinesso ID +description: Kinesso ID User ID sub-module +useridmodule: kinessoIdSystem +--- + + +Kinesso ID solution is a new approach to persistent cross domain authentication. + +## How it works + +The Kinesso identity solution creates a persistent cross domain authenticated user id that is then used to link users with their interest signals (commonly known as segments). The Kinesso user ID (knsso) is never broadcast into the bid stream. Instead it is sent to a server side data store, merged with accompanying data from the Prebid Id Library and shipped to Kinesso. All data is encrypted at rest and in transit so your identifiers are never stored or transmitted in an insecure manner. + +The Kinesso ID sub adapter sets two cookies, one as a third party cookie and the other as a first party cookie in the publisher's domain. These cookies are merged with the user's hashed email address (when present) server side and sent to Kinesso. The combined output looks like this: + +{: .table .table-bordered .table-striped } +| kpuid | knsso | hid | account_id | created on | +| --- | --- | --- | --- | --- | +| `` | `` | `` | `` | `` | + +Kinesso will then attach these users to deals ids that they will target in the ORTB bid stream by brands and agencies represented by IPG. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=kinessoIdSystem + +## Kinesso ID Registration + +You can set up Kinesso ID sub adapter by contacting Kinesso at + +The Kinesso ID privacy policy is covered under the [Kinesso Privacy Notice](https://kinesso.com/privacy-policy/). Please note, at present the Kinesso ID module is not meant for use inside the EEA. + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `'kpuid'` | +| params | Required | Object | Details for KinessoId initialization | | +| params.accountid | Required | Int | Your SSP Account Id | 123 | diff --git a/dev-docs/modules/userid-submodules/liveintent.md b/dev-docs/modules/userid-submodules/liveintent.md new file mode 100644 index 0000000000..882209903c --- /dev/null +++ b/dev-docs/modules/userid-submodules/liveintent.md @@ -0,0 +1,212 @@ +--- +layout: userid +title: LiveIntent nonID +description: LiveIntent nonID User ID sub-module +useridmodule: liveIntentIdSystem +--- + +LiveIntent offers audience resolution by leveraging its next-generation identity solutions. The LiveIntent identity graph is built around a people-based set of data that is authenticated daily through active engagements with email newsletters and media across the web. + +The LiveIntent `nonID` is a user identifier tied to an active, encrypted email in the graph and functions in cookie-challenged environments and browsers. Alongside the `nonID`, LiveIntent's user ID sub-module can resolve multiple other user identifiers called _attributes_ - such as `uid2`, `pubmatic`, and others. See the [Multiple user IDs](#multiple-user-ids) section for more details. + +There are two ways to add the functionality of LiveIntent Identity sub-module to your _Prebid.js_ package: + +1. The standard version, which allows publishers to include the module with full functionalities, like hashing email addresses and identity resolution. + + Add the **standard** LiveIntent Identity module to your Prebid.js package with: + + ```bash + gulp build --modules=userId,liveIntentIdSystem + ``` + +2. The minimal version, which allows publishers to deploy a smaller bundle with minimal features, including identity resolution. + + Add the **minimal** LiveIntent Identity module to your Prebid.js package with: + + ```bash + LiveConnectMode=minimal gulp build --modules=liveIntentIdSystem + ``` + +This is an example of how the `request.userId.lipb` object, which contains the resolution result, would look like: + +```json +{ +  "lipbid": "T7JiRRvsRAmh88", +  "pubmatic": "9E76F017-86D2-444B-BB4B-9DB35347DB54" +} +``` + +If you're not already a LiveIntent customer, feel free to [reach out](https://www.liveintent.com/get-in-touch/) to us. You can also explore the [LiveIntent’s privacy policies](https://www.liveintent.com/services-privacy-policy/). + +## How LiveIntent user ID sub-module works + +The LiveIntent user ID sub-module resolves the identity of audiences by connecting impression opportunities to a stable identifier. LiveIntent builds a model on the backend with data collected through an additional call issued on each page load. In order to provide ID resolution, the sub-module uses one or more first-party cookies. See the [query parameters description](https://github.com/LiveIntent/live-connect/blob/HEAD/COLLECTOR_PARAMS.md) for more details. + +The following first-party cookies are supported: + +1. Default first-party cookie: By default, LiveIntent ID sub-module generates its own first-party identifier on the publisher’s domain. Publishers have the option to disable the cookie generation when configuring the sub-module. +2. Publisher defined first-party cookie: Publishers have the flexibility to configure and choose additional first-party cookies for use in conjunction with the LiveIntent first-party cookie. + +### Identity resolution + +For the identity resolution, the LiveIntent ID sub-module makes a request to LiveIntent’s identity resolution API, which returns a `nonID` and additional attributes. The identifier and attributes are then exposed by the Prebid User ID Module to Prebid adapters to be sent out in a bid request. An SSP can then make the impression opportunity available to buyers that would like to target the audience. + +The first-party cookie generation and identity resolution functionality is provided by [LiveConnect JS](https://www.npmjs.com/package/live-connect-js) - an open source JS library which is included within the LiveIntent ID sub-module. + +The LiveIntent ID sub-module follows the standard _Prebid.js_ initialization based on the GDPR consumer opt-out choices. With regard to CCPA, the LiveConnect JS receives a us_privacy string from the Prebid US Privacy Consent Management Module and respects opt-outs. + +## Configure requested attributes + +Attributes other than the `nonID` can be requested using the `requestedAttributesOverrides` configuration option. + +For example, the configuration below requests the `nonID` as well as `uid2`, the `medianet` ID, the `bidswitch` ID and the `magnite` ID: + +```javascript +pbjs.setConfig({ +  userSync: { +    userIds: [{ +      name: "liveIntentId", +      params: { +        publisherId: "12432415", +        requestedAttributesOverrides: { +          uid2: true, +          medianet: true, +          bidswitch: true, +          magnite: true +        } +      } +    }] +  } +}); +``` + +### Multiple user IDs + +The attributes `uid2`, `medianet`, `magnite`, `bidswitch`, `pubmatic`, `openx`, `sovrn`, `index` and `thetradedesk` are treated specially by LiveIntent's user ID sub-module. Each of these attributes will result in a separate ID returned by the sub-module. + +For example, in case `uid2` is configured to be requested in addition to the `nonID`, the `request.userId` object would look like the following: + +```javascript +{ +  // ... +  "lipb" : { +    "lipbid": "sample-nonid-value", +    "uid2" : "sample-uid2-value" +  }, +  "uid2" : { +    "id" : "sample-uid2-value" +  } +  //... +} +``` + +NOTE: `uid2` is exposed as part of `lipb` as well as separately as `uid2`. `medianet`, `magnite`, `bidswitch`, `pubmatic`, `openx`, `sovrn`, `index` and `thetradedesk` behave the same way. + +For the attributes `lipbid` (nonID), `uid2`, `medianet`, `magnite`, `bidswitch`, `pubmatic`, `openx`, `sovrn`, `index` and `thetradedesk`, there is also support for their conversion into OpenRTB EIDS format. Please refer to [User ID Module](../userId.md) documentation for more information on conversion, and [Example of eids array generated by UserId Module](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.md) for output format examples. + +### Request uid2 + +An attribute that requires special mention here is `uid2`. If this attribute is resolved by the ID sub-module, it will be exposed in the same format as from the Unified ID 2.0 user ID module. If both the LiveIntent sub-module and the `uid2` module manage to resolve a `uid2`, the one with the highest priority according to the configuration will be used. See the [Prebid multiple identifiers populated by user id sub-module](../userId.md#prebid-multiple-identifiers-populated-by-user-id-submodule) section of the User ID documentation for more information. + +Enabling this option in addition to the `uid2` module is an easy way to increase your `uid2` resolution rates. The following is an example configuration of `uid2` resolution: + +```javascript +pbjs.setConfig({ +  userSync: { +    userIds: [{ +    name: "liveIntentId", +      params: { +        publisherId: "12432415", +        requestedAttributesOverrides: { uid2: true } +      } +    }] +  } +}); +``` + +## LiveIntent ID configuration + +{: .alert.alert-info :} +NOTE: For optimal performance, the LiveIntent ID sub-module should be called at every opportunity. It is best not to use `params.storage` with this sub-module as it has its own optimal caching mechanism. + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this sub-module. | `liveIntentId` | +| params | Required | Object | Container of all module params. || +| params.publisherId |Optional| String | The unique identifier for each publisher (for existing LiveIntent customers)|`12432415`| +| params.distributorId |Optional| String | The unique identifier for each distributor (for existing LiveIntent customers). It will be ignored if `params.liCollectConfig.appId` is provided. |`did-0123`| +| params.ajaxTimeout |Optional| Number |This configuration parameter defines the maximum duration of a call to the `IdentityResolution` endpoint. By default, 5000 milliseconds.|`5000`| +| params.partner | Optional| String |The name of the partner whose data will be returned in the response.|`prebid`| +| params.identifiersToResolve |Optional| Array[String] |Used to send additional identifiers in the request for LiveIntent to resolve against the LiveIntent ID and additional attributes.|`['my-id']`| +| params.requestedAttributesOverrides | Optional | Object | Object containing booleans used to override the default resolution. Attributes set to `true` will be added to the resolved list, while attributes set to `false` will be removed. Valid attributes are `nonId`, `uid2`, `medianet`, `magnite`, `bidswitch`, `pubmatic`, `openx`, `sovrn`, `index` and `thetradedesk`. | `{'uid2': true}` | +| params.emailHash |Optional| String |The hashed email address of a user. We can accept the hashes, which use the following hashing algorithms: md5, sha1, sha2.|`1a79a4d60de6718e8e5b326e338ae533`| +| params.url | Optional| String |Use this to change the default endpoint URL if you can call the LiveIntent Identity Exchange within your own domain.|`https://idx.my-domain.com`| +| params.liCollectConfig |Optional| Object |Container of all collector params.|| +| params.liCollectConfig.fpiStorageStrategy |Optional| String |This parameter defines whether the first-party identifiers that LiveConnect creates and updates are stored in a cookie jar, or in local storage. If nothing is set, default behaviour would be `cookie`. Allowed values: [`cookie`, `ls`, `none`]|`cookie`| +| params.liCollectConfig.ajaxTimeout |Optional| Number |This configuration parameter defines the maximum duration of a call to the collector endpoint. By default, 5000 milliseconds.|`5000`| +| params.liCollectConfig.fpiExpirationDays |Optional| Number |The expiration time of an identifier created and updated by LiveConnect. By default, 730 days.|`729`| +| params.liCollectConfig.collectorUrl |Optional| String |The parameter defines where the signal pixels are pointing to. The params and paths will be defined subsequently. If the parameter is not set, LiveConnect will by default emit the signal towards `https://rp.liadm.com`.| `https://rp.liadm.com`| +| params.liCollectConfig.appId |Optional| String |LiveIntent's media business entity application ID.|`a-0012`| + +## LiveIntent ID examples + +1. To receive the LiveIntent ID, the setup looks like the following example: + + ```javascript + pbjs.setConfig({ + userSync: { +    userIds: [{ + name: "liveIntentId", + params: { + publisherId: "9896876" + } + }] + } + }); + ``` + +2. If you are passing additional identifiers that you want to resolve to the LiveIntent ID, add the ID under the `identifiersToResolve` array in the configuration parameters as shown in the following example: + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "liveIntentId", + params: { + publisherId: "9896876", + identifiersToResolve: ["my-own-cookie"] + } + }] + } + }); + ``` + +3. If all the supported configuration params are passed, then the setup will look as follows: + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "liveIntentId", + params: { + publisherId: "9896876", + distributorId: "did-0123", + identifiersToResolve: ["my-own-cookie"], + requestedAttributesOverrides: { uid2: true, magnite: true, bidswitch: true }, + url: "https://publisher.liveintent.com/idex", + partner: "prebid", + ajaxTimeout: 1000, + liCollectConfig: { + fpiStorageStrategy: "cookie", + fpiExpirationDays: 730, + collectorUrl: "https://rp.liadm.com", + appId: "a-0012" + } + } + }] + } + }); + ``` + +Please note: the `distributorId` will be ignored when `liCollectConfig.appId` is present. diff --git a/dev-docs/modules/userid-submodules/lmpid.md b/dev-docs/modules/userid-submodules/lmpid.md new file mode 100644 index 0000000000..233eb0a430 --- /dev/null +++ b/dev-docs/modules/userid-submodules/lmpid.md @@ -0,0 +1,32 @@ +--- +layout: userid +title: LMPID +description: LMPID User ID sub-module +useridmodule: lmpIdSystem +--- + +The Loblaw Media Private ID (LMPID) is the Loblaw Advance identity solution deployed by its media partners. LMPID leverages encrypted user registration information to provide a privacy-conscious, secure, and reliable identifier to power Loblaw Advance's digital advertising ecosystem. + +## LMPID Registration + +If you're a media company looking to partner with Loblaw Advance, please reach out to us through our [Contact page](https://www.loblawadvance.ca/contact-us) + +## LMPID Configuration + +First, make sure to add the LMPID submodule to your Prebid.js package with: + +```bash +gulp build --modules=lmpIdSystem,userId +``` + +The following configuration parameters are available: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'lmpid' + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/lotame.md b/dev-docs/modules/userid-submodules/lotame.md new file mode 100644 index 0000000000..f9d9e89a3a --- /dev/null +++ b/dev-docs/modules/userid-submodules/lotame.md @@ -0,0 +1,51 @@ +--- +layout: userid +title: Lotame Panorama ID +description: Lotame Panorama ID User ID sub-module +useridmodule: lotamePanoramaIdSystem +--- + + +[Lotame Panorama](https://www.lotame.com/panorama/) is a suite of data-enrichment solutions for digital advertising that empowers marketers, agencies, publishers and media companies to transform consumer personas into addressable audiences. At the heart of Lotame Panorama is the Panorama ID, a people-based identifier powered by deterministic and probabilistic data, available across the cookie-challenged web and all browsers. + +Lotame’s Panorama ID module sends information from the request to its identity graph in order to successfully generate a Panorama ID. For more information on how the Panorama ID works, please visit [www.lotame.com/panorama/id/](https://www.lotame.com/panorama/id/). + +Lotame's privacy policy related to the Panorama ID and the collection of data and how data is used is available at [www.lotame.com/about-lotame/privacy/lotames-products-services-privacy-policy/](https://www.lotame.com/about-lotame/privacy/lotames-products-services-privacy-policy/). Consult with your legal counsel to determine the appropriate user disclosures with respect to use of the Lotame Panorama ID module. + +If you have any questions about Panorama ID, please reach out by emailing [prebid@lotame.com](mailto:prebid@lotame.com). + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=lotamePanoramaIdSystem + +## Lotame Panorama ID Registration & Implementation + +To get started, you will need to register with Lotame in order to receive your unique client ID for the userID module. You can [register here](https://www.cognitoforms.com/LotameSolutionsInc/PanoramaIDOfferingEnrollment) or contact [prebid@lotame.com](mailto:prebid@lotame.com) for any questions that you may have. + +Once you sign up, you will receive an email with your client ID and instructions for implementation. + +## Lotame Panorama ID Example + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of the module | "lotamePanoramaId" | +| params | Required | Object | Configuration options for the Lotame Panorama ID Module | | + | params.clientId | Required | String | The Lotame Client ID provided as part of your registration as noted above | "1001" | + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "lotamePanoramaId", + params: { + clientId: "1001" + } + }] + } +}); +``` + +{: .alert.alert-info :} +NOTE: For optimal performance, the Lotame Panorama Id module should be called at every opportunity. It is best not to use params.storage with this module as the module has its own optimal caching mechanism. diff --git a/dev-docs/modules/userid-submodules/mediawallah.md b/dev-docs/modules/userid-submodules/mediawallah.md new file mode 100644 index 0000000000..14e5e1bd06 --- /dev/null +++ b/dev-docs/modules/userid-submodules/mediawallah.md @@ -0,0 +1,48 @@ +--- +layout: userid +title: MediaWallah OpenLinkID +description: MediaWallah OpenLinkID User ID sub-module +useridmodule: mwOpenLinkIdSystem +--- + + +MediaWallah's openLink is an anonymous person based ID that enables buyers and sellers of media to connect a person and their devices across the web and mobile apps. openLink facilities the buying of media between DSPs, SSPs and publishers. + +Add support for MediaWallah OpenLinkID to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=userId,mwOpenLinkIdSystem + +## MediaWallah OpenLinkID Registration + +MediaWallah requires the creation of an accountId a partnerId in order to take advantage of openLink. Please contact your partner resource to get these Ids provisioned. + +## MediaWallah OpenLinkID Configuration + +

      +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `'mwOpenLinkId'` | +| params | Required | Object | Details for mwOLID syncing. || +| params.accountId | Required | String | The MediaWallah assigned Account Id | `1000` | +| params.partnerId | Required | String | The MediaWallah assign partner Id |`'1001'`| +| params.uid | Optional | String | Your unique Id for the user or browser. Used for matching. | `'u-123xyz'` | +{: .table .table-bordered .table-striped } +
      + +## MediaWallah OpenLinkID Examples + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'mwOpenLinkId', + params: { + accountId: '1000', + partnerId: '1001', + uid: 'u-123xyz' + } + }] + } +}) +``` diff --git a/dev-docs/modules/userid-submodules/merkle.md b/dev-docs/modules/userid-submodules/merkle.md new file mode 100644 index 0000000000..71f583c6a9 --- /dev/null +++ b/dev-docs/modules/userid-submodules/merkle.md @@ -0,0 +1,32 @@ +--- +layout: userid +title: Merkle ID +description: Merkle IDUser ID sub-module +useridmodule: merkleIdSystem +--- + + +[Merkury by Merkle](https://merkury.merkleinc.com/contact) enables marketers, media owners, and publishers to own, build, and control a cookie-less Private Identity Graph. Merkury uses an organization’s first-party CRM data and valuable interactions such as logins, outbound email campaigns and media reach to create and grow a universe of person-based IDs for cross-channel targeting, personalization, measurement and more. + +## Merkury by Merkle ID Examples + +Publisher stores Merkury by Merkle in local storage for 30 days + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'merkleId', + params: { + sv_pubid:'example_pubid', + ssp_ids: ['example_sspid_1', 'example_sspid_2'] + }, + storage: { + type: 'html5', + name: 'merkleId', + expires: 30 + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/mygaru.md b/dev-docs/modules/userid-submodules/mygaru.md new file mode 100644 index 0000000000..71ff9d2551 --- /dev/null +++ b/dev-docs/modules/userid-submodules/mygaru.md @@ -0,0 +1,41 @@ +--- +layout: userid +title: MyGaru ID +description: MyGaru User ID sub-module +useridmodule: mygaruIdSystem +--- + +MyGaru provides single use tokens as a UserId for SSPs and DSP that consume telecom DMP data. + +## MyGaru ID Configuration + +First, add the AMX ID module to your Prebid.js build: + +```shell +gulp build --modules=userId,myGaruIdSystem +``` + +Then configure the MyGaru id submodule in your `userSync` configuration: + +Params configuration is not required. +Mygaru id system is asynchronous and in order to get ids for initial ad auctions you need to add an `auctionDelay` param to your `userSync` config. +_Currently, Mygaru id system does not operate in EU region._ + +```javascript +pbjs.setConfig({ + userSync: { + auctionDelay: 100, + userIds: [{ + name: 'mygaruId', + }] + } +}); +``` + +This will add a `userId.mygaru` property to all bidRequests: + +```javascript +{ + mygaru: 'vatfS0UEgXShEqYuQy0lpzWl7rSuKeNs0U8C8841KoYbFUiyvTpS' +} +``` diff --git a/dev-docs/modules/userid-submodules/navegg.md b/dev-docs/modules/userid-submodules/navegg.md new file mode 100644 index 0000000000..f25391a90b --- /dev/null +++ b/dev-docs/modules/userid-submodules/navegg.md @@ -0,0 +1,22 @@ +--- +layout: userid +title: Navegg ID +description: Navegg ID User ID sub-module +useridmodule: naveggIdSystem +--- + +[Navegg](https://www.navegg.com) enables publishers, advertisers and agencies to use their own first party data together to activate media in a cookie-less way across several Ad Tech platforms. Navegg has one of the largest data networks in Latin America which also allows the enhancement of data with unique categories. + +## Navegg ID Examples + +Publisher stores NaveggId in local storage and/or 1st party cookies + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'naveggId' + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/netid.md b/dev-docs/modules/userid-submodules/netid.md new file mode 100644 index 0000000000..67c2ff79a2 --- /dev/null +++ b/dev-docs/modules/userid-submodules/netid.md @@ -0,0 +1,28 @@ +--- +layout: userid +title: netID +description: netID User ID sub-module +useridmodule: netIdSystem +--- + + +The [European netID Foundation (EnID)](https://developerzone.netid.de/index.html) aims to establish with the netID an independent European alternative in the digital market for Demand and Supply side. With the netID Single-Sign-On, the EnID established an open standard for consumer logins for services of Buyers and Brands, that also includes user-centric consent management capabilities that results in a standardized, EU-GDPR compliant, IAB TCF aware, cross-device enabled Advertising Identifier, which can be leveraged by publishers and advertisers (and vendors supporting them) to efficiently deliver targeted advertising through programmatic systems to already more than 38 million Europeans on mobile and desktop devices. + +The EnID is a non-profit organization which is open to any contributing party on both, the demand and supply side to make identity work for consumers as well as the advertising ecosystem. + +## netID Examples + +1. Publisher stores netID via his own logic + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "netId", + value: { + "netId":"fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg" + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/novatiq.md b/dev-docs/modules/userid-submodules/novatiq.md new file mode 100644 index 0000000000..cf86db5854 --- /dev/null +++ b/dev-docs/modules/userid-submodules/novatiq.md @@ -0,0 +1,98 @@ +--- +layout: userid +title: Novatiq Hyper ID +description: Novatiq Hyper ID User ID sub-module +useridmodule: novatiqIdSystem +--- + + +The [Novatiq](https://www.novatiq.com) proprietary dynamic Hyper ID is a unique, non sequential and single use identifier for marketing activation. Our in network solution matches verification requests to telco network IDs safely and securely inside telecom infrastructure. The Novatiq Hyper ID can be used for identity validation and as a secured 1st party data delivery mechanism. + +## Novatiq Hyper ID Configuration + +Enable by adding the Novatiq submodule to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=novatiqIdSystem,userId + +Module activation and configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'novatiq', + bidders: [ + `rubicon` + ], + params: { + // change to the Partner Number you received from Novatiq + sourceid '1a3' + } + } + }], + // 1000ms maximum auction delay, applies to all userId modules + auctionDelay: 1000 + } +}); +``` + +## Parameters for the Novatiq Module + +
      +| Param | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | Module identification: `"novatiq"` | `"novatiq"` | +| params | Required | Object | Configuration specifications for the Novatiq module. | | +| params.sourceid | Required (if applicable) | String | This is the Novatiq Partner Number obtained via Novatiq registration. | `1a3` | +| params.useSharedId | Optional | Boolean | Use the sharedID module if it's activated. | `true` | +| params.sharedIdName | Optional | String | Same as the SharedID "name" parameter
      Defaults to "_pubcid" | `"demo_pubcid"` | +| params.useCallbacks | Optional | Boolean | Use callbacks for custom integrations | `false` | +| params.urlParams | Optional | Object | Sync URl configuration for custom integrations | | +| params.urlParams.novatiqId | Optional | String | The name of the parameter used to indicate the Novatiq ID uuid | `snowflake` | +| params.urlParams.useStandardUuid | Optional | Boolean | Use a standard UUID format, or the Novatiq UUID format | `false` | +| params.urlParams.useSspId | Optional | Boolean | Send the sspid (sourceid) along with the sync request
      Makes the params.sourceid optional if set | `false` | +| params.urlParams.useSspHost | Optional | Boolean | Send the ssphost along with the sync request | `false` | +{: .table .table-bordered .table-striped } +
      + +## Novatiq Hyper ID with Prebid SharedID Support + +You can make use of the Prebid.js SharedId module as follows. + +Enable by adding the Novatiq and SharedId submodule to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=novatiqIdSystem,userId + +Module activation and configuration: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: 'novatiq', + bidders: [ + `rubicon` + ], + params: { + // change to the Partner Number you received from Novatiq + sourceid '1a3', + + // Use the sharedID module + useSharedId: true, + + // optional: will default to _pubcid if left blank. + // If not left blank must match "name" in the the module above + sharedIdName: 'demo_pubcid' + } + } + }], + // 1000ms maximum auction delay, applies to all userId modules + auctionDelay: 1000 + } +}); +``` + +If you have any questions, please reach out to us at [prebid@novatiq.com](mailto:prebid@novatiq.com) diff --git a/dev-docs/modules/userid-submodules/onekey.md b/dev-docs/modules/userid-submodules/onekey.md new file mode 100644 index 0000000000..9b4d937868 --- /dev/null +++ b/dev-docs/modules/userid-submodules/onekey.md @@ -0,0 +1,49 @@ +--- +layout: userid +title: OneKey IDs & Preferences +description: OneKey IDs & Preferences User ID sub-module +useridmodule: oneKeyIdSystem +--- + + +The OneKey real-time data module in Prebid has been built so that publishers +can quickly and easily setup the OneKey Addressability Framework. +This module is used along with the oneKeyRtdProvider to pass OneKey data to your partners. +Both modules are required. This module will pass oneKeyData to your partners +while the oneKeyRtdProvider will pass the transmission requests. + +Background information: + +- [OneKey-Network/addressability-framework](https://github.com/OneKey-Network/addressability-framework) +- [OneKey-Network/OneKey-implementation](https://github.com/OneKey-Network/OneKey-implementation) + +It can be added to you Prebid.js package with: + +{: .alert.alert-info :} +gulp build –modules=userId,oneKeyIdSystem + +⚠️ This module works with a RTD module. Both must be configured. See the [OneKey RTD Module](/dev-docs/modules/oneKeyRtdProvider.html). + +## OneKey Registration + +OneKey is a community based Framework with a decentralized approach. +Go to [onekey.community](https://onekey.community/) for more details. + +## OneKey Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module | `"oneKeyData"` | + +## OneKey Exemple + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'oneKeyData' + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/pair.md b/dev-docs/modules/userid-submodules/pair.md new file mode 100644 index 0000000000..b53ca71ec9 --- /dev/null +++ b/dev-docs/modules/userid-submodules/pair.md @@ -0,0 +1,62 @@ +--- +layout: userid +title: Google PAIR ID +description: pair PairId User ID sub-module +useridmodule: pairIdSystem +--- + +Developed by and for use with Display and Video 360, PAIR (Publisher Advertiser Identity Reconciliation) is a secure and privacy-forward way for enabling advertisers and publishers to reconcile their +first-party data for marketing use cases via advanced data encryption methods without the +reliance on third-party cookies. PAIR can help advertisers and publishers maintain control of first-party data while ensuring there is no pooling of data, no leakage of data, no leakage of insights, durablility for the future using secure encryption methods, and no user tracking across publishers. See this [document](https://services.google.com/fh/files/misc/pair_visual_final_10242022.pdf) for more information about PAIR. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=pairIdSystem + +## PAIR ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of PAIR ID user ID module. | `"pairId"` | +| params | Optional | Object | Container of all module params. | | +| params.liveramp | Optional | Object | Container of all liveramp cleanroom specified params. | | +| params.liveramp.storageKey | Optional | String | storage key to fetch liveramp provided PAIR Id, the default value is `"_lr_pairId"` | `"_lr_pairId"` | + +## PAIR ID Examples + +Publishers manage PAIR Ids themselves can store pairIds as a byte64 encoded array of ids in local storage and/or 1st party cookies entry `pairId`. + +```javascript + +// should have byte64 value ready in 'pairId' local storage/cookie entry + +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'pairId' + }] + } +}); +``` + +Or if to use cleanrooms provided implementation, it can be specified by adding the provider and their configs to the config, take liveramp as an example. + +```javascript + +// value in 'pairid' local storage/cookie entry will be combined with ids provided by cleamroom liveramp + +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'pairId', + params: { + liveramp: { + storageKey: '_lr_pairId' + } + }, + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/parrable.md b/dev-docs/modules/userid-submodules/parrable.md new file mode 100644 index 0000000000..f022af4c33 --- /dev/null +++ b/dev-docs/modules/userid-submodules/parrable.md @@ -0,0 +1,76 @@ +--- +layout: userid +title: Parrable ID +description: Parrable ID User ID sub-module +useridmodule: parrableIdSystem +--- + + +The Parrable ID is a Full Device Identifier that can be used to identify a device across different browsers and webviews on a single device including browsers that have third party cookie restrictions. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=parrableIdSystem + +## Parrable ID Registration + +Please contact Parrable to obtain a Parrable Partner Client ID and/or use the Parrable Partner Client ID provided by the vendor for each Parrable-aware bid adapter you will be using. Note that if you are working with multiple Parrable-aware bid adapters you may use multiple Parrable Partner Client IDs. + +The Parrable privacy policy as at [www.parrable.com/privacy-policy/](https://www.parrable.com/privacy-policy/). + +## Parrable ID Configuration + +In addition to the parameters documented above in the Basic Configuration section the following Parrable specific configuration is required: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| params | Required | Object | Details for the Parrable ID. | | +| params.partners | Required | Array[String] | A list of one or more Parrable Partner Client IDs for the Parrable-aware bid adapters you are using. Please obtain Parrable Partner Client IDs from them and/or obtain your own. | `[ '30182847-e426-4ff9-b2b5-9ca1324ea09b' ]` | +| params.timezoneFilter | Optional | Object | Configures a timezone or timezone offset filter | | +| params.timezoneFilter.allowedZones | Optional | Array[String] | description | `[ 'America/Anchorage' ]` | +| params.timezoneFilter.allowedOffsets | Optional | Array[Number] | description | `[ -4 ]` | +| params.timezoneFilter.blockedZones | Optional | Array[String] | description | `[ 'America/New_York' ]` | +| params.timezoneFilter.blockedOffsets | Optional | Array[Number] | description | `[ -5 ]` | + +{: .alert.alert-info :} +NOTE: The Parrable ID that is delivered to Prebid is encrypted by Parrable with a time-based key and updated frequently in the browser to enforce consumer privacy requirements and thus will be different on every page view, even for the same user. + +The Parrable ID system manages a cookie with the name of `_parrable_id` containing the ID and optout states of the user. +This cookie is used also by standalone Parrable integrations outside of Prebid. +It is for this reason that the cookie name is not configurable for the Parrable ID system. + +## Timezone and Timezone Offset Filtering + +The Parrable ID system enables a publisher to configure lists of **allowed** timezones (eg. `Europe/Dublin`) and/or timezone offsets (eg. `-4`) as well as a lists of **blocked** timezones and timezone offsets. + +- With no configuration (`params.timezoneFilter` not set, or all of the lists are empty) all impressions are permitted. +- With only allow lists configured a browser must match either a timezone or timezone offset for it to not be filtered. +- With only block lists configured an impression will be filtered only if it is from a browser matching a blocked timezone or timezone offset. +- An impression from a browser that matches any allowed timezone or timezone offset, but does not match a blocked timezone or timezone offset will engage in the Parrable ID syncronization process. +- If a browser has a stored Parrable ID then it will not be filtered even if the browser is in a timezone or timezone offset that is blocked. + +All configured timezones should follow the `TZ database name` column from the [IANA tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) + +## Parrable ID Examples + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: `'parrableId'`, + params: { + partners: [ + '30182847-e426-4ff9-b2b5-9ca1324ea09b', + 'b07cf20d-8b55-4cd7-9e84-d804ed66b644' + ], // change to the Parrable Partner Client ID(s) you received from the Parrable Partners you are using + timezoneFilter: { + allowedZones: ['America/New_York', 'Europe/Madrid'] + } + } + }], + syncDelay: 1000 + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/publisherlink.md b/dev-docs/modules/userid-submodules/publisherlink.md new file mode 100644 index 0000000000..2f6f44e965 --- /dev/null +++ b/dev-docs/modules/userid-submodules/publisherlink.md @@ -0,0 +1,55 @@ +--- +layout: userid +title: Publisher Link +description: Publisher Link User ID sub-module +useridmodule: publinkIdSystem +--- + + +Publisher Link, provided by [Epsilon](https://www.epsilon.com/us), is a cross-device identity solution that activates publisher first-party, authenticated +data to improve audience identification and increase bid opportunities, specifically designed for sites with authenticated +traffic. Publisher first-party authenticated data and a user's unique encrypted ID is linked to an existing people-based +Epsilon CORE ID. By utilizing Publisher Link, publishers are able to reap the benefits of Epsilon's CORE ID. + +## Publisher Link Registration + +Please contact [Epsilon](mailto:PublisherSupport@Epsilon.com) to sign up. + +The Epsilon privacy is covered in the [Epsilon Privacy Policy](https://www.epsilon.com/us/privacy-policy). + +The Publisher Link opt-out is included [here](https://www.epsilon.com/privacy/dms/opt-out/email) + +## Publisher Link Configuration + +In addition to the parameters documented above in the Basic Configuration section the following Publisher Link specific configuration is available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `'publinkId'` | +| params | Required | Object | Customized parameters. | | +| params.e | Required | String | Hashed email address of the user. Supports MD5 and SHA256. | `'7D320454942620664D96EF78ED4E3A2A'` | +| params.site_id | Required | String | Site ID provided by Epsilon. | `'123456'` | +| params.api_key | Required | String | API key provided by Epsilon. | `'00000000-0000-0000-0000-00000000000'` + +## Publisher Link Examples + +```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "publinkId", + storage: { + name: "pbjs_publink", + type: "cookie", + expires: 30 + }, + params: { + e: "7D320454942620664D96EF78ED4E3A2A", // example hashed email (md5) + site_id: "123456", + api_key: "00000000-0000-0000-0000-00000000000" + } + }] + } + }); +``` diff --git a/dev-docs/modules/userid-submodules/pubprovided.md b/dev-docs/modules/userid-submodules/pubprovided.md new file mode 100644 index 0000000000..ba15abfe25 --- /dev/null +++ b/dev-docs/modules/userid-submodules/pubprovided.md @@ -0,0 +1,120 @@ +--- +layout: userid +title: PubProvided ID +description: PubProvided ID User ID sub-module +useridmodule: pubProvidedIdSystem +--- + + +The PubProvided ID module allows publishers to set and pass a first-party user identifier into the bid stream. This module has several unique characteristics: + +1. The module supports a user-defined function, that generates an eids-style object: + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "pubProvidedId", + params: { + eidsFunction: getIdsFn // any function that exists in the page + } + }] + } + }); + ``` + + Or, the eids values can be passed directly into the `setConfig` or `mergeConfig` call: + + ```javascript + pbjs.mergeConfig({ + userSync: { + userIds: [{ + name: "pubProvidedId", + params: { + eids: [{ + source: "domain.com", + uids: [{ + id: "value read from a cookie or local storage", + atype: 1, + ext: { + stype: "ppuid" + } + + }] + }, { + source: "3rdpartyprovided.com", + uids: [{ + id: "value read from a cookie or local storage", + atype: 3, + ext: { + stype: "dmp" + } + }] + }] + } + }] + } + }); + ``` + +If multiple parties are writing to this object in an undetermined order, a setup that feels quite awkward, they should each do something of this nature: + +```javascript +pbjs.mergeConfig({ + userSync: { + userIds: (() => { + const uidCfgs = pbjs.getConfig('userSync.userIds') || []; + let ppid = uidCfgs.find(cfg => cfg.name === 'pubProvidedId'); + if (!ppid) { + ppid = {name: 'pubProvidedId', params: {eids: []}}; + uidCfgs.push(ppid); + } + ppid.params.eids.push({ + source: "example.com", + uids: [{ + id: "example", + atype: 1, + ext: { + stype: "ppuid" + } + + }] + }) + return uidCfgs; + })() + } +}) +pbjs.refreshUserIds({submoduleNames: ['pubProvidedId']}) +``` + +In each case, bid adapters will receive the eid values after consent is validated. The above examples, if calling `setConfig` instead of `mergeConfig`, will overwrite existing known IDs. If there is any possibility other id submodules have already been initiated or multiple scripts on the page are setting these fields, be sure to prefer `mergeConfig`. + +2. This design allows for the setting of any number of uuids in the eids object. Publishers may work with multiple ID providers and nest their own ID within the same eids object. The opportunity to link a 1st party uuid and a 3rd party generated UUID presents publishers with a unique ability to address their users in a way demand sources will understand. + +3. Finally, this module allows publishers to broadcast their user identifier, derived from in-house tech, directly to buyers within the confines of existing compliance (CCPA & GDPR) frameworks. + +4. The `eids.uids.ext.stype` "source-type" extension helps downstream entities know what do with the data. Currently defined values are: + + - dmp - this uid comes from the in-page dmp named in eids.source + - ppuid - this uid comes from the publisher named in eids.source + - other - for setting other id origin signals please use the [adCOM!](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#object--extended-identifier-uids-) `atype` spec + +5. Bid adapters listening for "userIds.pubProvidedId" will not receive a string, please use the userIdAsEids value/function to return the userid as a string. + +This module is distinct from the Google Ad Manager PPID; which we enable setting to any identifier that conforms to the character length requirements. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=pubProvidedIdSystem + +## PubProvided Configuration + +{: .table .table-bordered .table-striped } +| Params under usersync.userIds[]| Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the ID module | `"PubProvided"` | +| params | Optional | Object | Details for syncing. | | +| params.eidsFunction | Optional | function | any function that exists in the page | getIdsFn() | +| uids.atype | optional | int | ADCOM - Type of user agent the match is from | `"1"` | +| uids.ext.stype | Optional | String | Description of how the id was generated and by whom eg. ('ppuid','DMP','other') | `DMP` | diff --git a/dev-docs/modules/userid-submodules/quantcast.md b/dev-docs/modules/userid-submodules/quantcast.md new file mode 100644 index 0000000000..14ded4e370 --- /dev/null +++ b/dev-docs/modules/userid-submodules/quantcast.md @@ -0,0 +1,45 @@ +--- +layout: userid +title: Quantcast ID +description: Quantcast ID User ID sub-module +useridmodule: quantcastIdSystem +--- + +The Prebid Quantcast ID module stores a Quantcast ID in a first party cookie. The ID is then made available in the bid request. The ID from the cookie added in the bidstream allows Quantcast to more accurately bid on publisher inventories without third party cookies, which can result in better monetization across publisher sites from Quantcast. And, it’s free to use! For easier integration, you can work with one of our SSP partners, like PubMatic, who can facilitate the legal process as well as the software integration for you. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=userId,quantcastIdSystem + +Quantcast’s privacy policies for the services rendered can be found at + + +Publishers deploying the module are responsible for ensuring legally required notices and choices for users. + +The Quantcast ID module will only perform any action and return an ID in situations where: + +1. the publisher has not set a ‘coppa' flag on the prebid configuration on their site (see [pbjs.setConfig.coppa](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa)) +2. there is not a IAB us-privacy string indicating the digital property has provided user notice and the user has made a choice to opt out of sale +3. if GDPR applies, an IAB TCF v2 string exists indicating that Quantcast does not have consent for purpose 1 (cookies, device identifiers, or other information can be stored or accessed on your device for the purposes presented to you), or an established legal basis (by default legitimate interest) for purpose 10 (your data can be used to improve existing systems and software, and to develop new products). + +## Quantcast ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"quantcastId"` | `"quantcastId"` | +| params | Optional | Object | Details for Quantcast initialization. | | +| params.ClientID | Optional | String | Optional parameter for Quantcast prebid managed service partners. The parameter is not required for websites with Quantcast Measure tag. Reach out to Quantcast for ClientID if you are not an existing Quantcast prebid managed service partner: | | + +## Quantcast ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "quantcastId" + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/ramp.md b/dev-docs/modules/userid-submodules/ramp.md new file mode 100644 index 0000000000..bde1b08d33 --- /dev/null +++ b/dev-docs/modules/userid-submodules/ramp.md @@ -0,0 +1,86 @@ +--- +layout: userid +title: LiveRamp RampID +description: LiveRamp RampID User ID sub-module +useridmodule: identityLinkIdSystem +--- + + +RampID, formerly known as IdentityLink, provided by [LiveRamp](https://liveramp.com) is a single person-based identifier which allows marketers, platforms and publishers to perform personalized segmentation, targeting and measurement use cases that require a consistent, cross-channel view of the user in anonymous spaces. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=identityLinkIdSystem + +## RampID Registration + +LiveRamp's RampID is free of charge and only requires a simple registration with Liveramp. Please sign up through our [Console](https://launch.liveramp.com) platform and request a Placement ID, a unique identifier that is used to identify each publisher, to get started. + +The RampID privacy policy is at [liveramp.com/privacy/service-privacy-policy/](https://liveramp.com/privacy/service-privacy-policy/). + +## RampID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of LiveRamp's user ID module. | `"identityLink"` | +| params | Required | Object | Container of all module params. | | +| params.pid | Required | String | This is the Placement ID, a unique identifier that is used to identify each publisher, obtained from registering with LiveRamp. | `"999"` | +| params.notUse3P | Not required | Boolean | Property for choosing if a cookieable RampID envelope (RTIS) should be set and stored until the user authenticates which then will be replaced by an authenticated RampID envelope (ATS) (either `true` or `false`). | `false` | +| storage | Required | Object | This object defines where and for how long the results of the call to get a RampID envelope will be stored. | +| storage.type | Required | String | This parameter defines where the resolved RampID envelope will be stored (either `"cookie"` or `"html5"` localStorage). | `"cookie"` | +| storage.name | Required | String | The name of the cookie or html5 localstorage where the resolved RampID envelope will be stored. LiveRamp requires `"idl_env"`. | `"idl_env"` | +| storage.expires | Required | Integer | How long (in days) the RampID envelope information will be stored. To be GDPR and CCPA compliant, we strongly advise to set a 15-day TTL ("Time to Live" / expiration time). If you are not planning to obtain RampID envelopes for EU/EEA or U.S. users, we advise you to change the expiration time to 30 days. | `15` | +| storage.refreshInSeconds | Required | Integer | The amount of time (in seconds) the RampID envelope should be cached in storage before calling LiveRamp again to retrieve a potentially updated value for the RampID envelope. | `1800` + +{: .alert.alert-info :} +**NOTE:** The RampID envelope that is delivered to Prebid will be encrypted by LiveRamp with a rotating key to avoid unauthorized usage and to enforce privacy requirements. Therefore, we strongly recommend setting `storage.refreshInSeconds` to 30 minutes (1800 seconds) to ensure all demand partners receive an ID that has been encrypted with the latest key, has up-to-date privacy signals, and allows them to transact against it. + +## RampID Examples + +1. Publisher passes a Placement ID and elects to store the RampID envelope in a first-party cookie. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "identityLink", + params: { + pid: "999", // Set your Placement ID here + notUse3P: false + }, + storage: { + type: "cookie", + name: "idl_env", // "idl_env" is the required storage name + expires: 15, // RampID envelope can last for 15 days + refreshInSeconds: 1800 // RampID envelope will be updated every 30 minutes + } + }], + syncDelay: 3000 // 3 seconds after the first auction + } + }); + ``` + +2. Publisher passes a Placement ID and elects to store the RampID envelope in HTML5 localStorage. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "identityLink", + params: { + pid: "999", // Set your Placement ID here + notUse3P: false + }, + storage: { + type: "html5", + name: "idl_env", // "idl_env" is the required storage name + expires: 15, // RampID envelope can last for 15 days + refreshInSeconds: 1800 // RampID envelope will be updated every 30 minutes + } + }], + syncDelay: 3000 // 3 seconds after the first auction + } + }); + ``` diff --git a/dev-docs/modules/userid-submodules/sharedid.md b/dev-docs/modules/userid-submodules/sharedid.md new file mode 100644 index 0000000000..4c2c224b6a --- /dev/null +++ b/dev-docs/modules/userid-submodules/sharedid.md @@ -0,0 +1,104 @@ +--- +layout: userid +title: SharedID +description: SharedID User ID sub-module +useridmodule: sharedIdSystem +--- + + +This module stores an unique user id in the first party domain and makes it accessible to all adapters. Similar to IDFA and AAID, this is a simple UUID that can be utilized to improve user matching, especially for iOS and MacOS browsers, and is compatible with ITP (Intelligent Tracking Prevention). It’s lightweight and self contained. Adapters that support SharedId will be able to pick up the user ID and return it for additional server-side cross device tracking. + +There is no special registration or configuration for SharedID. Each publisher's privacy policy should take +SharedID into account. Prebid recommends implementing a method where users can easily opt-out of targeted advertising. Please refer to the User Opt-Out section located at the bottom of this page. For more information check out Prebid's dedicated [identity page](/identity/sharedid.html) + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=sharedIdSystem + +## SharedID ID Configuration + +In addition to the parameters documented above in the Basic Configuration section the following SharedID specific configuration is available: + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `'sharedId'` | +| params | Optional | Object | Customized parameters | | +| params.create | Optional | Boolean | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` | +| params.pixelUrl | Optional | String | For publisher server support only. Where to call out to for a server cookie -- see [Prebid Identity](/identity/sharedid.html) for more information. | `/wp-json/pubcid/v1/extend/` +| params.extend | Optional | Boolean | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `false` | +| storage | Required | Object | The publisher must specify some kind of local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | +| storage.expires | Integer | Required | How long the user ID information will be stored. | `365` | +| storage.name | String | Required | The name of the cookie or html5 local storage where the user ID will be stored. | `_pubcid` +| storage.type | String | Required | This is where the results of the user ID will be stored. Must be either: Must be either: "cookie" or "html5". For server side implementations, which have the best identifier life and revenue impact, this must be a cookie. | `cookie` + +## SharedID Examples + +1. Publisher supports SharedID and first party domain cookie storage + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "sharedId", + storage: { + type: "cookie", + name: "_sharedid", // create a cookie with this name + expires: 365 // expires in 1 years + } + }] + } + }); + ``` + +2. Publisher supports both UnifiedID and SharedID and first party domain cookie storage + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "unifiedId", + params: { + partner: "myTtdPid" + }, + storage: { + type: "cookie", + name: "pbjs-unifiedid", // create a cookie with this name + expires: 60 + } + },{ + name: "sharedId", + params: { + pixelUrl: "/wp-json/pubcid/v1/extend/" + }, + storage: { + type: "cookie", + name: "_sharedid", // create a cookie with this name + expires: 180 + } + }], + syncDelay: 5000 // 5 seconds after the first bidRequest() + } + }); + ``` + +3. Publisher supports SharedID and first party domain cookie storage initiated by a first party server + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "sharedId", + params: { + pixelUrl: "/wp-json/pubcid/v1/extend/" //pixelUrl should be specified when the server plugin is used + }, + storage: { + type: "cookie", + name: "_sharedid", // create a cookie with this name + expires: 365 // expires in 1 year + } + }] + } + }); + ``` diff --git a/dev-docs/modules/userid-submodules/tapad.md b/dev-docs/modules/userid-submodules/tapad.md new file mode 100644 index 0000000000..7fdd8cfaa0 --- /dev/null +++ b/dev-docs/modules/userid-submodules/tapad.md @@ -0,0 +1,50 @@ +--- +layout: userid +title: Tapad ID +description: Tapad ID User ID sub-module +useridmodule: tapadIdSystem +--- + + +Tapad's ID module provides access to a universal identifier that publishers, ad tech platforms and advertisers can use for data collection and collation without reliance on third-party cookies. +Tapad's ID module is free to use and promotes collaboration across the industry by facilitating interoperability between DSPs, SSPs and publishers. + +To register as an authorized user of the Tapad ID module, or for more information, documentation and access to Tapad’s Terms and Conditions please contact [prebid@tapad.com](mailto:prebid@tapad.com). + +Tapad’s Privacy landing page containing links to region-specific Privacy Notices may be found here: [tapad.com/privacy](https://www.tapad.com/privacy). + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=userId,tapadIdSystem + +## Tapad ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"tapadId"` | `"tapadId"` | +| params | Required | Object | Details for Tapad initialization. | | +| params.company_id | Required | Number | Tapad Company Id provided by Tapad | 1234567890 | + +## Tapad ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: "tapadId", + params: { + companyId: 1234567890 + }, + storage: { + type: "cookie", + name: "tapad_id", + expires: 1 + } + } + ] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/teads.md b/dev-docs/modules/userid-submodules/teads.md new file mode 100644 index 0000000000..dd8f7fffcb --- /dev/null +++ b/dev-docs/modules/userid-submodules/teads.md @@ -0,0 +1,52 @@ +--- +layout: userid +title: Teads ID +description: Teads ID User ID sub-module +useridmodule: teadsIdSystem +pbjs_version_notes: please avoid using v7.20.0 and v7.21.0 +--- + + +The Teads ID is a first-party identifier designed for publishers using the Teads adapter. For more information please contact [innov-ssp@teads.com](mailto:innov-ssp@teads.com) + +## Teads ID Configuration + +First, add the Teads ID module to your Prebid.js build: + +```shell +gulp build --modules=userId,teadsIdSystem +``` + +Then configure the teadsId in your `userSync` configuration. + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"teadsId"` | `"teadsId"` | +| params | Required | Object | Details for Teads initialization. | | +| params.pubId | Required | Number | Teads Publisher Id provided by Teads | 1234 | + +Replace the `pubId` value by your Publisher Teads Id that you will find in TODO + +## Teads ID Example + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'teadsId', + params: { + pubId: 1234 + } + }] + } +}); +``` + +This will add a `userId.teadsId` property to all bidRequests. This will be read by the Teads bid adapter, and any other adapters that support EIDs: + +```javascript +{ + teadsId: '2e3a00de-3800-11ed-a261-0242ac120002' +} +``` diff --git a/dev-docs/modules/userid-submodules/trustpid.md b/dev-docs/modules/userid-submodules/trustpid.md new file mode 100644 index 0000000000..ab4ec4d7ac --- /dev/null +++ b/dev-docs/modules/userid-submodules/trustpid.md @@ -0,0 +1,56 @@ +--- +layout: userid +title: Trustpid +description: Trustpid User ID sub-module +pbjs_version_notes: not in 8.x +useridmodule: trustpidSystem +--- + +{: .alert.alert-info :} +This ID module has been renamed [utiq](/dev-docs/modules/userid-submodules/utiq.html) as of Prebid.js 8.0. + +Trustpid generates unique tokens, enabling improved efficiency in programmatic advertising while safeguarding transparency and control for end customers via `trustpid.com`. A website visitor’s Trustpid is generated based on network identifiers provided by network operators and requires explicit user consent. + +Trustpid is also the brand name of the service, which is provided by Vodafone Sales and Services Limited (“VSSL”). + +## Trustpid configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of the module | `"trustpid"` +| params | Required | Object | Object with configuration parameters for trustpid User Id submodule | - | +| params.maxDelayTime | Required | Integer | Max amount of time (in seconds) before looking into storage for data | 2500 | +| bidders | Required | Array of Strings | An array of bidder codes to which this user ID may be sent. Currently required and supporting AdformOpenRTB | `['adf']` | +| storage | Required | Object | Local storage configuration object | - | +| storage.type | Required | String | Type of the storage that would be used to store user ID. Must be `"html5"` to utilise HTML5 local storage. | `"html5"` | +| storage.name | Required | String | The name of the key in local storage where the user ID will be stored. | `"trustpid"` | +| storage.expires | Required | Integer | How long (in days) the user ID information will be stored. For safety reasons, this information is required.| `1` | + +Configuration example: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: "trustpid", + params: { + maxDelayTime: 2500, + }, + bidders: ["adf"], + storage: { + type: "html5", + name: "trustpid", + expires: 1, + }, + }], + syncDelay: 3000, + auctionDelay: 3000 + } +}); +``` + +## Truspid onboarding + +If you wish to find out more about Trustpid, please contact diff --git a/dev-docs/modules/userid-submodules/unified.md b/dev-docs/modules/userid-submodules/unified.md new file mode 100644 index 0000000000..5c9fc0856b --- /dev/null +++ b/dev-docs/modules/userid-submodules/unified.md @@ -0,0 +1,95 @@ +--- +layout: userid +title: Unified ID +description: Unified ID User ID sub-module +useridmodule: unifiedIdSystem +--- + + +The Unified ID solution is provided by adsrvr.org and the Trade Desk. + +Add it to your Prebid.js package with: + +{: .alert.alert-info :} +gulp build --modules=unifiedIdSystem + +## Unified ID Registration + +You can set up Unified ID in one of these ways: + +- Register with The Trade Desk from their [Unified ID page](https://www.thetradedesk.com/industry-initiatives/unified-id-solution). +- Utilize a [managed services](https://prebid.org/product-suite/managed-services/) company who can do this for you. + +The Unified ID privacy is covered under the [TradeDesk Services Privacy Policy](https://www.thetradedesk.com/general/privacy). + +## Unified ID Configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | `"unifiedId"` | `"unifiedId"` | +| params | Required for UnifiedId | Object | Details for UnifiedId initialization. | | +| params.partner | Either this or url required for UnifiedId | String | This is the partner ID value obtained from registering with The Trade Desk or working with a Prebid.js managed services provider. | `"myTtdPid"` | +| params.url | Required for UnifiedId if not using TradeDesk | String | If specified for UnifiedId, overrides the default Trade Desk URL. | "" | +| value | Optional | Object | Used only if the page has a separate mechanism for storing the Unified ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"tdid": "D6885E90-2A7A-4E0F-87CB-7734ED1B99A3"}` | + +## Unified ID Examples + +1. Publisher has a partner ID with The Trade Desk, and is using the default endpoint for Unified ID. + + {: .alert.alert-warning :} + Bug: The default URL did not support HTTPS in Prebid.js 2.10-2.14. So instead of using + the 'partner' parameter, it's best to supply the Trade Desk URL as shown in this example. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "unifiedId", + params: { + url: "//match.adsrvr.org/track/rid?ttd_pid=MyTtidPid&fmt=json" + }, + storage: { + type: "cookie", + name: "pbjs-unifiedid", // create a cookie with this name + expires: 60 // cookie can last for 60 days + } + }], + syncDelay: 3000 // 3 seconds after the first auction + } + }); + ``` + +2. Publisher supports UnifiedID with a vendor other than Trade Desk and HTML5 local storage. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "unifiedId", + params: { + url: "URL_TO_UNIFIED_ID_SERVER" + }, + storage: { + type: "html5", + name: "pbjs-unifiedid", // set localstorage with this name + expires: 60 + } + }], + syncDelay: 3000 + } + }); + ``` + +3. Publisher has integrated with UnifiedID on their own and wants to pass the UnifiedID directly through to Prebid.js. + + ```javascript + pbjs.setConfig({ + userSync: { + userIds: [{ + name: "unifiedId", + value: {"tdid": "D6885E90-2A7A-4E0F-87CB-7734ED1B99A3"} + }] + } + }); + ``` diff --git a/dev-docs/modules/userid-submodules/unified2.md b/dev-docs/modules/userid-submodules/unified2.md new file mode 100644 index 0000000000..f2d2f23549 --- /dev/null +++ b/dev-docs/modules/userid-submodules/unified2.md @@ -0,0 +1,102 @@ +--- +layout: userid +title: Unified ID 2.0 +description: Unified ID 2.0 User ID sub-module +useridmodule: uid2IdSystem +--- + +Unified ID 2.0 (UID2) is an open-source identity solution built for the open internet. It leverages encrypted email and phone number data to provide a privacy-conscious, secure, and accurate identity standard for the entire digital advertising ecosystem. + +UID2 relies on user consent before an ID can be added to the bid stream. Consent can be gathered by SSO providers who have integrated against the UID2 framework, or through a publisher's own login and consent mechanism. + +To add UID2 to your Prebid.js package, run the following: + +{: .alert.alert-info :} +gulp build --modules=uid2IdSystem + +## Unified ID 2.0 Registration + +You can set up Unified ID 2.0 in one of these ways: + +- Include the module to your pb.js wrapper. You will need to apply for publisher access [on the UID2 website](https://unifiedid.com/request-access). Using this option, you must generate UID2 tokens server-side. There is currently no flow for client-side only, unless you use an SSO provider. You provide these tokens to Prebid.js either by using a cookie or directly in the configuration. +- Use a [managed services](https://prebid.org/product-suite/managed-services/) company that can do this for you. + +Each publisher’s privacy policy should take UnifiedID 2.0 into account. + +## Unified ID 2.0 Tokens + +UID2 tokens are generated on the server side by making an API call to a UID2 operator using details provided when you receive UID2 publisher access. This API returns a JSON data structure with multiple values, including an advertising token and a refresh token. For full functionality, provide the entire object in one of these ways: + +- JSON-encoded as a cookie. +- Included in the configuration object. + +For examples, see [Unified ID 2.0 Examples](#unified-id-20-examples). + +The following sample is fictitious, but shows what the token response object looks like: + +```javascript +{ + "advertising_token": "...", + "refresh_token": "...", + "identity_expires": 1633643601000, + "refresh_from": 1633643001000, + "refresh_expires": 1636322000000, + "refresh_response_key": "wR5t6HKMfJ2r4J7fEGX9Gw==" +} +``` + +When this full data structure is provided, the module automatically refreshes the token periodically, as long as the refresh token hasn't expired. + +## Unified ID 2.0 Server-Only Mode + +There is a server-only mode where the value of the advertising token can be provided either directly (see the `value` parameter in the [Unified ID 2.0 Configuration](#unified-id-20-configuration) section) or via a cookie. In this mode, no attempt is made to automatically refresh the token. + +To use the cookie-based server-only mode, set a cookie named `__uid2_advertising_token` to the value of the advertising token only, as shown in this fictitious example: + +`__uid2_advertising_token=eb33b0cb-8d35-4722-b9c0-1a31d4064888` + +## Unified ID 2.0 Configuration + +The following parameters apply only to the Unified ID 2.0 module integration. + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | ID value for the Unified ID 2.0 module - `"uid2"` | `"uid2"` | +| params.uid2Token | Optional | Object | The initial UID2 token. This should be the `body` element of the decrypted response from a call to the `/token/generate` or `/token/refresh` endpoint. | See the sample token above. | +| params.uid2ServerCookie | Optional | String | The name of a cookie that holds the initial UID2 token, set by the server. The cookie should contain JSON in the same format as the alternative uid2Token param. **If uid2Token is supplied, this param is ignored.** | See the sample token above. | +| params.uid2ApiBase | Optional | String | Overrides the default UID2 API endpoint. | `https://prod.uidapi.com` _(default)_ | +| value | Optional | Object | Used only if the page has a separate mechanism for storing the UID 2.0 ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage, and the tokens are **not** automatically refreshed. | `{"uid2": { "id": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}}` | +| params.storage | Optional, Client refresh | String | Specify whether to use `cookie` or `localStorage` for module-internal storage. It is recommended to not provide this and allow the module to use the default. | `localStorage` _(default)_ | + +## Unified ID 2.0 Examples + +In the following example, the publisher has set a cookie called `uid2_identity` containing the UID2 token generation response object: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'uid2', + params: { + uid2ServerCookie: 'uid2_identity' + } + }] + } +}); +``` + +In the following example, the publisher has retrieved a server-generated UID2 response, and it is currently stored in the JavaScript variable `uid2Identity`: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [{ + name: 'uid2', + params: { + uid2Token: uid2Identity + } + }] + } +}); +``` diff --git a/dev-docs/modules/userid-submodules/utiq.md b/dev-docs/modules/userid-submodules/utiq.md new file mode 100644 index 0000000000..e895f5268a --- /dev/null +++ b/dev-docs/modules/userid-submodules/utiq.md @@ -0,0 +1,35 @@ +--- +layout: userid +title: Utiq ID +description: Utiq User ID sub-module +useridmodule: utiqSystem +--- + +Utiq generates unique tokens, enabling improved efficiency in programmatic advertising while safeguarding transparency and control for end customers via `consenthub.utiq.com`. A website visitor’s Utiq is generated based on network identifiers provided by network operators and requires explicit user consent. + +Utiq is also the brand name of the service, which is provided by Utiq SA/NV. + +## Utiq ID configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of the module | `"utiq"` | + +Configuration example: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: "utiq", + }, + ], + }, +}) +``` + +## Utiq ID onboarding + +If you wish to find out more about Utiq, please contact diff --git a/dev-docs/modules/userid-submodules/utiqMtp.md b/dev-docs/modules/userid-submodules/utiqMtp.md new file mode 100644 index 0000000000..854042d27e --- /dev/null +++ b/dev-docs/modules/userid-submodules/utiqMtp.md @@ -0,0 +1,44 @@ +--- +layout: userid +title: UtiqMtp ID +description: UtiqMtp User ID sub-module +useridmodule: utiqMtpIdSystem +--- + +Utiq generates unique tokens, enabling improved efficiency in programmatic advertising while safeguarding transparency and control for end customers via `consenthub.utiq.com`. A website visitor’s Utiq ID is generated based on network identifiers provided by network operators and requires explicit user consent. + +Utiq provides different tokens type, known as 'adtechpass' and 'martechpass'. UtiqMtpId module helps publishers support and pass the 'martechpass' token to their SSP partners of choice. 'martechpass' is a first party ID meant to enable first party audiences in the SSP and shouldn't be forwarded to other parties. + +Both Utiq and UtiqMtpId user id submodules can be used in parallel as both supports different use cases and scenarios. + +Utiq is also the brand name of the service, which is provided by Utiq SA/NV. + +## Utiq installation + +In order to use utiq in your prebid setup, you must first integrate utiq solution on your website as per +If you are interested in using Utiq on your website, please contact Utiq on + +## UtiqMtp ID configuration + +{: .table .table-bordered .table-striped } +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of the module | `"utiqMtpId"` | + +Configuration example: + +```javascript +pbjs.setConfig({ + userSync: { + userIds: [ + { + name: "utiqMtpId", + }, + ], + }, +}) +``` + +## Utiq ID onboarding + +If you wish to find out more about Utiq, please contact diff --git a/dev-docs/modules/userid-submodules/yahoo.md b/dev-docs/modules/userid-submodules/yahoo.md new file mode 100644 index 0000000000..ee4eb0f50a --- /dev/null +++ b/dev-docs/modules/userid-submodules/yahoo.md @@ -0,0 +1,118 @@ +--- +layout: userid +title: Yahoo ConnectID +description: Yahoo ConnectID User ID sub-module +useridmodule: connectIdSystem +--- + +Yahoo ConnectID is a person based ID and does not depend on 3rd party cookies. It enables ad tech platforms to recognize and match users consistently across the open web. Built on top of Yahoo's robust and proprietary ID Graph it delivers higher monetization while respecting user privacy via multiple controls. + +Add support for Yahoo ConnectID to your Prebid.js package using: + +{: .alert.alert-info :} +gulp build --modules=userId,connectIdSystem + +## Yahoo ConnectID Registration + +A Yahoo-supplied publisher-specific pixel ID is required. Reach out to [connectid.support@yahooinc.com](mailto:connectid.support@yahooinc.com) for assistance with setup. + +## Yahoo ConnectID Configuration + +Note: Parameters are case-sensitive. ConnectID is the proper name of our product, however, when used in code it is spelled as connect**I**d. Follow the example in the table below. + +
      +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| name | Required | String | The name of this module. | `"connectId"` | +| params | Required | Object | Container of all module params. || +| params.pixelId | Required | Number | +The Yahoo-supplied publisher-specific pixel ID. | `"0000"` | +| params.he | Optional | String | The SHA-256 hashed user email address which has been lowercased prior to hashing. |`"ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4"`| +| params.puid | Optional | String | A domain-specific user identifier such as a first-party cookie. If not passed, a puid value will be auto-generated and stored in local and / or cookie storage. | `"ab9iibf5a231ii1db8ef911596ca297d5e3f84biii00041c5880dba3baf9c1da"` | +{: .table .table-bordered .table-striped } +
      + +## Yahoo ConnectID Examples + +```javascript +// [Sample #1]: Using a hashed email only. + +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "connectId", + params: { + pixelId: "0000", + he: "ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4" + } + }] + } +}) +``` + +```javascript +// [Sample #2]: Neither a hashed email nor a publisher user identifier is passed. + +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "connectId", + params: { + pixelId: "0000", + } + }] + } +}) +``` + +```javascript +// [Sample #3]: Using a hashed email and a publisher user identifier such as a first-party cookie. + +pbjs.setConfig({ + userSync: { + userIds: [{ + name: "connectId", + params: { + pixelId: "0000", + he: "ed8ddbf5a171981db8ef938596ca297d5e3f84bcc280041c5880dba3baf9c1d4" + puid: "ab9iibf5a231ii1db8ef911596ca297d5e3f84biii00041c580dba3baf9c1da" + } + }] + } +}) +``` + +## Implementation Verification + +Follow the steps below to check that ConnectIDs are being successfully retrieved and included on ad requests. + +1. Open a Prebid-enabled page on the website. +2. Open the browser console and enter pbjs.getUserIds(). +3. Verify connectId is in the list. + - If connectId is not in the list, the correct pixelId parameter is likely not being passed. Verify you are using the correct value provided by Yahoo. Reach out to [connectid.support@yahooinc.com](mailto:connectid.support@yahooinc.com) for assistance. +4. Verify that ConnectID is successfully included in the ad requests. + - Go to the Network tab and search for an ad call event to any of the SSPs that you are using (e.g., “prebid-client”). + - Navigate to the Payload tab. Check that yahoo.com is listed as a source in the user.ext.eids array. +5. Repeat steps 1-4 after an email is provided via login or some other mechanism used to collect user registration on the website. + +## Honoring Privacy Choices + +Yahoo ConnectID provides multiple mechanisms for users to manage their privacy choices. Users can manage their choices via [ConnectID Control Portal](http://connectid.yahoo.com), on the [Yahoo Privacy Dashboard](https://legal.yahoo.com/us/en/yahoo/privacy/dashboard/index.html) and [NAI’s Audience Matched Opt Out page](https://optout.networkadvertising.org/optout/email). No further actions are required by Publishers as Yahoo will ensure that privacy choices selected by users via one of these methods are honored. We will automatically stop generating ConnectIDs for users who have opted-out. + +When desired, additional privacy control can be provided to your users. Within your privacy policy or website privacy settings, [Create an Easy Opt-in Opt-out Toggle](https://documentation.help.yahooinc.com/platform/SSP/Sellers/Integrate/Create-an-Easy-OptIn-Optout-Toggle.htm) for ConnectID. + +Finally, ConnectID follows all global privacy laws (such as the CCPA) and industry frameworks (such as NAI, DAA and IAB). Yahoo will auto-detect most privacy signals present on the page (including those set by Prebid libraries) and not generate a ConnectID for users that have opted-out. + +## Yahoo ConnectID Optional Parameters + +Please note that the storage related parameters are optional. We recommend that you omit them, since ConnectID module is pre-configured with the most optimal storage parameters already. + +
      +| Param under userSync.userIds[] | Scope | Type | Description | Example | +| --- | --- | --- | --- | --- | +| storage | Optional | Object | Defines where and for how long the results of the call to get a user ID will be stored. | | +| storage.type | Optional | String | Defines where the resolved user ID will be stored (either 'cookie' or 'html5' local storage). | `'cookie'` | +| storage.name | Optional | String | The name of the cookie or html5 local storage where the resolved user ID will be stored. | `'connectId'` | +| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `15` | +{: .table .table-bordered .table-striped } +
      diff --git a/dev-docs/modules/validationFpdModule.md b/dev-docs/modules/validationFpdModule.md index 571eb26f7f..acf440cf89 100644 --- a/dev-docs/modules/validationFpdModule.md +++ b/dev-docs/modules/validationFpdModule.md @@ -10,6 +10,7 @@ sidebarType : 1 --- # First Party Data Validation Module + {:.no_toc} This module performs a number of validations on First Party Data (FPD) fields.The scope and number of validations is large enough that it increases the size of the PBJS package by about 1KB: verifying fields and data types. e.g. confirm that site.sectioncat is an array of strings. @@ -17,13 +18,14 @@ This module performs a number of validations on First Party Data (FPD) fields.Th For this reason, publishers sensitive to javascript size may want to consider running this module only when testing a new release of Prebid.js or during major changes to how Prebid.js is integrated into their pages. Add it to the Prebid.js build with this command: -``` + +```bash gulp build --modules=validationFpdModule ``` If included in the build, it will automatically perform the defined validations unless controlled with setConfig: -``` +```javascript pbjs.setConfig({ firstPartyData: { skipValidations: true // defaults to false @@ -33,7 +35,7 @@ pbjs.setConfig({ ## Validations -This module does its checks only once at the first auction. The checks can be re-run anytime by calling `pbjs.refreshFpd()`. +This module does its checks at the beginning of each auction. When a data field doesn't meet the defined validations, it will be removed. In addition, the module will look for the _pubcid_optout cookie (or local storage), and if it exists, certain fields will be removed. @@ -61,6 +63,7 @@ and if it exists, certain fields will be removed. | ortb2.user.data.ext | Must be an object | | # Related Reading + - [Prebid.js First Party Data feature](/features/firstPartyData.html) - [First Party Data Enrichment Module](/dev-docs/modules/enrichmentFpdModule) - [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) diff --git a/dev-docs/modules/video.md b/dev-docs/modules/video.md new file mode 100644 index 0000000000..7ef13c53a3 --- /dev/null +++ b/dev-docs/modules/video.md @@ -0,0 +1,24 @@ +--- +layout: page_v2 +title: Module - Video Module +display_name: Prebid Video Module +description: The Prebid Video Module allows Prebid to directly integrate with a Video Player. +page_type: module +module_code : videoModule +enable_download : true +vendor_specific: false +sidebarType : 1 +--- + +# Prebid Video Module + +The Prebid Video Module allows Prebid to directly integrate with a Video Player. + +When the Video Module is setup, Prebid.js will automatically: + +- render bids in the desired video player +- mark used bids as won +- trigger player and media events +- fill the oRTB Video Impression and Content params in the bid request + +For details on how to use the Video Module please visit the [docs]({{site.github.url}}/prebid-video/video-module.html). diff --git a/dev-docs/modules/videojsVideoProvider.md b/dev-docs/modules/videojsVideoProvider.md new file mode 100644 index 0000000000..603ab01b19 --- /dev/null +++ b/dev-docs/modules/videojsVideoProvider.md @@ -0,0 +1,19 @@ +--- +layout: page_v2 +page_type: module +title: Module - Video.js Video Submodule +description: Allows Prebid to integrate directly with Video.js video players. +module_code : videojsVideoProvider +display_name : Video.js Video Provider +enable_download : true +vendor_specific: true +sidebarType : 1 +--- + +# Video.js Video Provider + +The Video.js Video Provider is a submodule of the Prebid Video Module. + +The Video.js Vendor Code for the Video Module is `2`. + +For information on how to use the Video Module for video.js please visit the [docs]({{site.github.url}}/prebid-video/video-module.html). diff --git a/dev-docs/modules/viewability.md b/dev-docs/modules/viewability.md index b6d0e21104..3e8a7a1cc5 100644 --- a/dev-docs/modules/viewability.md +++ b/dev-docs/modules/viewability.md @@ -5,95 +5,138 @@ title: Module - Viewability description: Generic Viewability module, tracks element viewability based on given criteria module_code: viewability display_name: Viewability -enable_download: true +enable_download: false sidebarType: 1 --- # Generic Viewability + {:.no_toc} -* TOC +- TOC {:toc} ## Overview +{: .alert.alert-danger :} +Disclaimer: A potential security risk has been identified in this module. We do not recommend its usage unless you're confident about +the source of all code running on the page. This module will trigger a viewability pixel when a given HTML element becomes viewable according to custom viewability criteria. -Notes: -- Does not depend on publishers using GAM ad server (does not use GPT's ImpressionViewableEvent). +Features: + +- Does not depend on publishers using GAM ad server (i.e. does not use GPT's ImpressionViewableEvent). - Enables custom viewability criteria (timeInView and inViewThreshold). -- Aims to provide (and in some ways extend) functionality of https://github.com/InteractiveAdvertisingBureau/openvv-html , but keeping the size to the bare minimun (openvv-html is ~26kb in size). +- Aims to provide (and in some ways extend) functionality of , but keeping the size to the bare minimun (openvv-html is ~26kb in size). - Enables publishers to track viewability through callbacks or img/js pixels. +- Supports all mediatypes. - Enables buy side to track viewability by posting a message from within the creative iframe (including the postMessage call in the ad markup), thus avoiding custom viewability scripts. {: .alert.alert-warning :} -This module does not work on IE (uses IntersectionObserver). +This module does not work on IE because it uses the IntersectionObserver. + +Note that there are other viewability modules in Prebid.js: + +- [Bid Viewability - Ad Server Independent](/dev-docs/modules/bidViewableIO.html) +- [Bid Viewability - GAM](/dev-docs/modules/bidViewable.html) +- [Browsi Viewability](/dev-docs/modules/browsiRtdProvider.html) + +## Usage + +The viewability module provides two functions: `startMeasurement` and `stopMeasurement` which can be used to enable viewability measurements. +These functions are intended to be added to the page. Here's how they work: + +1. startMeasurement creates a browser [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) which triggers when the defined div is in view according to the defined criteria. +2. When the criteria is met, the IntersectionObserver is cancelled and the supplied tracking URL is hit (as an image or iframe) or the supplied callback function is called. +3. If for any reason the viewability measurement should be stopped (e.g. a slide show changed the contents), the stopMeasurement function can be used. + +### startMeasurement -## Configuration +This function has 4 positional parameters when called as a function: `pbjs.viewability.startMeasurement(vid, element, tracker, criteria)`: -Module does not need any configuration, as long as you include it in your PBJS bundle. -Viewability module has only two functions `startMeasurement` and `stopMeasurement` which can be used to enable more complex viewability measurements. Since it allows tracking from within creative (possibly inside a safe frame) this module registers a message listener, for messages with a format that is described bellow. +{: .table .table-bordered .table-striped } +| pos | param | scope | type | description | example | +|-----|-------|-------|------|-------------|---------| +| 1 | vid | required | string | unique viewability identifier, used to reference particular tracker which can later be used to stop the measurement. It allows for multiple trackers, with different criteria to be registered for a given HTML element, independently. vid is not autogenerated by startMeasurement(), it needs to be provided by caller so that it doesn't have to be posted back to the source iframe (in case viewability is started from within the creative). | 'test-div-1' | +| 2 | element | required | reference | reference to the HTML element that needs to be tracked. | test-div | +| 3 | tracker | required | object | an object type with two properties, `method` ('img','js','callback') and `value` which can be an URL string for 'img' and 'js' trackers, or a function for 'callback' tracker. | `{ method: 'img', value: 'http://my.tracker/123' }` | +| 4 | criteria | required | object | an object type with two properties, `inViewThreshold` which is a number (0, 1.0] representing a percentage of viewable element we're aiming at, and `timeInView` which is a number of milliseconds that a given element needs to be in view continuously, above a threshold. | `{ inViewThreshold: 0.5, timeInView: 1000 }` | -`startMeasurement` -This function has 4 parameters when called directly with `pbjs.viewability.startMeasurement()`: - - vid: unique viewability identifier, used to reference particular tracker which can later be used to stop the measurement. It allows for multiple trackers, with different criteria to be registered for a given HTML element, independently. vid is not autogenerated by startMeasurement(), it needs to be provided by caller so that it doesn't have to be posted back to the source iframe (in case viewability is started from within the creative). - - element: reference to an HTML element that needs to be tracked. - - tracker: ViewabilityTracker is an object type with two properties, `method` ('img'|'js'|'callback') and `value` which can be an URL string for 'img' and 'js' trackers, or a function for 'callback' tracker. Example: `{ method: 'img', value: 'http://my.tracker/123' }` - - criteria: ViewabilityCriteria is an object type with two properties, `inViewThreshold` which is a number (0, 1.0] representing a percentage of viewable element we're aiming at, and `timeInView` which is a number of milliseconds that a given element needs to be in view continuously, above a threshold. Example: `{ inViewThreshold: 0.5, timeInView: 1000 }` +When a tracker needs to be started without direct access to Prebid.js, postMessage mechanism can be used to invoke `startMeasurement` with the following payload: -When a tracker needs to be started, without direct access to pbjs, postMessage mechanism can be used to invoke `startMeasurement`, with a following payload: `vid`, `tracker` and `criteria` as described above, but also with `message: 'Prebid Viewability'` and `action: 'startMeasurement'`. Optionally payload can provide `elementId`, if available at that time (for ad servers where name of the iframe is known, or adservers that render outside an iframe). If `elementId` is not provided, viewability module will try to find the iframe that corresponds to the message source. +{: .table .table-bordered .table-striped } +| param | scope | type | description | example | +|-------|-------|------|-------------|---------| +| vid | required | string | unique viewability identifier. See the description above. | 'test-div-1' | +| tracker | required | object | see above | `{ method: 'img', value: 'http://my.tracker/123' }` | +| criteria | required | object | see above | `{ inViewThreshold: 0.5, timeInView: 1000 }` | +| message | required | string | must be 'Prebid Viewability' | 'Prebid Viewability' | +| action | required | string | must be 'startMeasurement' | 'startMeasurement' | +| elementId | optional | string | element ID. The message listener can figure this out from the source iframe. | 'test-div' | +### stopMeasurement -`stopMeasurement`: -This function has only 1 parementer when called directly with `pbjs.viewability.stopMeasurement()`: -- vid: unique viewability identifier, referencing an already started viewability tracker. +This function has only 1 parementer when called as a function: `pbjs.viewability.stopMeasurement()`: -When a tracker needs to be stopped, without direct access to pbjs, postMessage mechanism can be used here as well, to invoke `stopMeasurement`, providing payload with `vid`, `message: 'Prebid Viewability'` and `action: 'stopMeasurement`. +{: .table .table-bordered .table-striped } +| pos | param | scope | type | description | example | +|-----|-------|-------|------|-------------|---------| +| 1 | vid | required | string | the unique viewability identifier, referencing an already started viewability tracker. | 'test-div-1' | -## Example of starting a viewability measurement, when you have direct access to pbjs -{% highlight js %} +When a tracker needs to be stopped without direct access to Prebid.js, postMessage mechanism can be used here as well to invoke `stopMeasurement`, providing payload with these fields: - pbjs.viewability.startMeasurement( - 'ae0f9', - document.getElementById('test_div'), - { method: 'img', value: 'http://my.tracker/123' }, - { inViewThreshold: 0.5, timeInView: 1000 } - ); +{: .table .table-bordered .table-striped } +| param | scope | type | description | example | +|-------|-------|------|-------------|---------| +| vid | required | string | unique viewability identifier. See the description above. | 'test-div-1' | +| message | required | string | must be 'Prebid Viewability' | 'Prebid Viewability' | +| action | required | string | must be 'stopMeasurement' | 'stopMeasurement' | -{% endhighlight %} +## Examples -## Example of starting a viewability measurement from within a rendered creative -{% highlight js %} +### Starting a viewability measurement when you have direct access to Prebid.js - let viewabilityRecord = { - vid: 'ae0f9', - tracker: { method: 'img', value: 'http://my.tracker/123'}, - criteria: { inViewThreshold: 0.5, timeInView: 1000 }, - message: 'Prebid Viewability', - action: 'startMeasurement' - } +```javascript +pbjs.viewability.startMeasurement( + 'test-div-1', + document.getElementById('test-div'), + { method: 'img', value: 'http://my.tracker/123' }, + { inViewThreshold: 0.5, timeInView: 1000 } +); +``` - window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); +### Starting a viewability measurement from within a rendered creative -{% endhighlight %} +```javascript +let viewabilityRecord = { + vid: 'ae0f9', + tracker: { method: 'img', value: 'http://my.tracker/123'}, + criteria: { inViewThreshold: 0.5, timeInView: 1000 }, + message: 'Prebid Viewability', + action: 'startMeasurement' +} -## Example of stopping the viewability measurement, when you have direct access to pbjs -{% highlight js %} +window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); +``` - pbjs.viewability.stopMeasurement('ae0f9'); +### Stopping the viewability measurement when you have direct access to Prebid.js -{% endhighlight %} +```javascript +pbjs.viewability.stopMeasurement('test-div-1'); +``` -## Example of stopping the viewability measurement from within a rendered creative -{% highlight js %} +### Stopping the viewability measurement from within a rendered creative - let viewabilityRecord = { - vid: 'ae0f9', - message: 'Prebid Viewability', - action: 'stopMeasurement' - } +```javascript +let viewabilityRecord = { + vid: 'ae0f9', + message: 'Prebid Viewability', + action: 'stopMeasurement' +} +window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); +``` - window.parent.postMessage(JSON.stringify(viewabilityRecord), '*'); +## Related Reading -{% endhighlight %} +- Alternate module: [Bid Viewability - Ad Server Independent](/dev-docs/modules/bidViewableIO.html) diff --git a/dev-docs/modules/weboramaRtdProvider.md b/dev-docs/modules/weboramaRtdProvider.md index 63e8f4d96a..29d450291a 100644 --- a/dev-docs/modules/weboramaRtdProvider.md +++ b/dev-docs/modules/weboramaRtdProvider.md @@ -12,14 +12,23 @@ sidebarType : 1 --- # Weborama RTD Segmentation Module + {:.no_toc} * TOC {:toc} -Weborama provides a Semantic AI Contextual API that classifies in Real-time a web page seen by a web user within generic and custom topics. It enables publishers to better monetize their inventory and unlock it to programmatic. +## Description + +Weborama provides a Real-Time Data Submodule for `Prebid.js`, allowing to easy integrate different products such as: + +* Semantic AI Contextual API that classifies in Real-time a web page seen by a web user within generic and custom topics. It enables publishers to better monetize their inventory and unlock it to programmatic. + +* Weborama Audience Manager (WAM) is a DMP (Data Management Platform) used by over 60 companies in the world. This platform distinguishes itself particularly by a high level interconnexion with the adtech & martech ecosystem and a transparent access to the database intelligence. -Contact prebid-support@weborama.com for information. +* LiTE by SFBX® (Local inApp Trust Engine) provides “Zero Party Data” given by users, stored and calculated only on the user’s device. Through a unique cohorting system, it enables better monetization in a consent/consentless and identity-less mode. + +Contact [prebid-support@weborama.com] for more information. ### Publisher Usage @@ -27,10 +36,337 @@ Compile the Weborama RTD module into your Prebid build: `gulp build --modules=rtdModule,weboramaRtdProvider` -Add the Weborama RTD provider to your Prebid config. +Add the Weborama RTD provider to your Prebid config, use the configuration template below: + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function () { + pbjs.setConfig({ + debug: true, // Output debug messages to the web console, *should* be disabled in production + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + /* add weborama rtd submodule configuration here */ + }, + }, + // other modules... + ] + } + }); +}); +``` + +The module configuration has 3 independent sections (`weboCtxConf`, `weboUserDataConf` and `sfbxLiteDataConf`), each one mapped to a single product (`contextual`, `wam` and `lite`). No section is enabled by default, we must be explicit like in the minimal example below: + +```javascript +pbjs.setConfig({ + debug: true, + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + weboCtxConf: { // contextual site-centric configuration, *omit if not needed* + token: "<>", // mandatory + }, + weboUserDataConf: { // wam user-centric configuration, *omit if not needed* + enabled: true, + }, + sfbxLiteDataConf: { // sfbx-lite site-centric configuration, *omit if not needed* + enabled: true, + }, + } + }, + // other modules... + ] + } +}); +``` + +Each module can perform two actions: + +* set targeting on [GPT](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) / [AST](https://docs.prebid.org/dev-docs/publisher-api-reference/setTargetingForAst.html) via `prebid.js` + +* send data to other `prebid.js` bidder modules (check the complete list at the end of this page) + +### Parameter Descriptions for the Weborama Configuration Section + +This is the main configuration section + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| name | String | Real time data module name | Mandatory. Always 'Weborama' | +| waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true | +| params | Object | | Optional | +| params.setPrebidTargeting | Boolean | If true, may use the profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js | Optional. Affects the `weboCtxConf`, `weboUserDataConf` and `sfbxLiteDataConf` sections | +| params.sendToBidders | Boolean or Array | If true, may send the profile to all bidders. If an array, will specify the bidders to send data | Optional. Affects the `weboCtxConf`, `weboUserDataConf` and `sfbxLiteDataConf` sections | +| params.weboCtxConf | Object | Weborama Contextual Site-Centric Configuration | Optional | +| params.weboUserDataConf | Object | Weborama WAM User-Centric Configuration | Optional | +| params.sfbxLiteDataConf | Object | Sfbx LiTE Site-Centric Configuration | Optional | +| params.onData | Callback | If set, will receive the profile and metadata | Optional. Affects the `weboCtxConf`, `weboUserDataConf` and `sfbxLiteDataConf` sections | + +#### Contextual Site-Centric Configuration + +To be possible use the integration with Weborama Contextual Service you must be a client with a valid API token. Please contact weborama if you don't have it. + +On this section we will explain the `params.weboCtxConf` subconfiguration: + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| token | String | Security Token provided by Weborama, unique per client | Mandatory | +| targetURL | String | Url to be profiled in the contextual api | Optional. Defaults to `document.URL` | +| assetID | Function or String | if provided, we will call the document-profile api using this asset id. |Optional| +| setPrebidTargeting|Various|If true, will use the contextual profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or `true`.| +| sendToBidders|Various|If true, will send the contextual profile to all bidders. If an array, will specify the bidders to send data| Optional. Default is `params.sendToBidders` (if any) or `true`.| +| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | +| onData | Callback | If set, will receive the profile and metadata | Optional. Default is `params.onData` (if any) or log via prebid debug | +| enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present| +| baseURLProfileAPI | String| if present, update the domain of the contextual api| Optional. Default is `ctx.weborama.com` | + +#### User-Centric Configuration + +To be possible use the integration with Weborama Audience Manager (WAM) you must be a client with an account id and you must include the `wamfactory` script in your pages with `wam2gam` feature activated. +Please contact weborama if you don't have it. + +On this section we will explain the `params.weboUserDataConf` subconfiguration: + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| accountId|Number|WAM account id. If you don't have it, please contact weborama. | Recommended.| +| setPrebidTargeting|Various|If true, will use the user profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or `true`.| +| sendToBidders|Various|If true, will send the user profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or `true`.| +| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | +| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | +| localStorageProfileKey| String | can be used to customize the local storage key | Optional | +| enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present| + +##### User Consent + +The WAM User-Centric configuration will check for user consent if gdpr applies. It will check for consent: + +* Vendor ID 284 (Weborama) +* Purpose IDs: 1, 3, 4, 5 and 6 + +If the user consent does not match such conditions, this module will not load, means we will not check for any data in local storage and the default profile will be ignored. + +#### Sfbx LiTE Site-Centric Configuration + +To be possible use the integration between Weborama and Sfbx LiTE you should also contact SFBX® to setup this product. -Minimal configuration: +On this section we will explain the `params.sfbxLiteDataConf` subconfiguration: + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| setPrebidTargeting|Various|If true, will use the user profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or `true`.| +| sendToBidders|Varios|If true, will send the user profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or `true`.| +| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | +| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | +| localStorageProfileKey| String | can be used to customize the local storage key | Optional | +| enabled | Boolean| if false, will ignore this configuration| Default is `true` if this section is present| + +##### Property setPrebidTargeting supported types + +This property support the following types + +{: .table .table-bordered .table-striped } +| Type | Description | Example | Notes | +| :------------ | :------------ | :------------ |:------------ | +| Boolean|If true, set prebid targeting for all adunits, or not in case of false| `true` | default value | +| String|Will set prebid targeting only for one adunit | `'adUnitCode1'` | | +| Array of Strings|Will set prebid targeting only for some adunits| `['adUnitCode1','adUnitCode2']` | | +| Callback |Will be executed for each adunit, expects return a true value to set prebid targeting or not| `function(adUnitCode){return adUnitCode == 'adUnitCode';}` | | + +The complete callback function signature is: + +```javascript +setPrebidTargeting: function(adUnitCode, data, metadata){ + return true; // or false, depending on the logic +} ``` + +This callback will be executed with the adUnitCode, profile and a metadata with the following fields + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| user | Boolean | If true, it contains user-centric data | | +| source | String | Represent the source of data | can be `contextual`, `wam` or `lite` | +| isDefault | Boolean | If true, it contains the default profile defined in the configuration | | + +It is possible customize the targeting based on the parameters: + +```javascript +setPrebidTargeting: function(adUnitCode, data, metadata){ + // check metadata.source can be omitted if defined in params.weboUserDataConf + if (adUnitCode == 'adUnitCode1' && metadata.source == 'wam'){ + data['foo']=['bar']; // add this section only for adUnitCode1 + delete data['other']; // remove this section + } + return true; +} +``` + +##### Property sendToBidders supported types + +This property support the following types + +{: .table .table-bordered .table-striped } +| Type | Description | Example | Notes | +| :------------ | :------------ | :------------ |:------------ | +| Boolean|If true, send data to all bidders, or not in case of false| `true` | default value | +| String|Will send data to only one bidder | `'appnexus'` | | +| Array of Strings|Will send data to only some bidders | `['appnexus','pubmatic']` | | +| Object |Will send data to only some bidders and some ad units | `{appnexus: true, pubmatic:['adUnitCode1']}` | | +| Callback |Will be executed for each adunit, expects return a true value to set prebid targeting or not| `function(bid, adUnitCode){return bid.bidder == 'appnexus' && adUnitCode == 'adUnitCode';}` | | + +A better look on the `Object` type + +```javascript +sendToBidders: { + appnexus: true, // send profile to appnexus on all ad units + pubmatic: ['adUnitCode1'],// send profile to pubmatic on this ad units +} +``` + +The complete callback function signature is: + +```javascript +sendToBidders: function(bid, adUnitCode, data, metadata){ + return true; // or false, depending on the logic +} +``` + +This callback will be executed with the bid object (contains a field `bidder` with name), adUnitCode, profile and a metadata with the following fields + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| user | Boolean | If true, it contains user-centric data | | +| source | String | Represent the source of data | can be `contextual`, `wam` or `lite` | +| isDefault | Boolean | If true, it contains the default profile defined in the configuration | | + +It is possible customize the targeting based on the parameters: + +```javascript +sendToBidders: function(bid, adUnitCode, data, metadata){ + if (bid.bidder == 'appnexus' && adUnitCode == 'adUnitCode1'){ + data['foo']=['bar']; // add this section only for appnexus + adUnitCode1 + delete data['other']; // remove this section + } + return true; +} +``` + +To be possible customize the way we send data to bidders via this callback: + +```javascript +sendToBidders: function(bid, adUnitCode, data, metadata){ + if (bid.bidder == 'other'){ + /* use bid object to store data based on this specific logic, like in the example below */ + + bid.params = bid.params || {}; + bid.params['some_specific_key'] = data; + + return false; // will prevent the module to follow the pre-defined logic per bidder + } + // others + return true; +} +``` + +In case of using bid _aliases_, we should match the same string used in the adUnit configuration. + +```javascript +pbjs.aliasBidder('appnexus', 'foo'); +pbjs.aliasBidder('criteo', 'bar'); +pbjs.aliasBidder('pubmatic', 'baz'); +pbjs.setConfig({ + realTimeData: { + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + weboCtxConf: { + token: "to-be-defined", // mandatory + sendToBidders: ['foo','bar'], // will share site-centric data with bidders foo and bar + }, + weboUserDataConf: { + accountId: 12345, // recommended, + sendToBidders: ['baz'], // will share user-centric data with only bidder baz + } + } + }] + } +}); +``` + +##### Using onData callback + +We can specify a callback to handle the profile data from site-centric or user-centric data. + +This callback will be executed with the profile and a metadata with the following fields + +{: .table .table-bordered .table-striped } +| Name |Type | Description | Notes | +| :------------ | :------------ | :------------ |:------------ | +| user | Boolean | If true, it contains user-centric data | | +| source | String | Represent the source of data | can be `contextual`, `wam` or `lite` | +| isDefault | Boolean | If true, it contains the default profile defined in the configuration | | + +The metadata maybe not useful if we define the callback on site-centric of user-centric configuration, but if defined in the global level: + +```javascript +params: { + onData: function(data, metadata){ + var hasUserCentricData = metadata.user; + var dataSource = metadata.source; + console.log('onData', data, hasUserCentricData, dataSource); + } +} +``` + +an interesting example is to set GAM targeting in global level instead in slot level only for contextual data: + +```javascript +params: { + weboCtxConf: { + token: 'to-be-defined', + setPrebidTargeting: false, + onData: function(data, metadata){ + var googletag = googletag || {}; + googletag.cmd = googletag.cmd || []; + googletag.cmd.push(function () { + for(var key in data){ + googletag.pubads().setTargeting(key, data[key]); + } + }); + }, + } +} +``` + +### More configuration examples + +A more complete example can be found below. We can define default profiles, for each section, to be used in case of no data are found. + +We can control if we will set prebid targeting or send data to bidders in a global level or on each section (`contextual`, `wam` or `lite`). + +By default we try to send the data to all destinations, always. To restrict we can have two choices: + +* Set `setPrebidTargeting` or `sendToBidders` explicity to `true` or `false` on each section; +* Set `setPrebidTargeting` or `sendToBidders` globally to `false` and only enable on the right sections; + +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; @@ -43,23 +379,159 @@ pbjs.que.push(function () { name: "weborama", waitForIt: true, params: { - // you should choose activate the site-centric and/or the user-centric data management below: weboCtxConf: { - token: "to-be-defined", // mandatory to use the contextual api + token: "<>", // mandatory + targetURL: "https://example.org", // default is document.URL + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + sendToBidders: true, // override param.sendToBidders. default is true + defaultProfile: { // optional, used if nothing is found + webo_ctx: [ ... ], // contextual segments + webo_ds: [ ...], // data science segments + }, + enabled: true, + }, + weboUserDataConf: { + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + sendToBidders: true, // override param.sendToBidders. default is true + defaultProfile: { // optional, used if nothing is found + webo_cs: [...], // wam custom segments + webo_audiences: [...], // wam audiences + }, + enabled: true, + }, + sfbxLiteDataConf: { + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + sendToBidders: true, // override param.sendToBidders. default is true + defaultProfile: { // optional, used if nothing is found + /* add specific lite segments here */ + }, + enabled: true, }, - weboUserDataConf: { - accountId: 12345, // recommended to use the site-centric profile - } } }] } }); }); +``` + +An alternative version, using asset id instead of target url on contextual, can be found here: + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; +pbjs.que.push(function () { + pbjs.setConfig({ + debug: true, + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + weboCtxConf: { + token: "<>", // mandatory + assetID: "datasource:docId", // can be a callback to be executed in runtime and returns the identifier + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + sendToBidders: true, // override param.sendToBidders. default is true + defaultProfile: { // optional, used if nothing is found + webo_ctx: [ ... ], // contextual segments + webo_ds: [ ...], // data science segments + }, + enabled: true, + }, + ... + }); +}); ``` -More complete configuration +Imagine we need to configure the following options using the previous example, we can write the configuration like the one below. + +{: .table .table-bordered .table-striped } +||contextual|wam|lite| +| :------------ | :------------ | :------------ |:------------ | +|setPrebidTargeting|true|false|true| +|sendToBidders|false|true|true| + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function () { + pbjs.setConfig({ + debug: true, + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + setPrebidTargeting: false, // optional. set the default value of each section. + sendToBidders: false, // optional. set the default value of each section. + weboCtxConf: { + token: "<>", // mandatory + targetURL: "https://example.org", // default is document.URL + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + enabled: true, + }, + weboUserDataConf: { + sendToBidders: true, // override param.sendToBidders. default is true + enabled: true, + }, + sfbxLiteDataConf: { + setPrebidTargeting: true, // override param.setPrebidTargeting. default is true + sendToBidders: true, // override param.sendToBidders. default is true + enabled: true, + }, + } + }] + } + }); +}); ``` + +We can also define a list of adunits / bidders that will receive data instead of using boolean values. + +```javascript +var pbjs = pbjs || {}; +pbjs.que = pbjs.que || []; + +pbjs.que.push(function () { + pbjs.setConfig({ + debug: true, + realTimeData: { + auctionDelay: 1000, + dataProviders: [{ + name: "weborama", + waitForIt: true, + params: { + weboCtxConf: { + token: "to-be-defined", // mandatory + setPrebidTargeting: ['adUnitCode1',...], // set target only on certain adunits + sendToBidders: ['appnexus',...], // overide, send to only some bidders + enabled: true, + }, + weboUserDataConf: { + accountId: 12345, // recommended + setPrebidTargeting: ['adUnitCode2',...], // set target only on certain adunits + sendToBidders: ['rubicon',...], // overide, send to only some bidders + enabled: true, + }, + sfbxLiteDataConf: { + setPrebidTargeting: ['adUnitCode3',...], // set target only on certain adunits + sendToBidders: ['smartadserver',...], // overide, send to only some bidders + enabled: true, + } + } + }] + } + }); +}); +``` + +Finally, we can combine several styles in the same configuration if needed. Including the callback style. + +```javascript var pbjs = pbjs || {}; pbjs.que = pbjs.que || []; @@ -74,30 +546,55 @@ pbjs.que.push(function () { params: { setPrebidTargeting: true, // optional sendToBidders: true, // optional - onData: function(data, site){ // optional - var kind = (site)? 'site' : 'user'; - console.log('onData', kind, data); + onData: function(data, meta){ // optional + var userCentricData = meta.user; // maybe undefined + var sourceOfData = meta.source; // contextual, wam or lite + + var isDefault = meta.isDefault; // true if uses default profile + + console.log('onData', data, meta); }, weboCtxConf: { token: "to-be-defined", // mandatory targetURL: "https://prebid.org", // default is document.URL setPrebidTargeting: true, // override param.setPrebidTargeting or default true - sendToBidders: true, // override param.sendToBidders or default true + sendToBidders: ['appnexus',...], // overide, send to only some bidders defaultProfile: { // optional webo_ctx: ['moon'], webo_ds: ['bar'] - } + }, + enabled: true, //, onData: function (data, ...) { ...} }, weboUserDataConf: { - accountId: 12345, // optional, used for logging - setPrebidTargeting: true, // override param.setPrebidTargeting or default true - sendToBidders: true, // override param.sendToBidders or default true - defaultProfile: { // optional + accountId: 12345, // recommended + setPrebidTargeting: ['adUnitCode1',...], // set target only on certain adunits + sendToBidders: { // send to only some bidders and adunits + 'appnexus': true, // all adunits for appnexus + 'pubmatic': ['adUnitCode1',...] // some adunits for pubmatic + // other bidders will be ignored + }, + defaultProfile: { // optional webo_cs: ['Red'], webo_audiences: ['bam'] }, - localStorageProfileKey: 'webo_wam2gam_entry' // default + localStorageProfileKey: 'webo_wam2gam_entry', // default + enabled: true, + //, onData: function (data, ...) { ...} + }, + sfbxLiteDataConf: { + setPrebidTargeting: function(adUnitCode){ // specify set target via callback + return adUnitCode == 'adUnitCode1'; + }, + sendToBidders: function(bid, adUnitCode){ // specify sendToBidders via callback + return bid.bidder == 'appnexus' && adUnitCode == 'adUnitCode1'; + } + defaultProfile: { // optional + lite_occupation: ['gérant', 'bénévole'], + lite_hobbies: ['sport', 'cinéma'], + }, + localStorageProfileKey: '_lite', // default + enabled: true, //, onData: function (data, ...) { ...} } } @@ -107,52 +604,13 @@ pbjs.que.push(function () { }); ``` -### Parameter Descriptions for the Weborama Configuration Section - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| name | String | Real time data module name | Mandatory. Always 'Weborama' | -| waitForIt | Boolean | Mandatory. Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false but recommended to true | -| params | Object | | Optional | -| params.setPrebidTargeting | Boolean | If true, may use the profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | -| params.sendToBidders | Boolean | If true, may send the profile to all bidders | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | -| params.onData | Callback | If set, will receive the profile and site flag | Optional. Affects the `weboCtxConf` and `weboUserDataConf` sections | -| params.weboCtxConf | Object | Weborama Contextual Configuration | Optional -| params.weboUserDataConf | Object | Weborama User-Centric Configuration | Optional | - -#### Contextual Configuration - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| token | String | Security Token provided by Weborama, unique per client | Mandatory | -| targetURL | String | Url to be profiled in the contextual api | Optional. Defaults to `document.URL` | -| setPrebidTargeting|Boolean|If true, will use the contextual profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.| -| sendToBidders|Boolean|If true, will send the contextual profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.| -| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | -| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | -| enabled | Boolean| if false, will ignore this configuration| default true| - -#### User-Centric Configuration - -| Name |Type | Description | Notes | -| :------------ | :------------ | :------------ |:------------ | -| accountId|Number|WAM account id. If present, will be used on logging and statistics| Optional.| -| setPrebidTargeting|Boolean|If true, will use the user profile to set the prebid (GPT/GAM or AST) targeting of all adunits managed by prebid.js| Optional. Default is `params.setPrebidTargeting` (if any) or **true**.| -| sendToBidders|Boolean|If true, will send the user profile to all bidders| Optional. Default is `params.sendToBidders` (if any) or **true**.| -| defaultProfile | Object | default value of the profile to be used when there are no response from contextual api (such as timeout)| Optional. Default is `{}` | -| localStorageProfileKey| String | can be used to customize the local storage key | Optional | -| onData | Callback | If set, will receive the profile and site flag | Optional. Default is `params.onData` (if any) or log via prebid debug | -| enabled | Boolean| if false, will ignore this configuration| default true| - ### Supported Bidders -We currently support the following bidder adapters: -* SmartADServer SSP -* PubMatic SSP +We currently support the following bidder adapters with dedicated code: + * AppNexus SSP -* Rubicon SSP -We also set the bidder and global ortb2 `site` and `user` sections. The following bidders may support it, to be sure, check the `First Party Data Support` on the feature list for the particular bidder from here: https://docs.prebid.org/dev-docs/bidders +We also set the bidder (and global, if no specific bidders are set on `sendToBidders`) ortb2 `site.ext.data` and `user.ext.data` sections (as arbitrary data). The following bidders may support it, to be sure, check the `First Party Data Support` on the feature list for the particular bidder from [here](https://docs.prebid.org/dev-docs/bidders). * Adagio * AdformOpenRTB @@ -175,8 +633,11 @@ We also set the bidder and global ortb2 `site` and `user` sections. The followin * Opt Out Advertising * Ozone Project * Proxistore +* PubMatic SSP * Rise +* Rubicon SSP * Smaato +* Smart ADServer SSP * Sonobi * TheMediaGrid * TripleLift diff --git a/dev-docs/modules/yieldmoSyntheticInventoryModule.md b/dev-docs/modules/yieldmoSyntheticInventoryModule.md index 5b49276bd3..5115eb53c9 100644 --- a/dev-docs/modules/yieldmoSyntheticInventoryModule.md +++ b/dev-docs/modules/yieldmoSyntheticInventoryModule.md @@ -22,7 +22,7 @@ If publishers will enable this module and provide placementId and Google Ad Mana Build the Yieldmo Synthetic Inventory Module into the Prebid.js package with: -``` +```bash gulp build --modules=yieldmoSyntheticInventoryModule,... ``` @@ -64,7 +64,7 @@ googletag.defineSlot('/1234567/ad_unit_name_used_in_gam', [1, 1], 'ad-container- ### How to get Yieldmo placement id -Please reach out to your Yieldmo account's person or email to support@yieldmo.com +Please reach out to your Yieldmo account's person or email to ### Google Ad Manager setup @@ -73,8 +73,9 @@ Yieldmo Synthetic Inventory Module is designed to be used along with Google Ad M - Ad unit size should be 1x1 - Creative should NOT be served into a SafeFrame and also should have 1x1 size - Synthetic Inventory Universal Tag should be used as 3rd party creative code + ### Synthetic Inventory Universal Tag -```js +```html
      ``` diff --git a/dev-docs/modules/zeusPrimeRtdProvider.md b/dev-docs/modules/zeusPrimeRtdProvider.md new file mode 100644 index 0000000000..338bcee32a --- /dev/null +++ b/dev-docs/modules/zeusPrimeRtdProvider.md @@ -0,0 +1,72 @@ +--- +layout: page_v2 +title: Zeus Prime Real Time Data Provider +display_name: Zeus Prime RTD +description: Zeus Prime Real Time Data Module +page_type: module +module_code: zeusPrimeRtdProvider +module_type: rtd +enable_download: false +vendor_specific: true +sidebarType: 1 +--- + +# Zeus Prime Real Time Data Module + +# NOTE: ZEUS PRIME HAS BEEN DEPRECATED + +# THIS MODULE NO LONGER FUNCTIONS AND WILL BE REMOVED FROM A + +# FUTURE VERSION OF PREBID + +The Zeus Prime RTD Provider provides integration of Zeus Prime onto sites with Prebid. This module will request information from Zeus Prime servers to add the page level targeting required for Prime into the customer's ad setup. + +Zeus Prime runs as soon as the code is initialized, so it can retrieve the information required from the Zeus Prime server to create the targeting key-values. Zeus Prime will provide two page level key-values: `zeus_` and `zeus_insights`. Zeus Prime provides contextual information about a pages content, and does not provide user information that could present privacy implications. + +For more information and help with setting up Zeus Prime, see the [onboarding documentation site](https://zeustechnology.com). + +## Usage + +To use Zeus Prime, add `zeusPrimeRtdProvider` into your Prebid build: + +```bash +gulp build --modules=rtdModule,zeusPrimeRtdProvider +``` + +> Note that the global RTD module, `rtdModule`, is required for the Zeus Prime RTD module. + +Once the code is included, configure Zeus Prime in your Prebid configuration: + +```javascript +pbjs.setConfig({ + ..., + realTimeData: { + dataProviders: [{ + name: 'zeusPrime', + params: { + gamId: '' + } + }] + }, + ... +}) +``` + +## Parameters + +The parameters below describe the configuration object used to configure Zeus Prime. + +| Name | Type | Description | Notes | +| ------------ | ------- | ----------------------------------------------------------------------- | --------- | +| name | String | This will always be `zeusPrime` | - | +| waitForIt | Boolean | Should the auction delay until Zeus Prime completes. (optional) | Defaults to `false`. | +| params | Object | | - | +| params.gamId | String | The gamId or Google Ad Manager Network Code. | - | + +### `gamId` Parameter + +Zeus Prime requires the gamId parameter, or the Google Ad Manager Network Code, to reference your account. See the [Google documentation](https://support.google.com/admanager/answer/7674889?hl=en) to find out where you can retrieve the Network Code. + +## Troubleshooting + +For troubleshooting steps and guides to assist with verifying your Zeus Prime installation, see our [installation documentation](https://zeustechnology.com/docs/installation). diff --git a/dev-docs/pb7-notes.md b/dev-docs/pb7-notes.md new file mode 100644 index 0000000000..981ce9e4c7 --- /dev/null +++ b/dev-docs/pb7-notes.md @@ -0,0 +1,81 @@ +--- +layout: page_v2 +title: Prebid 7.0 Release Notes & Publisher API Changes +description: Description of the breaking changes included for Prebid 7.0 +sidebarType: 1 +--- + +# Prebid 7.0 Bidder Interface and Publisher API Changes + +{:.no_toc} + +This document describes the changes included for Prebid.js version 7.0. + +* TOC +{:toc} + +## Publisher Summary + +1. Be aware that a number of modules have been removed. See below for the list. +2. setConfig of 'publisherDomain' is no longer supported. Use setConfig({pageUrl: "URL"}) instead. +3. setConfig of 'fpd' is no longer supported. Use setConfig({ortb2: ...}) instead. +4. Please ensure your Prebid Server provider is running a relatively recent version of Prebid Server. Prebid.js 7 will not work with PBS-Go before 0.66 or PBS-Java before 1.55. + +Details on all of these below. + +## Removed Modules + +The following modules have been removed from Prebid.js as part of the 7.0 release. Publishers building with one of them will need to point to its replacement or remove the module from their build. + +{: .table .table-bordered .table-striped } + +| Module | Replacement | +|:-----------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| AdLive Bid Adapter +| Akamai ID Submodule | rearchitected to use RTD module +| AppNexus Analytics Adapter +| DistrictM DMX Bid Adapter | replaced by Sharethrough +| FLOC ID submodule +| Halo ID & RTD submodules | replaced by Hadron +| NextRoll ID submodule +| OneVideo Bid Adapter | replaced by YahooSSP +| Sortable Adapters +| TrustX Bid Adapter | now an alias of Grid +| UserId Targeting Module + +## Adapter Interface + +Following the precedent of Prebid 5, bidders must read additional values from the ad unit, global config, or the ortb2 object. Bidders may still take these values as parameters, but must also support the Prebid conventions; publishers do not want to set these values multiple times, one for each bid parter. Publishers can now rely on certain parameters no longer needing to be set in bidder configuration, including (a) the instl flag on an ad unit, (b) the position parameter, and (c) the banned categories (bcats). Bidders should consider that if they are accepting any openrtb field in their configuration, they should also check the ortb2 object for that parameter. + +In the Prebid 5 release notes, it was noted that publishers should no longer use publisherDomain as a setConfig parameter, and instead prefer PageURL. Adapters no longer read from this location. Also, the object presented to bidders with the page url and that page's referring page url has been re-implemented. Our goal was that adapters can rely on ortb2.site.page and ortb2.site.ref, with flags for when top is not reached, the canonical link is used, setConfig('pageUrl') is used, or when window.location.href is used for ortb2.site.page. Many bidders had disparate logic for this and the refererInfo.referer had different meanings in different contexts. + +Also, Bid Adapters (not other types of modules) no longer have access to the storage manager unless explicitly allowed by the publisher. We believe bidding functionality should rarely (if ever) need this access and that this extra functionality included in bid adapters must be consented to by the installer in their configuration. The following bid adapters' unit tests were affected by this change: Adagio, Adnuntius, AP Stream, Concert, Conversant, Craft, Criteo, E-Planning, Invibes, Kargo, Quantcast, Trion, Unicorn, and Vidazoo. Adapters simply setting a random identifier in the first party local storage or cookie should consider if the popular shared id user id submodule can fully achieve this functionality for them. See storageAllowed in the [BidderSettings Reference](/dev-docs/publisher-api-reference/bidderSettings.html#2-bidder-setting-attributes) + +Adapters are no longer allowed to return alternate bidder codes unless allowed by the publisher. See allowAlternateBidderCodes in the [BidderSettings Reference](/dev-docs/publisher-api-reference/bidderSettings.html#2-bidder-setting-attributes). + +Finally, adapters known to use HTTP-1 bidding endpoints may now have notices appended to their documentation. + +## Regulatory and Consent Strings + +TCF1 is no longer supported by the Consent Management (GDPR) module. The Consent Management USP module now defaults to framework 'iab' and will work without configuration if installed and a functioning `__uspapi()` exists on the page. + +## First Party Data + +Support has been removed for `setConfig('fpd')`, `config.getLegacyFpd`, `config.convertAdUnitFpd` and related relics of legacy first party data. Publishers should use the methods described in [First Party Data]({{site.baseurl}}/features/firstPartyData.html). + +First party data can also now be set on a specific auction. This is useful for example on infinite scroll pages when contextual segments change, or when the publisher wishes to express the context of an instream video ad but not the display advertising. As part of this change the ortb2 object is now made a part of bid requests, instead of necesitating a getConfig call by an adapter. This has led to slight changes in many dozens of bid adapters and substantial changes to all of the RTD adapters. + +## Prebid Server Adapter + +An undocumented feature "Stored Auction Response" has been deprecated. + +The Prebid Server committee moved the ortb2 location of bidder parameters from `imp[].ext.BIDDER` to `imp[].ext.prebid.bidder.BIDDER`. PBS versions before PBS-Go 0.66 (April 2019) and PBS-Java 1.55 (Feb 2021) are not compatible with Prebid 7+. + +## Build changes + +In later 6.x versions, an improvement in the build process introduced some undesirable behavior for users loading the library twice on the same pageview to the same global library name. If you load Prebid.js twice on a page using the same global, the second load is now prevented. + +## Further Reading + +* [Publisher API Reference](/dev-docs/publisher-api-reference.html) +* [First Party Data](/features/firstPartyData.html) diff --git a/dev-docs/pb8-notes.md b/dev-docs/pb8-notes.md new file mode 100644 index 0000000000..b227eace4d --- /dev/null +++ b/dev-docs/pb8-notes.md @@ -0,0 +1,87 @@ +--- +layout: page_v2 +title: Prebid.js 8.0 Release Notes & Publisher API Changes +description: Description of the breaking changes included for Prebid.js 8.0 +sidebarType: 1 +--- + +# Prebid.js 8.0 Bidder Interface and Publisher API Changes + +{:.no_toc} + +This document describes the changes included for Prebid.js version 8.0. + +* TOC +{:toc} + +## Publisher Summary + +1. Be aware that a number of modules have been removed. See below for the list. +2. Transaction identifiers are reliable but opt in. +3. Size Mapping has been pulled into its own module +4. Activity control interface defines behavior suppression, including RTD, Geo, and TIDs + +Details on all of these below. + +## Removed Modules + +The following modules have been removed from Prebid.js as part of the 8.0 release. Publishers building with one of them will need to point to its replacement or remove the module from their build. + +{: .table .table-bordered .table-striped } +| Module | Replacement | +|:-----------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Google Analytics Adapter | Recommend publishers explore the Generic Analytics Adapter +| Inmar Bid Adapter +| Inskin Bid Adapter +| MASS Deal Rendering Module | Replaced by (documentation) +| AOL Bid Adapter | Reach out to Yahoo +| CPEX ID submodule | CzechAdId Module +| PubcommonID module | SharedID Userid Submodule +| OpenX Analytics module +| Zeus Prime Module +| Captify RTD module | pending integration updates +| Realvu Analytics module | pending integration updates +| TrustPID userid submodule | Utiq userid submodule +| OpenX ORTB Bid Adapter | OpenX Bid Adapter +| Synacor Bid Adapter | IMDS Bid Adapter +| AdGeneration Bid Adapter +| EMX Bid Adapter | Cadent Aperture MX Bid Adapter +| Rubicon Analytics Adapter | Magnite Analytics Adapter + +## Transaction identifiers are now reliable and opt in + +Following the [OpenRTB 2.6 spec](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md) and the [imp.ext.tid](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/per-imp-tids.md) community extensions, several fields in Prebid have equivalents in OpenRTB. + +* $.id, the top level id, is now unique to each bid request. It may come from a bidder `getUUID` call or from the `bidderRequestId`. +* $.imp.ext.tid is the same for each bidder and differs for each slot in the auction. It is the request object `transactionId`. It can be set by the publisher to sync with other header bidding libraries on the page. +* $.source.tid is the same for each bidder and differs for each auction. We understand from buyer platform members that it is losing utility in favor of `imp.ext.tid`. It is the request object `auctionId`. It can be set by the publisher to sync with other header bidding libraries on the page. +* $.source.schain.nodes[0].rid is not generated by the Prebid.js core library nor the schain module and may vary unexpectedly. + +These identifiers are extremely powerful for discrepancy reconciliation, ad quality investigations, consent audits, and a huge range of other applications. They also allow data appended to different requests (eg dealIds) to be commingled downstream. For this reason, our publisher committee and Prebid.org counsel have decided to require publisher opt-in to their inclusion in the bid stream. This means Prebid engineering changed every openrtb request in the project to potentially transmit a null in these fields. Comments were added to bid adapters not using OpenRTB that send them over the wire to confirm they can accept null values. Publishers can use `pbjs.setConfig({enableTIDs: true})` to opt-in. + +## Activity Controls + +[Activity controls](/dev-docs/activity-controls.html) were very recently released, and are even more powerful in Prebid.js 8. `transmitTid` is a new control added. + +Also, in order to allow publishers to better comply with regulations around precise location, bid adapters must read location from the global, not from their own parameters. + +RTD Modules were also updated to require that they do not have bidder specific handling, and that all their bid enrichment data is routed through the global. This will make those enrichments subject to the data controller module settings as well as activity controls. + +Several activity control translation modules will be released in the near future, translating consent strings into suppressed behaviors and restricted information in the library. Your contributions on these modules and feedback are very welcome. + +Additionally, bidder aliases should now have their own gvl id if a user has the consent management module. + +## Size Mapping + +Users of the [label](/dev-docs/conditional-ad-units.html) feature should be careful to examine the new size mapping module. We moved it out of core to improve the build size. See [github.com/prebid/Prebid.js/issue/9597](https://github.com/prebid/Prebid.js/issues/9597) + +## Misc changes + +* `auctionInit` event payload is now less bloated. See [github.com/prebid/Prebid.js/pull/9897](https://github.com/prebid/Prebid.js/pull/9897) +* Bidder `categoryTranslation` is no longer in core. See [github.com/prebid/Prebid.js/pull/9898](https://github.com/prebid/Prebid.js/pull/9898) +* `bidderCode` can no longer come from the bid response, as this was breaking aliasing. See [github.com/prebid/Prebid.js/pull/9905](https://github.com/prebid/Prebid.js/pull/9905) +* `onBidWon` was often listened to by client side bid adapters and would get fired when a server side bid was won. This has been cleaned up. See [github.com/prebid/Prebid.js/pull/9919](https://github.com/prebid/Prebid.js/pull/9919) +* `ext.prebid.floorMin` has been dropped in favor of `ext.prebid.floors.floorMin` as a parameter on the PBS Bid adapter call See [github.com/prebid/Prebid.js/pull/9899](https://github.com/prebid/Prebid.js/pull/9899) +* `bidResponse` is emitted immediately after adding the bidResponse instead of immediately before. See [github.com/prebid/Prebid.js/pull/9847](https://github.com/prebid/Prebid.js/pull/9847) +* PBS bid adapter now supports native javascript trackers. See [github.com/prebid/Prebid.js/pull/9900](https://github.com/prebid/Prebid.js/pull/9900) +* `NO_BID` events no longer occur on bid rejections and zero-cpm bids. See [github.com/prebid/Prebid.js/pull/9902](https://github.com/prebid/Prebid.js/pull/9902) diff --git a/dev-docs/pbs-bidders.md b/dev-docs/pbs-bidders.md index d9b5ccee80..cbc289e03b 100644 --- a/dev-docs/pbs-bidders.md +++ b/dev-docs/pbs-bidders.md @@ -15,14 +15,16 @@ For each bidder listed below, you'll find the following information: {: .table .table-bordered .table-striped } | **Features** | A table of features supported by the adapter. | -| **"Send All Bids" Ad Server Keys** | Used for sending all bids to the ad server, as described in [Send All Bids to the Ad Server](/adops/send-all-bids-adops.html) | +| **"Send All Bids" Ad Server Keys** | Used for sending all bids to the ad server, as described in [Send All Bids vs Send Top Price](/adops/send-all-vs-top-price.html) | | **Bid Params** | Ad request parameters required by a given bidder, such as the tag ID, site ID, or query string parameters | You can also download the full CSV data file. - {% assign bidder_pages = site.pages | where: "layout", "bidder" | where: "pbs", true %} +{: .alert.alert-warning :} +Publishers are advised to check with legal counsel before doing business with any particular bidder. + ## Prebid Server Bidder List
        @@ -43,16 +45,7 @@ You can also download the full CSV

        Features

        -{: .table .table-bordered .table-striped } -| **Bidder Code** | {{ page.biddercode }} | **Prebid.org Member** | {% if page.prebid_member == true %}yes{% else %}no{% endif %} | -| **Media Types** | {% unless page.media_types contains 'no-display' %}display{% endunless %}{% if page.media_types contains 'video' %},{% endif %}{% if page.media_types contains 'video' %} video{% endif %}{% if page.media_types != "no-display, native" and page.media_types contains 'native' %}, native{% endif %}{% if page.media_types == "no-display, native" %}native{% endif %} | **GDPR TCF Support** | {% if page.gdpr_supported == true %}yes{% else %}no{% endif %} | -| **User IDs** | {% if page.userIds and page.userIds != '' %}{{page.userIds}}{% else %}none{% endif %} | **USP/CCPA Support** | {% if page.usp_supported == true %}yes{% else %}no{% endif %} | -| **Supply Chain Support** | {% if page.schain_supported == true %}yes{% else %}no{% endif %} | **COPPA Support** | {% if page.coppa_supported == true %}yes{% else %}no{% endif %} | -| **Demand Chain Support** | {% if page.dchain_supported == true %}yes{% else %}no{% endif %} | **Safeframes OK** | {% if page.safeframes_ok and page.safeframes_ok == false %}no{% elsif page.safeframes_ok and page.safeframes_ok == true %}yes{% else %}check with bidder{% endif %} | -| **Supports Deals** | {% if page.deals_supported and page.deals_supported == false %}no{% else %}yes{% endif %} | **Prebid.js Adapter** | {% if page.pbjs == true %}yes{% else %}no{% endif %} | -| **Mobile App Support** | {% if page.pbs_app_supported and page.pbs_app_supported == false %}no{% elsif page.pbs_app_supported and page.pbs_app_supported == true %}yes{% else %}check with bidder{% endif %} | **Prebid Server Adapter** | yes | -| **Floors Support** | {% if page.floors_supported == false %}no{% elsif page.floors_supported == true %}yes{% else %}check with bidder{% endif %} | **First Party Data Support** | {% if page.fpd_supported == true %}yes{% elsif page.fpd_supported == false %}no{% else %}check with bidder{% endif %} | - +{% include dev-docs/bidder-meta-data.html page=page %}

        "Send All Bids" Ad Server Keys

        diff --git a/dev-docs/pbsBidAdapter-video-overview.md b/dev-docs/pbsBidAdapter-video-overview.md new file mode 100644 index 0000000000..20e7096ab1 --- /dev/null +++ b/dev-docs/pbsBidAdapter-video-overview.md @@ -0,0 +1,110 @@ +--- +layout: page_v2 +title: Video Intro to Server-Side Header Bidding with Prebid.js +description: Video Intro to Server-Side Header Bidding with Prebid.js +sidebarType: 1 +--- + +# Server-Side Header Bidding with Prebid.js + +An introduction to using server-to-server header bidding with Prebid.js on websites. + +
        + +

        +Notes: + +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) +- [Prebid Managed Services](https://prebid.org/managed-services/) +- [Header Bidding with Prebid](/overview/intro.html) + +Related Videos: + +- [Introduction to Prebid.js](/prebid/prebidjs-video.html) +- [Prebid.js Impression Flow](/prebid/prebidjs-flow-video.html) +- [Components of Prebid.js](/prebid/prebidjs-components-video.html) +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview-video.html) +- [All Videos](/overview/all-videos.html) + +## Transcript + +### Introduction + +This video is for publishers interested in setting up server-side header bidding on websites running Prebid.js. + +In this video, we’ll start by discussing what server-side header bidding is and why you might want to try it. Next, we’ll give an overview of how it works in a typical Prebid.js auction, then give you an introduction on how to get started. + +Note that Prebid Server is a flexible product that is used in many types of Prebid integrations, including mobile app, long form video, and digital out-of-home. This video will focus specifically on the use of Prebid Server to monetize a website using Prebid.js. + +For information on how Prebid Server helps monetize mobile apps, check out our video on the subject. You can find the link in the notes below. + +This video assumes that you know how a typical Prebid.js auction works with client-side bidders. For an overview, check out our other videos on Prebid.js. You can find the links to these videos in the video description below. + +Server-side header bidding is all about how bidders connect to Prebid.js. + +Unlike client-side header bidding, in which there is a direct connection between the browser and a bidder’s server, server-side header bidding adds an intermediary into the path. This intermediary is Prebid Server. When it’s time to run a header bidding auction, Prebid.js makes a request to Prebid Server, which communicates with bidders over a server-to-server connection. + +Publishers that use Prebid.js have the flexibility to use client-side connections, server-side connections, or a mixture of the two. It’s common for publishers to set up auctions that contain a mix of client-side and server-side bidders. + +Server-side header bidding is one of the many techniques publishers can use to maximize the performance of their Prebid.js auctions. It does so chiefly by reducing the workload that the Prebid auction places on the user’s device, because Prebid Server takes over some of the work of managing bidder connections and processing bid responses. Sharing labor between the user device and a server could help to deliver better ad experiences to users or allow you to increase revenue by adding new bidders. + +Despite the benefits, most publishers have not migrated all of their bidders to server-side header bidding. This is because client-side bidders are more able to set and access third-party cookies that server-side bidders. This means that running a bidder through server-side header bidding will often cause the bidder to bid less often or at lower CPMs compared to a client-side integration. + +The good news is that you don’t have to commit entirely to using server-side auctions. Most publishers who use server-side header bidding employ a hybrid approach, in which some bidders bid directly into Prebid.js through client-side bid adapters, while others bid through the server-side path. + +The hybrid approach allows you to increase competition for your ad impressions by adding more bidders to the auction, without burdening the browser with the task of processing additional client-side bidders. + +Most publishers who use a hybrid approach give their highest-value bidders client-side connections to Prebid.js. These are the bidders that deliver the most revenue. Meanwhile, lower priority bidders and bidders who are being tested can be run server-side. + +### Prebid Server Auction Flow + +Next, we’ll explain how server-side header bidding works. + +Like any Prebid.js auction, auctions that include server-side bidding have three stages: Pre-Auction, Auction and Post-Auction. + +Server-side header bidding largely affects the Auction stage, because it has to do with how Prebid.js communicates with bidders. Some other tasks like user syncing are also influenced by the bidder connection type. We’ll touch on these at the end of this video. +When you set up Prebid.js for server-side header bidding, you’ll indicate which bidders you want to bid through the server-side path. All other bidders will use the standard client-side method. + +This example has one client-side bidder and two server-side bidders. When Prebid.js makes bid requests, it will make a direct request to the client-side bidder’s server, and it will use the Prebid Server bid adapter to make a request to a server that is running Prebid Server. + +Prebid Server receives the request and begins its own internal Pre-Auction phase. It gathers information about the page and user and prepares to make bid requests to bidders. + +Prebid Server will then make bid requests to the server-side bidders’ servers, then Prebid Server gathers the responses and returns them to Prebid.js. + +Separately, any client-side bidders that have been set up will also return their responses to Prebid.js. + +Having concluded the auction, Prebid.js’s Post Auction stage begins. Prebid.js will process bids and create ad server targeting key-value pairs. The ad server is called, and the ad renders. + +### Getting Started with Server-Side Header Bidding + +Now, let’s talk about how you can start using server-to-server header bidding with Prebid.js. + +The first component to discuss is the server. To use the Prebid.js server-to-server solution, you’ll need a server running the Prebid Server code. You can set this up yourself, or use someone else’s. + +The Prebid community includes many managed service providers that specialize in operating Prebid Server. + +These managed services will take care of running a global, high scale low-latency, 24x7 tier of servers, keep them upgraded, and manage the server-side bidders. + +Links to more information about Prebid Server Managed Services and to instructions on Prebid Server setup and installation can be found in the notes below this video. + +Once you’re set up and running Prebid Server, you’ll configure the parameters of your setup in the Prebid.js configuration. + +You can find the documentation for server-to-server header bidding at docs.prebid.org. The link to this document can be found in the notes below. The server-to-server configuration allows you to choose which bidders will bid through the server-side path. You can also set the timeout duration that sets the auction time for Prebid Server bids. This is an important setting, because it controls how quickly Prebid Server responds to Prebid.js. + +Because Prebid Server’s auction occurs within the Prebid.js timeout window, it’s important to make sure that Prebid Server responds to Prebid.js in a timely fashion. + +If Prebid Server fails to respond to Prebid.js before the Prebid.js bid timeout, then all of the Prebid Server bids will be lost. + +A good rule of thumb is to set your Prebid Server timeout 200 to 300 milliseconds less than the Prebid.js bid timeout. This gives Prebid Server bidders enough time to respond while leaving a healthy cushion for signals to flow between Prebid.js and Prebid Server. + +The endpoint parameter tells Prebid.js the location of the server that is running Prebid Server. + +There are also user sync settings that allow you to configure how Prebid Server performs user syncs for server-side bidders. Prebid Server will store cookies under the publisher’s domain on behalf of bidders. When an auction runs, it retrieves the stored cookies so that bidders are able to value the impression more effectively. + +Once you’ve got bidders set up in Prebid Server, you can start to test the performance. It’s a good idea to start testing in a development or staging environment, then move on to limited testing on production traffic. + +With Prebid’s Server-to-Server Testing Module, you can set up A/B tests that help you measure the influence that server-to-server header bidding has on your header bidding performance. + +The testing module has powerful features that allow you to set the proportion of a bidder’s bid requests that flow through the client and server paths. This proportion can even be set at the ad unit level for specific scenarios. + +That’s it for this walkthrough of server-to-server header bidding in Prebid.js. Check the links in the notes below this video for more information. diff --git a/dev-docs/plugins/bc/about-bc-prebid-plugin.md b/dev-docs/plugins/bc/about-bc-prebid-plugin.md index d82fd4648f..98f24954ca 100644 --- a/dev-docs/plugins/bc/about-bc-prebid-plugin.md +++ b/dev-docs/plugins/bc/about-bc-prebid-plugin.md @@ -19,105 +19,103 @@ The Brightcove Plugin for Prebid (BcPrebidVast) is a plugin to the Brightcove pl The Brightcove Prebid Plugin supports the following features: -- Several prebid styles, depending on how the prebid options are configured: - - No ad server is specified - - Google Ad Manager ad server is specified - - Publisher uses another preferred ad server - - Header bidding is conducted outside of the plugin - -- Video ad playback within a Brightcove player: - - Single Ad Playback via VAST XML at one or more ad break positions within a video. (For example, you can specify options for a preroll and a postroll ad in a single call to the plugin.) - - Versions up thru VAST 3.0 - - Both Video and VPAID creatives - - If the AppNexus Viewability Wrapper is delivered: - - AppNexus viewability measurement - - AppNexus domain detection - -- The plugin supports more than one ad renderer by default. - - If Google Ad Manager is detected as the primary ad server (indicated by the presence of dfpParameters) for *any* of the ad breaks specified in the Prebid options, then the Brightcove IMA Plugin will be used to render the ad. - - If Google Ad Manager is NOT detected as the primary ad server (indicated by the absence of dfpParameters) for *any* of the ad breaks specified in the Prebid options, then the MailOnline Plugin will be used to render the ad. - - Publishers can override this default behavior using the `adRenderer` option. Publishers can define this option only once in the set of Prebid config options. Additional specifications for this option will be ignored. - -- The plugin supports the use of one or more optional adapters. - - Adapters are a mechanism that a publisher can use to add some specific behavior at runtime to customize the behavior of the Prebid plugin. - - Adapters can be especially useful to modify the runtime behavior of the plugin when the plugin is configured with Brightcove Studio. - - Adapters are defined within the Prebid configuration parameters. See [Prebid Options]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-prebid-options.html#pb-adapters) for more details on how to specify the use of an adapter. - - See [How To Build An Adapter for Prebid Plugin]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-building-adapter.html) for details on how to build an adapter. - - -- Open source project +* Several prebid styles, depending on how the prebid options are configured: + * No ad server is specified + * Google Ad Manager ad server is specified + * Publisher uses another preferred ad server + * Header bidding is conducted outside of the plugin + +* Video ad playback within a Brightcove player: + * Single Ad Playback via VAST XML at one or more ad break positions within a video. (For example, you can specify options for a preroll and a postroll ad in a single call to the plugin.) + * Versions up thru VAST 3.0 + * Both Video and VPAID creatives + * If the AppNexus Viewability Wrapper is delivered: + * AppNexus viewability measurement + * AppNexus domain detection + +* The plugin supports more than one ad renderer by default. + * If Google Ad Manager is detected as the primary ad server (indicated by the presence of dfpParameters) for *any* of the ad breaks specified in the Prebid options, then the Brightcove IMA Plugin will be used to render the ad. + * If Google Ad Manager is NOT detected as the primary ad server (indicated by the absence of dfpParameters) for *any* of the ad breaks specified in the Prebid options, then the MailOnline Plugin will be used to render the ad. + * Publishers can override this default behavior using the `adRenderer` option. Publishers can define this option only once in the set of Prebid config options. Additional specifications for this option will be ignored. + +* The plugin supports the use of one or more optional adapters. + * Adapters are a mechanism that a publisher can use to add some specific behavior at runtime to customize the behavior of the Prebid plugin. + * Adapters can be especially useful to modify the runtime behavior of the plugin when the plugin is configured with Brightcove Studio. + * Adapters are defined within the Prebid configuration parameters. See [Prebid Options]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-prebid-options.html#pb-adapters) for more details on how to specify the use of an adapter. + * See [How To Build An Adapter for Prebid Plugin]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-building-adapter.html) for details on how to build an adapter. + +* Open source project If the MailOnline plugin is used to render the ads, the plugin will support the following UI features: -- Standard ad controls used for single ads: - - Ad Indicator with configurable text - - Optional skip button including countdown text with configurable text - - Ad pause and resume - - Fullscreen support -- Disabled scrubbing during ad playback -- Standard click-through support +* Standard ad controls used for single ads: + * Ad Indicator with configurable text + * Optional skip button including countdown text with configurable text + * Ad pause and resume + * Fullscreen support +* Disabled scrubbing during ad playback +* Standard click-through support If the Brightcove IMA Plugin is used to render the ad, then the UI features of the ad will be governed by the standard behavior of Google IMA. The plugin supports one or more of the following ad slot locations in a single video and/or in a player configured for playlisting: -- Preroll -- Midroll - - by time - - by percentage -- Postroll -- Ad Icons -- Playlisting Players - - This feature includes the ability to customize how often, by video clips, you want to display an ad during a playlist. - - Be default, the plugin will attempt to play an ad for every video in the playlist. - +* Preroll +* Midroll + * by time + * by percentage +* Postroll +* Ad Icons +* Playlisting Players + * This feature includes the ability to customize how often, by video clips, you want to display an ad during a playlist. + * Be default, the plugin will attempt to play an ad for every video in the playlist. ## Components BcPrebidVast is supported by the following components: -- **bc_prebid_vast** -- **bc_prebid_vast_plugin** -- **MailOnline Plugin** -- **Brightcove IMA Plugin** -- **CSS files** +* **bc_prebid_vast** +* **bc_prebid_vast_plugin** +* **MailOnline Plugin** +* **Brightcove IMA Plugin** +* **CSS files** ### bc_prebid_vast `bc_prebid_vast` is a loader script that loads in the full Prebid plugin. The loader was added to: -- make it easier to debug the plugin, particularly when the plugin is directly embedded into the Brightcove Player in the Studio -- remove the necessity to have to re-publish a Brightcove Player instance every time the code in the main plugin has been modified. The only time a player instance would need to be re-published is when the code in the loader itself changes. +* make it easier to debug the plugin, particularly when the plugin is directly embedded into the Brightcove Player in the Studio +* remove the necessity to have to re-publish a Brightcove Player instance every time the code in the main plugin has been modified. The only time a player instance would need to be re-published is when the code in the loader itself changes. You can think of the “plugin” as being a combination of the loader and the plugin code itself. However, when registering the Prebid plugin, either on page or in the Brightcove Studio, the URL to the loader should be used. This loader will then load in the main plugin script, either from the default location or from a custom location that may be specified in the Prebid options passed via the plugin configuration. -#### Minified Version +#### Minified Version (bc_prebid_vast) -- Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast.min.js` -- Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` - - after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast.min.js` +* Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast.min.js` +* Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` + * after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast.min.js` -#### Non-Minified Version +#### Non-Minified Version (bc_prebid_vast) -- Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast.js` -- Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` - - after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast.js` +* Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast.js` +* Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` + * after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast.js` ### bc_prebid_vast_plugin `bc_prebid_vast_plugin` is the main Brightcove plugin itself, which invokes the Prebid process and renders the selected video ad. This script is loaded by the Prebid plugin loader described above. -#### Minified Version +#### Minified Version (bc_prebid_vast_plugin) -- Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_plugin.min.js` -- Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` - - after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast_plugin.min.js` +* Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_plugin.min.js` +* Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` + * after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast_plugin.min.js` -#### Non-Minified Version +#### Non-Minified Version (bc_prebid_vast_plugin) -- Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_plugin.js` -- Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` - - after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast_plugin.js` +* Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_plugin.js` +* Repository location: `https://github.com/prebid/prebid-js-plugin-brightcove.git` + * after building: `./prebid-js-plugin-brightcove/dist/bc_prebid_vast_plugin.js` ### MailOnline Plugin @@ -133,16 +131,16 @@ This plugin includes modifications that can be found in the MailOnline repositor #### Minified Version -- Default location: `https://acdn.adnxs.com/video/plugins/mol/videojs_5.vast.vpaid.min.js` -- Repository location: `https://github.com/prebid/videojs-mailonline-plugin.git` - - after building: `./videojs-mailonline-plugin/dist/videojs_5.vast.vpaid.min.js` +* Default location: `https://acdn.adnxs.com/video/plugins/mol/videojs_5.vast.vpaid.min.js` +* Repository location: `https://github.com/prebid/videojs-mailonline-plugin.git` + * after building: `./videojs-mailonline-plugin/dist/videojs_5.vast.vpaid.min.js` #### Non-Minified Version -- Default location: `https://acdn.adnxs.com/video/plugins/mol/videojs_5.vast.vpaid.js` -- Debuggable Non-Minified Version: `https://acdn.adnxs.com/video/plugins/mol/debug/videojs_5.vast.vpaid.js` -- Repository location: `https://github.com/prebid/videojs-mailonline-plugin.git` - - after building: `./videojs-mailonline-plugin/dist/videojs_5.vast.vpaid.js` +* Default location: `https://acdn.adnxs.com/video/plugins/mol/videojs_5.vast.vpaid.js` +* Debuggable Non-Minified Version: `https://acdn.adnxs.com/video/plugins/mol/debug/videojs_5.vast.vpaid.js` +* Repository location: `https://github.com/prebid/videojs-mailonline-plugin.git` + * after building: `./videojs-mailonline-plugin/dist/videojs_5.vast.vpaid.js` ### Brightcove IMA Plugin @@ -164,41 +162,41 @@ If you will be using the Brightcove IMA plugin as the ad renderer, either becaus The plugin relies on one or two CSS files to control the ad playback, depending on which plugin is used to render the ad: -- Prebid plugin CSS: `bc_prebid_vast_vjs.css` -- MailOnline plugin CSS: `bc_vpaid_vast_mo.css` +* Prebid plugin CSS: `bc_prebid_vast_vjs.css` +* MailOnline plugin CSS: `bc_vpaid_vast_mo.css` #### Prebid Plugin CSS Defines CSS styles that are used directly by the plugin. -- Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_vjs.css` -- Repository location: `./prebid-js-plugin-brightcove/src/bc_prebid_vast_vjs.css` +* Default location: `https://acdn.adnxs.com/video/plugins/bc/prebid/bc_prebid_vast_vjs.css` +* Repository location: `./prebid-js-plugin-brightcove/src/bc_prebid_vast_vjs.css` #### MailOnline Plugin CSS Defines CSS styles that are used by the MailOnline Plugin. If you are using another renderer, you might need to include your own CSS file for that renderer. Also, if the Brightcove IMA Plugin is used to render the ad, then this CSS file is not used. -- Default location: `https://acdn.adnxs.com/video/plugins/css/mol/bc_vpaid_vast_mo.css` -- After building: `./videojs-mailonline-plugin/bin/bc_vpaid_vast_mo.css` +* Default location: `https://acdn.adnxs.com/video/plugins/css/mol/bc_vpaid_vast_mo.css` +* After building: `./videojs-mailonline-plugin/bin/bc_vpaid_vast_mo.css` ## Models Supported The plugin supports several styles of prebid processing: -- Google Ad Manager is the primary ad server - - Bids from defined bidders will be passed to Google Ad Manager - - Google Ad Manager will return the ad URL to play +* Google Ad Manager is the primary ad server + * Bids from defined bidders will be passed to Google Ad Manager + * Google Ad Manager will return the ad URL to play -- An ad server other than Google Ad Manager is the primary ad server - - Publishers will provide a callback that the plugin will use to pass the list of bids to consider to the publisher's code - - Publisher code and your preferred ad server will be responsible for determining which ad to play - - Publisher code will specify the selected ad when requesting playback of the ad by the plugin +* An ad server other than Google Ad Manager is the primary ad server + * Publishers will provide a callback that the plugin will use to pass the list of bids to consider to the publisher's code + * Publisher code and your preferred ad server will be responsible for determining which ad to play + * Publisher code will specify the selected ad when requesting playback of the ad by the plugin -- There is no main ad server - - Only the bidders defined in the ad unit will be considered - - Bids from the defined bidders will be collected by the plugin - - The plugin will pick the highest bid - - The plugin will then play the ad it selected +* There is no main ad server + * Only the bidders defined in the ad unit will be considered + * Bids from the defined bidders will be collected by the plugin + * The plugin will pick the highest bid + * The plugin will then play the ad it selected In addition, the publisher can run its own prebid code outside the of the plugin but use the plugin to render the ad in the Brightcove Player. @@ -206,13 +204,13 @@ In addition, the publisher can run its own prebid code outside the of the plugin For each ad break that will be shown in a video: -- The plugin will use the parameters passed to it to invoke prebid. -- If a primary ad server is being used to make the final decision, the prebid bidding results will be passed to the desired ad server. -- The response should provide a URL to a VAST creative or a VAST XML document that defines an ad to play. -- Upon completion of the prebid, the winning ad can then be played by the plugin at the specified time. -- By default, the prebid plugin implicitly invokes the default MailOnline plugin to render the ad. -- If a valid VAST creative is not returned or if the prebid process does not complete successfully within a specified period of time, then no ad will play. -- A publisher can invoke the prebid/render methods as many times as desired if they want to play ads at different points along the video timeline. +* The plugin will use the parameters passed to it to invoke prebid. +* If a primary ad server is being used to make the final decision, the prebid bidding results will be passed to the desired ad server. +* The response should provide a URL to a VAST creative or a VAST XML document that defines an ad to play. +* Upon completion of the prebid, the winning ad can then be played by the plugin at the specified time. +* By default, the prebid plugin implicitly invokes the default MailOnline plugin to render the ad. +* If a valid VAST creative is not returned or if the prebid process does not complete successfully within a specified period of time, then no ad will play. +* A publisher can invoke the prebid/render methods as many times as desired if they want to play ads at different points along the video timeline. ### Where Prebid Can be Invoked @@ -230,18 +228,18 @@ The plugin can run the prebid process in the header so that it can be started be **Advantages** -- Potentially lower latency in rendering the selected ad. The reduction in latency is directly related on how long the prebid process is allowed to run. +* Potentially lower latency in rendering the selected ad. The reduction in latency is directly related on how long the prebid process is allowed to run. **Disadvantages** -- Requires publisher code both in the header, to start the prebid process, and also in the body, to render the ad once the Brightcove Player is loaded. - - See **[Sample Brightcove Player Prebid Plugin Integration - Prebid in Header]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.html)** -- Publisher *must* register the plugin on the page; it cannot register the plugin in the Brightcove Studio. +* Requires publisher code both in the header, to start the prebid process, and also in the body, to render the ad once the Brightcove Player is loaded. + * See **[Sample Brightcove Player Prebid Plugin Integration * Prebid in Header]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.html)** +* Publisher *must* register the plugin on the page; it cannot register the plugin in the Brightcove Studio. **Caveats** -- There is no guarantee that the prebid process will complete *before* the Brightcove Player is loaded, so there may still be some latency. -- If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame, then the prebid process must occur in the header of the iFrame and *not* in the header of the page. +* There is no guarantee that the prebid process will complete *before* the Brightcove Player is loaded, so there may still be some latency. +* If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame, then the prebid process must occur in the header of the iFrame and *not* in the header of the page. #### Plugin running prebid from the Brightcove Player @@ -249,73 +247,74 @@ The plugin can run the prebid process after the Brightcove Player has been loade **Advantages** -- Simpler publisher integration: the integration code only needs to occur in the body of the document where the Brightcove Player is loaded. -- Publisher can register and completely configure the plugin in the Brightcove Studio or on page, according to their preference. Doing this means you do not need to add any code to a publisher page when using this plugin. -- Because all of the code will run in the same document where the Brightcove Player is located, there are no cross-domain issues (with one potential exception, noted in the Caveats below). -- See **[Sample Brightcove Player Prebid Plugin Integration - Prebid After Player is Loaded]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-body.html)** +* Simpler publisher integration: the integration code only needs to occur in the body of the document where the Brightcove Player is loaded. +* Publisher can register and completely configure the plugin in the Brightcove Studio or on page, according to their preference. Doing this means you do not need to add any code to a publisher page when using this plugin. +* Because all of the code will run in the same document where the Brightcove Player is located, there are no cross-domain issues (with one potential exception, noted in the Caveats below). +* See **[Sample Brightcove Player Prebid Plugin Integration * Prebid After Player is Loaded]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-body.html)** **Disadvantages** -- Potentially longer latency in rendering the selected ad. The observed latency is directly related to how long the prebid process is allowed to run. +* Potentially longer latency in rendering the selected ad. The observed latency is directly related to how long the prebid process is allowed to run. **Caveats** -- If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame *and* the publisher is using a preferred ad server to determine the selected ad, then the publisher's code to select the winning ad must run within the same iFrame where the Brightcove Player is located. +* If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame *and* the publisher is using a preferred ad server to determine the selected ad, then the publisher's code to select the winning ad must run within the same iFrame where the Brightcove Player is located. #### Publishers can run header bidding outside of the plugin Publishers can decide to implement their own custom header bidding outside of the plugin. However, they can use the plugin to render the ad in a Brightcove Player. -- The result of the header bidding process must be stored and then provided to the plugin when the request to start the ad playback is made. -- This result should be a URL which returns a valid VAST creative defining the ad to be played. The result may also be a string containing the valid VAST creative. -- The winning ad will then be played by the plugin at the specified time. +* The result of the header bidding process must be stored and then provided to the plugin when the request to start the ad playback is made. +* This result should be a URL which returns a valid VAST creative defining the ad to be played. The result may also be a string containing the valid VAST creative. +* The winning ad will then be played by the plugin at the specified time. If the result is not a valid VAST creative, then no ad will play. **Advantages** -- Potentially lower latency in rendering selected ad. The reduction in latency is directly related to how long the prebid process is allowed to run. -- Publisher only needs to call `renderAd()` to ask the plugin to play the ad at the selected time. -- Publisher does not need to implement code to render the ad. -- Publisher can register the plugin in the Brightcove Studio or on page, according to their preference. +* Potentially lower latency in rendering selected ad. The reduction in latency is directly related to how long the prebid process is allowed to run. +* Publisher only needs to call `renderAd()` to ask the plugin to play the ad at the selected time. +* Publisher does not need to implement code to render the ad. +* Publisher can register the plugin in the Brightcove Studio or on page, according to their preference. **Disadvantages** -- Publisher is responsible for managing the prebid process as well as providing the results of the prebid. -- Publisher is responsible for syncing the results of prebid with the call to render the results. +* Publisher is responsible for managing the prebid process as well as providing the results of the prebid. +* Publisher is responsible for syncing the results of prebid with the call to render the results. **Caveats** -- There is no guarantee that the prebid process will complete before the Brightcove Player is loaded, so there might still be some latency. -- If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame, then the prebid process must occur in the header of the iFrame and *not* in the header of the page. +* There is no guarantee that the prebid process will complete before the Brightcove Player is loaded, so there might still be some latency. +* If the Brightcove Player is being embedded in a cross-domain (unfriendly) iFrame, then the prebid process must occur in the header of the iFrame and *not* in the header of the page. ## How To Integrate and Configure The Brightcove Prebid Plugin can be integrated and configured in one of two ways: -- Directly on the publisher page and/or through scripts that are loaded directly by the publisher page. This method of integration is required if you want to run prebid in the header of the page. -- In the Brightcove Studio in the same area where you set up the Brightcove Player instance that you are going to use. +* Directly on the publisher page and/or through scripts that are loaded directly by the publisher page. This method of integration is required if you want to run prebid in the header of the page. +* In the Brightcove Studio in the same area where you set up the Brightcove Player instance that you are going to use. Details about the Integration Methods can be found in [How to Integrate and Configure Prebid Plugin for Brightcove (Videojs) Player]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-integration.html). ## Plugin API + The Brightcove Prebid Plugin supports an API. Information about this API can be found in the [Prebid Plugin for Brightcove (Videojs) Player API]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-api.html). ## Plugin Options Configuration options are passed into the plugin via a JSON structure. This structure includes: -- Prebid configuration settings +* Prebid configuration settings These are options that define how the prebid process should be executed. These options include: - - Definitions of the bidders that should be used by prebid.js - - Configuration settings used when Google Ad Manager is the primary ad server - - Configuration settings if you are using another ad server as the primary ad server - - Other bidding settings used by prebid.js + * Definitions of the bidders that should be used by prebid.js + * Configuration settings used when Google Ad Manager is the primary ad server + * Configuration settings if you are using another ad server as the primary ad server + * Other bidding settings used by prebid.js -- Rendering options +* Rendering options These options configure some of the aspects of video ad playback, such as: - - Skippable behavior - - Custom translations for UI components such as the Ad Indicator, the Skip button and the countdown text + * Skippable behavior + * Custom translations for UI components such as the Ad Indicator, the Skip button and the countdown text {: .alert.alert-info :} NOTE: If you are requesting prebid for more than one ad break in a video, you need to define an array of configuration options, one for each ad break. The configuration should include the `timeOffset` option to identify when the ad break should occur. See [Specifying Multiple Ad Breaks for a Video]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.html) for more details. @@ -326,14 +325,10 @@ Details about the options supported by the Brightcove Prebid Plugin can be found Sample implementations are provided at: -- **[Sample Brightcove Player Prebid Plugin Integration - Prebid in Header]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.html)** - -- **[Sample Brightcove Player Prebid Plugin Integration - Prebid After Player is Loaded]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-body.html)** - -- **[Sample Brightcove Player Prebid Plugin Integration - Using Publisher Preferred Ad Server]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-third-party-ad-server.html)** - -- **[Sample Brightcove Player Prebid Plugin Integration - Publisher Uses Custom Header Bidding, Plugin Renders the Ad]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-custom-header-bidding.html)** - -- **[Specifying Multiple Ad Breaks for a Video]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.html)** +* **[Sample Brightcove Player Prebid Plugin Integration - Prebid in Header]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-header.html)** +* **[Sample Brightcove Player Prebid Plugin Integration - Prebid After Player is Loaded]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-prebid-body.html)** +* **[Sample Brightcove Player Prebid Plugin Integration - Using Publisher Preferred Ad Server]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-third-party-ad-server.html)** +* **[Sample Brightcove Player Prebid Plugin Integration - Publisher Uses Custom Header Bidding, Plugin Renders the Ad]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-sample-custom-header-bidding.html)** +* **[Specifying Multiple Ad Breaks for a Video]({{site.baseurl}}/dev-docs/plugins/bc/bc-prebid-plugin-multiad-options.html)** diff --git a/dev-docs/plugins/bc/bc-prebid-plugin-api.md b/dev-docs/plugins/bc/bc-prebid-plugin-api.md index 143fd7add2..1225dab7a0 100644 --- a/dev-docs/plugins/bc/bc-prebid-plugin-api.md +++ b/dev-docs/plugins/bc/bc-prebid-plugin-api.md @@ -18,29 +18,29 @@ The Brightcove Prebid Plugin supports an API that publishers can use to interact The Brightcove Prebid Plugin supports the following methods: -- `init ()` -- `renderAd (options, id, creative)` -- `stop ()` +* `init ()` +* `renderAd (options, id, creative)` +* `stop ()` ### init() The `init()` method registers the Brightcove Prebid Plugin within Brightcove Player (Videojs) as `BCVideo_PrebidVastPlugin`. This method must be called first before any other plugin API methods. -- Internal name = `bcPrebidVastPlugin` - This name is used only when you are specifying the plugin in Brightcove Studio. +* Internal name = `bcPrebidVastPlugin` - This name is used only when you are specifying the plugin in Brightcove Studio. **NOTE:** This initial registration must be done after the Brightcove Player is loaded. If the plugin is performing the pre-bidding in the header, then the call to `init()` must wait until the Brightcove Player has been loaded. -#### Arguments: +#### Arguments for init() None -#### Return Value: +#### Return Value for init() None -#### Sample Code: +#### Sample Code for init() -``` +```html + ## pbjs + {% for page in api_pages %}

      • {{page.title}}
      • {% endfor %} - - diff --git a/dev-docs/publisher-api-reference/adServers.dfp.buildAdpodVideoUrl.md b/dev-docs/publisher-api-reference/adServers.dfp.buildAdpodVideoUrl.md index 7b3821aa4e..02adfbb293 100644 --- a/dev-docs/publisher-api-reference/adServers.dfp.buildAdpodVideoUrl.md +++ b/dev-docs/publisher-api-reference/adServers.dfp.buildAdpodVideoUrl.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.adServers.dfp.buildAdpodVideoUrl(options) [Alpha] -description: +description: adServers.dfp.buildAdpodVideoUrl API +sidebarType: 1 --- @@ -56,4 +57,4 @@ pbjs.que.push(function(){ }); ``` -{% include alerts/alert_warning.html content="Set the `pbjs.setConfig.cache.url` to the URL that will cache the VAST XML. " %} \ No newline at end of file +{% include alerts/alert_warning.html content="Set the `pbjs.setConfig.cache.url` to the URL that will cache the VAST XML. " %} diff --git a/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.md b/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.md index 9ae6710664..6c8ccae331 100644 --- a/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.md +++ b/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.adServers.dfp.buildVideoUrl(options) -description: +description: adServers.dfp.buildVideoUrl API +sidebarType: 1 --- @@ -80,4 +81,4 @@ var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ {: .alert.alert-warning :} -In the event of collisions, querystring values passed via `options.params` take precedence over those passed via `options.url`. \ No newline at end of file +In the event of collisions, querystring values passed via `options.params` take precedence over those passed via `options.url`. diff --git a/dev-docs/publisher-api-reference/adServers.freewheel.getTargeting.md b/dev-docs/publisher-api-reference/adServers.freewheel.getTargeting.md index 005ec19f3d..12b22adfb9 100644 --- a/dev-docs/publisher-api-reference/adServers.freewheel.getTargeting.md +++ b/dev-docs/publisher-api-reference/adServers.freewheel.getTargeting.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.adServers.freewheel.getTargeting(options) -description: +description: adServers.freewheel.getTargeting API +sidebarType: 1 --- @@ -13,7 +14,6 @@ Use this method to get targeting key-value pairs to be sent to the ad server. + `pbjs.adServers.freewheel.getTargeting(options)`: returns key-value pair from the ad server. ```javascript - pbjs.adServers.freewheel.getTargeting({ codes: [adUnitCode1], callback: function(err, targeting) { @@ -21,6 +21,7 @@ pbjs.adServers.freewheel.getTargeting({ } }); ``` + #### Argument Reference ##### The `options` object @@ -29,4 +30,4 @@ pbjs.adServers.freewheel.getTargeting({ | Param | Scope | Type | Description | | --- | --- | --- | --- | | codes | Optional | `Array` | [`adUnitCode1`] | -| callback | Required | `Function` | Callback function to execute when targeting data is back. | \ No newline at end of file +| callback | Required | `Function` | Callback function to execute when targeting data is back. | diff --git a/dev-docs/publisher-api-reference/addAdUnits.md b/dev-docs/publisher-api-reference/addAdUnits.md index 60df9ebc50..4af75f0210 100644 --- a/dev-docs/publisher-api-reference/addAdUnits.md +++ b/dev-docs/publisher-api-reference/addAdUnits.md @@ -2,15 +2,16 @@ layout: api_prebidjs title: pbjs.addAdUnits(Array|Object) description: +sidebarType: 1 --- Takes one ad unit object or an array of ad unit objects and adds them to the Prebid auction. For usage examples, see [Examples](#addAdUnits-Examples) below and the [Getting Started]({{site.baseurl}}/dev-docs/getting-started.html) page. -+ [Ad Unit Properties](#addAdUnits-AdUnitProperties) -+ [Examples](#addAdUnits-Examples) +* [Ad Unit Properties](#addAdUnits-AdUnitProperties) +* [Examples](#addAdUnits-Examples) - + #### Ad Unit Properties @@ -21,17 +22,20 @@ See the table below for the list of properties on the ad unit. For example ad u |--------------+----------+---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `code` | Required | String | Unique identifier that you create and assign to this ad unit. Used to set query string targeting on the ad. If using GPT, we recommend setting this to slot element ID. | | `sizes` | Required | Array[Number] or Array[Array[Number]] | All the sizes that this ad unit can accept. Examples: `[400, 600]`, `[[300, 250], [300, 600]]`. For 1.0 and later, prefer [`mediaTypes.banner.sizes`](#adUnit-banner). | -| `bids` | Required | Array[Object] | Each bid represents a request to a bidder. For a list of properties, see [Bids](#addAdUnits-Bids) below. | +| `bids` | Optional | Array[Object] | Each bid represents a request to a bidder. For a list of properties, see [Bids](#addAdUnits-Bids) below. | | `mediaTypes` | Optional | Object | Defines one or multiple media types the ad unit supports. For a list of properties, see [Media Types](#addAdUnits-MediaTypes) below. | | `labelAny` | optional | array | An array of string labels, used for showing responsive ads. With the `labelAny` operator, just one label has to match for the condition to be true. Works with the `sizeConfig` object passed in to [pbjs.setConfig]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html). | | `labelAll` | optional | array | An array of string labels, used for showing responsive and conditional ads. With the `labelAll` conditional, every element of the target array must match an element of the label array in order for the condition to be true. Works with the `sizeConfig` object passed in to [pbjs.setConfig]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html). | +| `video` | Optional | Object | Used to link an Ad Unit to the [Video Module]({{site.github.url}}/prebid-video/video-module.html). For allowed params see the [adUnit.video reference](#adUnit-video). | - + ##### Bids See the table below for the list of properties in the `bids` array of the ad unit. For example ad units, see the [Examples](#addAdUnits-Examples) below. +Note that `bids` is optional only for [Prebid Server stored impressions](/dev-docs/modules/prebidServer.html#stored-imp), and required in all other cases. + {: .table .table-bordered .table-striped } | Name | Scope | Type | Description | @@ -41,7 +45,7 @@ See the table below for the list of properties in the `bids` array of the ad uni | `labelAny` | optional | array | An array of string labels, used for showing responsive ads. With the `labelAny` operator, just one label has to match for the condition to be true. Works with the `sizeConfig` object passed in to [pbjs.setConfig]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html). | | `labelAll` | optional | array | An array of string labels, used for showing responsive and conditional ads. With the `labelAll` conditional, every element of the target array must match an element of the label array in order for the condition to be true. Works with the `sizeConfig` object passed in to [pbjs.setConfig]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html). | - + ##### Media Types @@ -54,19 +58,27 @@ See the table below for the list of properties in the `mediaTypes` object of the | `native` | optional | Object | Defines properties of a native ad. For an example native ad unit, see [the native example below](#adUnit-native). | | `video` | optional | Object | Defines properties of a video ad. For examples, see [the video examples below](#adUnit-video). | - +#### Video -#### Examples +For the list of properties please visit the [adUnit.video reference]({{site.baseurl}}/dev-docs/adunit-reference.html#adUnit.video). + + -+ [Native](#adUnit-native) -+ [Video](#adUnit-video) -+ [Banner](#adUnit-banner) -+ [Multi-format](#adUnit-multi-format) +#### Examples +* [Ad Unit Properties](#ad-unit-properties) + * [Bids](#bids) + * [Media Types](#media-types) +* [Video](#video) +* [Examples](#examples) + * [Native](#mediatype-native) + * [Video](#mediatype-video) + * [Banner](#mediatype-banner) + * [Multi-format](#multi-format) - + -##### Native +##### MediaType Native For an example of a native ad unit, see below. For more detailed instructions, see [Show Native Ads]({{site.baseurl}}/dev-docs/show-native-ads.html). @@ -111,11 +123,35 @@ pbjs.addAdUnits({ {% include dev-docs/native-image-asset-sizes.md %} - + + +##### MediaType Video + +If using the Video Module, see below. For more information on the Video Module, see the [Video Module docs]({{site.github.url}}/prebid-video/video-module.html). -##### Video +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + video: {}, + }, + video: { + divId: 'playerDiv', + adServer: { + vendorCode: 'gam', // constant variable is GAM_VENDOR - see vendorCodes.js in the video library + baseAdTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/12345/' + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361 + } + }] +}); +``` -For an example of an instream video ad unit, see below. For more detailed instructions, see [Show Video Ads]({{site.baseurl}}/dev-docs/show-video-with-a-dfp-video-tag.html). +For an example of an instream video ad unit where the integration is handled on your own, see below. For more detailed instructions, see [Show Video Ads]({{site.baseurl}}/dev-docs/show-video-with-a-dfp-video-tag.html). ```javascript pbjs.addAdUnits({ @@ -167,9 +203,9 @@ pbjs.addAdUnit({ }) ``` - + -##### Banner +##### MediaType Banner For an example of a banner ad unit, see below. For more detailed instructions, see [Getting Started]({{site.baseurl}}/dev-docs/getting-started.html). @@ -192,7 +228,7 @@ pbjs.addAdUnits({ }) ``` - + ##### Multi-format @@ -214,10 +250,10 @@ pbjs.addAdUnits({ video: { context: 'outstream', playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [2], + skip: 1 }, }, bids: [ diff --git a/dev-docs/publisher-api-reference/aliasBidder.md b/dev-docs/publisher-api-reference/aliasBidder.md index 2e8e35c8a9..fd0a7248ef 100644 --- a/dev-docs/publisher-api-reference/aliasBidder.md +++ b/dev-docs/publisher-api-reference/aliasBidder.md @@ -2,16 +2,16 @@ layout: api_prebidjs title: pbjs.aliasBidder(adapterName, aliasedName, options) description: +sidebarType: 1 --- - To define an alias for a bidder adapter, call this method at runtime: -{% highlight js %} +```javascript -pbjs.aliasBidder('appnexus', 'newAlias', options: { gvlid: 111111} ); +pbjs.aliasBidder('appnexus', 'newAlias', optionsObject ); -{% endhighlight %} +``` Defining an alias can help avoid user confusion since it's possible to send parameters to the same adapter but in different contexts (e.g, The publisher uses `"appnexus"` for demand and also uses `"newAlias"` which is an SSP partner that uses the `"appnexus"` adapter to serve their own unique demand). @@ -33,4 +33,8 @@ The options object supports these parameters: Creating an alias for a Prebid Server adapter is done differently. See 'extPrebid' config in the [`s2sConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Server-to-Server) object. -
        +For example: + +```javascript +pbjs.aliasBidder('bidderA', 'aliasOfBidderA', {gvlid: 9999}); +``` diff --git a/dev-docs/publisher-api-reference/aliasRegistry.md b/dev-docs/publisher-api-reference/aliasRegistry.md new file mode 100644 index 0000000000..6740d839ca --- /dev/null +++ b/dev-docs/publisher-api-reference/aliasRegistry.md @@ -0,0 +1,24 @@ +--- +layout: api_prebidjs +title: pbjs.aliasRegistry +description: +sidebarType: 1 +--- + + +Exposes the aliasRegistry. It can be used to fetch the entire aliasRegistry object or an individual adapter code by alias name. + +```javascript +pbjs.aliasRegistry; +// or +pbjs.aliasRegistry['aliasName']; +``` + +{: .alert.alert-warning :} +Note that by default, the alias registry will be made public. If you would like the registry to be private, you can utilize the `setConfig` option below: + +```javascript +pbjs.setConfig({aliasRegistry: 'private'}) +``` + +
        diff --git a/dev-docs/publisher-api-reference/bidderSettings.md b/dev-docs/publisher-api-reference/bidderSettings.md index ddc7e5b5ec..f40399cd2e 100644 --- a/dev-docs/publisher-api-reference/bidderSettings.md +++ b/dev-docs/publisher-api-reference/bidderSettings.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.bidderSettings -description: +description: bidderSettings API +sidebarType: 1 --- @@ -10,8 +11,7 @@ description: The bidderSettings object provides a way to define some behaviors for the platform and specific adapters. The basic structure is a 'standard' section with defaults for all adapters, and then one or more adapter-specific sections that override behavior for that bidder: -{% highlight js %} - +```javascript pbjs.bidderSettings = { standard: { [...] @@ -23,8 +23,7 @@ pbjs.bidderSettings = { [...] }, } - -{% endhighlight %} +``` Defining bidderSettings is optional; the platform has default values for all of the options. Adapters may specify their own default settings, though this isn't common. @@ -40,10 +39,15 @@ Some sample scenarios where publishers may wish to alter the default settings: | Attribute | Scope | Version | Default | Description | | --- | --- | --- | --- | --- | | adserverTargeting | standard or adapter-specific | all | see below | Define which key/value pairs are sent to the ad server. | -| bidCpmAdjustment | standard or adapter-specific | all | n/a | Could, for example, adjust a bidder's gross-price bid to net price. | +| bidCpmAdjustment | standard or adapter-specific | all | n/a | Custom CPM adjustment function. Could, for example, adjust a bidder's gross-price bid to net price. | +| inverseBidAdjustment | standard or adapter-specific | 7.33.0 | n/a | Inverse of `bidCpmAdjustment` | | sendStandardTargeting | adapter-specific | 0.13.0 | true | If adapter-specific targeting is specified, can be used to suppress the standard targeting for that adapter. | | suppressEmptyKeys | standard or adapter-specific | 0.13.0 | false | If custom adserverTargeting functions are specified that may generate empty keys, this can be used to suppress them. | -| allowZeroCpmBids | standard of adapter-specific | 6.2.0 | false | Would allow bids with a 0 CPM to be accepted by Prebid.js and could be passed to the ad server. | +| allowZeroCpmBids | standard or adapter-specific | 6.2.0 | false | Would allow bids with a 0 CPM to be accepted by Prebid.js and could be passed to the ad server. | +| storageAllowed | standard or adapter-specific | 6.13.0 | true in 6.x, false after 7.0 | Allow use of cookies and/or local storage. | +| allowAlternateBidderCodes | standard or adapter-specific | 6.23.0 | true in v6.x
        false from v7.0| Allow adapters to bid with alternate bidder codes. | +| allowedAlternateBidderCodes | standard or adapter-specific | 6.23.0 | n/a | Array of bidder codes for which an adapter can bid.
        `undefined` or `['*']` will allow adapter to bid with any bidder code. | +| adjustAlternateBids | standard or adapter-specific | 7.48.0 | false | Optionally allow alternate bidder codes to use an adapter's bidCpmAdjustment function by default instead of the standard bidCpmAdjustment function if present (note: if a bidCpmAdjustment function exists for the alternate bidder code within bidderSettings, then this will be used instead of falling back to the adapter's bidCpmAdjustment function). | ##### 2.1. adserverTargeting @@ -66,12 +70,11 @@ The key value pair targeting is applied to the bid's corresponding ad unit. Your If you'd like to customize the key value pairs, you can overwrite the settings as the below example shows. *Note* that once you updated the settings, let your ad ops team know about the change, so they can update the line item targeting accordingly. See the [Ad Ops](/adops/before-you-start.html) documentation for more information. - + There's no need to include the following code if you choose to use the *below default setting*. -{% highlight js %} - +```javascript pbjs.bidderSettings = { standard: { adserverTargeting: [{ @@ -107,8 +110,7 @@ pbjs.bidderSettings = { }] } } - -{% endhighlight %} +``` {: .alert.alert-warning :} Note that the existence of `bidderSettings.adserverTargeting.standard` will prevent the system from adding the standard display targeting values: hb_bidder, hb_adid, hb_pb, hb_size, and hb_format. However, if the mediaType is video and `bidderSettings.adserverTargeting.standard` does not specify hb_uuid, hb_cache_id, or hb_cache_host, they will be added unless `bidderSettings.sendStandardTargeting` is set to false. @@ -121,7 +123,7 @@ settings as the below example for AppNexus shows. *Note that the line item setup has to match the targeting change* -{% highlight js %} +```javascript pbjs.bidderSettings = { appnexus: { sendStandardTargeting: false, @@ -140,8 +142,7 @@ pbjs.bidderSettings = { ] } } -{% endhighlight %} - +``` In other words, the above config sends 2 pairs of key/value strings targeting for every AppNexus bid and for every ad unit. The 1st pair would be `apn_pbMg` => the value of `bidResponse.pbMg`. The 2nd pair would be `apn_adId` => the value of `bidResponse.adId`. You can find the bidResponse object documentation [here](/troubleshooting/troubleshooting-guide.html#common-bid-response-parameters). @@ -153,8 +154,7 @@ Now let's say you would like to define a bidder-specific price bucket function r *Note: this will only impact the price bucket sent to the ad server for targeting. It won't actually impact the cpm value used for ordering the bids.* -{% highlight js %} - +```javascript pbjs.bidderSettings = { standard: { [...] @@ -175,10 +175,10 @@ pbjs.bidderSettings = { return "pb6"; // all bids $6 and above are assigned to price bucket 'pb6' } }] - [...] + // [...] } } -{% endhighlight %} +``` ##### 2.2. bidCpmAdjustment @@ -188,8 +188,12 @@ In this case, the publisher may want to adjust the bidder's returned price to ru header bidding auction. Otherwise, this bidder's gross price will unfairly win over your other demand sources who report the real price. -{% highlight js %} +Custom adjustment can be provided as a function taking 3 arguments: `bidCpmAdjustment(cpm, bidResponse, bidRequest)`. +Note that either `bidResponse` or `bidRequest` may be missing, although at least one of them is guaranteed to be present. This is because Prebid will sometimes need to run adjustment when no bid has been made yet; see [inverseBidAdjustment](#23-inversebidadjustment) below. +For example: + +```javascript pbjs.bidderSettings = { standard: { ... } aol: { @@ -200,12 +204,31 @@ pbjs.bidderSettings = { } } }; - -{% endhighlight %} +``` In the above example, the AOL bidder will inherit from "standard" adserverTargeting keys, so that you don't have to define the targeting keywords again. -##### 2.3. sendStandardTargeting +##### 2.3. inverseBidAdjustment + +When using [price floors](/dev-docs/modules/floors.html), Prebid attempts to calculate the inverse of `bidCpmAdjustment`, so that the floor values it requests from SSPs take into account how the bid will be adjusted. +For example, if the adjustment is `bidCpm * .85` as above, floors are adjusted by `bidFloor * 1 / .85`. + +The automatically derived inverse function is correct only when `bidCpmAdjustment` is a simple multiplication. If it isn't, the inverse should also be provided through `inverseBidAdjustment`. For example: + +```javascript +pbjs.bidderSettings = { + aol: { + bidCpmAdjustment : function(cpm) { + return Math.max(0.2, (cpm - 0.2) * .85) + }, + inverseBidAdjustment: function(cpm) { + return Math.max(0.2, (cpm / .85) + 0.2) + } + } +}; +``` + +##### 2.4. sendStandardTargeting This boolean flag minimizes key/value pairs sent to the ad server when adapter-specific targeting is specified. By default, the platform will send both adapter-specific adServerTargeting as well as the standard adServerTargeting. @@ -215,14 +238,107 @@ suppress the standard targeting for adapters that define their own. See the [example above](#key-targeting-specific-bidder) for example usage. -##### 2.4. suppressEmptyKeys +##### 2.5. suppressEmptyKeys If a custom adServerTargeting function can return an empty value, this boolean flag can be used to avoid sending those empty values to the ad server. -##### 2.5. allowZeroCpmBids +##### 2.6. allowZeroCpmBids By default, 0 CPM bids are ignored by Prebid.js entirely. However if there's a valid business reason to allow these bids, this setting can be enabled to allow -either specific bid adapter(s) or all bid adapters the permission for these bids to be processed by Prebid.js and potentially sent to the respective ad server +either specific bid adapter(s) or all bid adapters the permission for these bids to be processed by Prebid.js and potentially sent to the respective ad server (depending on the Prebid.js auction results). + + +##### 2.7. storageAllowed + +This setting defines if the bid adapter can access browser cookies or local storage. Allowed values are: + +* an array containing either `'html5'`, `'cookie'` or both to allow specific storage methods (e.g. `['cookie']` enables cookies but not local storage) +* `true` to allow any storage method; +* `false` to disable all storage. + +
        Default value is `true` in version 6.x +
        Default value is `false` in version 7.x + +Note that: + +* [Disabling device access](/dev-docs/publisher-api-reference/setConfig.html#setConfig-deviceAccess) will prevent access to storage regardless of this setting; +* `storageAllowed` will only affect bid adapters and not any other type of module (such as analytics or RTD). + + + +##### 2.8. allowAlternateBidderCodes + +If this flag is set to `true`, bidders that have not been explicitly requested in [`adUnit.bids`](../adunit-reference.html#adunitbids) may take part in the auction. +
        Default value is `true` in version 6.x +
        Default value will be `false` from version 7.0 + +##### 2.9. allowedAlternateBidderCodes + +This array will work in conjunction with `allowAlternateBidderCodes`. In this array, you can specify the names of the bidder for which an adapter can accept the bid. If the value is not specified for the array or `[‘*’]` is specified, Prebid will accept bids of all the bidders for the given adapter. + +```javascript + +pbjs.bidderSettings = { + standard: { + allowAlternateBidderCodes: false, + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .95; }, + [...] + }, + pubmatic: { + allowAlternateBidderCodes: true, + allowedAlternateBidderCodes: ["groupm"], + [...] + }, + appnexus: { + allowAlternateBidderCodes: true, + allowedAlternateBidderCodes: ["*"], + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .90; }, + [...] + }, + groupm:{ + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .80; }, + [...] + } +} +``` + +In the above example, `groupm` bid will have a bid adjustment of 80% since the `bidCpmAdjustment` function says so.
        +If `appnexus` bids with another bidder code, say `appnexus2`. This bidder code will adjust the bid cpm to 95% because it will apply the `bidCpmAdjustment` function from `standard` setting, since the `bidCpmAdjustment` is missing for given bidder code I.e `appnexus2` + +##### 2.10. adjustAlternateBids + +Optionally allow alternate bidder codes originating from a specific bid adapter to fallback to that same adapter's bidCpmAdjustment function. When adjustAlternateBids is set to true, the prioity of which bidCpmAdjustment function to utilize will be as follows based on what is present within the bidderSettings object: + +1. Alternate bidder code bidCpmAdjustment function +2. Adapter bidCpmAdjustment function +3. The standard bidCpmAdjustment function + +```javascript + +pbjs.bidderSettings = { + standard: { + allowAlternateBidderCodes: false, + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .95; }, + [...] + }, + pubmatic: { + allowAlternateBidderCodes: true, + allowedAlternateBidderCodes: ["groupm"], + adjustAlternateBids: true, + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .85; }, + [...] + }, + appnexus: { + allowAlternateBidderCodes: true, + allowedAlternateBidderCodes: ["*"], + bidCpmAdjustment: function(bidCpm, bid){ return bidCpm * .90; }, + [...] + } +} +``` + +In the above example, if PubMatic were to return the "groupm" bidder code then the bidCpmAdjustment function under `pubmatic` would be used instead of what is available under `standard`. +
        diff --git a/dev-docs/publisher-api-reference/enableAnalytics.md b/dev-docs/publisher-api-reference/enableAnalytics.md index ff6f16ff8d..7ba8ac6852 100644 --- a/dev-docs/publisher-api-reference/enableAnalytics.md +++ b/dev-docs/publisher-api-reference/enableAnalytics.md @@ -1,26 +1,43 @@ --- layout: api_prebidjs title: pbjs.enableAnalytics(config) -description: +description: enableAnalytics API +sidebarType: 1 --- -Enables sending analytics data to the analytics provider of your choice. For a list of analytics adapters, see [Analytics for Prebid](/overview/analytics.html). +Enables sending event data to the analytics provider of your choice. For a list of analytics adapters, see [Analytics for Prebid](/overview/analytics.html). -Note that each analytics adapter has it's own invocation parameters. Analytics adapters that are built in the standard way should -support a `sampling` option. You'll need to check with your analytics provider to confirm -whether their system recommends the use of this parameter. They may have alternate methods of sampling. +### Example -``` +```javascript pbjs.enableAnalytics([{ - provider: "analyticsA", + provider: "analyticsA", options: { - providerSpecificParams: ... sampling: 0.25 // only call the analytics adapter this percent of the time - } + providerSpecificParams: ... + }, + excludeEvents: ['auctionDebug'], }]); ``` -To learn how to build an analytics adapter, see [How to Add an Analytics Adapter](/dev-docs/integrate-with-the-prebid-analytics-api.html). +### Parameters + +{: .table .table-bordered .table-striped } +| Param | Scope | Type | Description | +| --- | --- | --- | --- | +| `provider` | Required | String | Analytics adapter code | +| `options` | Required | Object | Adapter specific options | +| `includeEvents` | Optional | Array of strings | Event whitelist; if provided, only these events will be forwarded to the adapter | +| `excludeEvents` | Optional | Array of strings | Event blacklist; if provided, these events will not be forwarded to the adapter | + +Note each analytics adapter has its own invocation parameters. Analytics adapters that are built in the standard way should +support a `option.sampling` parameter. You'll need to check with your analytics provider to confirm +whether their system recommends the use of this parameter. They may have alternate methods of sampling. + +### See also + +* [Prebid.js events](/dev-docs/publisher-api-reference/getEvents.html) +* [How to Add an Analytics Adapter](/dev-docs/integrate-with-the-prebid-analytics-api.html). -
        \ No newline at end of file +
        diff --git a/dev-docs/publisher-api-reference/getAdserverTargeting.md b/dev-docs/publisher-api-reference/getAdserverTargeting.md index 4dd9d7047b..296c69a785 100644 --- a/dev-docs/publisher-api-reference/getAdserverTargeting.md +++ b/dev-docs/publisher-api-reference/getAdserverTargeting.md @@ -1,12 +1,12 @@ --- layout: api_prebidjs title: pbjs.getAdserverTargeting() -description: +description: getAdserverTargeting API +sidebarType: 1 ---
        - Returns all ad server targeting for all ad units. Note that some bidder's response may not have been received if you call this function too quickly after the requests are sent. The targeting keys can be configured in [ad server targeting](/dev-docs/publisher-api-reference/bidderSettings.html). @@ -19,7 +19,7 @@ When [deals are enabled]({{site.baseurl}}/adops/deals.html), the object returned **Returned Object Example:** -{% highlight js %} +```javascript { "/9968336/header-bid-tag-0": { "hb_bidder": "rubicon", @@ -38,4 +38,4 @@ When [deals are enabled]({{site.baseurl}}/adops/deals.html), the object returned "hb_deal_appnexus": "ABC_123" } } -{% endhighlight %} +``` diff --git a/dev-docs/publisher-api-reference/getAdserverTargetingForAdUnitCode.md b/dev-docs/publisher-api-reference/getAdserverTargetingForAdUnitCode.md index ed6a8c91d7..4d76b7681e 100644 --- a/dev-docs/publisher-api-reference/getAdserverTargetingForAdUnitCode.md +++ b/dev-docs/publisher-api-reference/getAdserverTargetingForAdUnitCode.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getAdserverTargetingForAdUnitCode([adunitCode]) -description: +description: getAdserverTargetingForAdUnitCode API +sidebarType: 1 --- @@ -20,10 +21,10 @@ This function returns the query string targeting parameters available at this mo **Returned Object Example:** -{% highlight js %} +```javascript { "hb_bidder": "rubicon", "hb_adid": "13f44b0d3c", "hb_pb": "0.50" } -{% endhighlight %} +``` diff --git a/dev-docs/publisher-api-reference/getAllPrebidWinningBids.md b/dev-docs/publisher-api-reference/getAllPrebidWinningBids.md index 26db627c5d..9d9bb09271 100644 --- a/dev-docs/publisher-api-reference/getAllPrebidWinningBids.md +++ b/dev-docs/publisher-api-reference/getAllPrebidWinningBids.md @@ -1,10 +1,11 @@ --- layout: api_prebidjs title: pbjs.getAllPrebidWinningBids() -description: +description: getAllPrebidWinningBids API +sidebarType: 1 --- Use this method to get all of the bids that have won their respective auctions but not rendered on the page. Useful for [troubleshooting your integration]({{site.baseurl}}/dev-docs/prebid-troubleshooting-guide.html). -+ `pbjs.getAllPrebidWinningBids()`: returns an array of bid objects that have won their respective auctions but not rendered on the page. \ No newline at end of file +* `pbjs.getAllPrebidWinningBids()`: returns an array of bid objects that have won their respective auctions but not rendered on the page. diff --git a/dev-docs/publisher-api-reference/getAllWinningBids.md b/dev-docs/publisher-api-reference/getAllWinningBids.md index bfba36e1ac..f05f13bb93 100644 --- a/dev-docs/publisher-api-reference/getAllWinningBids.md +++ b/dev-docs/publisher-api-reference/getAllWinningBids.md @@ -1,10 +1,11 @@ --- layout: api_prebidjs title: pbjs.getAllWinningBids() -description: +description: getAllWinningBids API +sidebarType: 1 --- Use this method to get all of the bids that have won their respective auctions and also rendered on the page. Useful for [troubleshooting your integration]({{site.baseurl}}/dev-docs/prebid-troubleshooting-guide.html). -+ `pbjs.getAllWinningBids()`: returns an array of bid objects that have won their respective auctions and also rendered on the page. \ No newline at end of file +* `pbjs.getAllWinningBids()`: returns an array of bid objects that have won their respective auctions and also rendered on the page. diff --git a/dev-docs/publisher-api-reference/getBidResponses.md b/dev-docs/publisher-api-reference/getBidResponses.md index 9de6907ceb..44ae1d92d0 100644 --- a/dev-docs/publisher-api-reference/getBidResponses.md +++ b/dev-docs/publisher-api-reference/getBidResponses.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getBidResponses() -description: +description: getBidResponses API +sidebarType: 1 --- @@ -17,7 +18,7 @@ This function returns the bid responses at the given moment. | Param | Type | Description | | |---------------------+---------+---------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------| | `bidder` | String | The bidder code. Used by ad server's line items to identify bidders | `rubicon` | -| `adId` | String | The unique identifier of a bid creative. It's used by the line item's creative as in [this example]({{site.github.url}}/adops/send-all-bids-adops.html#step-3-add-a-creative). | `123` | +| `adId` | String | The unique identifier of a bid creative. It's used by the line item's creative as in [this example](/adops/gam-creative-banner-sbs.html). | `123` | | `width` | Integer | The width of the returned creative size. | 300 | | `height` | Integer | The height of the returned creative size. | 250 | | `size` | String | The width x height of the returned creative size. | "300x250" | @@ -46,14 +47,12 @@ This function returns the bid responses at the given moment. -
        - -{% highlight bash %} +```json { "/9968336/header-bid-tag-0": { "bids": [ @@ -167,7 +166,8 @@ This function returns the bid responses at the given moment. ] } } -{% endhighlight %} +``` +
        @@ -181,84 +181,83 @@ This function returns the bid responses at the given moment. -
        -{% highlight bash %} +```json { - "div-banner-outstream-native" : { - "bids" : [ - { - "pbMg" : "10.00", - "pbLg" : "5.00", - "width" : 0, - "requestTimestamp" : 1516315716062, - "creativeId" : 81589325, - "pbCg" : "", - "adUnitCode" : "div-banner-outstream-native", - "size" : "0x0", - "bidder" : "appnexus", - "pbAg" : "10.00", - "adId" : "473965c9df19d2", - "adserverTargeting" : { - "hb_native_icon" : "https://vcdn.adnxs.com/p/creative-image/d4/06/e2/33/d406e233-a5f9-44a6-a3e0-8a714bf0e980.png", - "hb_native_title" : "This is a Prebid Native Multi-Format Creative", - "hb_native_brand" : "Prebid.org", - "hb_adid" : "473965c9df19d2", - "hb_pb" : "10.00", - "hb_source" : "client", - "hb_bidder" : "appnexus", - "hb_native_image" : "https://vcdn.adnxs.com/p/creative-image/9e/26/5f/b2/9e265fb2-50c8-43f0-88ef-a5a48a9d0dcf.jpg", - "hb_size" : "0x0", - "hb_mediatype" : "native", - "hb_native_body" : "This is a Prebid Native Creative. There are many like it, but this one is mine.", - "hb_native_linkurl" : "https://prebid.org/dev-docs/show-native-ads.html" - }, - "native" : { - "icon" : { - "url" : "https://vcdn.adnxs.com/p/creative-image/d4/06/e2/33/d406e233-a5f9-44a6-a3e0-8a714bf0e980.png", - "height" : 75, - "width" : 75 - }, - "body" : "This is a Prebid Native Creative. There are many like it, but this one is mine.", - "image" : { - "url" : "https://vcdn.adnxs.com/p/creative-image/9e/26/5f/b2/9e265fb2-50c8-43f0-88ef-a5a48a9d0dcf.jpg", - "height" : 2250, - "width" : 3000 - }, - "clickUrl" : "https://prebid.org/dev-docs/show-native-ads.html", - "clickTrackers" : [ - "..." - ], - "title" : "This is a Prebid Native Multi-Format Creative", - "impressionTrackers" : [ - "..." - ], - "sponsoredBy" : "Prebid.org" - }, - "timeToRespond" : 143, - "mediaType" : "native", - "bidderCode" : "appnexus", - "source" : "client", - "auctionId" : "1338a6fb-e514-48fc-8db6-872ddf3babdb", - "responseTimestamp" : 1516315716205, - "netRevenue" : true, - "pbDg" : "10.00", - "pbHg" : "10.00", - "ttl" : 300, - "status" : "targetingSet", - "height" : 0, - "statusMessage" : "Bid available", - "cpm" : 10, - "currency" : "USD" - } - ] - } - } -{% endhighlight %} + "div-banner-outstream-native" : { + "bids" : [ + { + "pbMg" : "10.00", + "pbLg" : "5.00", + "width" : 0, + "requestTimestamp" : 1516315716062, + "creativeId" : 81589325, + "pbCg" : "", + "adUnitCode" : "div-banner-outstream-native", + "size" : "0x0", + "bidder" : "appnexus", + "pbAg" : "10.00", + "adId" : "473965c9df19d2", + "adserverTargeting" : { + "hb_native_icon" : "https://vcdn.adnxs.com/p/creative-image/d4/06/e2/33/d406e233-a5f9-44a6-a3e0-8a714bf0e980.png", + "hb_native_title" : "This is a Prebid Native Multi-Format Creative", + "hb_native_brand" : "Prebid.org", + "hb_adid" : "473965c9df19d2", + "hb_pb" : "10.00", + "hb_source" : "client", + "hb_bidder" : "appnexus", + "hb_native_image" : "https://vcdn.adnxs.com/p/creative-image/9e/26/5f/b2/9e265fb2-50c8-43f0-88ef-a5a48a9d0dcf.jpg", + "hb_size" : "0x0", + "hb_mediatype" : "native", + "hb_native_body" : "This is a Prebid Native Creative. There are many like it, but this one is mine.", + "hb_native_linkurl" : "https://prebid.org/dev-docs/show-native-ads.html" + }, + "native" : { + "icon" : { + "url" : "https://vcdn.adnxs.com/p/creative-image/d4/06/e2/33/d406e233-a5f9-44a6-a3e0-8a714bf0e980.png", + "height" : 75, + "width" : 75 + }, + "body" : "This is a Prebid Native Creative. There are many like it, but this one is mine.", + "image" : { + "url" : "https://vcdn.adnxs.com/p/creative-image/9e/26/5f/b2/9e265fb2-50c8-43f0-88ef-a5a48a9d0dcf.jpg", + "height" : 2250, + "width" : 3000 + }, + "clickUrl" : "https://prebid.org/dev-docs/show-native-ads.html", + "clickTrackers" : [ + "..." + ], + "title" : "This is a Prebid Native Multi-Format Creative", + "impressionTrackers" : [ + "..." + ], + "sponsoredBy" : "Prebid.org" + }, + "timeToRespond" : 143, + "mediaType" : "native", + "bidderCode" : "appnexus", + "source" : "client", + "auctionId" : "1338a6fb-e514-48fc-8db6-872ddf3babdb", + "responseTimestamp" : 1516315716205, + "netRevenue" : true, + "pbDg" : "10.00", + "pbHg" : "10.00", + "ttl" : 300, + "status" : "targetingSet", + "height" : 0, + "statusMessage" : "Bid available", + "cpm" : 10, + "currency" : "USD" + } + ] + } +} +```
        diff --git a/dev-docs/publisher-api-reference/getBidResponsesForAdUnitCode.md b/dev-docs/publisher-api-reference/getBidResponsesForAdUnitCode.md index f57774ceaa..7e2c984bdd 100644 --- a/dev-docs/publisher-api-reference/getBidResponsesForAdUnitCode.md +++ b/dev-docs/publisher-api-reference/getBidResponsesForAdUnitCode.md @@ -1,11 +1,11 @@ --- layout: api_prebidjs title: pbjs.getBidResponsesForAdUnitCode(adUnitCode) -description: +description: getBidResponsesForAdUnitCode API +sidebarType: 1 --- - -Returns bidResponses for the specified adUnitCode. See full documentation at [pbjs.getBidResponses()](#module_pbjs.getBidResponses). +Returns bidResponses for the specified adUnitCode. See full documentation at [pbjs.getBidResponses()](/dev-docs/publisher-api-reference/getBidResponses.html). **Kind**: static method of `pbjs` diff --git a/dev-docs/publisher-api-reference/getConfig.md b/dev-docs/publisher-api-reference/getConfig.md index 99ac02fd88..d614562e17 100644 --- a/dev-docs/publisher-api-reference/getConfig.md +++ b/dev-docs/publisher-api-reference/getConfig.md @@ -1,28 +1,27 @@ --- layout: api_prebidjs title: pbjs.getConfig([string]) -description: +description: getConfig API +sidebarType: 1 --- ## Overview -The `getConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. Be careful with use of this function, as it returns a reference to the configuration instead of a clone. The readConfig function has been introduced for safer use. +The `getConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. Be careful with use of this function, as it returns a reference to the configuration instead of a clone. The readConfig function has been introduced for safer use. -{% highlight js %} +```javascript /* Get config object */ config.getConfig() /* Get debug config */ config.getConfig('debug') -{% endhighlight %} - +``` ### Subscribe The `getConfig` function contains a `subscribe` feature that adds a callback function to a set of listeners that are invoked whenever `setConfig` is called. The `subscribed` function will be passed the `options` object that was used in the `setConfig` call. Individual topics can be subscribed to by passing a string as the first parameter and a callback function as the second. For example: -{% highlight js %} - +```javascript /* Subscribe to all configuration changes */ getConfig((config) => console.log('config set:', config)); @@ -32,7 +31,6 @@ getConfig('logging', (config) => console.log('logging set:', config)); /* Unsubscribe */ const unsubscribe = getConfig(...); unsubscribe(); // no longer listening - -{% endhighlight %} +```
        diff --git a/dev-docs/publisher-api-reference/getConsentMetadata.md b/dev-docs/publisher-api-reference/getConsentMetadata.md new file mode 100644 index 0000000000..663dac84b9 --- /dev/null +++ b/dev-docs/publisher-api-reference/getConsentMetadata.md @@ -0,0 +1,25 @@ +--- +layout: api_prebidjs +title: pbjs.getConsentMetadata() +description: getConsentMetadata API +sidebarType: 1 +--- + +The `getConsentMetadata()` function will return basic information about the status of supported (and configured!) consent content within Prebid. + +```javascript +pbjs.getConsentMetadata() // returns e.g. +{ + "coppa": false, + "gdpr": { + "apiVersion": 2, + "consentStringSize": 100, + "gdprApplies": true, + "generatedAt": 1644358143306 + }, + "usp": { + "generatedAt": 1644358143306, + "usp": "1YYY" + } +} +``` diff --git a/dev-docs/publisher-api-reference/getEvents.md b/dev-docs/publisher-api-reference/getEvents.md index 64c0752206..ccf5c2711f 100644 --- a/dev-docs/publisher-api-reference/getEvents.md +++ b/dev-docs/publisher-api-reference/getEvents.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getEvents() -description: +description: getEvents API +sidebarType: 1 --- The `getEvents` method returns a copy of all emitted events since the page loaded. @@ -13,22 +14,25 @@ The `getEvents` method returns a copy of all emitted events since the page loade **Returns**: `array of objects` **Returned Object Params**: -- eventType (see table below) -- args (varies for each event type) -- id (only for bidWon, set to adUnit.code) -- elapsedTime + +* eventType (see table below) +* args (varies for each event type) +* id (only for bidWon, set to adUnit.code) +* elapsedTime The available events are: {: .table .table-bordered .table-striped } | Event | Description | Callback Arguments | -|---------------+-----------------------------------------|--------------------| +| --- | --- | --- | | auctionInit | The auction has started | Object containing auction details | | auctionEnd | The auction has ended | Object containing auction details | | beforeRequestBids | Bids are about to be requested from adapters (added in 3.x) | Array of adunits in the auction | | beforeBidderHttp | bidder network request is about be triggered | Array of Bid request objects | | bidRequested | A bid was requested from a specific bidder | Bid request object | | bidResponse | A bid response has arrived | Bid response object | +| seatNonBid | Prebid Server has returned nonbid information. Must be enabled in s2sConfig.extPrebid | None | +| bidRejected | A bid was rejected | Bid response object | | bidAdjustment | A bid was adjusted | Bid response object | | bidWon | A bid has won | Bid response object | | bidTimeout | A bid timed out | Array of objects with timed out bids | @@ -36,21 +40,22 @@ The available events are: | requestBids | Bids have been requested from adapters (i.e. pbjs.requestBids() was called) | None | | addAdUnits | Ad units have been added to the auction | None | | adRenderFailed| Ad rendering failed | Object containing 'reason' and 'message' | -| adRenderSucceeded | Ad rendering succeeded| Object containing 'doc', 'bid', and 'adId'. 'doc' is the DOM root containing the ad and may be `null` if it was rendered in a cross-origin iframe.| +| adRenderSucceeded | Ad rendering succeeded| Object containing 'doc', 'bid', and 'adId'. 'doc' is the DOM root containing the ad and may be `null` if it was rendered in a cross-origin iframe. This event indicates that the render function did not generate an error, it does not guarantee that tracking for this event has occurred yet.| | auctionDebug | An error was logged to the console | Object containing 'type' and 'arguments' | | bidderDone | A bidder has signaled they are done responding | Bid request object | | bidderError | A bidder responded with an error | Object with the XMLHttpRequest error and the bid request object `{ error, bidderRequest }` | | tcf2Enforcement | There was a TCF2 enforcement action taken | `{ storageBlocked: ['moduleA', 'moduleB'], biddersBlocked: ['moduleB'], analyticsBlocked: ['moduleC'] }` | +| bidAccepted | A bid was accepted and is about to be added to auction | Bid response object | The example below shows how these events can be used. -{% highlight js %} - pbjs.getEvents().forEach(event => { - console.log("event: "+event.eventType) - }); -{% endhighlight %} - +```javascript +pbjs.getEvents().forEach(event => { + console.log("event: "+event.eventType) +}); +``` ## See Also -- [onEvent](/dev-docs/publisher-api-reference/onEvent.html) -- [offEvent](/dev-docs/publisher-api-reference/offEvent.html) + +* [onEvent](/dev-docs/publisher-api-reference/onEvent.html) +* [offEvent](/dev-docs/publisher-api-reference/offEvent.html) diff --git a/dev-docs/publisher-api-reference/getHighestCpmBids.md b/dev-docs/publisher-api-reference/getHighestCpmBids.md index 804d7b6d71..6794aac0e2 100644 --- a/dev-docs/publisher-api-reference/getHighestCpmBids.md +++ b/dev-docs/publisher-api-reference/getHighestCpmBids.md @@ -1,14 +1,15 @@ --- layout: api_prebidjs title: pbjs.getHighestCpmBids([adUnitCode]) -description: +description: getHighestCpmBids API +sidebarType: 1 --- Use this method to retrieve an array of winning bids. -+ `pbjs.getHighestCpmBids()`: with no argument, returns an array of winning bid objects for each ad unit on page -+ `pbjs.getHighestCpmBids(adUnitCode)`: when passed an ad unit code, returns an array with the winning bid object for that ad unit +* `pbjs.getHighestCpmBids()`: with no argument, returns an array of winning bid objects for each ad unit on page +* `pbjs.getHighestCpmBids(adUnitCode)`: when passed an ad unit code, returns an array with the winning bid object for that ad unit {: .alert.alert-warning :} -Note that from **Prebid 3.0** onwards, `pbjs.getHighestCpmBids` will not return rendered bids. \ No newline at end of file +Note that from **Prebid 3.0** onwards, `pbjs.getHighestCpmBids` will not return rendered bids. diff --git a/dev-docs/publisher-api-reference/getHighestUnusedBidResponseForAdUnitCode.md b/dev-docs/publisher-api-reference/getHighestUnusedBidResponseForAdUnitCode.md index 6a0f1541d3..03058d70c3 100644 --- a/dev-docs/publisher-api-reference/getHighestUnusedBidResponseForAdUnitCode.md +++ b/dev-docs/publisher-api-reference/getHighestUnusedBidResponseForAdUnitCode.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getHighestUnusedBidResponseForAdUnitCode(adUnitCode) -description: +description: getHighestUnusedBidResponseForAdUnitCode API +sidebarType: 1 --- Use this method to retrieve the highest unused bid for the specified adUnit. Unused means not it's not rendered. diff --git a/dev-docs/publisher-api-reference/getNoBids.md b/dev-docs/publisher-api-reference/getNoBids.md index aa2ebd491f..deb7ff2082 100644 --- a/dev-docs/publisher-api-reference/getNoBids.md +++ b/dev-docs/publisher-api-reference/getNoBids.md @@ -1,10 +1,11 @@ --- layout: api_prebidjs title: pbjs.getNoBids() -description: +description: getNoBids API +sidebarType: 1 --- Use this method to get all of the bid requests that resulted in a NO_BID. These are bid requests that were sent to a bidder but, for whatever reason, the bidder decided not to bid on. Used by debugging snippet in the [Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html). -+ `pbjs.getNoBids()`: returns an array of bid request objects that were deliberately not bid on by a bidder. +* `pbjs.getNoBids()`: returns an array of bid request objects that were deliberately not bid on by a bidder. diff --git a/dev-docs/publisher-api-reference/getNoBidsForAdUnitCode.md b/dev-docs/publisher-api-reference/getNoBidsForAdUnitCode.md index f9c2648203..395e46d353 100644 --- a/dev-docs/publisher-api-reference/getNoBidsForAdUnitCode.md +++ b/dev-docs/publisher-api-reference/getNoBidsForAdUnitCode.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getNoBidsForAdUnitCode(adUnitCode) -description: +description: getNoBidsForAdUnitCode API +sidebarType: 1 --- diff --git a/dev-docs/publisher-api-reference/getPAAPIConfig.md b/dev-docs/publisher-api-reference/getPAAPIConfig.md new file mode 100644 index 0000000000..34aeb84746 --- /dev/null +++ b/dev-docs/publisher-api-reference/getPAAPIConfig.md @@ -0,0 +1,109 @@ +--- +layout: api_prebidjs +title: pbjs.getPAAPIConfig(options) +description: getPAAPIConfig API +sidebarType: 1 +--- + +Return the latest available PAAPI auction configuration for each ad unit, optionally filtered by auction or ad unit. + +**Kind**: static method of pbjs API. Only available when the [PAAPI module](/dev-docs/modules/paapi.html) is installed. + +**Returns**: `object` - Map from ad unit code to a (partial) [PAAPI auction configuration](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) object for that ad unit. Only the `componentAuctions` field is guaranteed to be present; future PAAPI modules may provide more. + +**Parameters**: + +{: .table .table-bordered .table-striped } +| Param | Scope | Type | Description | +| --- | --- | --- | --- | +| options | Optional | `Object` | | +| options.adUnitCode | Optional | `String` | Ad unit filter; if provided, only return configuration for this ad unit | +| options.auctionId | Optional | `String` | Auction filter; if provided, only return configuration from this auction | + +**Example**: + +```js +pbjs.getPAAPIConfig({adUnitCode: 'test-slot'}) +``` + +```json +{ + "test-slot": { + "componentAuctions": [ + { + "auctionSignals": { + "prebid": { + "bidfloor": 8.463, + "bidfloorcur": "USD" + } + }, + "trustedScoringSignalsUrl": "https://pa.openx.net/tss", + "sellerCurrency": "USD", + "perBuyerSignals": { + "https://explorefledge.com": { + "ortb2Imp": { + "secure": 1, + "exp": 900, + "ext": { + "ae": 1 + }, + "id": "1", + "banner": { + "format": [ + { + "h": 250, + "w": 300 + } + ], + "w": 300, + "h": 250, + "battr": [ + 17 + ], + "topframe": 1 + }, + "tagid": "538703464", + "bidfloor": 0.02, + "bidfloorcur": "USD" + } + } + }, + "perBuyerExperimentGroupIds": { + "https://privacysandbox.openx.net": 1 + }, + "seller": "https://pa.openx.net", + "decisionLogicUrl": "https://pa.openx.net/s/537291777.js", + "interestGroupBuyers": [ + "https://explorefledge.com" + ], + "sellerSignals": { + "igDomainToSeat": { + "https://privacysandbox.openx.net": "openx" + }, + "bcat": { + "IABv1": [ + "IAB7-44", + "IAB26", + "IAB25" + ], + "IABv2": [ + "231" + ] + }, + "adUnitId": "538703464", + "currency": "USD", + "advertiserId": "537113485", + "auctionId": "b49d3b43-1094-4686-a67c-f5abb695db2d", + "igDomainToDsp": { + "https://explorefledge.com": "560434471", + }, + "reportingUrl": "https://privacysandbox-reporting.openx.net/fledgeReporting", + "publisherId": "537143056", + "floor": 8.463, + "auctionTimestamp": 1707259930 + } + } + ] + } +} +``` diff --git a/dev-docs/publisher-api-reference/getUserIds.md b/dev-docs/publisher-api-reference/getUserIds.md index 7aea7bb6cb..839454f111 100644 --- a/dev-docs/publisher-api-reference/getUserIds.md +++ b/dev-docs/publisher-api-reference/getUserIds.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getUserIds() -description: +description: getUserIds API +sidebarType: 1 --- @@ -10,6 +11,6 @@ To use this function, include the [UserId module](/dev-docs/modules/userId.html) If you need to export the user IDs stored by Prebid User ID module, the `getUserIds()` function will return an object formatted the same as bidRequest.userId. -``` +```javascript pbjs.getUserIds() // returns object like bidRequest.userId. e.g. {"pubcid":"1111", "tdid":"2222"} -``` \ No newline at end of file +``` diff --git a/dev-docs/publisher-api-reference/getUserIdsAsEids.md b/dev-docs/publisher-api-reference/getUserIdsAsEids.md index ba4793cdb3..2aa58a6965 100644 --- a/dev-docs/publisher-api-reference/getUserIdsAsEids.md +++ b/dev-docs/publisher-api-reference/getUserIdsAsEids.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.getUserIdsAsEids() -description: +description: getUserIdsAsEids API +sidebarType: 1 --- @@ -10,7 +11,7 @@ To use this function, include the [UserId module](/dev-docs/modules/userId.html) If you need to export the user IDs stored by Prebid User ID module in ORTB Eids frormat, then the `getUserIdsAsEids()` function will return an array formatted as per [ORTB Eids](https://github.com/prebid/Prebid.js/blob/master/modules/userId/eids.md). -``` +```javascript pbjs.getUserIdsAsEids() // returns userIds in ORTB Eids format. e.g. [ { @@ -32,4 +33,4 @@ pbjs.getUserIdsAsEids() // returns userIds in ORTB Eids format. e.g. }] } ] -``` \ No newline at end of file +``` diff --git a/dev-docs/publisher-api-reference/getUserIdsAsync.md b/dev-docs/publisher-api-reference/getUserIdsAsync.md new file mode 100644 index 0000000000..fb00216016 --- /dev/null +++ b/dev-docs/publisher-api-reference/getUserIdsAsync.md @@ -0,0 +1,19 @@ +--- +layout: api_prebidjs +title: pbjs.getUserIdsAsync() +description: getUserIdsAsync API +sidebarType: 1 +--- + +{: .alert.alert-info :} +To use this function, include the [UserId module](/dev-docs/modules/userId.html) in your Prebid.js build. + +`getUserIdsAsync()` returns a promise to the same value returned by [getUserIds()](/dev-docs/publisher-api-reference/getUserIds.html), but it's guaranteed to resolve only once the complete set of IDs is available: + +```javascript +pbjs.getUserIdsAsync().then(function (userIds) { + // all IDs are available here: + pbjs.getUserIds() // same as the `userIds` argument + pbjs.getUserIdsAsEids() +}); +``` diff --git a/dev-docs/publisher-api-reference/installedModules.md b/dev-docs/publisher-api-reference/installedModules.md index 07ef0f3291..51686a3cdd 100644 --- a/dev-docs/publisher-api-reference/installedModules.md +++ b/dev-docs/publisher-api-reference/installedModules.md @@ -1,17 +1,16 @@ --- layout: api_prebidjs title: pbjs.installedModules -description: +description: installedModules API +sidebarType: 1 --- When a Prebid.js package is built, the list of modules compiled into it are placed in the pbjs.installedModules array. e.g. if this builds the package: -``` + +```bash gulp build --modules=a,b,c ``` pbjs.installedModules would have the value ['a','b','c']. - -If you happen to compile in all 400+ modules (not a good idea!), the value of pbjs.installedModules will be an empty array. - diff --git a/dev-docs/publisher-api-reference/markWinningBidAsUsed.md b/dev-docs/publisher-api-reference/markWinningBidAsUsed.md index 935739943b..45dfbdd629 100644 --- a/dev-docs/publisher-api-reference/markWinningBidAsUsed.md +++ b/dev-docs/publisher-api-reference/markWinningBidAsUsed.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.markWinningBidAsUsed(markBidRequest) -description: +description: markWinningBidAsUsed API +sidebarType: 1 --- @@ -16,4 +17,4 @@ If you know the adId, then be specific, otherwise Prebid will retrieve the winni | Param | Type | Description | | --- | --- | --- | | adUnitCode | `string` | (Optional) The ad unit code | -| adId | `string` | (Optional) The id representing the ad we want to mark | \ No newline at end of file +| adId | `string` | (Optional) The id representing the ad we want to mark | diff --git a/dev-docs/publisher-api-reference/mergeBidderConfig.md b/dev-docs/publisher-api-reference/mergeBidderConfig.md new file mode 100644 index 0000000000..25673d0027 --- /dev/null +++ b/dev-docs/publisher-api-reference/mergeBidderConfig.md @@ -0,0 +1,21 @@ +--- +layout: api_prebidjs +title: pbjs.mergeBidderConfig(options) +description: mergeBidderConfig API +sidebarType: 1 +--- + +This is the same as [`setBidderConfig(options, true)`](/dev-docs/publisher-api-reference/setBidderConfig.html) -- it merges the supplied bidder config into the config structure rather than replacing it. + +The page usage is: + +```javascript +pbjs.mergeBidderConfig({ + bidders: ['bidderA'], + config: { + customArg: "customVal" + } +}); +``` + +Intrepration: When 'bidderA' calls `getConfig('customArg')`, it will receive the object that contains 'customArg'. If any other bidder calls `getConfig('customArg')`, it will receive nothing. diff --git a/dev-docs/publisher-api-reference/mergeConfig.md b/dev-docs/publisher-api-reference/mergeConfig.md new file mode 100644 index 0000000000..ef31eacf83 --- /dev/null +++ b/dev-docs/publisher-api-reference/mergeConfig.md @@ -0,0 +1,11 @@ +--- +layout: api_prebidjs +title: pbjs.mergeConfig(options) +description: mergeConfig API +sidebarType: 1 +--- + +This is the same as [`setConfig(options)`](/dev-docs/publisher-api-reference/setConfig.html) except that it merges the supplied config into the structure rather than replacing it. + +This is a convenience function, particularly useful to real time data modules, so one doesn't have to read the +config structure, update it, then call setConfig. diff --git a/dev-docs/publisher-api-reference/offEvent.md b/dev-docs/publisher-api-reference/offEvent.md index 31dc71af82..603b168032 100644 --- a/dev-docs/publisher-api-reference/offEvent.md +++ b/dev-docs/publisher-api-reference/offEvent.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.offEvent(eventType, handler, id) -description: +description: offEvent API +sidebarType: 1 --- Turns off an event callback defined with [onEvent](/dev-docs/publisher-api-reference/onEvent.html) @@ -12,7 +13,7 @@ Turns off an event callback defined with [onEvent](/dev-docs/publisher-api-refer **Returns**: none -See the [getEvents](/publisher-api-reference/getEvents.html) function for the full list of eventTypes supported. +See the [getEvents](/dev-docs/publisher-api-reference/getEvents.html) function for the full list of eventTypes supported. Causes PBJS to search through registered event callbacks and remove the supplied callbackFunction for the specifc eventType. @@ -23,34 +24,34 @@ events for a specific item in the event context. Example -{% highlight js %} - /* This handler will be called only for rightAdUnit */ - /* Uses the `pbjs.offEvent` method to remove the handler once it has been called */ - var bidWonHandler = function bidWonHandler() { - console.log('bidWonHandler: ', arguments); - pbjs.offEvent('bidWon', bidWonHandler, rightAdUnit); - }; - - var rightAdUnit="/111111/right"; - pbjs.que.push(function () { - var adUnits = [{ - code: rightAdUnit, - ... - },{ - ... - }]; - pbjs.addAdUnits(adUnits); - pbjs.requestBids({ - ... - }); - - /* Register a callback for just the rightSlot `bidWon` event */ - /* Note that defining an event that uses the 3rd parameter must come after initiating the auction */ - pbjs.onEvent('bidWon', bidWonHandler, rightAdUnit); - - ... -{% endhighlight %} +```javascript +/* This handler will be called only for rightAdUnit */ +/* Uses the `pbjs.offEvent` method to remove the handler once it has been called */ +var bidWonHandler = function bidWonHandler() { + console.log('bidWonHandler: ', arguments); + pbjs.offEvent('bidWon', bidWonHandler, rightAdUnit); +}; + +var rightAdUnit="/111111/right"; +pbjs.que.push(function () { + var adUnits = [{ + code: rightAdUnit, + // ... + },{ + // ... + }]; + pbjs.addAdUnits(adUnits); + pbjs.requestBids({ + //... + }); + + /* Register a callback for just the rightSlot `bidWon` event */ + /* Note that defining an event that uses the 3rd parameter must come after initiating the auction */ + pbjs.onEvent('bidWon', bidWonHandler, rightAdUnit); +}); +``` ## See Also -- [getEvents](/dev-docs/publisher-api-reference/getEvents.html) -- [onEvent](/dev-docs/publisher-api-reference/onEvent.html) + +* [getEvents](/dev-docs/publisher-api-reference/getEvents.html) +* [onEvent](/dev-docs/publisher-api-reference/onEvent.html) diff --git a/dev-docs/publisher-api-reference/onEvent.md b/dev-docs/publisher-api-reference/onEvent.md index 6e779971ca..92d26e975a 100644 --- a/dev-docs/publisher-api-reference/onEvent.md +++ b/dev-docs/publisher-api-reference/onEvent.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.onEvent(eventType, handler, id) -description: +description: onEvent API +sidebarType: 1 --- This routine allows the page (or module) to create a callback function that's invoked when heading bidding events are fired. @@ -14,6 +15,9 @@ This routine allows the page (or module) to create a callback function that's in See the [getEvents](/dev-docs/publisher-api-reference/getEvents.html) function for the full list of eventTypes supported. +{: .alert.alert-info :} +The `adRenderSucceeded` event indicates that the render function did not generate an error, it does not guarantee that tracking for this event has occurred yet. + The optional `id` parameter provides more finely-grained event callback registration. This makes it possible to register callback events for a specific item in the event context. @@ -27,39 +31,42 @@ this method registers the callback for every `bidWon` event. Currently, `bidWon` is the only event that accepts the `id` parameter. Example 1: Basic event logging -``` - /* Log when ad units are added to Prebid */ - pbjs.onEvent('addAdUnits', function() { - console.log('Ad units were added to Prebid.') - console.log(pbjs.adUnits); - }); - /* Log when Prebid wins the ad server auction */ - pbjs.onEvent('bidWon', function(data) { - console.log(data.bidderCode+ ' won the ad server auction for ad unit ' +data.adUnitCode+ ' at ' +data.cpm+ ' CPM'); - }); +```javascript +/* Log when ad units are added to Prebid */ +pbjs.onEvent('addAdUnits', function() { + console.log('Ad units were added to Prebid.') + console.log(pbjs.adUnits); +}); +/* Log when Prebid wins the ad server auction */ +pbjs.onEvent('bidWon', function(data) { + console.log(data.bidderCode+ ' won the ad server auction for ad unit ' +data.adUnitCode+ ' at ' +data.cpm+ ' CPM'); +}); ``` Example 2: Dynamically modify the auction -``` - var bidderFilter = function bidderFilter(adunits) { - // pub-specific logic to optimize bidders - // e.g. "remove any that haven't bid in the last 4 refreshes" - }; - pbjs.onEvent('beforeRequestBids', bidderFilter); + +```javascript +var bidderFilter = function bidderFilter(adunits) { + // pub-specific logic to optimize bidders + // e.g. "remove any that haven't bid in the last 4 refreshes" +}; +pbjs.onEvent('beforeRequestBids', bidderFilter); ``` Example 3: Log errors and render fails to your own endpoint -``` - pbjs.onEvent('adRenderFailed', function () { - // pub-specific logic to call their own endpoint - }); - pbjs.onEvent('auctionDebug', function () { - // pub-specific logic to call their own endpoint - }); + +```javascript +pbjs.onEvent('adRenderFailed', function () { + // pub-specific logic to call their own endpoint + }); +pbjs.onEvent('auctionDebug', function () { + // pub-specific logic to call their own endpoint + }); ``` ## See Also -- [getEvents](/dev-docs/publisher-api-reference/getEvents.html) -- [offEvent](/dev-docs/publisher-api-reference/offEvent.html) + +* [getEvents](/dev-docs/publisher-api-reference/getEvents.html) +* [offEvent](/dev-docs/publisher-api-reference/offEvent.html) diff --git a/dev-docs/publisher-api-reference/readConfig.md b/dev-docs/publisher-api-reference/readConfig.md index 734647e762..8d1c53a0f6 100644 --- a/dev-docs/publisher-api-reference/readConfig.md +++ b/dev-docs/publisher-api-reference/readConfig.md @@ -2,17 +2,18 @@ layout: api_prebidjs title: pbjs.readConfig([string]) description: +sidebarType: 1 --- -The `readConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. The readConfig function has been introduced for safer use of the getConfig functionality, as it returns a clone. +The `readConfig` function is used for retrieving the current configuration object or subscribing to configuration updates. When called with no parameters, the entire config object is returned. When called with a string parameter, a single configuration property matching that parameter is returned. The readConfig function has been introduced for safer use of the getConfig functionality, as it returns a clone. -{% highlight js %} +```javascript /* Get config object */ config.readConfig() /* Get debug config */ config.readConfig('debug') -{% endhighlight %} +```
        diff --git a/dev-docs/publisher-api-reference/refreshUserIds.md b/dev-docs/publisher-api-reference/refreshUserIds.md index cfb4edaabb..8e7eccb5f2 100644 --- a/dev-docs/publisher-api-reference/refreshUserIds.md +++ b/dev-docs/publisher-api-reference/refreshUserIds.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.refreshUserIds(options, callback) -description: +description: refreshUserIds API +sidebarType: 1 --- @@ -17,8 +18,7 @@ The `refreshUserIds` function allows you to force either all or a subset of user | options.submoduleNames | optional | Array of strings | The userId submodule names that should be refreshed. If this option is omitted, all userId submodules are refreshed. | | callback | optional | Function | Callback that is called after refreshing user ids has completed | - -``` +```javascript pbjs.refreshUserIds(); pbjs.refreshUserIds({ submoduleNames: ['britepoolId'] }, () => console.log("Done!")); -``` \ No newline at end of file +``` diff --git a/dev-docs/publisher-api-reference/registerSignalSources.md b/dev-docs/publisher-api-reference/registerSignalSources.md new file mode 100644 index 0000000000..aca0b73b8d --- /dev/null +++ b/dev-docs/publisher-api-reference/registerSignalSources.md @@ -0,0 +1,35 @@ +--- +layout: api_prebidjs +title: pbjs.registerSignalSources() +description: enabling ESP (encrypt signals) for Open Bidding +sidebarType: 1 +--- + +{: .alert.alert-info :} +To use this function, include the [UserId module](/dev-docs/modules/userId.html) in your Prebid.js build. + +This function will register all configured encrypted signals as described in the [UserId module ESP configuration](/dev-docs/modules/userId.html#esp-configurations). + +The condition can only be called under two conditions + +1. The `pbjs.setConfig` call with the user sync config must have already happend +2. The `gpt.js` tag must already be loaded + +Example + +```js +// initialze command queues +window.pbjs = window.pbjs || { que: []}; +window.googletag = window.googletag || { cmd: []}; + +// wait for prebid and configure it +const prebidConfigured = new Promise(resolve => window.pbjs.que.push(resolve)) + .then(() => window.pbjs.setConfig(/* your prebid config */)); + +// wait for gpt.js +const gptLoaded = new Promise(resolve => window.googletag.cmd.push(resolve)); + +// wait for gpt and prebid to be loaded and configured +Promise.all([prebidConfigured, gptLoaded]) + .then(() => window.pbjs.registerSignalSources()); +``` diff --git a/dev-docs/publisher-api-reference/removeAdUnit.md b/dev-docs/publisher-api-reference/removeAdUnit.md index 1edef5a24b..e70baf5f7c 100644 --- a/dev-docs/publisher-api-reference/removeAdUnit.md +++ b/dev-docs/publisher-api-reference/removeAdUnit.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.removeAdUnit(adUnitCode) -description: +description: removeAdUnit API +sidebarType: 1 --- @@ -9,7 +10,6 @@ Remove adUnit(s) from the pbjs configuration, If adUnit is not given then it wil **Kind**: static method of pbjs API. - {: .table .table-bordered .table-striped } | Param | Scope | Type | Description | | --- | --- | --- | --- | diff --git a/dev-docs/publisher-api-reference/renderAd.md b/dev-docs/publisher-api-reference/renderAd.md index f642f845a8..8e07f516e1 100644 --- a/dev-docs/publisher-api-reference/renderAd.md +++ b/dev-docs/publisher-api-reference/renderAd.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs -title: pbjs.renderAd(doc, id) -description: +title: pbjs.renderAd(doc, id, options) +description: renderAd API +sidebarType: 1 --- @@ -9,9 +10,22 @@ This function will render the ad (based on params) in the given iframe document **Kind**: static method of pbjs API +`options.clickThrough` optionally enables publishers to count clicks on prebid inventory in their distributing adserver. +The publisher may call renderAd with a third param accepting an object where the value of clickThrough will be checked. +If this property is set the value of clickThrough will replace any occurrence of ${CLICKTHROUGH} inside of the properties ad and adUrl. If no match is found nothing will be replaced. + +{: .alert.alert-info :} +Note: In regards to `options.clickThrough`: + +- To make use of this feature, bid adapters would be required to respond with ad tags including the ${CLICKTHROUGH} macro. +- The renderAd function must be invoked with the options argument. Ex: `renderAd(doc, bidId, {clickThrough: 'https://someadserverclickurl.com'});` +- Not compatible with safeframes (since the logic around rendering safeframe's does not invoke the renderAd function). +- Not supported with Prebid Universal Creative at this time, only the standard pbjs.renderAd method. {: .table .table-bordered .table-striped } | Param | Scope | Type | Description | | --- | --- | --- | --- | | doc | Required | `object` | document | | id | Required | `string` | bid id to locate the ad | +| options | Optional | `object` | object containing other additional params to be used (listed below) | +| options.clickThrough | Optional | `string` | a url used to keep track of clicks on the ad to be rendered (used to resolve the ${CLICKTHROUGH} macro) | diff --git a/dev-docs/publisher-api-reference/requestBids.md b/dev-docs/publisher-api-reference/requestBids.md index 103b2db8d2..94af1512c9 100644 --- a/dev-docs/publisher-api-reference/requestBids.md +++ b/dev-docs/publisher-api-reference/requestBids.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.requestBids(requestObj) -description: +description: requestBids API +sidebarType: 1 --- @@ -9,6 +10,9 @@ Request bids. When `adUnits` or `adUnitCodes` are not specified, request bids fo **Kind**: static method of pbjs API +**Returns**: a promise to an object `{bids, timedOut, auctionId}` - [see below](#result) + +**Parameters**: {: .table .table-bordered .table-striped } | Param | Scope | Type | Description | @@ -17,12 +21,26 @@ Request bids. When `adUnits` or `adUnitCodes` are not specified, request bids fo | requestObj.adUnitCodes | Optional | `Array of strings` | adUnit codes to request. Use this or `requestObj.adUnits`. Default to all `adUnitCodes` if empty. | | requestObj.adUnits | Optional | `Array of objects` | AdUnitObjects to request. Use this or `requestObj.adUnitCodes`. Default to all `adUnits` if empty. | | requestObj.timeout | Optional | `Integer` | Timeout for requesting the bids specified in milliseconds | -| requestObj.bidsBackHandler | Optional | `function` | Callback to execute when all the bid responses are back or the timeout hits. Callback will be passed three parameters, the [bidResponses](#module_pbjs.getBidResponses) themselves, a `timedOut` flag (true if any bidders timed out) and the `auctionId`. | -| requestObj.labels | Optional | `Array of strings` | Defines [labels](#labels) that may be matched on ad unit targeting conditions. | +| requestObj.bidsBackHandler | Optional | `function` | Callback to execute when all the bid responses are back or the timeout hits. Callback will be passed 3 arguments - `bids`, `timedOut`, and `auctionId` - [see below](#result) | +| requestObj.labels | Optional | `Array of strings` | Defines `labels` that may be matched on ad unit targeting conditions. | | requestObj.auctionId | Optional | `String` | Defines an auction ID to be used rather than having the system generate one. This can be useful if there are multiple wrappers on a page and a single auction ID is desired to tie them together in analytics. | +| requestObj.ortb2 | Optional | `Object` | Additional [first-party data](/features/firstPartyData.html) to use for this auction only | +| requestObj.ttlBuffer | Optional | `Number` | TTL buffer override for this auction. See [setConfig({ttlBuffer})](/dev-docs/publisher-api-reference/setConfig.html#setConfig-ttlBuffer) | -Example call -``` + + +**Result**: + +{: .table .table-bordered .table-stripped :} +| Param | Type | Description | +| --- | --- | --- | +| bids | Object | Bids received; see [getBidResponses](getBidResponses.html) for details | +| timedOut | Boolean | true if any bidder timed out | +| auctionId | String | the auction's ID | + +Example call: + +```javascript pbjs.requestBids({ bidsBackHandler: sendAdserverRequest, timeout: 1000, @@ -31,11 +49,11 @@ pbjs.requestBids({ ``` Example parameters sent to the bidsBackHandler: -``` + +```javascript function sendAdserverRequest(bids, timedOut, auctionId) { // bids // {"test-div":{"bids":[{"bidderCode":"bidderA", ...}]}} - // See [getBidResponses function](#module_pbjs.getBidResponses) for details // timedOut=false // auctionId="130aad5e-eb1a-4b7d-8939-0663ba251887" ... diff --git a/dev-docs/publisher-api-reference/setBidderConfig.md b/dev-docs/publisher-api-reference/setBidderConfig.md index accaca9548..3a2cbf0a26 100644 --- a/dev-docs/publisher-api-reference/setBidderConfig.md +++ b/dev-docs/publisher-api-reference/setBidderConfig.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs -title: pbjs.setBidderConfig(options) -description: +title: pbjs.setBidderConfig(options, mergeFlag) +description: setBidderConfig API +sidebarType: 1 --- @@ -12,18 +13,22 @@ globally available to all bidder adapters. This makes sense because most of these settings are global in nature. However, there are use cases where different bidders require different data, or where certain parameters apply only to a given bidder. Use `setBidderConfig` when you need to support these cases. +Note if you would like to add to existing config you can pass `true` for the optional second `mergeFlag` argument like `setBidderConfig(options, true)`. If not passed, this argument defaults to false and `setBidderConfig` replaces all values for specified bidders. + The page usage is: -{% highlight js %} +```javascript pbjs.setBidderConfig({ bidders: ['bidderA'], config: { customArg: "customVal" } }); -{% endhighlight %} +``` + or -{% highlight js %} + +```javascript pbjs.setBidderConfig({ bidders: ['bidderB'], config: { @@ -47,11 +52,12 @@ pbjs.setBidderConfig({ } } }); -{% endhighlight %} +``` How to interpret these examples: -- When 'bidderA' calls `getConfig('customArg')`, it will receive the object that contains 'customArg'. If any other bidder calls `getConfig('customArg')`, it will receive nothing. -- When 'bidderB' calls `getConfig('ortb2')`, it will receive this override definition rather than whatever else might have been defined globally. If any other bidder calls `getConfig('ortb2')`, it will receive the globally defined objects. + +* When 'bidderA' calls `getConfig('customArg')`, it will receive the object that contains 'customArg'. If any other bidder calls `getConfig('customArg')`, it will receive nothing. +* When 'bidderB' calls `getConfig('ortb2')`, it will receive this override definition rather than whatever else might have been defined globally. If any other bidder calls `getConfig('ortb2')`, it will receive the globally defined objects. {: .alert.alert-info :} This function is also used by the `schain` feature. Refer to the [schain](/dev-docs/modules/schain.html) documentation for examples. diff --git a/dev-docs/publisher-api-reference/setConfig.md b/dev-docs/publisher-api-reference/setConfig.md index b2d9c12be6..73ad3d0643 100644 --- a/dev-docs/publisher-api-reference/setConfig.md +++ b/dev-docs/publisher-api-reference/setConfig.md @@ -1,50 +1,59 @@ --- layout: api_prebidjs title: pbjs.setConfig(options) -description: +description: setConfig API +sidebarType: 1 --- - -`setConfig` supports a number of advanced configuration options: +`setConfig` supports a number of configuration options. Every +call to setConfig overwrites supplied values at the top level. e.g. if `ortb2` is provided as a value, any previously-supplied `ortb2` values will disappear. +If this is not the desired behavior, there is a [`mergeConfig()`](mergeConfig.html) function that will preserve previous values to do not conflict with the newly supplied values. See below for usage examples. Core config: -+ [Debugging](#setConfig-Debugging) -+ [Device Access](#setConfig-deviceAccess) -+ [Bidder Timeouts](#setConfig-Bidder-Timeouts) -+ [Max Requests Per Origin](#setConfig-Max-Requests-Per-Origin) -+ [Disable Ajax Timeout](#setConfig-Disable-Ajax-Timeout) -+ [Set Timeout Buffer](#setConfig-timeoutBuffer) -+ [Turn on send all bids mode](#setConfig-Send-All-Bids) -+ [Configure send bids control](#setConfig-Send-Bids-Control) -+ [Bid cache](#setConfig-Use-Bid-Cache) -+ [Set the order in which bidders are called](#setConfig-Bidder-Order) -+ [Set the page URL](#setConfig-Page-URL) -+ [Set the publisher's domain](#setConfig-Publisher-Domain) -+ [Set price granularity](#setConfig-Price-Granularity) -+ [Set media type price granularity](#setConfig-MediaType-Price-Granularity) -+ [Configure server-to-server header bidding](#setConfig-Server-to-Server) -+ [Configure user syncing](#setConfig-Configure-User-Syncing) -+ [Configure targeting controls](#setConfig-targetingControls) -+ [Configure responsive ad units with `sizeConfig` and `labels`](#setConfig-Configure-Responsive-Ads) -+ [COPPA](#setConfig-coppa) -+ [First Party Data](#setConfig-fpd) -+ [Caching VAST XML](#setConfig-vast-cache) -+ [Site Metadata](#setConfig-site) -+ [Generic Configuration](#setConfig-Generic-Configuration) -+ [Troubleshooting configuration](#setConfig-Troubleshooting-your-configuration) +* [Debugging](#setConfig-Debugging) +* [Device Access](#setConfig-deviceAccess) +* [Bidder Timeouts](#setConfig-Bidder-Timeouts) +* [Enable sharing of transaction IDs](#setConfig-enableTIDs) +* [Max Requests Per Origin](#setConfig-Max-Requests-Per-Origin) +* [Disable Ajax Timeout](#setConfig-Disable-Ajax-Timeout) +* [Set Timeout Buffer](#setConfig-timeoutBuffer) +* [Set TTL Buffer](#setConfig-ttlBuffer) +* [Turn on send all bids mode](#setConfig-Send-All-Bids) +* [Configure send bids control](#setConfig-Send-Bids-Control) +* [Bid cache](#setConfig-Use-Bid-Cache) +* [Minimum bid cache TTL](#setConfig-minBidCacheTTL) +* [Event history TTL](#setConfig-eventHistoryTTL) +* [Set the order in which bidders are called](#setConfig-Bidder-Order) +* [Set the page URL](#setConfig-Page-URL) +* [Set price granularity](#setConfig-Price-Granularity) +* [Set media type price granularity](#setConfig-MediaType-Price-Granularity) +* [Set custom cpm rounding](#setConfig-Cpm-Rounding) +* [Configure server-to-server header bidding](#setConfig-Server-to-Server) +* [Configure user syncing](#setConfig-Configure-User-Syncing) +* [Configure targeting controls](#setConfig-targetingControls) +* [Configure responsive ad units with `sizeConfig` and `labels`](#setConfig-Configure-Responsive-Ads) +* [COPPA](#setConfig-coppa) +* [First Party Data](#setConfig-fpd) +* [Video Module to integrate with Video Players](#video-module) +* [Caching VAST XML](#setConfig-vast-cache) +* [Site Metadata](#setConfig-site) +* [Disable performance metrics](#setConfig-performanceMetrics) +* [Setting alias registry to private](#setConfig-aliasRegistry) +* [Generic Configuration](#setConfig-Generic-Configuration) +* [Troubleshooting configuration](#setConfig-Troubleshooting-your-configuration) Module config: other options to `setConfig()` are available if the relevant module is included in the Prebid.js build. -+ [Currency module](/dev-docs/modules/currency.html) -+ [Consent Management](/dev-docs/modules/consentManagement.html#page-integration) -+ [User ID module](/dev-docs/modules/userId.html#configuration) -+ [Adpod](/dev-docs/modules/adpod.html) -+ [IAB Category Translation](/dev-docs/modules/categoryTranslation.html) +* [Currency module](/dev-docs/modules/currency.html) +* [Consent Management](/dev-docs/modules/consentManagement.html#page-integration) +* [User ID module](/dev-docs/modules/userId.html#configuration) +* [Adpod](/dev-docs/modules/adpod.html) +* [IAB Category Translation](/dev-docs/modules/categoryTranslation.html) - + #### Debugging @@ -55,34 +64,37 @@ Note that debugging can be specified for a specific page view by adding `pbjs_debug=true` to the URL's query string. e.g. /pbjs_demo.html?pbjs_debug=true See [Prebid.js troubleshooting guide](/troubleshooting/troubleshooting-guide.html) for more information. Turn on debugging permanently in the page: -{% highlight js %} + +```javascript pbjs.setConfig({ debug: true }); -{% endhighlight %} +``` {: .alert.alert-warning :} Note that turning on debugging for Prebid Server causes most server-side adapters to consider it a test request, meaning that they won't count on reports. - + #### Device Access You can prevent Prebid.js from reading or writing cookies or HTML localstorage by setting this flag: -{% highlight js %} +```javascript pbjs.setConfig({ deviceAccess: false }); -{% endhighlight %} +``` This can be useful in GDPR, CCPA, COPPA or other privacy scenarios where a publisher has determined that header bidding should not read from or write the user's device. - +Note that bid adapters are normally denied access to device storage even when `deviceAccess` is `true`; see the [`storageAllowed` bidder setting](/dev-docs/publisher-api-reference/bidderSettings.html#deviceAccess). + + #### Bidder Timeouts Set a global bidder timeout: -{% highlight js %} +```javascript pbjs.setConfig({ bidderTimeout: 3000 }); -{% endhighlight %} +``` {: .alert.alert-warning :} **Bid Timeouts and JavaScript Timers** @@ -90,47 +102,69 @@ Note that it's possible for the timeout to be triggered later than expected, lea With a busy page load, bids can be included in the auction even if the time to respond is greater than the timeout set by Prebid.js. However, we do close the auction immediately if the threshold is greater than 200ms, so you should see a drop off after that period. For more information about the asynchronous event loop and `setTimeout`, see [How JavaScript Timers Work](https://johnresig.com/blog/how-javascript-timers-work/). + + +#### Enable sharing of transaction IDs + +Prebid generates unique IDs for both auctions and ad units within auctions; these can be used by DSPs to correlate requests from different sources, which is useful for many applications but also a potential privacy concern. Since version 8 they are disabled by default (see [release notes](/dev-docs/pb8-notes.html)), and can be re-enabled with `enableTIDs`: + +```javascript +pbjs.setConfig({ enableTIDs: true }); +``` + #### Max Requests Per Origin - + Since browsers have a limit of how many requests they will allow to a specific domain before they block, Prebid.js will queue auctions that would cause requests to a specific origin to exceed that limit. The limit is different for each browser. Prebid.js defaults to a max of `4` requests per origin. That value can be configured with `maxRequestsPerOrigin`. -{% highlight js %} +```javascript // most browsers allow at least 6 requests, but your results may vary for your user base. Sometimes using all // `6` requests can impact performance negatively for users with poor internet connections. pbjs.setConfig({ maxRequestsPerOrigin: 6 }); // to emulate pre 1-x behavior and have all auctions queue (no concurrent auctions), you can set it to `1`. pbjs.setConfig({ maxRequestsPerOrigin: 1 }); -{% endhighlight %} +``` #### Disable Ajax Timeout - + Prebid core adds a timeout on XMLHttpRequest request to terminate the request once auction is timedout. Since Prebid is ignoring all the bids after timeout it does not make sense to continue the request after timeout. However, you have the option to disable this by using `disableAjaxTimeout`. -{% highlight js %} +```javascript pbjs.setConfig({ disableAjaxTimeout: true }); -{% endhighlight %} +``` #### Set Timeout Buffer - + Prebid core adds a timeout buffer to extend the time that bidders have to return a bid after the auction closes. This buffer is used to offset the "time slippage" of the setTimeout behavior in browsers. Prebid.js sets the default value to 400ms. You can change this value by setting `timeoutBuffer` to the amount of time you want to use. The following example sets the buffer to 300ms. -{% highlight js %} +```javascript pbjs.setConfig({ timeoutBuffer: 300 }); -{% endhighlight %} +``` + +#### Set TTL Buffer + + + +When an adapter bids, it provides a TTL (time-to-live); the bid is considered expired and unusuable after that time has elapsed. Core subtracts from it a buffer of 1 second; that is, a bid with TTL of 30 seconds is considered expired after 29 seconds. You can adjust this buffer with: + +```javascript +pbjs.setConfig({ + ttlBuffer: 10 // TTL buffer in seconds +}); +``` #### Send All Bids - + When enableSendAllBids is **true** (the default), the page will send keywords for all bidders to your ad server. The ad server can then make the decision on which bidder will win. Some ad servers, such as Google Ad Manager, can then generate reporting on historical bid prices from all bidders. @@ -147,7 +181,7 @@ Note that targeting config must be set before either `pbjs.setTargetingForGPTAsy ##### Example results where enableSendAllBids is true -{% highlight bash %} +```bash { "hb_adid_audienceNetw": "1663076dadb443d", "hb_pb_audienceNetwor": "9.00", @@ -172,7 +206,7 @@ Note that targeting config must be set before either `pbjs.setTargetingForGPTAsy "hb_size": "300x250", "hb_format": "banner" } -{% endhighlight %} +``` You can see how the number of ad server targeting variable could get large when many bidders are present. @@ -199,11 +233,11 @@ pbjs.setConfig({ }); ``` - + #### Configure Send Bids Control - + The `sendBidsControl` object passed to `pbjs.setConfig` provides the publisher with the ability to adjust the targeting behavior when [sendAllBids](#setConfig-Send-All-Bids) is enabled. @@ -224,6 +258,7 @@ pbjs.setConfig({ } }); ``` + When this property is set, the value assigned to `bidLimit` is the maximum number of bids that will be sent to the ad server. If `bidLimit` is set to 0, sendAllBids will have no maximum bid limit and *all* bids will be sent. This setting can be helpful if you know that your ad server has a finite limit to the amount of query characters it will accept and process. {: .alert.alert-info :} @@ -231,7 +266,7 @@ Note that this feature overlaps and can be used in conjunction with [targetingCo #### Use Bid Cache - + Prebid.js currently allows for [caching and reusing bids in a very narrowly defined scope](/dev-docs/faq.html#does-prebidjs-cache-bids). However, if you'd like, you can disable this feature and prevent Prebid.js from using anything but the latest bids for @@ -241,98 +276,112 @@ a given auction. This option is available in version 1.39 as true-by-default and became false-by-default as of Prebid.js 2.0. If you want to use this feature in 2.0 and later, you'll need to set the value to true. -{% highlight js %} +```javascript pbjs.setConfig({ useBidCache: true }) -{% endhighlight %} - +``` #### Bid Cache Filter Function - + When [Bid Caching](#setConfig-Use-Bid-Cache) is turned on, a custom Filter Function can be defined to gain more granular control over which "cached" bids can be used. This function will only be called for "cached" bids from previous auctions, not "current" bids from the most recent auction. The function should take a single bid object argument, and return `true` to use the cached bid, or `false` to not use the cached bid. For Example, to turn on Bid Caching, but exclude cached video bids, you could do this: -{% highlight js %} +```javascript pbjs.setConfig({ useBidCache: true, bidCacheFilterFunction: bid => bid.mediaType !== 'video' }); -{% endhighlight %} +``` + +#### Minimum bid cache TTL + + + +By default, Prebid keeps every bid it receives stored in memory until the user leaves the page, even after the bid actually times out and is no longer available for new auctions. This can cause high memory usage on long-running single-page apps; you can configure Prebid to drop stale bids from memory with `minBidCacheTTL`: +```javascript +pbjs.setConfig({ + minBidCacheTTL: 60 // minimum time (in seconds) that bids should be kept in cache +}) +``` + +When set, bids are only kept in memory for the duration of their actual TTL lifetime or the value of `minBidCacheTTL`, whichever is greater. Setting `minBidCacheTTL: 0` causes bids to be dropped as soon as they expire. + +Put another way, this setting doesn't define each bid's TTL, but rather controls how long it's kept around in memory for analytics purposes. + +#### Event history TTL + + + +By default, Prebid keeps in memory a log of every event since the initial page load, and makes it available to analytics adapters and [getEvents()](/dev-docs/publisher-api-reference/getEvents.html). +This can cause high memory usage on long-running single-page apps; you can set a limit on how long events are preserved with `eventHistoryTTL`: + +```javascript +pbjs.setConfig({ + eventHistoryTTL: 60 // maximum time (in seconds) that events should be kept in memory +}) +``` #### Bidder Order Set the order in which bidders are called: -{% highlight js %} +```javascript pbjs.setConfig({ bidderSequence: "fixed" }) /* default is "random" */ -{% endhighlight %} +``` - + #### Page URL Override the Prebid.js page referrer for some bidders. -{% highlight js %} +```javascript pbjs.setConfig({ pageUrl: "https://example.com/index.html" }) -{% endhighlight %} - - - -#### Publisher Domain - -{: .alert.alert-warning :} -This API is deprecated. Please use 'pageUrl' instead. - -Set the publisher's domain where Prebid is running, for cross-domain iframe communication: - -{% highlight js %} -pbjs.setConfig({ publisherDomain: "https://www.theverge.com" ) -{% endhighlight %} +``` - + #### Price Granularity This configuration defines the price bucket granularity setting that will be used for the `hb_pb` keyword. -{% highlight js %} +```javascript pbjs.setConfig({ priceGranularity: "medium" }) -{% endhighlight %} +``` Standard values: -+ `"low"`: $0.50 increments, capped at $5 CPM -+ `"medium"`: $0.10 increments, capped at $20 CPM (the default) -+ `"high"`: $0.01 increments, capped at $20 CPM -+ `"auto"`: Applies a sliding scale to determine granularity as shown in the [Auto Granularity](#autoGranularityBucket) table below. -+ `"dense"`: Like `"auto"`, but the bid price granularity uses smaller increments, especially at lower CPMs. For details, see the [Dense Granularity](#denseGranularityBucket) table below. -+ `customConfigObject`: If you pass in a custom config object (as shown in the [Custom CPM Bucket Sizing](#customCPMObject) example below), you can have much finer control over CPM bucket sizes, precision, and caps. +* `"low"`: $0.50 increments, capped at $5 CPM +* `"medium"`: $0.10 increments, capped at $20 CPM (the default) +* `"high"`: $0.01 increments, capped at $20 CPM +* `"auto"`: Applies a sliding scale to determine granularity as shown in the [Auto Granularity](#autoGranularityBucket) table below. +* `"dense"`: Like `"auto"`, but the bid price granularity uses smaller increments, especially at lower CPMs. For details, see the [Dense Granularity](#denseGranularityBucket) table below. +* `customConfigObject`: If you pass in a custom config object (as shown in the [Custom CPM Bucket Sizing](#customCPMObject) example below), you can have much finer control over CPM bucket sizes, precision, and caps. ##### Auto Granularity {: .table .table-bordered .table-striped } -| CPM | Granularity | Example | +| CPM | Granularity | Example | |---------------------+----------------------------------+--------| -| CPM <= $5 | $0.05 increments | $1.87 floored to $1.85 | -| CPM <= $10 and > $5 | $0.10 increments | $5.09 floored to $5.00 | -| CPM <= $20 and > $10 | $0.50 increments | $14.26 floored to $14.00 | -| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | +| CPM <= $5 | $0.05 increments | $1.87 floored to $1.85 | +| CPM <= $10 and > $5 | $0.10 increments | $5.09 floored to $5.00 | +| CPM <= $20 and > $10 | $0.50 increments | $14.26 floored to $14.00 | +| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | ##### Dense Granularity {: .table .table-bordered .table-striped } -| CPM | Granularity | Example | +| CPM | Granularity | Example | |------------+-------------------------------+---------| -| CPM <= $3 | $0.01 increments | $1.87 floored to $1.87 | -| CPM <= $8 and >$3 | $0.05 increments | $5.09 floored to $5.05 | -| CPM <= $20 and >$8 | $0.50 increments | $14.26 floored to $14.00 | -| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | +| CPM <= $3 | $0.01 increments | $1.87 floored to $1.87 | +| CPM <= $8 and >$3 | $0.05 increments | $5.09 floored to $5.05 | +| CPM <= $20 and >$8 | $0.50 increments | $14.26 floored to $14.00 | +| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | @@ -365,9 +414,9 @@ pbjs.setConfig({ Here are the rules for CPM intervals: -- `max` and `increment` must be specified -- A range's minimum value is assumed to be the max value of the previous range. The first interval starts at a min value of 0. -- `precision` is optional and defaults to 2 +* `max` and `increment` must be specified +* A range's minimum value is assumed to be the max value of the previous range. The first interval starts at a min value of 0. +* `precision` is optional and defaults to 2 {% capture warning-granularity %} As of Prebid.js 3.0, the 'min' parameter is no longer supported in custom granularities. @@ -383,8 +432,7 @@ This implies that ranges should have max values that are really the min value of {% include alerts/alert_warning.html content=warning-granularity %} - - + #### Media Type Price Granularity @@ -392,10 +440,11 @@ The standard [Prebid price granularities](#setConfig-Price-Granularity) cap out granularity as described above. Another approach is to use `mediaTypePriceGranularity` config that may be set to define different price bucket structures for different types of media: -- for each of five media types: banner, video, video-instream, video-outstream, and native. -- it is recommended that defined granularities be custom. It's possible to define "standard" granularities (e.g. "medium"), but it's not possible to mix both custom and standard granularities. -{% highlight js %} +* for each of five media types: banner, video, video-instream, video-outstream, and native. +* it is recommended that defined granularities be custom. It's possible to define "standard" granularities (e.g. "medium"), but it's not possible to mix both custom and standard granularities. + +```javascript const customPriceGranularityVideo = { 'buckets': [ { 'precision': 2, 'max': 5, 'increment': 0.25 }, @@ -412,11 +461,11 @@ const customPriceGranularityBanner = { pbjs.setConfig({'mediaTypePriceGranularity': { 'video': customPriceGranularity, // used as default for instream video - 'video-outstream': customPriceGranularityBanner, + 'video-outstream': customPriceGranularityBanner, 'banner': 'customPriceGranularityBanner' } }); -{% endhighlight %} +``` Any `mediaTypePriceGranularity` setting takes precedence over `priceGranularity`. @@ -430,181 +479,67 @@ are recognized. This was driven by the recognition that outstream often shares l If the mediatype is video, the price bucketing code further looks at the context (e.g. outstream) to see if there's a price granularity override. If it doesn't find 'video-outstream' defined, it will then look for just 'video'. - - -#### Server to Server - -{: .alert.alert-info :} -Use of this config option requires the `prebidServerBidAdapter` module. + +#### Custom CPM Rounding -Prebid.js can be configured to connect to one or more [Prebid Servers](/prebid-server/overview/prebid-server-overview.html) for one or more bidders. - -Example config: - -{% highlight js %} -pbjs.setConfig({ - s2sConfig: [{ - accountId: '1', - bidders: ['appnexus', 'openx', 'tripleliftVideo'], - defaultVendor: 'appnexus', - timeout: 500, - adapterOptions: { - openx: { key: 'value' }, - appnexus: { key: 'value' } - }, - syncUrlModifier: { - 'openx': function(type, url, bidder) { - const publisherId = '00000123231231' - url += `&ri=${publisherId}`; - return url - } - }, - extPrebid: { - aliases: { - tripleliftVideo: tripleLift - } - } - }] -}) -{% endhighlight %} - -{: .alert.alert-info :} -Note that `s2sConfig` can be specified as an object or an array. - -The `s2sConfig` properties: - -{: .table .table-bordered .table-striped } -| Attribute | Scope | Type | Description | -|------------+---------+---------+---------------------------------------------------------------| -| `accountId` | Required | String | Your Prebid Server account ID. This is obtained from whoever's hosting your Prebid Server. | -| `bidders` | Required | Array of Strings | Which bidders auctions should take place on the server side | -| `allowUnknownBidderCodes` | Optional | Boolean | Allow Prebid Server to bid on behalf of bidders that are not explicitly listed in the adUnit. See important [note](#allowUnknownBidderCodes) below. Defaults to `false`. | -| `defaultVendor` | Optional | String | Automatically includes all following options in the config with vendor's default values. Individual properties can be overridden by including them in the config along with this setting. See the Additional Notes below for more information. | -| `enabled` | Optional | Boolean | Enables this s2sConfig block - defaults to `false` | -| `timeout` | Required | Integer | Number of milliseconds allowed for the server-side auctions. This should be approximately 200ms-300ms less than your Prebid.js timeout to allow for all bids to be returned in a timely manner. See the Additional Notes below for more information. | -| `adapter` | Required | String | Adapter to use to connect to Prebid Server. Defaults to 'prebidServer' | -| `endpoint` | Required | URL or Object | Defines the auction endpoint for the Prebid Server cluster. See table below for object config properties. | -| `syncEndpoint` | Required | URL or Object | Defines the cookie_sync endpoint for the Prebid Server cluster. See table below for object config properties. | -| `userSyncLimit` | Optional | Integer | Max number of userSync URLs that can be executed by Prebid Server cookie_sync per request. If not defined, PBS will execute all userSync URLs included in the request. | -| `syncTimeout` | Optional | Integer | Maximum number of milliseconds allowed for each server-side userSync to load. Default is 1000. | -| `syncUrlModifier` | Optional | Object | Function to modify a bidder's sync url before the actual call to the sync endpoint. Bidder must be enabled for s2sConfig. | -| `coopSync` | Optional | Boolean | Whether or not PBS is allowed to perform "cooperative syncing" for bidders not on this page. Publishers help each other improve match rates by allowing this. Default is true. | -| `defaultTtl` | Optional | Integer | Configures the default TTL in the Prebid Server adapter to use when Prebid Server does not return a bid TTL - 60 if not set | -| `adapterOptions` | Optional | Object | Arguments will be added to resulting OpenRTB payload to Prebid Server in every impression object at request.imp[].ext.BIDDER. See the example above. | -| `extPrebid` | Optional | Object | Arguments will be added to resulting OpenRTB payload to Prebid Server in request.ext.prebid. See the examples below. | - -If `endpoint` and `syncEndpoint` are objects, these are the supported properties: - -{: .table .table-bordered .table-striped } -| Attribute | Scope | Type | Description | -|------------+---------+---------+---------------------------------------------------------------| -| p1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for non-consent requests or users who grant consent. | -| noP1Consent | Required | String | Defines the auction endpoint or the cookie_sync endpoint for the Prebid Server cluster for users who do not grant consent. (This is useful for a server configured to not accept any cookies to ensure compliance regulations.) | - -**Notes on s2sConfig properties** - -- Currently supported vendors are: appnexus, openx, and rubicon -- When using `defaultVendor` option, `accountId` and `bidders` properties still need to be defined. -- If the `s2sConfig` timeout is greater than the Prebid.js timeout, the `s2sConfig` timeout will be automatically adjusted to 75% of the Prebid.js timeout in order to fit within the auction process. -- When using the `endpoint` or `syncEndpoint` object configs, you should define both properties. If either property is not defined, Prebid Server requests for that type of user will not be made. If you do not need to distinguish endpoints for consent reasons, you can simply define the same URL value in both fields or use the String version of the field (which is configured to use defined URL for all users). -- When `allowUnknownBidderCodes` is `true`, bidders that have not been explicitly requested in [`adUnit.bids`](../adunit-reference.html#adunitbids) may take part in the auction. This can break custom logic that relies on the availability of a bid request object for any given bid; in particular, "unknown" bidders will not trigger a [`bidRequested`](getEvents.html) event and will have an undefined `payload.bidRequest` in [MASS custom renderers](../modules/mass.html#configuration-parameters). - -{: .alert.alert-warning :} -**Errors in bidder parameters will cause Prebid Server to reject the -entire request.** The Prebid Server philosophy is to avoid silent failures -- -we assume you will test changes, and that it will be easier to notice a -4xx error coming from the server than a silent failure where it skips just -the bad parameter. - -**Video via s2sConfig** - -Supporting video through the Server-to-Server route can be done by providing a couple of extra arguments on the `extPrebid` object. e.g. - -{% highlight js %} -pbjs.setConfig({ - s2sConfig: [{ - accountId: '1001', - bidders: ['rubicon', 'pubmatic'], - defaultVendor: 'rubicon', - timeout: 250, - extPrebid: { - cache: { - vastxml: { returnCreative: false } - }, - targeting: { - pricegranularity: {"ranges": [{"max":40.00,"increment":1.00}]} - } - } - }] -}) -{% endhighlight %} - -Additional options for `s2sConfig` may be enabled by including the [Server-to-Server testing module]({{site.baseurl}}/dev-docs/modules/s2sTesting.html). - -s2sConfig example with the endpoint attributes defined as strings: -{% highlight js %} -pbjs.setConfig({ - s2sConfig: [{ - accountId: '1001', - bidders: ['bidderA', 'bidderB'], - endpoint: 'https://mypbs.example.com/path', - syncEndpoint: 'https://mypbs.example.com/path', - timeout: 300 - }] -}) -{% endhighlight %} +Prebid defaults to rounding down all bids to the nearest increment, which may cause lower CPM ads to be selected. +While this can be addressed through higher [price granularity](#setConfig-Price-Granularity), Prebid also allows setting a custom rounding function. +This function will be used by Prebid to determine what increment a bid will round to. +
        +
        +You can set a simple rounding function: -s2sConfig example with the endpoint attributes defined as objects: -{% highlight js %} -pbjs.setConfig({ - s2sConfig: [{ - accountId: '1001', - bidders: ['bidderA', 'bidderB'], - endpoint: { - p1Consent: 'https://mypbs.example.com/path', - noP1Consent: 'https://mypbs2.example.com/path' - }, - syncEndpoint: { - p1Consent: 'https://mypbs.example.com/path', - noP1Consent: 'https://mypbs2.example.com/path' - } - timeout: 300 - }] -}) -{% endhighlight %} +```javascript +// Standard rounding +pbjs.setConfig({'cpmRoundingFunction': Math.round}); +``` -**Server-Side Aliases** +Or you can round according to more complex considerations: -You may want to run a particular bidder on the client for banner, but that same bidder on the -server for video. You would do this by setting a **server-side** alias. The -[example](#setConfig-Server-to-Server) at the start of this section provides an example. Here's how it works: +```javascript +// Custom rounding function +const roundToNearestEvenIncrement = function (number) { + let ceiling = Math.ceil(number); + let ceilingIsEven = ceiling % 2 === 0; + if (ceilingIsEven) { + return ceiling; + } else { + return Math.floor(number); + } +} +pbjs.setConfig({'cpmRoundingFunction': roundToNearestEvenIncrement}); +``` -1. Video ad units are coded with the dynamic alias. e.g. tripleliftVideo -1. The s2sConfig.bidders array contains 'tripleliftVideo' telling Prebid.js to direct bids for that code to the server -1. Finally, the extPrebid.aliases line tells Prebid Server to route the 'tripleliftVideo' biddercode to the 'triplelift' server-side adapter. +
        -**Passing the Referrer to Server Side Adapters** +#### Server to Server -* Setting `extPrebid.origreferrer` will be recognized by some server-side adapters as the referring URL for the current page. +See the [Prebid Server module](/dev-docs/modules/prebidServer.html). - + #### Mobile App Post-Bid To support [post-bid](/overview/what-is-post-bid.html) scenarios on mobile apps, the -prebidServerBidAdapter module recognizes the `app` config object to +prebidServerBidAdapter module will accept `ortb2.app` config to forward details through the server: -{% highlight js %} +```javascript pbjs.setConfig({ - app: { + ortb2: { + app: { bundle: "org.prebid.mobile.demoapp", domain: "prebid.org" - } -{% endhighlight %} + } + } +}); +``` - +{: .alert.alert-warning :} +In PBJS 4.29 and earlier, don't add the `ortb2` level here -- just `app` directly. Oh, and please upgrade. 4.29 was a long time ago. + + #### Configure User Syncing @@ -613,9 +548,9 @@ This practice is called "user syncing" because the aim is to let the bidders mat There's a good reason for bidders to be doing this -- DSPs are more likely to bid on impressions where they know something about the history of the user. However, there are also good reasons why publishers may want to control the use of these practices: -- *Page performance*: Publishers may wish to move ad-related cookie work to much later in the page load after ads and content have loaded. -- *User privacy*: Some publishers may want to opt out of these practices even though it limits their users' values on the open market. -- *Security*: Publishers may want to control which bidders are trusted to inject images and JavaScript into their pages. +* *Page performance*: Publishers may wish to move ad-related cookie work to much later in the page load after ads and content have loaded. +* *User privacy*: Some publishers may want to opt out of these practices even though it limits their users' values on the open market. +* *Security*: Publishers may want to control which bidders are trusted to inject images and JavaScript into their pages. {: .alert.alert-info :} **User syncing default behavior** @@ -623,11 +558,11 @@ If you don't tweak any of the settings described in this section, the default be For more information, see the sections below. -- [User Sync Properties](#setConfig-ConfigureUserSyncing-UserSyncProperties) -- [User Sync Examples](#setConfig-ConfigureUserSyncing-UserSyncExamples) -- [How User Syncing Works](#setConfig-ConfigureUserSyncing-HowUserSyncingWorks) +* [User Sync Properties](#setConfig-ConfigureUserSyncing-UserSyncProperties) +* [User Sync Examples](#setConfig-ConfigureUserSyncing-UserSyncExamples) +* [How User Syncing Works](#setConfig-ConfigureUserSyncing-HowUserSyncingWorks) - + ##### User Sync Properties @@ -644,7 +579,7 @@ For descriptions of all the properties that control user syncs, see the table be | `enableOverride` | Boolean | Enable/disable publisher to trigger user syncs by calling `pbjs.triggerUserSyncs()`. Default: `false`. | | `aliasSyncEnabled` | Boolean | Enable/disable registered syncs for aliased adapters. Default: `false`. | - + ##### User Sync Examples @@ -652,37 +587,37 @@ For examples of configurations that will change the default behavior, see below. Push the user syncs to later in the page load: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { syncDelay: 5000 // write image pixels 5 seconds after the auction } }); -{% endhighlight %} +``` Turn off user syncing entirely: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { syncEnabled: false } }); -{% endhighlight %} +``` Delay auction to retrieve userId module IDs first: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { auctionDelay: 1000 // delay auction up to 1 second } }); -{% endhighlight %} +``` Allow iframe-based syncs (the presence of a valid `filterSettings.iframe` object automatically enables iframe type user-syncing): -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { filterSettings: { @@ -693,12 +628,13 @@ pbjs.setConfig({ } } }); -{% endhighlight %} -_Note - iframe-based syncing is disabled by default. Image-based syncing is enabled by default; it can be disabled by excluding all/certain bidders via the `filterSettings` object._ +``` + +Note - iframe-based syncing is disabled by default. Image-based syncing is enabled by default; it can be disabled by excluding all/certain bidders via the `filterSettings` object._ Only certain bidders are allowed to sync and only certain types of sync pixels: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { filterSettings: { @@ -715,11 +651,11 @@ pbjs.setConfig({ syncDelay: 6000, // 6 seconds after the auction } }); -{% endhighlight %} +``` If you want to apply the same bidder inclusion/exlusion rules for both types of sync pixels, you can use the `all` object instead specifying both `image` and `iframe` objects like so: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { /* only these bidders are allowed to sync. Both iframe and image pixels are permitted. */ @@ -733,13 +669,13 @@ pbjs.setConfig({ syncDelay: 6000, // 6 seconds after the auction } }); -{% endhighlight %} +``` -_Note - the `all` field is mutually exclusive and cannot be combined with the `iframe`/`image` fields in the `userSync` config. This restriction is to promote clear logic as to how bidders will operate in regards to their `userSync` pixels. If the fields are used together, this will be considered an invalid config and Prebid will instead use the default `userSync` logic (all image pixels permitted and all iframe pixels are blocked)._ +Note - the `all` field is mutually exclusive and cannot be combined with the `iframe`/`image` fields in the `userSync` config. This restriction is to promote clear logic as to how bidders will operate in regards to their userSync` pixels. If the fields are used together, this will be considered an invalid config and Prebid will instead use the default `userSync` logic (all image pixels permitted and all iframe pixels are blocked)._ The same bidders can drop sync pixels, but the timing will be controlled by the page: -{% highlight js %} +```javascript pbjs.setConfig({ userSync: { /* only these bidders are allowed to sync, and only image pixels */ @@ -752,15 +688,15 @@ pbjs.setConfig({ enableOverride: true // publisher will call `pbjs.triggerUserSyncs()` } }); -{% endhighlight %} +``` As noted, there's a function available to give the page control of when registered user syncs are added. -{% highlight js %} +```javascript pbjs.triggerUserSyncs(); -{% endhighlight %} +``` - + ##### How User Syncing Works @@ -772,7 +708,7 @@ The [userSync.registerSync()]({{site.baseurl}}/dev-docs/bidder-adaptor.html#bidd When user syncs are run, regardless of whether they are invoked by the platform or by the page calling pbjs.triggerUserSyncs(), the queue entries are randomized and appended to the bottom of the HTML tag. - + #### Configure Targeting Controls @@ -830,7 +766,7 @@ Between these two values (Prebid's targeting key count and the overall ad URL qu Between this feature and the overlapping [sendBidsControl.bidLimit](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-Bids-Control), you should be able to make sure that there's not too much data going to the ad server. - + ##### Details on the allowTargetingKeys setting @@ -839,6 +775,7 @@ The `allowTargetingKeys` config creates a targeting key mask based on the defaul Prebid.js introduced the concept of optional targeting keys with 4.23. CONSTANTS.DEFAULT_TARGETING_KEYS is defined as a subset of CONSTANTS.TARGETING_KEYS. When a publisher defines targetingControls.allowTargetingKeys, this replaces the constant CONSTANTS.DEFAULT_TARGETING_KEYS and can include optional keys defined in CONSTANTS.TARGETING_KEYS. One example of this would be to make `hb_adomain` part of the default set. To accomplish this, Prebid does the following: + * Collect original targeting generated by the auction. * Generate new targeting filtered against allowed keys. * Custom targeting keys are always added to targeting. @@ -861,6 +798,10 @@ The targeting key names and the associated prefix value filtered by `allowTarget | CACHE_ID | `hb_cache_id` | yes | Network cache ID for AMP or Mobile | | CACHE_HOST | `hb_cache_host` | yes | | | ADOMAIN | `hb_adomain` | no | Set to bid.meta.advertiserDomains[0]. Use cases: report on VAST errors, set floors on certain buyers, monitor volume from a buyer, track down bad creatives. | +| ACAT | `hb_acat` | no | Set to bid.meta.primaryCatId. Optional category targeting key that can be sent to ad servers that stores the value of the Primary IAB category ID if present. Use cases: category exclusion with an ad server order or programmatic direct deal on another ad slot (good for contextual targeting and/or brand +safety/suitability). | +| CRID | `hb_crid` | no | Set to bid.creativeId. Use cases: report on VAST errors, track down bad creatives. | +| DSP | `hb_dsp` | no | Set to bid.meta.networkName, falling back to bid.meta.networkId. Optional targeting key identifying the DSP or seat | | title | `hb_native_title` | yes | | | body | `hb_native_body` | yes | | | body2 | `hb_native_body2` | yes | | @@ -889,6 +830,7 @@ config.setConfig({ } }); ``` + Another example config showing the addition of `hb_adomain` and excluding all default targeting keys except `hb_bidder`, `hb_adid`, `hb_size` and `hb_pb`: ```javascript @@ -899,11 +841,11 @@ config.setConfig({ }); ``` - + ##### Details on the addTargetingKeys setting -The `addTargetingKeys` config is similar to `allowTargetingKeys`, except it adds to the keys in CONSTANTS.DEFAULT_TARGETING_KEYS instead of replacing them. This is useful if you need Prebid.js to generate targeting for some keys that are not allowed by default without removing any of the default ones (see [allowTargetingKeys](#targetingControls-allowTargetingKeys) for details on how targeting is generated). +The `addTargetingKeys` config is similar to `allowTargetingKeys`, except it adds to the keys in CONSTANTS.DEFAULT_TARGETING_KEYS instead of replacing them. This is useful if you need Prebid.js to generate targeting for some keys that are not allowed by default without removing any of the default ones (see [allowTargetingKeys](#targetingControls-allowTargetingKeys) for details on how targeting is generated). Note that you may specify only one of `allowTargetingKeys` or `addTargetingKeys`. @@ -957,7 +899,6 @@ config.setConfig({ }); ``` - ##### Details on the allowSendAllBidsTargetingKeys setting The `allowSendAllBidsTargetingKeys` is similar to `allowTargetingKeys` except it limits any default bidder specific keys sent to the adserver when sendAllBids is enabled. Any default bidder specific keys that do not match the mask will not be sent to the adserver. This setting can be helpful if you find that your default Prebid.js implementation is sending key values that your adserver isn't configured to process; extraneous key values may lead to the ad server request being truncated, which can cause potential issues with the delivery or rendering ads. An example of an extraneous key value many publishers may find redundant and want to remove is `hb_bidder_biddercode = biddercode`. @@ -972,194 +913,13 @@ config.setConfig({ }); ``` - - + #### Configure Responsive Ads -The `sizeConfig` object passed to `pbjs.setConfig` provides a global way to describe types of devices and screens using [CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries). See below for an explanation of the feature and examples showing how to use it. - -{% capture tip-choosing %} -As of Prebid.js 3.11.0, the [Advanced SizeMapping module](/dev-docs/modules/sizeMappingV2.html) provides an alternate way to handle responsive AdUnits. -You should consider using that module if any of these scenarios are true: -{::nomarkdown} -
          -
        • You need to work with video or native AdUnits
        • -
        • The site needs to alter different AdUnits at different screen widths; e.g., the left-nav changes sizes at 600 pixels, but the footer's size behavior changes at 620 pixels.
        • -
        • The site needs to alter different mediaTypes at different screen widths; e.g., the banner size ranges are 0-400px, 401-700px, and 701+px, but the native ads appear at 500px.
        • -
        • Some bidders or mediaTypes should be included (or removed) at different overlapping size ranges.
        • -
        -
        -{:/} -If, on the other hand, you're only working with the banner mediaType and the AdUnits all change behavior together at the same viewport width, then the built-in sizeConfig feature is appropriate. -{% endcapture %} -{% include alerts/alert_tip.html content=tip-choosing %} - -+ [How it works](#sizeConfig-How-it-Works) -+ [Example](#sizeConfig-Example) -+ [Labels](#labels) - - +See the [size mapping](/dev-docs/modules/sizeMapping.html) or [advanced size mapping](/dev-docs/modules/sizeMappingV2.html) modules. -##### How Size Config Works for Banners - -- Before `requestBids` sends bid requests to adapters, it will evaluate and pick the appropriate label(s) based on the `sizeConfig.mediaQuery` and device properties. Once it determines the active label(s), it will then filter the `adUnit.bids` array based on the `labels` defined and whether the `banner` mediaType was included. Ad units that include a `banner` mediaType that don't match the label definition are dropped. -- The required `sizeConfig.mediaQuery` property allows [CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries). The queries are tested using the [`window.matchMedia`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) API. -- If a label conditional (e.g. `labelAny`) doesn't exist on an ad unit, it is automatically included in all requests for bids. -- If multiple rules match, the sizes will be filtered to the intersection of all matching rules' `sizeConfig.sizesSupported` arrays. -- The `adUnit.mediaTypes.banner.sizes` selected will be filtered based on the `sizesSupported` of the matched `sizeConfig`. So the `adUnit.mediaTypes.banner.sizes` is a subset of the sizes defined from the resulting intersection of `sizesSupported` sizes and `adUnit.mediaTypes.banner.sizes`. (Note: size config will also operate on `adUnit.sizes`, however `adUnit.sizes` is deprecated in favor of `adUnit.mediaTypes`) - -###### Note on sizeConfig and different mediaTypes - -The sizeConfig logic only applies to `adUnits`/`bids` that include the `banner` `mediaType` (regardless of whether the request is single or multi-format). - -For example, if a request contained the `banner` and `video` `mediaTypes` and it failed the label check, then the entire adUnit/bid would be dropped (including the `video` part of the request). However if the same request passed the label check, then the `adUnit.mediaTypes.banner.sizes` would be filtered as per the matching sizeConfig and the multi-format request would proceed as normal. - -If the ad unit does not include `banner` `mediaType` at all, then the sizeConfig logic will not influence that ad Unit; it will automatically be passed into the auction. - - - -##### Example - -To set size configuration rules, pass in `sizeConfig` as follows: - -{% highlight js %} - -pbjs.setConfig({ - sizeConfig: [{ - 'mediaQuery': '(min-width: 1600px)', - 'sizesSupported': [ - [1000, 300], - [970, 90], - [728, 90], - [300, 250] - ], - 'labels': ['desktop-hd'] - }, { - 'mediaQuery': '(min-width: 1200px)', - 'sizesSupported': [ - [970, 90], - [728, 90], - [300, 250] - ], - 'labels': ['desktop'] - }, { - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': [ - [728, 90], - [300, 250] - ], - 'labels': ['tablet'] - }, { - 'mediaQuery': '(min-width: 0px)', - 'sizesSupported': [ - [300, 250], - [300, 100] - ], - 'labels': ['phone'] - }] -}); - -{% endhighlight %} - -##### Labels - -There are two parts to defining responsive and conditional ad units with labels: - -1. Defining the labels -2. Defining the conditional ad unit targeting for the labels - -Labels may be defined in two ways: - -1. Through [`sizeConfig`](#setConfig-Configure-Responsive-Ads) -2. As an argument to [`pbjs.requestBids`](/dev-docs/publisher-api-reference/requestBids.html) - -{% highlight js %} -pbjs.requestBids({labels: []}); -{% endhighlight %} - -Labels may be targeted in the AdUnit structure by two conditional operators: `labelAny` and `labelAll`. - -With the `labelAny` operator, just one label has to match for the condition to be true. In the example below, either A or B can be defined in the label array to activate the bid or ad unit: -{% highlight bash %} -labelAny: ["A", "B"] -{% endhighlight %} - -With the `labelAll` conditional, every element of the target array must match an element of the label array in -order for the condition to be true. In the example below, both A and B must be defined in the label array to activate the bid or ad unit: -{% highlight bash %} -labelAll: ["A", "B"] -{% endhighlight %} - -{: .alert.alert-warning :} -Only one conditional may be specified on a given AdUnit or bid -- if both `labelAny` and `labelAll` are specified, only the first one will be utilized and an error will be logged to the console. It is allowable for an AdUnit to have one condition and a bid to have another. - -{: .alert.alert-warning :} -If either `labeAny` or `labelAll` values is an empty array, it evaluates to `true`. - -{: .alert.alert-warning :} -It is important to note that labels do not act as filters for sizeConfig. In the example above, using a screen of 1600px wide and `labelAll:["desktop"]` will *not* filter out sizes defined in the `desktop-hd` sizeConfig. Labels in sizeConfig are only used for selecting or de-selecting AdUnits and AdUnit.bids. - -Label targeting on the ad unit looks like the following: - -{% highlight js %} - -pbjs.addAdUnits([{ - code: "ad-slot-1", - mediaTypes: { - banner: { - sizes: [ - [970, 90], - [728, 90], - [300, 250], - [300, 100] - ] - } - }, - labelAny: ["visitor-uk"] - /* The full set of bids, not all of which are relevant on all devices */ - bids: [{ - bidder: "pulsepoint", - /* Labels flag this bid as relevant only on these screen sizes. */ - labelAny: ["desktop", "tablet"], - params: { - "cf": "728X90", - "cp": 123456, - "ct": 123456 - } - }, - { - bidder: "pulsepoint", - labelAny: ["desktop", "phone"], - params: { - "cf": "300x250", - "cp": 123456, - "ct": 123456 - } - }, - { - bidder: "sovrn", - labelAny: ["desktop", "tablet"], - params: { - "tagid": "123456" - } - }, - { - bidder: "sovrn", - labelAny: ["phone"], - params: { - "tagid": "111111" - } - } - ] -}]); - -{% endhighlight %} - -See [Conditional Ad Units]({{site.baseurl}}/dev-docs/conditional-ad-units.html) for additional use cases around labels. - - - + #### COPPA @@ -1167,11 +927,11 @@ Bidder adapters that support the Child Online Privacy Protection Act (COPPA) rea Publishers with content falling under the scope of this regulation should consult with their legal teams. The flag may be passed to supporting adapters with this config: -{% highlight js %} +```javascript pbjs.setConfig({coppa: true}); -{% endhighlight %} +``` - + #### First Party Data @@ -1183,36 +943,115 @@ Not all bid adapters currently support reading first party data in this way, but **Scenario 1** - Global (cross-adunit) First Party Data open to all bidders -{% highlight js %} +```javascript pbjs.setConfig({ ortb2: { site: { - ... + // ... }, user: { - ... + // ... } } }); -{% endhighlight %} +``` The `ortb2` JSON structure reflects the OpenRTB standard: -- Fields that like keywords, search, content, gender, yob, and geo are values defined in OpenRTB, so should go directly under the site or user objects. -- Arbitrary values should go in site.ext.data or user.ext.data. -- Segments should go in site.content.data[] or user.data[]. -- Any other OpenRTB 2.5 field could be added here as well, e.g. site.content.language. -**Scenario 2** - Global (cross-adunit) First Party Data open only to a subset of bidders +* Fields that like keywords, search, content, gender, yob, and geo are values defined in OpenRTB, so should go directly under the site or user objects. +* Arbitrary values should go in site.ext.data or user.ext.data. +* Segments should go in site.content.data[] or user.data[]. +* Any other OpenRTB 2.5 field could be added here as well, e.g. site.content.language. + +**Scenario 2** - Auction (cross-adunit) First Party Data open to all bidders + +If a page needs to specify multiple different sets of top-level data (`site`, `user`, or `app`), use the `ortb2` parameter of [`requestBids`](/dev-docs/publisher-api-reference/setConfig.html) ([example](/features/firstPartyData.html#supplying-auction-specific-data) + +**Scenario 3** - Global (cross-adunit) First Party Data open only to a subset of bidders If a publisher only wants certain bidders to receive the data, use the [setBidderConfig](/dev-docs/publisher-api-reference/setBidderConfig.html) function. -**Scenario 3** - AdUnit-specific First Party Data +**Scenario 4** - AdUnit-specific First Party Data See the [AdUnit Reference](/dev-docs/adunit-reference.html) for AdUnit-specific first party data. See [Prebid Server First Party Data](/prebid-server/features/pbs-fpd.html) for details about passing data server-side. - + + +#### Video Module to integrate with Video Players + +The Prebid Video Module allows Prebid to directly integrate with a Video Player, allowing Prebid to automatically load the winning ad into the player, mark bids as won, fill the video and content oRTB params in the bid request, surface video analytics, and more. For more information please visit the [Video Module docs]({{site.github.url}}/prebid-video/video-module.html). +To register a video player with Prebid, you must use `setConfig` to set a `video` config compliant with the following structure: + +{: .table .table-bordered .table-striped } +| Field | Required? | Type | Description | +|---|---|---|---| +| video.providers[] | yes | array of objects | List of Provider configurations. You must define a provider configuration for each player instance that you would like integrate with. | +| video.providers[] .vendorCode | yes | number | The identifier of the Video Provider vendor (i.e. 1 for JW Player, 2 for videojs, etc). Allows Prebid to know which submodule to instantiate. | +| video.providers[].divId | yes | string | The HTML element id of the player or its placeholder div. All analytics events for that player will reference this ID. Additionally, used to indicate which HTLM element must contain the Video Player instance when instantiated. | +| video.providers[] .playerConfig.autoStart | no | boolean | Defaults to false | +| video.providers[] .playerConfig.mute | no | boolean | Defaults to false | +| video.providers[] .playerConfig.licenseKey | no | boolean | The license key or account key. Required by most commercial video players. | +| video.providers[] .playerConfig.setupAds | no | boolean | Defaults to true. Setting to false will prevent Prebid from setting up the ads components for the player. Disable when you wish to setup the player's ad components yourself. | +| video.providers[] .playerConfig.params .vendorConfig | no | object | The configuration block specific to a video player. Use this when setting configuration options not available in `video.providers[].playerConfig`. Its properties supersede the equivalents in `video.providers[].playerConfig`. | +| video.providers[] .playerConfig.params .adPluginConfig | no | object | The configuration block specific to the video player's ad plugin. Use this to customize the ad experience. The configuration spec is defined by your video player's ad plugin. | +| video.providers[] .adServer | no | object | Configuration for ad server integration. Applies to all Ad Units linked to a video provider. Superseded by `video.adServer` configurations defined at the Ad Unit level. | +| video.providers[] .adServer.vendorCode | yes | string | The identifier of the AdServer vendor (i.e. gam, etc) | +| video.providers[] .adServer.baseAdTagUrl | yes | string | Your AdServer Ad Tag. The targeting params of the winning bid will be appended. Required when `video.providers[].adServer.params` is absent. | +| video.providers[] .adServer.params | yes | object | Querystring parameters that will be used to construct the video ad tag URL. Required when `video.providers[].adServer.baseAdTagUrl` is absent. | +| video.contentEnrichmentEnabled | no | boolean | Defaults to true. Set to false to prevent the Video Module from enriching the `site.content` params in the bidder request. | +| video.mainContentDivId | no | string | Div Id of the video player intended to populate the `bidderRequest.site.content` params. Used when multiple video players are registered with the Video Module to indicate which player is rendering the main content. The `bidderRequest.site.content` params will be populated by said video player for all auctions where a Video Player is registered with an Ad Unit in the auction. | +| video.adServer | no | object | Configuration for ad server integration. Applies to all Video Providers and all Ad Units linked to a video provider. Superseded by `video.adServer` configurations defined at the Ad Unit level, and `video.providers[] .adServer` configurations. | +| video.adServer .vendorCode | yes | string | The identifier of the AdServer vendor (i.e. gam, etc) | +| video.adServer .baseAdTagUrl | yes | string | Your AdServer Ad Tag. The targeting params of the winning bid will be appended. Required when `video.adServer.params` is absent. | +| video.adServer .params | yes | object | Querystring parameters that will be used to construct the video ad tag URL. Required when `video.adServer.baseAdTagUrl` is absent. | + +**Note:** You can integrate with different Player vendors. For this to work, you must ensure that the right Video Submodules are included in your build, and that the providers have the right `vendorCode`s and `divId`s. + +##### Player Integration Example + +Assuming your page has 2 JW Player video players, 1 video.js video player, and your ad server is GAM. + +```javascript +pbjs.setConfig({ + video: { + providers: [{ + vendorCode: 1, // constant variable is JWPLAYER_VENDOR - see vendorCodes.js in the video library + divId: 'jwplayer-div-1', + playerConfig: { + autoStart: true, + } + }, { + vendorCode: 2, // constant variable is VIDEO_JS_VENDOR - see vendorCodes.js in the video library + divId: 'videojs-div', + playerConfig: { + params : { + adPluginConfig: { + numRedirects: 10 + }, + vendorConfig: { + controls: true, + preload: "auto", + } + } + } + }, { + vendorCode: 1, // constant variable is JWPLAYER_VENDOR - see vendorCodes.js in the video library + divId: 'jwplayer-div-2', + playerConfig: { + mute: true + } + }], + adServer: { + vendorCode: 'gam', // constant variable is GAM_VENDOR - see vendorCodes.js in the video library + baseAdTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/12345/' + } + } +}); +``` + + #### Client-side Caching of VAST XML @@ -1221,64 +1060,87 @@ video player can retrieve them when it's ready. Players don't obtain the VAST XM the JavaScript DOM in Prebid.js, but rather expect to be given a URL where it can be retrieved. There are two different flows possible with Prebid.js around VAST XML caching: -- Server-side caching: +* Server-side caching: Some video bidders (e.g. Rubicon Project) always cache the VAST XML on their servers as part of the bid. They provide a 'videoCacheKey', which is used in conjunction with the VAST URL in the ad server to retrieve the correct VAST XML when needed. In this case, Prebid.js has nothing else to do. As of Prebid.js 4.28, a publisher may specify the `ignoreBidderCacheKey` flag to re-cache these bids somewhere else using a VAST wrapper. -- Client-side caching: +* Client-side caching: Video bidders that don't cache on their servers return the entire VAST XML body. In this scenario, Prebid.js needs to copy the VAST XML to a publisher-defined cache location on the network. Prebid.js POSTs the VAST XML to the named Prebid Cache URL. It then sets the 'videoCacheKey' to the key that's returned in the response. {: .table .table-bordered .table-striped } | Cache Attribute | Required? | Type | Description | |----+--------+-----+-------| | cache.url | yes | string | The URL of the Prebid Cache server endpoint where VAST creatives will be sent. | +| cache.timeout | no | number | Timeout (in milliseconds) for network requests to the cache | | cache.vasttrack | no | boolean | Passes additional data to the url, used for additional event tracking data. Defaults to `false`. | | cache.ignoreBidderCacheKey | no | boolean | If the bidder supplied their own cache key, setting this value to true adds a VAST wrapper around that URL, stores it in the cache defined by the `url` parameter, and replaces the original video cache key with the new one. This can dramatically simplify ad server setup because it means all VAST creatives reside behind a single URL. The tradeoff: this approach requires the video player to unwrap one extra level of VAST. Defaults to `false`. | +| cache.batchSize | no | number | Enables video cache requests to be batched by a specified amount (defaults to 1) instead of making a single request per each video. | +| cache.batchTimeout | no | number | Used in conjunction with `batchSize`, `batchTimeout` specifies how long to wait in milliseconds before sending a batch video cache request based on the value for `batchSize` (if present). A batch request will be made whether the `batchSize` amount was reached or the `batchTimeout` timer runs out. `batchTimeout` defaults to 0. | Here's an example of basic client-side caching. Substitute your Prebid Cache URL as needed: -{% highlight js %} +```javascript pbjs.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' } }); -{% endhighlight %} +``` {: .alert.alert-warning :} The endpoint URL provided must be a Prebid Cache or be otherwise compatible with the [Prebid Cache interface](https://github.com/prebid/prebid-cache). As of Prebid.js 4.28, you can specify the `ignoreBidderCacheKey` option: -{% highlight js %} +```javascript pbjs.setConfig({ cache: { url: 'https://my-pbs.example.com/cache', - ignoreBidderCacheKey: true + ignoreBidderCacheKey: true } }); -{% endhighlight %} +``` As of Prebid.js 2.36, you can track client-side cached VAST XML. This functionality is useful for publishers who want to allow their analytics provider to measure video impressions. The prerequisite to using this feature is the availability of a Prebid Server that supports: -- the /vtrack endpoint -- an analytics module with connection to an analytics system that supports joining the impression event to the original auction request on the bidid -- the ability of a publisher to utilize the feature (if account-level permission is enabled) +* the /vtrack endpoint +* an analytics module with connection to an analytics system that supports joining the impression event to the original auction request on the bidid +* the ability of a publisher to utilize the feature (if account-level permission is enabled) Given those conditions, the `vasttrack` flag can be specified: -{% highlight js %} +```javascript pbjs.setConfig({ cache: { url: 'https://my-pbs.example.com/vtrack', vasttrack: true } }); -{% endhighlight %} +``` Setting the `vasttrack` parameter to `true` supplies the POST made to the `/vtrack` Prebid Server endpoint with a couple of additional parameters needed by the analytics system to join the event to the original auction request. - +Optionally, `batchSize` and `batchTimeout` can be utlilized as illustrated with the example below: + +```javascript +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache', + batchSize: 4, + batchTimeout: 50 + } +}); +``` + +The example above states that a timer will be initialized and wait up to 50ms for 4 responses to have been collected and then will fire off one batch video cache request for all 4 responses. Note that the batch request will be made when the specified `batchSize` number is reached or with the number of responses that could be collected within the timeframe specified by the value for `batchTimeout`. + +If a batchSize is set to 2 and 5 video responses arrive (within the timeframe specified by `batchTimeout`), then three batch requests in total will be made: + +1. Batch 1 will contain cache requests for 2 videos +2. Batch 2 will contain cache requests for 2 videos +3. Batch 3 will contain cache requests for 1 video + + #### Instream tracking @@ -1296,39 +1158,41 @@ This configuration will allow Analytics Adapters and Bid Adapters to track `BID_ | `instreamTracking.pollingFreq` | Optional | Integer |The frequency of polling. Default: `500`ms | | `instreamTracking.urlPattern` | Optional | RegExp | Regex for cache url patterns, to avoid false positives. | -#### Example +#### Instream Tracking Example -{% highlight js %} +```javascript pbjs.setConfig({ 'instreamTracking': { enabled: true, } }); -{% endhighlight %} +``` More examples [here](/dev-docs/modules/instreamTracking.html#example-with-urlpattern). - + #### Site Configuration -{: .alert.alert-info :} -This setting is obsolete as of Prebid.js 4.30. Please set site fields in `ortb2.site` as [First Party Data](#setConfig-fpd). - Adapters, including Prebid Server adapters, can support taking site parameters like language. -The structure here is OpenRTB; the site object will be available to client- and server-side adapters. +Just set the `ortb2.site` object as First Party Data to make it available to client- and server-side adapters. -{% highlight js %} +```javascript pbjs.setConfig({ - site: { + ortb2: { + site: { content: { language: "en" } - } + } + } }); -{% endhighlight %} +``` - +{: .alert.alert-warning :} +In PBJS 4.29 and earlier, don't add the `ortb2` level here -- just `site` directly. Oh, and please upgrade. 4.29 was a long time ago. + + #### Auction Options @@ -1341,47 +1205,51 @@ The `auctionOptions` object controls aspects related to auctions. | `suppressStaleRender` | Optional | Boolean | When true, prevents `banner` bids from being rendered more than once. It should only be enabled after auto-refreshing is implemented correctly. Default is false. ##### Examples -Exclude status of bidder _doNotWaitForMe_ when checking auction completion. -{% highlight js %} + +Exclude status of bidder *doNotWaitForMe* when checking auction completion. + +```javascript pbjs.setConfig({ 'auctionOptions': { 'secondaryBidders': ['doNotWaitForMe'] } }); -{% endhighlight %} +``` Render winning bids only once. -{% highlight js %} + +```javascript pbjs.setConfig({ 'auctionOptions': { 'suppressStaleRender': true } }); -{% endhighlight %} +``` ##### More on Stale Rendering + When auto-refreshing is done incorrectly, it could cause the same bids to be rendered repeatedly. For instance, when googletag.pubads.refresh() is called directly without removing the PBJS targeting, the same hb_ variables get re-sent to GAM, re-chosen, and re-rendered. Over and over without ever asking PBJS for updated targeting variables. PBJS performs following actions when stale rendering is detected. + * Log a warning in the browser console if pbjs_debug=true. * Emit a `STALE_RENDER` event before `BID_WON` event. Stale winning bids will continue to be rendered unless `suppressStaleRender` is set to true. Events including `STALE_RENDER` and `BID_WON` are unaffected by this option. - - + #### maxNestedIframes Prebid.js will loop upward through nested iframes to find the top-most referrer. This setting limits how many iterations it will attempt before giving up and not setting referrer. -``` +```javascript pbjs.setConfig({ maxNestedIframes: 5 // default is 10 }); ``` - + #### Real-Time Data Modules @@ -1391,22 +1259,22 @@ RTD modules, define an overall amount of time they're willing to wait for results, and even flag some of the modules as being more "important" than others. -``` +```javascript pbjs.setConfig({ - ..., + // ..., realTimeData: { auctionDelay: 100, // REQUIRED: applies to all RTD modules dataProviders: [{ name: "RTD-MODULE-1", waitForIt: true, // OPTIONAL: flag this module as important params: { - ... module-specific parameters ... + // ... module-specific parameters ... } },{ name: "RTD-MODULE-2", waitForIt: false, // OPTIONAL: flag this module as less important params: { - ... module-specific parameters ... + //... module-specific parameters ... } }] } @@ -1433,39 +1301,107 @@ Some publishers carefully manage these precious milliseconds, balancing impact of the real-time data with the revenue loss from auction delay. Notes: -- The only time `waitForIt` means anything is if some modules are flagged as true and others as false. If all modules are the same (true or false), it has no effect. -- Likewise, `waitForIt` doesn't mean anything without an auctionDelay specified. - +* The only time `waitForIt` means anything is if some modules are flagged as true and others as false. If all modules are the same (true or false), it has no effect. +* Likewise, `waitForIt` doesn't mean anything without an auctionDelay specified. + + + +#### Topics Iframe Configuration + +Topics iframe implementation is the enhancements of existing module under topicsFpdModule.js where different bidders will call the topic API under their domain to fetch the topics for respective domain and the segment data will be part of ORTB request under user.data object. Default config is maintained in the module itself. Below are the configuration which can be used to configure and override the default config maintained in the module. + +```javascript +pbjs.setConfig({ + userSync: { + ..., + topics: { + maxTopicCaller: 3, // SSP rotation + bidders: [{ + bidder: 'pubmatic', + iframeURL: 'https://ads.pubmatic.com/AdServer/js/topics/topics_frame.html', + expiry: 7 // Configurable expiry days + },{ + bidder: 'rubicon', + iframeURL: 'https://rubicon.com:8080/topics/fpd/topic.html', // dummy URL + expiry: 7 // Configurable expiry days + },{ + bidder: 'appnexus', + iframeURL: 'https://appnexus.com:8080/topics/fpd/topic.html', // dummy URL + expiry: 7 // Configurable expiry days + }] + } + .... + } +}) + +``` + +{: .table .table-bordered .table-striped } +| Field | Required? | Type | Description | +|---|---|---|---| +| topics.maxTopicCaller | no | integer | Defines the maximum numbers of Bidders Iframe which needs to be loaded on the publisher page. Default is 1 which is hardcoded in Module. Eg: topics.maxTopicCaller is set to 3. If there are 10 bidders configured along with their iframe URLS, random 3 bidders iframe URL is loaded which will call TOPICS API. If topics.maxTopicCaller is set to 0, it will load random 1(default) bidder iframe atleast. | +| topics.bidders | no | Array of objects | Array of topics callers with the iframe locations and other necessary informations like bidder(Bidder code) and expiry. Default Array of topics in the module itself.| +| topics.bidders[].bidder | yes | string | Bidder Code of the bidder(SSP). | +| topics.bidders[].iframeURL | yes | string | URL which is hosted on bidder/SSP/third-party domains which will call Topics API. | +| topics.bidders[].expiry | no | integer | Max number of days where Topics data will be persist. If Data is stored for more than mentioned expiry day, it will be deleted from storage. Default is 21 days which is hardcoded in Module. | + + + +#### Disable performance metrics + +Since version 7.17, Prebid collects fine-grained performance metrics and attaches them to several events for the purpose of analytics. If you find that this generates too much data for your analytics provider you may disable this feature with: + +```javascript +pbjs.setConfig({performanceMetrics: false}) +``` + + + +#### Setting alias registry to private + +The alias registry is made public by default during an auction. It can be referenced in the following way: + +```javascript +pbjs.aliasRegistry or pbjs.aliasRegistry[aliasName]; +``` + +Inversely, if you wish for the alias registry to be private you can do so by using the option below (causing `pbjs.aliasRegistry` to return undefined): + +```javascript +pbjs.setConfig({aliasRegistry: 'private'}) +``` + + #### Generic setConfig Configuration Some adapters may support other options, as defined in their documentation. To set arbitrary configuration values: -{% highlight js %} +```javascript pbjs.setConfig({ : }); -{% endhighlight %} +``` - + #### Troubleshooting your configuration Towards catching syntax errors, one tip is to call `pbjs.setConfig` without an object, e.g., -{% highlight js %} -pbjs.setConfig('debug', 'true')); -{% endhighlight %} +```javascript +pbjs.setConfig('debug', 'true'); +``` then Prebid.js will print an error to the console that says: -``` +```noformat ERROR: setConfig options must be an object ``` If you don't see that message, you can assume the config object is valid. -
        +
        ## Related Reading -- [Prebid.js and Ad Server Key Values](/features/adServerKvps.html) +* [Prebid.js and Ad Server Key Values](/features/adServerKvps.html) diff --git a/dev-docs/publisher-api-reference/setPAAPIConfigForGPT.md b/dev-docs/publisher-api-reference/setPAAPIConfigForGPT.md new file mode 100644 index 0000000000..cf47f90a4c --- /dev/null +++ b/dev-docs/publisher-api-reference/setPAAPIConfigForGPT.md @@ -0,0 +1,25 @@ +--- +layout: api_prebidjs +title: pbjs.setPAAPIConfigForGPT(options) +description: setPAAPIConfigForGPT API +sidebarType: 1 +--- + +Configure GPT slots to use PAAPI. + +**Kind**: static method of pbjs API. Only available when the [fledgeForGpt module](/dev-docs/modules/fledgeForGpt.html) is installed. + +**Parameters**: + +{: .table .table-bordered .table-striped } +| Param | Scope | Type | Description | +| --- | --- | --- | --- | +| options | Optional | `Object` | | +| options.adUnitCode | Optional | `String` | Ad unit filter; if provided, only configure the GPT slot that matches this ad unit | +| options.auctionId | Optional | `String` | Auction filter; if provided, only configure GPT slots with PAAPI configs from this auction | + +**Example**: + +```js +pbjs.setPAAPIConfigForGPT({adUnitCode: 'test-slot'}) +``` diff --git a/dev-docs/publisher-api-reference/setTargetingForAst.md b/dev-docs/publisher-api-reference/setTargetingForAst.md index 0304512529..5a58ec6ff9 100644 --- a/dev-docs/publisher-api-reference/setTargetingForAst.md +++ b/dev-docs/publisher-api-reference/setTargetingForAst.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.setTargetingForAst(adUnitCode) -description: +description: setTargetingForAst API +sidebarType: 1 --- diff --git a/dev-docs/publisher-api-reference/setTargetingForGPTAsync.md b/dev-docs/publisher-api-reference/setTargetingForGPTAsync.md index ee5e94dc81..16d682dfe3 100644 --- a/dev-docs/publisher-api-reference/setTargetingForGPTAsync.md +++ b/dev-docs/publisher-api-reference/setTargetingForGPTAsync.md @@ -1,7 +1,8 @@ --- layout: api_prebidjs title: pbjs.setTargetingForGPTAsync([codeArr], customSlotMatching) -description: +description: setTargetingForGPTAsync API +sidebarType: 1 --- @@ -19,6 +20,7 @@ This function matches AdUnits that have returned from the auction to a GPT ad sl targeting attributes to the slot so they get sent to GAM. Here's how it works: + 1. For each AdUnit code that's returned from auction or is specified in the `codeArr` parameter: 2. For each GPT ad slot on the page: 3. If the `customSlotMatching` function is defined, call it. Else, try to match the AdUnit `code` with the GPT slot name. Else try to match the AdUnit `code` with the ID of the HTML div containing the slot. @@ -33,7 +35,7 @@ the ad results should render into. This could be useful on long-scrolling pages. short to make sure they get good viewability, the logic can find an appropriate placement for the auction result depending on where the user is once the auction completes. -``` +```javascript // returns a filter function that matches either with the slot or the adUnitCode // this filter function is being invoked after the auction has completed // this means that it can be used in order to place this within viewport instead of a static div naming diff --git a/dev-docs/publisher-api-reference/triggerBilling.md b/dev-docs/publisher-api-reference/triggerBilling.md new file mode 100644 index 0000000000..1e5e392731 --- /dev/null +++ b/dev-docs/publisher-api-reference/triggerBilling.md @@ -0,0 +1,79 @@ +--- +layout: api_prebidjs +title: pbjs.triggerBilling +description: triggerBilling API +sidebarType: 1 +--- + + +Allows a publisher the option to manually trigger billing for a winning bid or bids when ready to do so. + +{: .alert.alert-warning :} +Note: In order to use `pbjs.triggerBilling`, see the following bullet points below: + +- Any bid adapters a publisher integrates with must include the onBidBillable(bid) method which will be invoked by Prebid.js when it deems a bid to be billable (When a bid wins, it is by default also billable. That is, by default, Prebid.js will invoke onBidWon and onBidBillable one after the other). +- A publisher must flag all adUnits as being separately billable via the deferBilling key: `pbjs.addAdUnits({deferBilling: true, ...})` (Setting deferBilling to true will trigger onBidWon but not onBidBillable). +- When appropriate (e.g. an interstitial is displayed), the publisher may call `pbjs.triggerBilling(winningBidObjectToBill)`, which would then trigger onBidBillable. + +See below for an example of how triggerBilling can be used: + +{: .alert.alert-warning :} +Note: The logic to decide when to invoke `pbjs.triggerBilling` is open-ended. One common use case could be to listen for an "on view" event emitted from your ad server.

        For instance, the example below listens for GPT's "impressionViewable" event to determine if a deferred ad unit has become visible and is therefore ready for billing. The utilized approach to determine when to invoke `pbjs.triggerBilling` should be customized to your specific needs (For more on GPT's "impressionViewable" event, see: [developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent](https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent)).

        Additionally, the example below takes into account the possibility of multiple deferred ad units being present on a page that could potentially invoke the triggerBilling function (see the "deferredAdUnitIds" variable in the snippet below). The amount of deferred ad units needed on a page are dependent on your needs and could vary. + +```javascript +... + +var adUnits = [ + { + code: "deferred-ad-element-id-1", + deferBilling: true, // decide whether an ad unit should be deferred + ... + }, + { + code: "deferred-ad-element-id-2", + deferBilling: true, // decide whether an ad unit should be deferred + ... + } +]; + +pbjs.que.push(function () { // standard prebid configuration + pbjs.addAdUnits(adUnits); + pbjs.requestBids({ + bidsBackHandler: sendAdserverRequest, + timeout: 1000, + }); +}); + +function sendAdserverRequest(bids, timedOut, auctionId) { + let winningBidsWithDeferredAdUnits = []; // bids associated with deferred ad units that win the Prebid auction will be added to this array (there could be one or many winning bids) + let deferredAdUnitIds = ['deferred-ad-element-id-1', 'deferred-ad-element-id-2']; // enter the ad unit ids you would like to defer billing for (there could be one or many deferred ad unit ids) + + deferredAdUnitIds.forEach(deferredAdUnitId => { + if (bids[deferredAdUnitId]) { + // confirm each deferred ad unit came back with the bid responses + pbjs.onEvent("bidWon", (bid) => { + if (bid.adUnitCode === deferredAdUnitId) { + // confirm bid for deferred ad unit has won + winningBidsWithDeferredAdUnits.push(bid); + } + }); + } + }); + + // next, run some custom logic to detect if a publisher is ready to trigger billing (ex: the ad unit became visible). + // note: the following code block inside of the "impressionViewable" event listener is just one example of how to trigger billing for deferred ad units by utilizing GPT's "impressionViewable" event. + googletag.pubads().addEventListener("impressionViewable", (event) => { + const adSlotId = event.slot.getSlotElementId(); + winningBidsWithDeferredAdUnits.find(bid => { + if (bid.adUnitCode === adSlotId) { // confirm if the ad slot that became viewable was a deferred ad slot + pbjs.triggerBilling(bid); + } + }); + }); +} + +... + +``` + +
        diff --git a/dev-docs/release-notes.md b/dev-docs/release-notes.md index 7cae1390fc..e85e26c54f 100644 --- a/dev-docs/release-notes.md +++ b/dev-docs/release-notes.md @@ -7,6 +7,7 @@ description: Release Notes
        # Release Notes + {:.no_toc} This page has links to release notes for each of the projects associated with Prebid.org. @@ -14,6 +15,12 @@ This page has links to release notes for each of the projects associated with Pr ## Prebid.js + [Release notes on GitHub](https://github.com/prebid/Prebid.js/releases) ++ [Prebid.js 8 Release Notes](/dev-docs/pb8-notes.html) ++ [Prebid.js 7 Release Notes](/dev-docs/pb7-notes.html) ++ [Prebid.js 6 Blog Post](https://prebid.org/blog/prebid-6-0-release/) ++ [Prebid.js 5 Blog Post](https://prebid.org/blog/prebid-5-0-release/) ++ [Prebid.js 4 Blog Post](https://prebid.org/blog/prebid-js-release-4-0/) ++ [Prebid.js before 4.0](/prebid/prebidjsReleases.html) ## Prebid Server diff --git a/dev-docs/show-long-form-video-with-gam.md b/dev-docs/show-long-form-video-with-gam.md index b14d30180f..7f9d4ef178 100644 --- a/dev-docs/show-long-form-video-with-gam.md +++ b/dev-docs/show-long-form-video-with-gam.md @@ -16,16 +16,18 @@ In this tutorial, we'll detail how to set up Prebid.js to display a Programmatic ## Prerequisites -The code example below was built with Prebid.js and the following: -- At least one video-enabled bidder supporting `adpod`. -- The [`dfpAdServerVideo` module](/dev-docs/modules/dfp_video.html), which will provide the video ad support. -- The [`categoryTranslation` module](/dev-docs/modules/categoryTranslation.html), to enable competitive separation. +The code example below was built with Prebid.js and the following: + +* At least one video-enabled bidder supporting `adpod`. +* The [`dfpAdServerVideo` module](/dev-docs/modules/dfp_video.html), which will provide the video ad support. +* The [`categoryTranslation` module](/dev-docs/modules/categoryTranslation.html), to enable competitive separation. For example, to build with the AppNexus bidder adapter and GAM use the following command: ```bash gulp build --modules=appnexusBidAdapter,dfpAdServerVideo ``` + For more information about how to build with modules, see the [Prebid module documentation](/dev-docs/modules/). {% include alerts/alert_important.html content="If competitve separation is required the optional [`categoryTranslation` module](/dev-docs/modules/categoryTranslation.html) needs to be added to the build command." %} @@ -33,12 +35,14 @@ For more information about how to build with modules, see the [Prebid module doc {% include alerts/alert_important.html content="Ensure your ad ops team has set up line items in Google Ad Manager." %} ## Ad Pod Module + When the [`dfpAdServerVideo` module](/dev-docs/modules/dfp_video.html) is included in the Prebid.js build, the [Ad Pod module](/dev-docs/modules/adpod.html), for working with ad pods, is automatically included. This module enables developers to add support for an adserver, like Google Ad Manager or Freewheel, that handles ad unit types of adpod. Specifically, the module provides functions to validate, cache, and modify long-form video bids. ## Implementation + This section provides information on how to implement and configure Prebid.js to display ad unit types of adpod. -**1. Create an ad unit** +### 1. Create an ad unit Create an ad unit that contains a video `mediaType` object and set the `mediaTypes.video.context` to `adpod`. Set the other parameters to the specific properties for the publisher's inventory. @@ -46,30 +50,29 @@ Create an ad unit that contains a video `mediaType` object and set the `mediaTyp ```javascript var videoAdUnit = [{ - code: 'sample-code', - sizes: [640,480], - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: true - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 14542875 - } + code: 'sample-code', + sizes: [640,480], + mediaTypes: { + video: { + context: 'adpod', + playerSize: [640, 480], + adPodDurationSec: 300, + durationRangeSec: [15, 30], + requireExactDuration: true + } + }, + bids: [ + { + bidder: 'appnexus', + params: { + placementId: 14542875 } - ] - }]; -}; + } + ] +}] ``` -**2. Get ad pod targeting** +### 2. Get ad pod targeting If a publisher wants to retrieve ad pod targeting and create the master tag themselves they can use the getAdPodTargeting method of the `dfpAdServerVideo` module. The method requires an array of ad unit codes and returns targeting key values and the cache id as JSON. @@ -86,23 +89,23 @@ pbjs.adServers.dfp.getAdpodTargeting({ Sample return: -```JSON +```json { - 'adUnitCode-1': [ + "adUnitCode-1": [ { - 'hb_pb_cat_dur': '10.00_
        - + -{% highlight js %} +```javascript pbjs.addAdUnits({ code: slot.code, @@ -151,7 +152,7 @@ pbjs.addAdUnits({ }, ] }) -{% endhighlight %} +``` {: .alert.alert-danger :} For each native ad unit, all of the bidders within that ad unit must have declared native support in their adapter if you want ads to appear. If there are any bidders without native support in a native ad unit, requests will not be made to those bidders. For a list of bidders with native support, see [Bidders with Video and Native Demand]({{site.baseurl}}/dev-docs/bidders.html#bidders-with-video-and-native-demand). @@ -164,16 +165,16 @@ For now there is only the `image` type, but more will be added. The image native ad type implies the following required fields: -+ image -+ title -+ sponsoredBy -+ clickUrl +* image +* title +* sponsoredBy +* clickUrl And the following optional fields: -+ body -+ icon -+ cta +* body +* icon +* cta A native "image-type" ad unit can be set up as shown in the following example. @@ -196,9 +197,9 @@ const adUnits = [{ {% include dev-docs/native-image-asset-sizes.md %} -### 3. Add your native ad tag to the page body as usual: +### 3. Add your native ad tag to the page body as usual -{% highlight html %} +```html
        -{% endhighlight %} +``` ## Sending Asset Placeholders @@ -276,12 +277,12 @@ it will respond to that request with the actual asset values for that `adId` in A script within the native template can listen for this response and replace the placeholder values with their actual values. {: .alert.alert-success :} -The `native-trk.js` script from `prebid-universal-creative` can replace native placeholder values with their actual values. If a native template includes a link with a `pbAdId` attribute set to the targeting key `hb_adid`, and a `class` attribute set to `"pb-click"`, the function `pbNativeTag.startTrackers` will replace any placeholders found within the HTML template (but not CSS template) with their actual values automatically. For more on how to set this up in a native template, see [Style your native ad]({{site.github.url}}/adops/setting-up-prebid-native-in-dfp.html#3-style-your-native-ad) +The `native-trk.js` script from `prebid-universal-creative` can replace native placeholder values with their actual values. If a native template includes a link with a `pbAdId` attribute set to the targeting key `hb_adid`, and a `class` attribute set to `"pb-click"`, the function `pbNativeTag.startTrackers` will replace any placeholders found within the HTML template (but not CSS template) with their actual values automatically. For more on how to set this up in a native template, see [Style Your Native Ad](/adops/gam-native.html#style-your-native-ad) ## Working Examples -+ [Prebid Native Examples](/dev-docs/examples/native-ad-example.html) +* [Prebid Native Examples](/dev-docs/examples/native-ad-example.html) -## Related Topics +## Further Reading -+ [Setting up Prebid Native in Google Ad Manager]({{site.github.url}}/adops/setting-up-prebid-native-in-dfp.html) (Ad Ops Setup Instructions) +* [GAM Step by Step - Native Creatives](/adops/gam-native.html) (Ad Ops Setup Instructions) diff --git a/dev-docs/show-outstream-video-ads.md b/dev-docs/show-outstream-video-ads.md index 6b4a9dde66..0f6c066454 100644 --- a/dev-docs/show-outstream-video-ads.md +++ b/dev-docs/show-outstream-video-ads.md @@ -9,6 +9,7 @@ sidebarType: 4
        # Show Outstream Video Ads + {: .no_toc} Unlike instream video ads, which require you to have your own video inventory, Outstream video ads can be shown on any web page, even pages that only have text content. @@ -24,16 +25,15 @@ There should be no changes required on the ad ops side, since the outstream unit ## Prerequisites -+ Inclusion of at least one demand adapter that supports the `"video"` media type +* Inclusion of at least one demand adapter that supports the `"video"` media type ## Step 1: Set up ad units with the video media type and outstream context Use the `adUnit.mediaTypes` object to set up your ad units with the `video` media type and assign the appropriate context -The fields supported in a given `bid.params.video` object will vary based on the rendering options supported by each bidder. For more information, see [Bidders' Params]({{site.github.url}}/dev-docs/bidders.html). - -{% highlight js %} +For full details on video ad unit parameters, see [Ad Unit Reference for Video]({{site.baseurl}}/dev-docs/adunit-reference.html#adunitmediatypesvideo) +```javascript var videoAdUnits = [{ code: 'video1', mediaTypes: { @@ -43,22 +43,18 @@ var videoAdUnits = [{ mimes: ['video/mp4'], protocols: [1, 2, 3, 4, 5, 6, 7, 8], playbackmethod: [2], - skip: 1 + skip: 1, + playback_method: ['auto_play_sound_off'] } }, bids: [{ bidder: 'appnexus', params: { placementId: 13232385, - video: { - skip: 1, - playback_method: ['auto_play_sound_off'] - } } }] }]; - -{% endhighlight %} +``` ### Renderers @@ -76,18 +72,21 @@ Prebid.js will select the `renderer` used to display the outstream video in the {: .alert.alert-warning :} At this time, since not all demand partners return a renderer with their video bid responses, we recommend that publishers associate a `renderer` with their Prebid video adUnits, if possible. By doing so, any Prebid adapter that supports video will be able to provide demand for a given outstream slot. -Renderers are associated with adUnits in two ways. -Primarily through the `adUnit.renderer` object. But also, especially for multiFormat adUnits, through the specified mediaType `adUnit.mediaTypes.video.renderer`. -This object contains these fields: +Renderers can be attached to adUnits in three ways; Prebid will pick the first that is defined as: + + 1. `adUnit.mediaTypes[type].renderer` (for example, `adUnit.mediaTypes.video.renderer`); + 2. `adUnit.bids[].renderer`; + 3. `adUnit.renderer`. + +A renderer is an object containing these properties: 1. `url` -- Points to a file containing the renderer script. 2. `render` -- A function that tells Prebid.js how to invoke the renderer script. 3. `backupOnly` -- Optional field, if set to true, buyer or adapter renderer will be preferred - In a multiFormat adUnit, you might want the renderer to only apply to only one of the mediaTypes. You can do this by defining the renderer on the media type itself. -{% highlight js %} +```javascript pbjs.addAdUnit({ code: 'video1', // This renderer would apply to all prebid creatives... @@ -119,12 +118,11 @@ pbjs.addAdUnit({ }, ... }); -{% endhighlight %} +``` Some demand partners that return a renderer with their video bid responses may support renderer configuration with the `adUnit.renderer.options` object. These configurations are bidder specific and may include options for skippability, player size, and ad text, for example. An example renderer configuration follows: -{% highlight js %} - +```javascript pbjs.addAdUnit({ code: 'video1', mediaTypes: { @@ -144,8 +142,7 @@ pbjs.addAdUnit({ }, ... }); - -{% endhighlight %} +``` For more technical information about renderers, see [the pull request originally adding the 'Renderer' type](https://github.com/prebid/Prebid.js/pull/1082) and [the pull request allowing the 'renderer' type in the mediaType](https://github.com/prebid/Prebid.js/pull/5760). @@ -157,8 +154,7 @@ Invoke your ad server for the outstream adUnit from the body of the page in the For a live example, see [Outstream with Google Ad Manager]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html). -{% highlight html %} - +```html

        Prebid Outstream Video Ad

        - -{% endhighlight %} +``` ### Option 2: Serving without an ad server @@ -184,8 +179,7 @@ In the Prebid.js event queue, you'll need to add a function that: 1. Selects the bid that will serve for the appropriate adUnit 2. Renders the ad -{% highlight js %} - +```javascript pbjs.que.push(function () { pbjs.addAdUnits(videoAdUnits); pbjs.requestBids({ @@ -196,20 +190,19 @@ pbjs.que.push(function () { } }); }); - -{% endhighlight %} +``` For more information, see the API documentation for: -+ [requestBids](/dev-docs/publisher-api-reference/requestBids.html) -+ [getHighestCpmBids](/dev-docs/publisher-api-reference/getHighestCpmBids.html) -+ [renderAd](/dev-docs/publisher-api-reference/renderAd.html) +* [requestBids](/dev-docs/publisher-api-reference/requestBids.html) +* [getHighestCpmBids](/dev-docs/publisher-api-reference/getHighestCpmBids.html) +* [renderAd](/dev-docs/publisher-api-reference/renderAd.html) ## Working Examples Below, find links to end-to-end "working examples" demonstrating Prebid Outstream: -+ [Outstream with Google Ad Manager]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html) -+ [Outstream without an Ad Server]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-no-server.html) +* [Outstream with Google Ad Manager]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html) +* [Outstream without an Ad Server]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-no-server.html)
        diff --git a/dev-docs/show-prebid-ads-on-amp-pages.md b/dev-docs/show-prebid-ads-on-amp-pages.md index e03048365e..555b42648b 100644 --- a/dev-docs/show-prebid-ads-on-amp-pages.md +++ b/dev-docs/show-prebid-ads-on-amp-pages.md @@ -6,6 +6,7 @@ sidebarType: 2 --- # Prebid AMP Implementation Guide + {: .no_toc} This page has instructions for showing ads on Accelerated Mobile Pages (AMP) using Prebid.js. @@ -14,14 +15,14 @@ Through this implementation, [Prebid Server][PBS] fetches demand and returns key For more information about AMP RTC, see: -+ [Prebid Server and AMP](/prebid-server/use-cases/pbs-amp.html) -+ [Prebid Server AMP Endpoint Technical Documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) -+ [Prebid Server Stored Bid Requests](https://github.com/prebid/prebid-server/blob/master/docs/developers/stored-requests.md#stored-bidrequests) -+ [AMP RTC Overview](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md) -+ [AMP RTC Publisher Integration Guide](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-publisher-implementation-guide.md) +* [Prebid Server and AMP](/prebid-server/use-cases/pbs-amp.html) +* [Prebid Server AMP Endpoint Technical Documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) +* [Prebid Server Stored Bid Requests](https://github.com/prebid/prebid-server/blob/master/docs/developers/stored-requests.md#stored-bidrequests) +* [AMP RTC Overview](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md) +* [AMP RTC Publisher Integration Guide](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-publisher-implementation-guide.md) {% capture tipNote %} -For ad ops setup instructions, see [Setting up Prebid for AMP in Google Ad Manager]({{site.github.url}}/adops/setting-up-prebid-for-amp-in-dfp.html). +For ad ops setup instructions, see [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html). {% endcapture %} {% include alerts/alert_note.html content=tipNote %} @@ -33,18 +34,18 @@ For ad ops setup instructions, see [Setting up Prebid for AMP in Google Ad Manag To set up Prebid to serve ads into your AMP pages, you'll need: -+ An account with a [Prebid Server][PBS] instance -+ One or more Prebid Server Stored Bid Requests. A Stored Bid Request is a partial OpenRTB JSON request which: - + Specifies properties like currency, schain, price granularity, etc. - + Contains a list of demand partners and their respective parameters -+ An AMP page containing at least one amp-ad element for an AMP ad network that supports Fast Fetch and AMP RTC +* An account with a [Prebid Server][PBS] instance +* One or more Prebid Server Stored Bid Requests. A Stored Bid Request is a partial OpenRTB JSON request which: + * Specifies properties like currency, schain, price granularity, etc. + * Contains a list of demand partners and their respective parameters +* An AMP page containing at least one amp-ad element for an AMP ad network that supports Fast Fetch and AMP RTC ## Implementation -+ [Prebid Server Stored Request](#prebid-server-stored-request): This is the Prebid Server Stored Bid Request. -+ [AMP content page](#amp-content-page): This is where your content lives. -+ [HTML Creative](#html-creative): This is the creative your Ad Ops team puts in your ad server. -+ [User Sync in AMP](#user-sync): This is the `amp-iframe` pixel that must be added to your AMP page to sync users with Prebid Server. +* [Prebid Server Stored Request](#prebid-server-stored-request): This is the Prebid Server Stored Bid Request. +* [AMP content page](#amp-content-page): This is where your content lives. +* [HTML Creative](#html-creative): This is the creative your Ad Ops team puts in your ad server. +* [User Sync in AMP](#user-sync): This is the `amp-iframe` pixel that must be added to your AMP page to sync users with Prebid Server. ### Prebid Server Stored Request @@ -53,15 +54,14 @@ You will have to create at least one Stored Request for Prebid Server. Valid St An example Stored Request is given below. You'll see that the Stored Request contains some important info that doesn't come from /amp parameters: -- cur -- schain -- ext.prebid.cache.bids - needed to let Prebid Server know that you want it to store the result in PBC -- ext.prebid.targeting.pricegranularity - needed to let Prebid Server know how to calculate the price bucket -- ext.prebid.aliases -- bidders and their parameters - -```html +* cur +* schain +* ext.prebid.cache.bids - needed to let Prebid Server know that you want it to store the result in PBC +* ext.prebid.targeting.pricegranularity - needed to let Prebid Server know how to calculate the price bucket +* ext.prebid.aliases +* bidders and their parameters +```json { "id": "some-request-id", "cur": ["USD"], @@ -114,34 +114,38 @@ that doesn't come from /amp parameters: }] } ``` + This basic OpenRTB record will be enhanced by the parameters from the call to the [/amp endpoint](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html). ### AMP content page First ensure that the amp-ad component is imported in the header. -``` +```html ``` + This script provides code libraries that will convert `` properties to the endpoint query parameters usint the [Real Time Config](https://github.com/ampproject/amphtml/blob/main/extensions/amp-a4a/rtc-documentation.md) (RTC) protocol. The `amp-ad` elements in the page body need to be set up as shown below, especially the following attributes: -+ `data-slot`: Identifies the ad slot for the auction. -+ `rtc-config`: Used to pass JSON configuration data to [Prebid Server][PBS], which handles the communication with AMP RTC. - + `vendors` is an object that defines any vendors that will be receiving RTC callouts (including Prebid Server) up to a maximum of five. The list of supported RTC vendors is maintained in [callout-vendors.js](https://github.com/ampproject/amphtml/blob/master/src/service/real-time-config/callout-vendors.js). We recommend working with your Prebid Server hosting company to set up which bidders and parameters should be involved for each AMP ad unit. - + `timeoutMillis` is an optional integer that defines the timeout in milliseconds for each individual RTC callout. The configured timeout must be greater than 0 and less than 1000ms. If omitted, the timeout value defaults to 1000ms. +* `data-slot`: Identifies the ad slot for the auction. +* `rtc-config`: Used to pass JSON configuration data to [Prebid Server][PBS], which handles the communication with AMP RTC. + * `vendors` is an object that defines any vendors that will be receiving RTC callouts (including Prebid Server) up to a maximum of five. The list of supported RTC vendors is maintained in [callout-vendors.js](https://github.com/ampproject/amphtml/blob/master/src/service/real-time-config/callout-vendors.js). We recommend working with your Prebid Server hosting company to set up which bidders and parameters should be involved for each AMP ad unit. + * `timeoutMillis` is an optional integer that defines the timeout in milliseconds for each individual RTC callout. The configured timeout must be greater than 0 and less than 1000ms. If omitted, the timeout value defaults to 1000ms. e.g. for the AppNexus cluster of Prebid Servers: + ```html + rtc-config='{"vendors": {"prebidappnexuspsp": {"PLACEMENT_ID": "13144370"}}, "timeoutMillis": 500}'> ``` e.g. for Rubicon Project's cluster of Prebid Servers: + ```html + - - -``` - For all other ad servers: ```html - - + - ``` Replace `MACRO` in the preceding example with the appropriate macro for the ad server. (Refer to your ad server's documentation or consult with a representative for specific details regarding the proper macros and how to use them.) @@ -243,17 +224,16 @@ Replace `MACRO` in the preceding example with the appropriate macro for the ad s To sync user IDs with Prebid Server, the `amp-iframe` below may be added to your AMP pages referring to `load-cookie.html` or if you're running an IAB-compliant AMP CMP you can use `load-cookie-with-consent.html`. -{% capture tipNote %} -The following examples include a transparent image as a placeholder which will allow you to place the example at the top within the HTML body. If this is not included the iFrame must be either 600px away from the top or not within the first 75% of the viewport when scrolled to the top – whichever is smaller. For more information on this, see [amp-iframe](https://amp.dev/documentation/components/amp-iframe/) -{% endcapture %} -{% include alerts/alert_tip.html content=tipNote %} +Note that AMP constrains syncing as described in the [amp-iframe](https://amp.dev/documentation/components/amp-iframe) documentation. You may only have *one* amp-iframe on your page that is small, e.g. 1x1. Many publishers already have some kind of analytics or tracking frame on their page, so they may find it difficult to manage this. Several hacks are possible, including building a 'frankenstein' script that combines all of your required tracking into one or tying the sync to an image that's large enough to be visible. -{% capture consentNote %} - The load-cookie-with-consent.html file has the same argument syntax as load-cookie.html. It's a different file because it's larger and depends on the existence of an AMP Consent Management Platform. Note that the `sandbox` parameter to the amp-iframe must include both "allow-scripts" and "allow-same-origin". -{% endcapture %} -{% include alerts/alert_tip.html content=consentNote %} +Notes: + +* The following examples include a transparent image as a placeholder which will allow you to place the example at the top within the HTML body. If this is not included the iFrame must be either 600px away from the top or not within the first 75% of the viewport when scrolled to the top – whichever is smaller. For more information on this, see [amp-iframe](https://amp.dev/documentation/components/amp-iframe/) +* Note that the `sandbox` parameter to the amp-iframe must include both "allow-scripts" and "allow-same-origin". +* The load-cookie-with-consent.html file has the same argument syntax as load-cookie.html. It's a different file because it's larger and depends on the existence of an AMP Consent Management Platform. If you're using AppNexus' managed service, you would enter something like this: + ```html ``` -The usage of `load-cookie.html` and `load-cookie-with-consent.html` is the same. The arguments available on the query string are: - -{: .table .table-bordered .table-striped } -| Param | Scope | Values | Description | -| --- | --- | --- | --- | -| endpoint | recommended | 'appnexus', 'rubicon', or URL | Determines which cluster of prebid servers to load from. Default, for legacy reasons, is appnexus. | -| source | optional | recommended | Set it to 'amp' to tell Prebid Server to exclude iframe syncs, which don't work on AMP. | -| max_sync_count | optional | integer | How many sync pixels should be returned from Prebid Server | -| args | optional | attr1:val1,attr2:val2 | These attribute value pairs will be passed to Prebid Server in the /cookie_sync call. The attribute and value will be quoted by the system when appropriate. | -| gdpr | optional | 0 or 1 | Defines whether GDPR processing is in scope for this request. 0=no, 1=yes. Leave unknown if not sure. | -| gdpr_consent | optional | String | IAB CMP-formatted consent string | - -### AMP RTC and GDPR - -The two Prebid Server RTC vendor strings 'prebidappnexus' and 'prebidrubicon' -support passing GDPR consent to Prebid Server. - -The CONSENT_STRING macro will be populated if you've integrated with a CMP -that supports amp-consent v2 -- custom CMP integration. - -If you're using a custom RTC callout, here are the parameters that can be passed through the RTC string: -- tag_id -- w=ATTR(width) -- h=ATTR(height) -- ow=ATTR(data-override-width) -- oh=ATTR(data-override-height) -- ms=ATTR(data-multi-size) -- slot=ATTR(data-slot) -- targeting=TGT -- curl=CANONICAL_URL -- timeout=TIMEOUT -- adc=ADCID -- purl=HREF -- gdpr_consent=CONSENT_STRING -- consent_type=CONSENT_METADATA(consentStringType) -- gdpr_applies=CONSENT_METADATA(gdprApplies) -- attl_consent=CONSENT_METADATA(additionalConsent) - -See the entries in the [AMP vendors callout file](https://github.com/ampproject/amphtml/blob/main/src/service/real-time-config/callout-vendors.js). +See [manually initiating a sync](/prebid-server/developers/pbs-cookie-sync.html#manually-initiating-a-sync) for more information about the available parameters. + +### AMP RTC + +If you're using a custom RTC callout rather than one of the pre-defined [vendor callouts](https://github.com/ampproject/amphtml/blob/main/src/service/real-time-config/callout-vendors.js), here are the parameters that can be passed through the RTC string: + +* tag_id (this correspondes to the Prebid Server stored request ID) +* w=ATTR(width) +* h=ATTR(height) +* ow=ATTR(data-override-width) +* oh=ATTR(data-override-height) +* ms=ATTR(data-multi-size) +* slot=ATTR(data-slot) +* targeting=TGT +* curl=CANONICAL_URL +* timeout=TIMEOUT +* adc=ADCID +* purl=HREF +* gdpr_consent=CONSENT_STRING +* consent_type=CONSENT_METADATA(consentStringType) +* gdpr_applies=CONSENT_METADATA(gdprApplies) +* attl_consent=CONSENT_METADATA(additionalConsent) ## Debugging Tips + To review that Prebid on AMP is working properly the following aspects can be looked at: -+ Include `#development=1` to the URL to review AMP specifc debug messages in the browser console. -+ Look for the Prebid server call in the network panel. You can open this URL in a new tab to view additional debugging information relating to the Prebid Server Stored Bid Request. If working properly, Prebid server will display the targeting JSON for AMP to use. -+ Look for the network call from the Ad Server to ensure that key values are being passed. (For Google Ad Manager these are in the `scp` query string parameter in the network request) -+ Most of the debugging information is omitted from the Prebid Server response unless the `debug=1` parameter is present in the Prebid Server query string. AMP won't add this parameter, so you'll need to grab the Prebid Server URL and manually add it to see the additional information provided. + +* Include `#development=1` to the URL to review AMP specifc debug messages in the browser console. +* Look for the Prebid server call in the network panel. You can open this URL in a new tab to view additional debugging information relating to the Prebid Server Stored Bid Request. If working properly, Prebid server will display the targeting JSON for AMP to use. +* Look for the network call from the Ad Server to ensure that key values are being passed. (For Google Ad Manager these are in the `scp` query string parameter in the network request) +* Most of the debugging information is omitted from the Prebid Server response unless the `debug=1` parameter is present in the Prebid Server query string. AMP won't add this parameter, so you'll need to grab the Prebid Server URL and manually add it to see the additional information provided. ## Further Reading -+ [Prebid Server and AMP](/prebid-server/use-cases/pbs-amp.html) -+ [Setting up Prebid for AMP in Google Ad Manager](/adops/setting-up-prebid-for-amp-in-dfp.html) (Ad Ops Setup) -+ [AMP RTC Overview](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md) +* [Prebid Server and AMP](/prebid-server/use-cases/pbs-amp.html) +* [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) (Ad Ops Setup) +* [AMP RTC Overview](https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md) +* [callout-vendors.js] [PBS]: /prebid-server/overview/prebid-server-overview.html [callout-vendors.js]: https://github.com/ampproject/amphtml/blob/master/src/service/real-time-config/callout-vendors.js +[RTC-Overview]: https://github.com/ampproject/amphtml/blob/master/extensions/amp-a4a/rtc-documentation.md diff --git a/dev-docs/show-video-with-a-dfp-video-tag.md b/dev-docs/show-video-with-a-dfp-video-tag.md index 929cffe49b..b14353a036 100644 --- a/dev-docs/show-video-with-a-dfp-video-tag.md +++ b/dev-docs/show-video-with-a-dfp-video-tag.md @@ -8,6 +8,7 @@ sidebarType: 4
        # Show Video Ads with Google Ad Manager + {: .no_toc} In this tutorial, we'll show how to set up Prebid to show a video ad @@ -22,13 +23,13 @@ different video players and video-enabled bidders. The code example below was built using the following libraries: -+ [video.js](https://videojs.com/) version 5.9.2 -+ MailOnline's [videojs-vast-vpaid plugin](https://github.com/MailOnline/videojs-vast-vpaid) version 2.0.2 +* [video.js](https://videojs.com/) version 5.9.2 +* MailOnline's [videojs-vast-vpaid plugin](https://github.com/MailOnline/videojs-vast-vpaid) version 2.0.2 Also, you need to make sure to build Prebid.js with: -+ Support for at least one video-enabled bidder -+ Support for the `dfpAdServerVideo` ad server adapter, which will provide the video ad support +* Support for at least one video-enabled bidder +* Support for the `dfpAdServerVideo` ad server adapter, which will provide the video ad support For example, to build with the AppNexus bidder adapter and the Google Ad Manager Video ad server adapter, use the following command: @@ -75,6 +76,8 @@ var videoAdUnit = { }; ``` +For full details on video ad unit parameters, see [Ad Unit Reference for Video]({{site.baseurl}}/dev-docs/adunit-reference.html#adunitmediatypesvideo) + ### 2. Implement Custom Price Buckets By default, Prebid.js caps all CPMs at $20. As a video seller, you may expect to see CPMs over $20. In order to receive those bids, you'll need to implement custom price buckets setting the [priceGranularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity) object in the `setConfig` method. @@ -119,12 +122,12 @@ pbjs.que.push(function() { The VAST XML has to be cached somewhere because most video players can only work with a URL that returns VAST XML, not VAST directly. Some bidders cache the VAST XML on the server side, while others depend on Prebid.js to perform the caching. -+ In general, video-enabled bidders must supply `bid.videoCacheKey`, `bid.vastXml`, or `bid.vastUrl` on their responses, and can provide any combination of the three. -+ If `pbjs.setConfig({cache: {URL}})` isn't set and the bidder supplies only `bid.vastXml` in its bid response, [`pbjs.adServers.dfp.buildVideoUrl`](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html) will not be able to generate a videoCacheKey, and it will be dropped from the auction. -+ If `pbjs.setConfig({cache: {URL}})` is defined and the bidder responds with `bid.videoCacheKey`, Prebid.js will not re-cache the VAST XML. -+ If `options.url` is passed as an argument to [`pbjs.adServers.dfp.buildVideoUrl`](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html): - + If Prebid Cache is disabled, Prebid sets `description_url` field to the bid response's `bid.vastUrl`. - + If Prebid Cache is enabled, Prebid sets `description_url` field to the cache URL. +* In general, video-enabled bidders must supply `bid.videoCacheKey`, `bid.vastXml`, or `bid.vastUrl` on their responses, and can provide any combination of the three. +* If `pbjs.setConfig({cache: {URL}})` isn't set and the bidder supplies only `bid.vastXml` in its bid response, [`pbjs.adServers.dfp.buildVideoUrl`](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html) will not be able to generate a videoCacheKey, and it will be dropped from the auction. +* If `pbjs.setConfig({cache: {URL}})` is defined and the bidder responds with `bid.videoCacheKey`, Prebid.js will not re-cache the VAST XML. +* If `options.url` is passed as an argument to [`pbjs.adServers.dfp.buildVideoUrl`](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html): + * If Prebid Cache is disabled, Prebid sets `description_url` field to the bid response's `bid.vastUrl`. + * If Prebid Cache is enabled, Prebid sets `description_url` field to the cache URL. #### Notes on multiple video advertisements on one page @@ -193,29 +196,14 @@ If you have [set up your ad server line items and creatives correctly]({{site.ba Below, find links to end-to-end "working examples" integrating Prebid.js demand with various video players: ### Using client-side adapters -+ [Akamai AMP]({{site.github.url}}/examples/video/instream/akamai/pb-ve-amp.html) -+ [Brid]({{site.github.url}}/examples/video/instream/brid/pb-ve-brid.html) -+ [Brightcove]({{site.github.url}}/examples/video/instream/brightcove/pb-ve-brightcove.html) -+ [Flowplayer]({{site.github.url}}/examples/video/instream/flowplayer/pb-ve-flowplayer.html) -+ [JWPlayer - Platform]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) -+ [JWPlayer - Hosted]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) -+ [Kaltura]({{site.github.url}}/examples/video/instream/kaltura/pb-ve-kaltura.html) -+ [Ooyala]({{site.github.url}}/examples/video/instream/ooyala/pb-ve-ooyala.html) -+ [VideoJS]({{site.github.url}}/examples/video/instream/videojs/pb-ve-videojs.html) -+ [Instream and Banner Mixed](/dev-docs/examples/instream-banner-mix.html) - -### Using Prebid Server Video - -+ [Brid]({{site.baseurl}}/examples/video/server/brid/pbs-ve-brid.html) -+ [JW Player - Platform]({{site.baseurl}}/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html) -+ [JW Player - Hosted]({{site.baseurl}}/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html) -+ [Kaltura]({{site.baseurl}}/examples/video/server/kaltura/pbs-ve-kaltura.html) -+ [Ooyala]({{site.baseurl}}/examples/video/server/ooyala/pbs-ve-ooyala.html) -+ [VideoJS]({{site.baseurl}}/examples/video/server/videojs/pbs-ve-videojs.html) +* [JWPlayer - Platform]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) +* [JWPlayer - Hosted]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) +* [VideoJS]({{site.github.url}}/examples/video/instream/videojs/pb-ve-videojs.html) +* [Instream and Banner Mixed](/dev-docs/examples/instream-banner-mix.html) ## Related Topics -+ [Setting up Prebid Video in Google Ad Manager]({{site.baseurl}}/adops/setting-up-prebid-video-in-dfp.html) +* [Setting up Prebid Video in Google Ad Manager]({{site.baseurl}}/adops/setting-up-prebid-video-in-dfp.html)
        diff --git a/dev-docs/testing-prebid.md b/dev-docs/testing-prebid.md index 9706a054cd..97168f7182 100644 --- a/dev-docs/testing-prebid.md +++ b/dev-docs/testing-prebid.md @@ -4,14 +4,13 @@ layout: page_v2 title: Testing Prebid.js description: How to write tests for the Prebid.js library pid: 199 - top_nav_section: dev_docs - ---
        # Testing Prebid.js + {: .no_toc} Starting on 21 June 2016, all pull requests to the Prebid.js library will need to include tests with greater than 80% code coverage for any changed/added code before they can be merged into master. @@ -27,68 +26,67 @@ This page describes how to test code in the Prebid.js repository to help prepare When you are adding code to Prebid.js, or modifying code that isn't covered by an existing test, test the code according to these guidelines: -- If the module you are working on is already partially tested by a file within the `test` directory, add tests to that file -- If the module does not have any tests, create a new test file -- Group tests in a `describe` block -- Test individual units of code within an `it` block -- Within an `it` block, it may be helpful to use the "Arrange-Act-Assert" pattern - - _Arrange_: set up necessary preconditions and inputs - - e.g., creating objects, spies, etc. - - _Act_: call or act on the unit under test - - e.g., call the function you are testing with the parameters you set up - - _Assert_: check that the expected results have occurred - - e.g., use Chai assertions to check that the expected output is equal to the actual output -- Test the public interface, not the internal implementation -- If using global `pbjs` data structures in your test, take care to not completely overwrite them with your own data as that may affect other tests relying on those structures, e.g.: - - **OK**: `pbjs._bidsRequested.push(bidderRequestObject);` - - **NOT OK**: `pbjs._bidsRequested = [bidderRequestObject];` -- If you need to check `adloader.loadScript` in a test, use a `stub` rather than a `spy`. `spy`s trigger a network call which can result in a `script error` and cause unrelated unit tests to fail. `stub`s will let you gather information about the `adloader.loadScript` call without affecting external resources - -- When writing tests you may use ES2015 syntax if desired +* If the module you are working on is already partially tested by a file within the `test` directory, add tests to that file +* If the module does not have any tests, create a new test file +* Group tests in a `describe` block +* Test individual units of code within an `it` block +** Within an `it` block, it may be helpful to use the "Arrange-Act-Assert" pattern + * _Arrange_: set up necessary preconditions and inputs + * e.g., creating objects, spies, etc. + * _Act_: call or act on the unit under test + * e.g., call the function you are testing with the parameters you set up + * _Assert_: check that the expected results have occurred + * e.g., use Chai assertions to check that the expected output is equal to the actual output +* Test the public interface, not the internal implementation +* If using global `pbjs` data structures in your test, take care to not completely overwrite them with your own data as that may affect other tests relying on those structures, e.g.: + * **OK**: `pbjs._bidsRequested.push(bidderRequestObject);` + * **NOT OK**: `pbjs._bidsRequested = [bidderRequestObject];` +* If you need to check `adloader.loadScript` in a test, use a `stub` rather than a `spy`. `spy`s trigger a network call which can result in a `script error` and cause unrelated unit tests to fail. `stub`s will let you gather information about the `adloader.loadScript` call without affecting external resources +* When writing tests you may use ES2015 syntax if desired ## Running tests After checking out the Prebid.js repository and installing dev dependencies with `npm install`, use the following commands to run tests as you are working on code: -- `gulp test` will run the test suite once (`npm test` is aliased to call `gulp test`) -- `gulp serve` will run tests once and stay open, re-running tests whenever a file in the `src` or `test` directory is modified +* `gulp test` will run the test suite once (`npm test` is aliased to call `gulp test`) +* `gulp serve` will run tests once and stay open, re-running tests whenever a file in the `src` or `test` directory is modified ## Checking results and code coverage Check the test results using these guidelines: -- Look at the total number of tests run, passed, and failed (shown below the rainbow Nyan Cat in the shell window). -- If all tests are passing, great. -- Otherwise look for errors printed in the console for a description of the failing test. -- You may need to iterate on your code or tests until all tests are passing. -- Make sure existing tests still pass. -- There is a table below the testing report that shows code coverage percentage, for each file under the `src` directory. -- Each time you run tests, a code coverage report is generated in `build/coverage/lcov/lcov-report/index.html`. -- This is a static HTML page that you can load in your browser. -- On that page, navigate to the file you are testing to see which lines are being tested. -- Red indicates that a line isn't covered by a test. -- Gray indicates a line that doesn't need coverage, such as a comment or blank line. -- Green indicates a line that is covered by tests. -- The code you have added or modified must have greater than 80% coverage to be accepted. +* Look at the total number of tests run, passed, and failed (shown below the rainbow Nyan Cat in the shell window). +* If all tests are passing, great. +* Otherwise look for errors printed in the console for a description of the failing test. +* You may need to iterate on your code or tests until all tests are passing. +* Make sure existing tests still pass. +* There is a table below the testing report that shows code coverage percentage, for each file under the `src` directory. +* Each time you run tests, a code coverage report is generated in `build/coverage/lcov/lcov-report/index.html`. +* This is a static HTML page that you can load in your browser. +* On that page, navigate to the file you are testing to see which lines are being tested. +* Red indicates that a line isn't covered by a test. +* Gray indicates a line that doesn't need coverage, such as a comment or blank line. +* Green indicates a line that is covered by tests. +* The code you have added or modified must have greater than 80% coverage to be accepted. ## Examples Prebid.js already has lots of tests. Read them to see how Prebid.js is tested, and for inspiration: -- Look in `test/spec` and its subdirectories -- Tests for bidder adaptors are located in `test/spec/adapters` +* Look in `test/spec` and its subdirectories +* Tests for bidder adaptors are located in `test/spec/adapters` A test module might have the following general structure: -{% highlight js %} +```javascript // Import or require modules necessary for the test, e.g.: import { expect } from 'chai'; // may prefer 'assert' in place of 'expect' -import adapter from 'src/adapters/'; +import adapter from 'src/adapters/[adapter]'; -describe('', () => { +describe('[Adapter]', () => { - it('', () => { + it('[description of unit or feature being tested]', () => { // Arrange - set up preconditions and inputs // Act - call or act on the code under test // Assert - use chai to check that expected results have occurred @@ -98,14 +96,14 @@ describe('', () => { }); -{% endhighlight %} +``` ## Resources The Prebid.js testing stack contains some of the following tools. It may be helpful to consult their documentation during the testing process. -- [Mocha - test framework](https://mochajs.org/) -- [Chai - BDD/TDD assertion library](https://chaijs.com/) -- [Sinon - spy, stub, and mock library](https://sinonjs.org/) +* [Mocha - test framework](https://mochajs.org/) +* [Chai - BDD/TDD assertion library](https://chaijs.com/) +* [Sinon - spy, stub, and mock library](https://sinonjs.org/)
        diff --git a/dev-docs/troubleshooting-tips.md b/dev-docs/troubleshooting-tips.md index 1b2375c9e1..45b47efd77 100644 --- a/dev-docs/troubleshooting-tips.md +++ b/dev-docs/troubleshooting-tips.md @@ -11,6 +11,7 @@ sidebarType: 1 # Tips for Troubleshooting + {:.no_toc} Moved to [the PBJS Troubleshooting Guide](/troubleshooting/troubleshooting-guide.html). diff --git a/dev-docs/vendor-billing.md b/dev-docs/vendor-billing.md new file mode 100644 index 0000000000..ce22b26d35 --- /dev/null +++ b/dev-docs/vendor-billing.md @@ -0,0 +1,59 @@ +--- +layout: page_v2 +title: Vendor Billing in Prebid.js +description: Documentation on how to add Vendor Billing in Prebid.js +sidebarType: 1 +--- + +# Vendor Billing in Prebid.js + +{:.no_toc} + +Prebid.js now supports a new event type: **Billable Event**. Billable events allow **Real Time Data (RTD)** modules to signal that their system calculated that a billing event occurred. Billable events are trackable by analytics adapters as well as publishers to track and aggregate billing data. + +## Emitting Events + +In order to emit events, **RTD** modules simply need to utilize the existing Events system already integrated into Prebid.js. A new event, **BILLABLE_EVENT**, is registered inside the constants.json file for usage. + +At this time there are limited requirements about the contents of billable events. However, it should be expected that partners who choose to leverage billable events may have unique requirements or implementations that will be documented individually, including adding additional parameters to the events as they see fit. + +### Event Payload Parameters + +There are two parameters that emitters of this event must supply. Other parameters may be supplied as desired by the application. + +{: .table .table-bordered .table-striped } +| **Required Parameter** | **Type** | **Definition** | +|----------------+-----------+-----------------| +| vendor | string | Contains the unique name of the vendor, and will be used to identify which vendor triggered a given event. | +| billingId | UUID | A unique UUID associated with a given billing event. Generated by the vendor. | + +For example, a RTD module could emit an event like this: + +```javascript +events.emit(CONSTANTS.EVENTS.BILLABLE_EVENT, { + vendor: 'vendorA', + billingId: generateUUID(), + type: 'ad_request', + transactionId: transactionId, + auctionId: auctionId +}) +``` + +It is expected that vendors will not emit duplicate events. + +## Analytics Adapter Interface + +[Analytics Adapters](/dev-docs/integrate-with-the-prebid-analytics-api.html) just listen for the **BILLABLE_EVENT**. It is assumed that analytics adapters and their downstream reporting handles their own tracking of events any validation of the contract between vendors and publishers. + +```javascript +switch (eventType) { + // ... + case BILLABLE_EVENT: + // ... +``` + +## Related Reading + +- [pbjs.getEvents()](/dev-docs/publisher-api-reference/getEvents.html) +- [Real Time Data modules](/dev-docs/add-rtd-submodule.html) +- [Analytics Adapters](/dev-docs/integrate-with-the-prebid-analytics-api.html) diff --git a/developers.md b/developers.md index 274e831ba4..905b77d29d 100644 --- a/developers.md +++ b/developers.md @@ -6,8 +6,7 @@ description: Developers Landing Page sidebarType: 0 --- - - + # Developers @@ -31,7 +30,7 @@ Key links for publisher developers. **Prebid Mobile** - integrating display, video, and native ads into iOS and Android apps: -+ [Getting started with Prebid Mobile](/prebid-mobile/prebid-mobile-pbs.html) ++ [Getting started with Prebid Mobile](/prebid-mobile/prebid-mobile-getting-started.html) + [Android code integration](/prebid-mobile/pbm-api/android/code-integration-android.html) + [iOS code integration](/prebid-mobile/pbm-api//ios/code-integration-ios.html) diff --git a/docs-examples/tab-example.md b/docs-examples/tab-example.md new file mode 100644 index 0000000000..6b92f6bc4f --- /dev/null +++ b/docs-examples/tab-example.md @@ -0,0 +1,82 @@ +--- +layout: page_v2 +title: Tab example +description: How tabs can be used +--- + +# How to implement tabs for code + +The prebid documentation uses bootstrap for styling. Bootstrap offers a [tab component](https://getbootstrap.com/docs/4.6/components/navs/#javascript-behavior). + +## Example + +{% capture iosCode %}struct Player { + var name: String + var highScore: Int = 0 + var history: [Int] = [] + + init(_ name: String) { + self.name = name + } +} + +var player = Player("Tomas") +{% endcapture %} + +{% capture androidCode %}fun main() { + val name = "stranger" // Declare your first variable + println("Hi, $name!") // ...and use it! + print("Current count:") + for (i in 0..10) { // Loop over a range from 0 to 10 + print(" $i") + } +} +{% endcapture %} + +{% include code/mobile-sdk.html id="hello-world" kotlin=androidCode swift=iosCode %} + +The code you need to for this looks like this + +{% raw %} + +```liquid + +{% capture iosCode %}struct Player { + var name: String + var highScore: Int = 0 + var history: [Int] = [] + + init(_ name: String) { + self.name = name + } +} + +var player = Player("Tomas") +{% endcapture %} + +{% capture androidCode %}fun main() { + val name = "stranger" // Declare your first variable + println("Hi, $name!") // ...and use it! + print("Current count:") + for (i in 0..10) { // Loop over a range from 0 to 10 + print(" $i") + } +} +{% endcapture %} + + +{% include code/mobile-sdk.html id="hello-world" kotlin=androidCode swift=iosCode %} +``` + +{% endraw %} + +There are few things to understand here + +1. The `include` directive requires a unique `id` for the page. Otherwise the tabs won't work properly +2. Capturing the code into a variable makes everything a lot more readable + +## More information + +- [jekyll includes](https://jekyllrb.com/docs/includes/) +- [jekyll includes with parameters](https://jekyllrb.com/docs/includes/#passing-parameter-variables-to-includes) +- [bootstrap tabs](https://getbootstrap.com/docs/4.6/components/navs/#javascript-behavior) diff --git a/download.md b/download.md index 4415723c6f..9c6f6fcacd 100644 --- a/download.md +++ b/download.md @@ -33,146 +33,7 @@ a.tip:hover span { - - + - - - - - - - -

        Prebid Multi-Format Testing

        - -

        div-banner-native

        -
        -

        No response

        - -
        - -

        div-banner-outstream

        -
        -

        No response

        - -
        -
        - -

        div-banner-outstream-native

        -
        -

        No response

        - -
        -
        - - - diff --git a/examples/legacy/native/index.md b/examples/legacy/native/index.md deleted file mode 100644 index d2c7be8cf9..0000000000 --- a/examples/legacy/native/index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -layout: page_v2 -title: Prebid Hosted Examples -description: This section provides examples of native ads with Prebid.js. -sidebarType: ---- - -# {{page.title}} - -{{page.description}} - - - [Native with two ad slots](native-demo.html) diff --git a/examples/legacy/native/native-demo.html b/examples/legacy/native/native-demo.html deleted file mode 100644 index 787f83fc05..0000000000 --- a/examples/legacy/native/native-demo.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - -

        Prebid Native

        -
        -

        No response

        - -
        - -
        -
        - -
        -

        No response

        - -
        - - - - diff --git a/examples/legacy/pbjs_demo.html b/examples/legacy/pbjs_demo.html deleted file mode 100644 index c9083bf46f..0000000000 --- a/examples/legacy/pbjs_demo.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - -
        -

        No response

        - -
        - - - - - diff --git a/examples/legacy/simple.html b/examples/legacy/simple.html deleted file mode 100644 index 2cc6b3fd00..0000000000 --- a/examples/legacy/simple.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - -

        Prebid.js Test

        -
        Div-1
        -
        - -
        - - - diff --git a/examples/pb-video-template.html b/examples/pb-video-template.html deleted file mode 100644 index a1482bdfcf..0000000000 --- a/examples/pb-video-template.html +++ /dev/null @@ -1,6 +0,0 @@ -{% include head.html %} - -{% include nav.html %} - - -{% include footer.html %} \ No newline at end of file diff --git a/examples/video/crossplayer/flowplayer/pb-cp-flowplayer.html b/examples/video/crossplayer/flowplayer/pb-cp-flowplayer.html deleted file mode 100644 index db7f0ab6b2..0000000000 --- a/examples/video/crossplayer/flowplayer/pb-cp-flowplayer.html +++ /dev/null @@ -1,272 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Flowplayer -description: An example of an instream pre-roll ad using Cross-Player Prebid Communication Component and Flowplayer. -videoType: pb-cp-fp -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - -
        -
        - -

        The button will be enabled only during ads

        -
        - -
        - -
        - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -

        - To allow the Cross-Player plugin to load your custom build of Prebid.js ensure that the option key `prebidPath` is set to the custom build's location. If `prebidPath` is not set, the plugin will point to `//acdn.adnxs.com/prebid/not-for-prod/prebid.js`.

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<link rel="stylesheet" href="//cdn.flowplayer.com/releases/native/stable/style/flowplayer.css">
        -<script src="//cdn.flowplayer.com/releases/native/stable/flowplayer.min.js"></script>
        -<script src="//cdn.flowplayer.com/releases/native/stable/plugins/ads.min.js"></script>
        -<script src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
        -
        -<style>
        -        #player {
        -            max-width: 40em;
        -            width: 100%;
        -            float: left;
        -        }
        -
        -        #controls {
        -            float: left;
        -            padding: 1em;
        -        }
        -    </style>
        -
        -<script type="text/javascript">
        -  var options = {
        -    biddersSpec: {
        -      code: 'video1',
        -      sizes: [640,480],
        -      mediaTypes: {
        -        video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -        }
        -      },
        -      bids: [
        -        {
        -          bidder: 'appnexus',
        -          params: {
        -              placementId: '13232361'  // Add your own placement id here 
        - } - } - } - ] - }, - prebidConfigOptions: { - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }, - dfpParameters: { - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }, - }; - function doHeaderBidding() { - window.prebidPluginCP.doPrebid(options); - } - -</script> -<script src="//acdn.adnxs.com/video/plugins/cp/PrebidPluginCP.min.js" onload="doHeaderBidding()"></script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="player"></div>
        -<!--video player div-->
        -<div id="player"></div>
        -<div id="controls">
        -    <button id="ad-toggle" disabled>
        -        Toggle ad playback
        -    </button>
        -    <p>The button will be enabled only during ads</p>
        -</div>
        -
        -<script type="text/javascript">
        -var messageId = 100;
        -var asyncTag = function() {
        -  var message = {
        -    command: 'PPCP:prebidRequest',
        -    messageId: ++messageId
        -  };
        -  return new Promise(function(resolve) {
        -    var listener = function(event) {
        -      if (event && event.data) {
        -        var data = JSON.parse(event.data);
        -        if (data.command === 'PPCP:prebidResponse' && data.messageId === messageId) {
        -          window.removeEventListener('message', listener);
        -          if (data.url && data.url != 'failed') {
        -            resolve(data.url);
        -          }
        -          else {
        -            resolve(null);
        -          }
        -        }
        -      }
        -    };
        -    window.addEventListener('message', listener);
        -    top.postMessage(JSON.stringify(message), '*');
        -    setTimeout(function() {
        -      window.removeEventListener('message', listener);
        -      resolve(null);
        -    }, 2000);
        -  })
        -}
        -
        -
        -var player = flowplayer('#player', {
        -src: "//edge.flowplayer.org/drive.mp4",
        -title: "Flowplayer demo",
        -description: "Demo showing ads",
        -autoplay: true,
        -ima: {
        -  ads: [
        -    {"time":0,"adTag":asyncTag}
        -  ]
        -},
        -token:"eyJraWQiOiJZSVI0VVJZODA2TGoiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjIjoie1wiYWNsXCI6NixcImlkXCI6XCJZSVI0VVJZODA2TGpcIn0iLCJpc3MiOiJGbG93cGxheWVyIn0.YUoY8b2vl1Z15PikwgYeWQ8Cp85C-TvtmwIJ_UFxpfAYYH8yiiUrhmd3SaY_qb3AvVDz45xVV6R9wizYl-NRGQ"
        -})
        -
        -var btn = document.querySelector('#ad-toggle');
        -
        -btn.addEventListener('click', function() {
        -if (player.ads.adPlaying) player.ads.pause();
        -else player.ads.resume();
        -})
        -
        -function toggleDisabled(disabled) {
        -return function() { btn.disabled = disabled }
        -}
        -
        -player.ads.on(flowplayer.AdEvents.AD_STARTED, toggleDisabled(false));
        -player.ads.on(flowplayer.AdEvents.AD_COMPLETED, toggleDisabled(true));
        -player.ads.on(flowplayer.AdEvents.AD_SKIPPED, toggleDisabled(true));
        -
        -</script>
        -
        -
        -
        - -
        -
        - - - - - - diff --git a/examples/video/crossplayer/jwplayer/pb-cp-jwplayer.html b/examples/video/crossplayer/jwplayer/pb-cp-jwplayer.html deleted file mode 100644 index 1f34020895..0000000000 --- a/examples/video/crossplayer/jwplayer/pb-cp-jwplayer.html +++ /dev/null @@ -1,231 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with JW Player (Platform) -description: An example of an instream pre-roll ad using Cross-Player Prebid Communication Component and JW Player (Platform). -videoType: pb-cp-jw -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -

        - To allow the Cross-Player plugin to load your custom build of Prebid.js ensure that the option key `prebidPath` is set to the custom build's location. If `prebidPath` is not set, the plugin will point to `//acdn.adnxs.com/prebid/not-for-prod/prebid.js`.

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script type="text/javascript">
        -var options = {
        -  biddersSpec: {
        -    code: 'video1',
        -    sizes: [640,480],
        -    mediaTypes: {
        -      video: {
        -	context: 'instream',
        -	playerSize: [640, 480],
        -	mimes: ['video/mp4'],
        -	protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -	playbackmethod: [2],
        -	skip: 1
        -      }
        -    },
        -    bids: [
        -      {
        -        bidder: 'appnexus',
        -        params: {
        -          placementId: '13232361'  // Add your own placement id here
        - } - } - ] - }, - prebidConfigOptions: { - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }, - dfpParameters: { - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }, -}; -function doHeaderBidding() { - window.prebidPluginCP.doPrebid(options); -} - -</script> -<script src="//acdn.adnxs.com/video/plugins/cp/PrebidPluginCP.min.js" onload="doHeaderBidding()"></script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -  
        -  <div id="myElement1"></div>
        -
        -  <!-- This line loads a player without loading any video content -->
        -  <!-- Replace this with the correct url for your player -->
        -  <script src="YOUR_JW_URL"></script>
        -  <script>
        -      // we initialize our player instance, specifying the div to load it into
        -      var playerInstance = jwplayer('myElement1');
        -
        -      function invokeVideoPlayer(url) {
        -          // this calls setup on the player we initialized
        -          // this will use the settings defined in the player we loaded above unless you override them here
        -          playerInstance.setup({
        -              "file": "https://vjs.zencdn.net/v/oceans.mp4",
        -              // or "file" could be replaced with "playlist" and a URL
        -              // from your JW Platform account in either json or rss format.
        -              "width": 640,
        -              "height": 480,
        -              // we enable vast advertising for this player
        -              "advertising": {
        -                  "client": "vast",
        -                  // url is the vast tag url that we passed in when we called invokeVideoPlayer in the header
        -                  "tag": url
        -              },
        -          });
        -      }
        -
        -      var messageId = 100;
        -      var getVastUrl = function() {
        -        var message = {
        -          command: 'PPCP:prebidRequest',
        -          messageId: ++messageId
        -        };
        -        return new Promise(function(resolve) {
        -          var listener = function(event) {
        -            if (event && event.data) {
        -              var data = JSON.parse(event.data);
        -              if (data.command === 'PPCP:prebidResponse' && data.messageId === messageId) {
        -                window.removeEventListener('message', listener);
        -                if (data.url && data.url != 'failed') {
        -                  resolve(data.url);
        -                }
        -                else {
        -                  resolve(null);
        -                }
        -              }
        -            }
        -          };
        -          window.addEventListener('message', listener);
        -          top.postMessage(JSON.stringify(message), '*');
        -          setTimeout(function() {
        -            window.removeEventListener('message', listener);
        -            resolve(null);
        -          }, 2000);
        -        })
        -      };
        -
        -      getVastUrl().then(function(url) {
        -        invokeVideoPlayer(url);
        -      })
        -      .catch(function() {
        -        invokeVideoPlayer(null);
        -      });
        -  </script>
        -
        -
        -
        - -
        -
        - - - - - - - - - diff --git a/examples/video/crossplayer/kaltura/pb-cp-kaltura.html b/examples/video/crossplayer/kaltura/pb-cp-kaltura.html deleted file mode 100644 index 994abea4e0..0000000000 --- a/examples/video/crossplayer/kaltura/pb-cp-kaltura.html +++ /dev/null @@ -1,275 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Kaltura -description: An example of an instream pre-roll ad using Cross-Player Prebid Communication Component and Kaltura. -videoType: pb-cp-kl -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -

        - To allow the Cross-Player plugin to load your custom build of Prebid.js ensure that the option key `prebidPath` is set to the custom build's location. If `prebidPath` is not set, the plugin will point to `//acdn.adnxs.com/prebid/not-for-prod/prebid.js`.

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script type="text/javascript">
        -var options = {
        -  biddersSpec: {
        -    code: 'video1',
        -    sizes: [640,480],
        -    mediaTypes: {
        -      video: {
        -	context: 'instream',
        -	playerSize: [640, 480],
        -	mimes: ['video/mp4'],
        -	protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -	playbackmethod: [2],
        -	skip: 1
        -      }
        -    },
        -    bids: [
        -      {
        -        bidder: 'appnexus',
        -        params: {
        -          placementId: '13232361'  // Add your own placement id here
        - } - } - ] - }, - prebidConfigOptions: { - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }, - dfpParameters: { - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }, -}; -function doHeaderBidding() { - window.prebidPluginCP.doPrebid(options); -} - -</script> -<script src="//acdn.adnxs.com/video/plugins/cp/PrebidPluginCP.min.js" onload="doHeaderBidding()"></script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="myPlayer" style="width:640px; height:480px;"></div>
        -<!-- INCLUDE KALTURA PLAYER SCRIPT
        -
        -Add the script for your Kaltura player. This will be part of
        -the code you will copy-paste from Kaltura. -->
        -
        -<script src="https://cdnapi.kaltura.com/p/2222001/sp/222200100/embedIframeJs/uiconf_id/37440401/partner_id/2222001"></script>
        -
        -    <script type="text/javascript">
        -     invokeVideoPlayer = function(url) {
        -
        -       /* EMBED KALTURA PLAYER
        -
        -         Call `kWidget.embed()` and pass in a JSON object of your
        -         player settings. Most of this JSON object will be part of
        -         the code you will copy paste from Kaltura.
        -
        -         Documentation for kWidget available here:
        -         https://player.kaltura.com/docs/kwidget */
        -
        -         kWidget.embed({
        -             "targetId": "myPlayer",
        -             "wid": "_2222001",
        -             "uiconf_id": 37440401,
        -
        -             /* ADD VAST SETTINGS TO THE PLAYER SETTINGS
        -
        -                 Inside `flashVars`, add another key called `"vast"` and
        -                 pass in a JSON object with:
        -
        -                 - the position where you want your ad to play
        -
        -                 - the URL of the ad (which in this case will be the `url`
        -                 we got back from Prebid) */
        -
        -             "flashvars": {
        -                 "streamerType": "auto",
        -                 "vast": {
        -                     "plugin": true,
        -                     "prerollUrl": url,
        -                 }
        -             },
        -             "entry_id": "1_k4eka7er",
        -
        -             /* ADD A READY CALLBACK AND GET A REFERENCE TO THE PLAYER
        -
        -                 Add a ready callback to the player settings. This allows
        -                 us to get a reference to the player (stored in the
        -                 variable `kdp`) in order to interact with it later. */
        -
        -             readyCallback: function(playerId) {
        -                 console.log("Kaltura player " + playerId + " is ready.");
        -             }
        -           });
        -       }
        -       var messageId = 100;
        -       var getVastUrl = function() {
        -         var message = {
        -           command: 'PPCP:prebidRequest',
        -           messageId: ++messageId
        -         };
        -         return new Promise(function(resolve) {
        -           var listener = function(event) {
        -             if (event && event.data) {
        -               var data = JSON.parse(event.data);
        -               if (data.command === 'PPCP:prebidResponse' && data.messageId === messageId) {
        -                 window.removeEventListener('message', listener);
        -                 if (data.url && data.url != 'failed') {
        -                   resolve(data.url);
        -                 }
        -                 else {
        -                   resolve(null);
        -                 }
        -               }
        -             }
        -           };
        -           window.addEventListener('message', listener);
        -           top.postMessage(JSON.stringify(message), '*');
        -           setTimeout(function() {
        -             window.removeEventListener('message', listener);
        -             resolve(null);
        -           }, 2000);
        -         })
        -       };
        -
        -       getVastUrl().then(function(url) {
        -         invokeVideoPlayer(url);
        -       })
        -       .catch(function() {
        -         invokeVideoPlayer(null);
        -       });
        -   </script>
        -
        -
        - -
        -
        - - - - - - - - - diff --git a/examples/video/crossplayer/videojs/pb-cp-videojs.html b/examples/video/crossplayer/videojs/pb-cp-videojs.html deleted file mode 100644 index 8d626ebc4f..0000000000 --- a/examples/video/crossplayer/videojs/pb-cp-videojs.html +++ /dev/null @@ -1,293 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with VideoJS -description: An example of an instream pre-roll ad using Cross-Player Prebid Communication Component and VideoJS. -videoType: pb-cp-vjs -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -

        - To allow the Cross-Player plugin to load your custom build of Prebid.js ensure that the option key `prebidPath` is set to the custom build's location. If `prebidPath` is not set, the plugin will point to `//acdn.adnxs.com/prebid/not-for-prod/prebid.js`.

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<!-- use recent version of videojs to ensure proper functioning with the iOS devices -->
        -<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video-js.css">
        -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video.js"></script>
        -<!-- videojs-vast-vpaid -->
        -<link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs.vast.vpaid.min.css" rel="stylesheet">
        -<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs_5.vast.vpaid.min.js"></script>
        -
        -<script type="text/javascript">
        -  var options = {
        -    biddersSpec: {
        -      code: 'video1',
        -      sizes: [640,480],
        -      mediaTypes: {
        -        video: {
        -	  context: 'instream',
        -	  playerSize: [640, 480],
        -	  mimes: ['video/mp4'],
        -	  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -	  playbackmethod: [2],
        -	  skip: 1
        -        }
        -      },
        -      bids: [
        -        {
        -          bidder: 'appnexus',
        -          params: {
        -            placementId: '13232361'  // Add your own placement id here
        - } - } - ] - }, - prebidConfigOptions: { - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }, - dfpParameters: { - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }, - }; - function doHeaderBidding() { - window.prebidPluginCP.doPrebid(options); - } - -</script> -<script src="//acdn.adnxs.com/video/plugins/cp/PrebidPluginCP.min.js" onload="doHeaderBidding()"></script> - -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div class="example-video-container">
        -<video id="vid1" class="video-js vjs-default-skin vjs-big-play-centered" controls data-setup='{}' width='640' height='480'>
        -  <source src="https://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'/>
        -  <source src="https://vjs.zencdn.net/v/oceans.webm" type='video/webm'/>
        -  <source src="https://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'/>
        -</video>
        -</div>
        -<script>
        -var page_load_time;
        -
        -page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -console.log(page_load_time + "ms -- Player loading!");
        -
        -var vid1 = videojs('vid1');
        -
        -page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -console.log(page_load_time + "ms -- Player loaded!");
        -
        -function invokeVideoPlayer(url) {
        -
        -  page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -  console.log(page_load_time + "ms -- Prebid VAST url = " + url);
        -
        -  /* Access the player instance by calling `videojs()` and passing
        -    in the player's ID. Add a `ready` listener to make sure the
        -    player is ready before interacting with it. */
        -
        -  videojs("vid1").ready(function() {
        -
        -      page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -      console.log(page_load_time + "ms -- Player is ready!");
        -
        -      /* PASS SETTINGS TO VAST PLUGIN
        -
        -        Pass in a JSON object to the player's `vastClient` (defined
        -        by the VAST/VPAID plugin we're using). The requires an
        -        `adTagUrl`, which will be the URL returned by Prebid. You
        -        can view all the options available for the `vastClient`
        -        here:
        -
        -        https://github.com/MailOnline/videojs-vast-vpaid#options */
        -
        -      var player = this;
        -      var vastAd = player.vastClient({
        -          adTagUrl: url,
        -          playAdAlways: true,
        -          verbosity: 4,
        -          vpaidFlashLoaderPath: "https://github.com/MailOnline/videojs-vast-vpaid/blob/RELEASE/bin/VPAIDFlash.swf?raw=true",
        -          autoplay: true
        -      });
        -
        -      page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -      console.log(page_load_time + "ms -- Prebid VAST tag inserted!");
        -
        -      player.muted(true);
        -      player.play();
        -
        -      page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -      console.log(page_load_time + "ms -- invokeVideoPlayer complete!");
        -
        -  });
        -}
        -var messageId = 100;
        -var getVastUrl = function() {
        -var message = {
        -  command: 'PPCP:prebidRequest',
        -  messageId: ++messageId
        -};
        -return new Promise(function(resolve) {
        -  var listener = function(event) {
        -    if (event && event.data) {
        -      var data = JSON.parse(event.data);
        -      if (data.command === 'PPCP:prebidResponse' && data.messageId === messageId) {
        -        window.removeEventListener('message', listener);
        -        if (data.url && data.url != 'failed') {
        -          resolve(data.url);
        -        }
        -        else {
        -          resolve(null);
        -        }
        -      }
        -    }
        -  };
        -  window.addEventListener('message', listener);
        -  top.postMessage(JSON.stringify(message), '*');
        -  setTimeout(function() {
        -    window.removeEventListener('message', listener);
        -    resolve(null);
        -  }, 2000);
        -})
        -};
        -
        -getVastUrl().then(function(url) {
        -  invokeVideoPlayer(url);
        -})
        -.catch(function() {
        -  invokeVideoPlayer(null);
        -});
        -
        -</script>
        -
        -
        - -
        -
        - - - - diff --git a/examples/video/index.md b/examples/video/index.md index 434817b52e..b2d5210f38 100644 --- a/examples/video/index.md +++ b/examples/video/index.md @@ -1,7 +1,7 @@ --- layout: page_v2 title: Prebid Video Examples -description: This section provides examples of instream, outstream, server and long-form videos with Prebid.js. +description: This section provides examples of instream, outstream and long-form videos with Prebid.js. sidebarType: 4 --- @@ -17,35 +17,30 @@ sidebarType: 4 The following examples are available: -## Instream +## Prebid Video Module: Instream - - [Brid](/examples/video/server/brid/pbs-ve-brid.html) - - [Brightcove](/examples/video/instream/brightcove/pb-ve-brightcove.html) - - [Flowplayer](/examples/video/instream/flowplayer/pb-ve-flowplayer.html) - - [JW Player](/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) - - [JW Player (Self-Hosted)](/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) - - [Kaltura](/examples/video/instream/kaltura/pb-ve-kaltura.html) - - [Ooyala](/examples/video/instream/ooyala/pb-ve-ooyala.html) - - [VideoJS](/examples/video/instream/videojs/pb-ve-videojs.html) +- [VideoJS](/examples/video/instream/videoModule/videojs/video-module-videojs.html) -## Instream and Banner Mixed Page +## Prebid Video Module: Outstream - - [Instream/Banner Mixed](/dev-docs/examples/instream-banner-mix.html) +## Instream -## Server +- [Brightcove](/examples/video/instream/brightcove/pb-ve-brightcove.html) +- [Flowplayer](/examples/video/instream/flowplayer/pb-ve-flowplayer.html) +- [JW Player](/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) +- [JW Player (Self-Hosted)](/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) +- [Kaltura](/examples/video/instream/kaltura/pb-ve-kaltura.html) +- [VideoJS](/examples/video/instream/videojs/pb-ve-videojs.html) + +## Instream and Banner Mixed Page - - [Brid](/examples/video/server/brid/pbs-ve-brid.html) - - [JW Player](/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html) - - [JW Player (Self-Hosted)](/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html) - - [Kaltura](/examples/video/server/kaltura/pbs-ve-kaltura.html) - - [Ooyala](/examples/video/server/ooyala/pbs-ve-ooyala.html) - - [VideoJS](/examples/video/server/videojs/pbs-ve-videojs.html) +- [Instream/Banner Mixed](/dev-docs/examples/instream-banner-mix.html) ## Outstream - - [Google Ad Manager](/examples/video/outstream/pb-ve-outstream-dfp.html) - - [No Server](/examples/video/outstream/pb-ve-outstream-no-server.html) +- [Google Ad Manager](/examples/video/outstream/pb-ve-outstream-dfp.html) +- [No Server](/examples/video/outstream/pb-ve-outstream-no-server.html) ## Long-Form (Ad Pods) - - [Freewheel](/examples/video/long-form/pb-ve-lf-freewheel.html) +- [Freewheel](/examples/video/long-form/pb-ve-lf-freewheel.html) diff --git a/examples/video/instream/adplayerpro/pb-ve-adplayerpro.html b/examples/video/instream/adplayerpro/pb-ve-adplayerpro.html deleted file mode 100644 index e97457c5f4..0000000000 --- a/examples/video/instream/adplayerpro/pb-ve-adplayerpro.html +++ /dev/null @@ -1,161 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with AdPlayer.Pro Player -description: An example of an instream pre-roll ad using Prebid.js and AdPlayer.Pro player. -videoType: pb-is-app -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script type="text/javascript" src="https://static.adplayer.pro/player/demo.js"></script> -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - - // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - } - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13232361 // Add your own placement id here
        - } - }] - }; - - pbjs.que.push(function() { - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -
        -<!--player div-->
        -<div id="playerContainerADP" style="width:640px; height:480px;"></div>
        -<script type="text/javascript">
        -  invokeVideoPlayer = function(url) {
        -        AdPlayerPro('playerContainerADP').setup({
        -	        "file": "https://static.adplayer.pro/video/640.mp4",
        -          "width": 640,
        -          "height": 480,
        -	        "autoStart": true,
        -          "muted": true,
        -          "advertising": {
        -            "tag": url
        -          }
        -        });
        -  };
        -
        -  if (tempTag) {
        -    invokeVideoPlayer(tempTag);
        -    tempTag = false;
        -  }
        -  </script>
        -
        -
        - -
        -
        - - - -
        - - - diff --git a/examples/video/instream/akamai/pb-ve-amp.html b/examples/video/instream/akamai/pb-ve-amp.html deleted file mode 100644 index 6d832a0f47..0000000000 --- a/examples/video/instream/akamai/pb-ve-amp.html +++ /dev/null @@ -1,255 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Akamai Adaptive Media Player (AMP) -description: An example of an instream pre roll ad with Akamai AMP and Prebid.js. Akamai AMP also provides a built-in prebid plugin - wich simplifies and integrates the common prebid.js bidding workflow without extra efforts. -videoType: pb-is-amp -isVideo: true -sidebarType: 4 ---- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production - use. It includes all available adapters. Production implementations should build from source or - customize the build using the Download page to make sure only the necessary bidder adapters are - included.

        -
        - -
        -
        -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script type="text/javascript" src="https://amp.akamaized.net/hosted/1.x/player?apikey=sample"></script> -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - } - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13232361 /* Add own placement id */ - } - }] - }; - - pbjs.que.push(function() { - pbjs.addAdUnits(videoAdUnit); - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -<!--player container-->
        -<div style="width:604px; height:341px;">
        -    <div id="akamai-player" </div>
        -</div>
        -<script type="text/javascript">
        -  invokeVideoPlayer = function(url) {
        -    var config = {
        -        plugins: {
        -            ima: {
        -                resources: [
        -                    { src: "//imasdk.googleapis.com/js/sdkloader/ima3.js", type: "text/javascript", async: true },
        -                    { src: "${paths.plugins}ima/Ima.min.js", type: "text/javascript", async: true }
        -                ],
        -                adTagUrl: url
        -            }
        -        },
        -        autoplay: 'muted',
        -        media: {
        -            src: "https://mdtp-a.akamaihd.net/customers/akamai/video/VfE.mp4"
        -        }
        -    }
        -
        -    akamai.amp.AMP.create('#akamai-player', config)
        -  };
        -
        -  if (tempTag) {
        -    invokeVideoPlayer(tempTag);
        -    tempTag = false;
        -  }
        -  </script>
        -
        -
        - -
        - - -
        - -
        -

        Using Prebid Plugin for AMP

        -

        As an alternative an adUnit can be passed within the built-int prebid plugin for AMP. The prebid bid request will be handled by prebid plugin automatically just before the ad request takes place.

        -

        The plugin can be implemented by providing a prebid object to the player config as follows

        -
        -    <head>
        -        <script type="text/javascript" src="https://amp.akamaized.net/hosted/1.x/player?apikey=sample"></script>
        -    </head>
        -    <body>
        -        <!--player container-->
        -         <div style="width:604px; height:341px;">
        -            <div id="akamai-player"/div> </div>
        -        </div>
        -        <script type="text/javascript">
        -        var config = {
        -            plugins: {
        -              prebid: {
        -                adServer: {
        -                  name: "dfp"
        -                },
        -                resources: [
        -                  { src: "https://acdn.adnxs.com/prebid/not-for-prod/1/prebid.js", type: "text/javascript", async: true },
        -                  { src: "${paths.plugins}prebid/Prebid.min.js", type: "text/javascript", async: true }
        -                ],
        -                adUnits: {
        -                  code: "video-1",
        -                  mediaTypes: {
        -                    video: {
        -                      playerSize: [640, 480],
        -                      context: 'instream',
        -                      mimes: ['video/mp4'],
        -                      protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                      playbackmethod: [2]
        -                    }
        -                  },
        -                  bids: [
        -                    {
        -                      bidder: "appnexus",
        -                      params: {
        -                        placementId: 13232361 /* Test placementId not for prod */
        -                      }
        -                    }
        -                  ]
        -                },
        -                options: {
        -                  cache: {
        -                    url: "https://prebid.adnxs.com/pbc/v1/cache"
        -                  },
        -                  enableSendAllBids: true
        -                }
        -              },
        -              ima: {
        -                resources: [
        -                  { src: "//imasdk.googleapis.com/js/sdkloader/ima3.js", type: "text/javascript", async: true },
        -                  { src: "${paths.plugins}ima/Ima.min.js", type: "text/javascript", async: true }
        -                ],
        -                adTagUrl: {
        -                  params: {
        -                    sz: "640x480",
        -                    iu: "/19968336/prebid_cache_video_adunit",
        -                    output: "vast",
        -                    correlator: "#{now}"
        -                  }
        -                }
        -              }
        -            },
        -            autoplay: 'muted',
        -            media: {
        -                src: "https://mdtp-a.akamaihd.net/customers/akamai/video/VfE.mp4"
        -            }
        -          };
        -
        -        akamai.amp.AMP.create('#akamai-player', config)
        -      </script>
        -    </body>
        -  
        -
        - - - - - diff --git a/examples/video/instream/brid/pb-ve-brid.html b/examples/video/instream/brid/pb-ve-brid.html deleted file mode 100644 index 5b7da01cdf..0000000000 --- a/examples/video/instream/brid/pb-ve-brid.html +++ /dev/null @@ -1,191 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Brid Player -description: An example of an instream pre-roll ad using Prebid.js and Brid player. -videoType: pb-is-br -isVideo: true -sidebarType: 4 ---- - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script type="text/javascript" src="//services.brid.tv/player/build/brid.min.js"></script> -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - - // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        - var tempTag = false; - var invokeVideoPlayer = function(url){ - tempTag = url; - } - - /* - Prebid Video adUnit - */ - - var videoAdUnit = { - code: 'video1', - sizes: [640,480], - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [ - { - bidder: 'appnexusAst', - params: { - placementId: '13232361' // Add your own placement id here
        - } - } - ] - }; - - pbjs.que.push(function(){ - // add your ad units to the bid request
        - pbjs.addAdUnits(videoAdUnit); - - pbjs.setConfig({ - usePrebidCache: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - - pbjs.bidderSettings = - { - standard: { - adserverTargeting: [ - { - key: "hb_bidder", - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: "hb_adid", - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: "hb_pb", - val: function (bidResponse) { - return "10.00"; - } - }, { - key: "hb_size", - val: function (bidResponse) { - return bidResponse.size; - - } - } - ] - } - }; - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="myDiv" class="brid" style="width:640px; height:360;"></div>
        -
        -<script type="text/javascript">
        -	invokeVideoPlayer = function(url) {
        -	$bp("myDiv", {"id":"17041","width":"640","height":"360","video":"400684",
        -	"Ad": [
        -	        {
        -	            "mobile": url, // Array of url's will get called in succession
        -	            "desktop": null, // Array of url's will get called in succession
        -	            "adType": "0", // Type 0 for pre roll
        -	            "adTimeType": "s",
        -	            "overlayStartAt": null,
        -	            "overlayDuration": null,
        -	            "cuepoints": null
        -	        }
        -	    ]
        -	});
        -	}
        -  </script>
        -
        -
        - -
        -
        - - - - - diff --git a/examples/video/instream/brightcove/pb-ve-brightcove.html b/examples/video/instream/brightcove/pb-ve-brightcove.html deleted file mode 100644 index 2e808b4501..0000000000 --- a/examples/video/instream/brightcove/pb-ve-brightcove.html +++ /dev/null @@ -1,302 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Brightcove Player -description: An example of an instream pre-roll ad using Prebid.js and Brightcove player. -videoType: pb-is-bc -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<!--brightcove & prebid js code--> -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - iosDevice = !!navigator.platform.match(/iPhone|iPod|iPad/); - - /* PRE-DEFINE `invokeVideoPlayer` - - Because we have no way of knowing when all the bids will be - returned from Prebid we can't be sure that the browser will - reach the point where `invokeVideoPlayer` is defined before - `bidsBackHandler` fires and tries to call it. - - To prevent an "`invokeVideoPlayer` not defined" error, we - pre-define it before we make the call to Prebid, and redefine - it later on with the code to create the player and play the - ad. - - In this first version, it simply stores the winning VAST to - use later. */ - - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - } - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: iosDevice ? 13239390 : 13232361 // Add your own placement id here. - } - }] - }; - - pbjs.que.push(function() { - pbjs.addAdUnits(videoAdUnit); - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<!-- INCLUDE PLAYER AND IMA3 PLUGIN SCRIPTS
        -
        -First, include the player script from Brightcove. This will
        -also be part of the embed code provided by Video Cloud. Then
        -include the ima3 plugin script.
        -
        -Since we are not configuring the plugin in Video Cloud, we
        -need to include this script on the page.  -->
        -
        -<script src="//players.brightcove.net/5530036758001/HJMTvh2YZ_default/index.min.js"></script>
        -<script src="//players.brightcove.net/videojs-ima3/2/videojs.ima3.min.js"></script>
        -
        -<script type="text/JavaScript">
        -
        -	  // REDEFINE `invokeVideoPlayer`
        - function invokeVideoPlayer(url) { - - // USE `bc()` TO REFERENCE VIDEO PLAYER, PASS OPTIONS INTO IMA3 PLUGIN
        - bc("myVideo").ima3({ - serverUrl: url, - debug: true, - timeout: 5000, - ima3SdkSettings: { - "disableCustomPlaybackForIOS10Plus": true - }, - adTechOrder: [ - "html5", - "flash" - ], - }); - - // ADD A `ready` LISTENER AND INTERACT WITH THE PLAYER   - - // Call `videojs()` and pass in the ID of the video element to   - // get a reference to the player. Call `.ready` on the player   - // to set up the event listener, and place any code that will   - // interact with the player inside the callback (such as   - // loading media files, logging events for the player or ads).
        - - videojs("myVideo").ready(function() { - var myPlayer = this; - - // LOAD THE MEDIA FILE   - - // Once we know the player is ready and we have our prebid ad   - // ready, load the content video from Brightcove Studio.   - - // Replace this ID with the ID with one of your own media file IDs   - // which can be found in your Brightcove Studio account.
        - - myPlayer.catalog.getVideo("5530880848001", function(error, video){ - myPlayer.catalog.load(video); - if(error) { - console.log("There was an error retrieving the media file: " + error); - } - }); - - myPlayer.on("ima3error", function() { - console.log("There was an ima3 error."); - }); - }); - }; - - // ACCOUNT FOR PAGE SPEED   - - // If prebid returned bids before the browser reached the end of   - // the page, the first version of `invokeVideoPlayer` will have   - // been called from `bidsBackHandler` so the winning vast tag   - // will be stored in `tempTag`.   - - // If that's the case, we want to call the 'real' version of   - // `invokeVideoPlayer` with the stored url to create the player   - // and play the ad.   - - // If `tempTag` is not defined, that means the browser reached   - // the end of the page before the bids came back from prebid,   - // meaning the 'real' version of `invokeVideoPlayer` was already   - // called.
        - - if (tempTag) { - invokeVideoPlayer(tempTag); - tempTag = false; - } - </script> - -
        -
        - -
        -
        - - - - - - - - - - diff --git a/examples/video/instream/flowplayer/pb-ve-flowplayer.html b/examples/video/instream/flowplayer/pb-ve-flowplayer.html deleted file mode 100644 index e5744635ba..0000000000 --- a/examples/video/instream/flowplayer/pb-ve-flowplayer.html +++ /dev/null @@ -1,237 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Flowplayer -description: An example of an instream pre-roll ad using Prebid.js and Flowplayer. -videoType: pb-is-fp -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - -
        -
        - -

        The button will be enabled only during ads

        -
        - -
        - -
        - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<link rel="stylesheet" href="//cdn.flowplayer.com/releases/native/stable/style/flowplayer.css">
        -<script src="//cdn.flowplayer.com/releases/native/stable/flowplayer.min.js"></script>
        -<script src="//cdn.flowplayer.com/releases/native/stable/plugins/ads.min.js"></script>
        -<script src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
        -<style>
        -    #player {
        -        max-width: 40em;
        -        width: 100%;
        -        float: left;
        -    }
        -
        -    #controls {
        -        float: left;
        -        padding: 1em;
        -    }
        -</style>
        -<script>
        -  var pbjs = pbjs || {};
        -  pbjs.que = pbjs.que || [];
        -
        -  // The ad tag in Flowplayer can be actual ad tag or promise to an ad tag.  
        -  // We return the ad tag if it is available before the player is ready to play  
        -  // Otherwise the player waits for 2 secs for tag to be available.
        - var adtag = null - var timeout = 2000 - var asyncTag = function() { - if (adtag) return Promise.resolve(adtag) - - return new Promise(function (resolve) { - setTimeout(function() { - resolve(adtag) - }, timeout) - }) - } - - /* - Prebid Video adUnit - */ - - var videoAdUnit = { - code: 'video1', - sizes: [640,480], - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: '13232361' // Add your own placement id here
        - } - } - ] - }; - - pbjs.que.push(function(){ - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: "blog", - anotherKey: "anotherValue" - }, - output: "vast" - } - }); - adtag = videoUrl; - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="player"></div>
        -<!--video player div-->
        -<div id="player"></div>
        -<div id="controls">
        -    <button id="ad-toggle" disabled>
        -        Toggle ad playback
        -    </button>
        -    <p>The button will be enabled only during ads</p>
        -</div>
        -	
        -<script type="text/javascript">
        -  var player = flowplayer('#player', {
        -    src: "//edge.flowplayer.org/drive.mp4",
        -    title: "Flowplayer demo",
        -    description: "Demo showing ads",
        -    autoplay: true,
        -    ima: {
        -      ads: [
        -        {"time":0,"adTag":asyncTag}
        -      ]
        -    },
        -    token:"eyJraWQiOiJZSVI0VVJZODA2TGoiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjIjoie1wiYWNsXCI6NixcImlkXCI6XCJZSVI0VVJZODA2TGpcIn0iLCJpc3MiOiJGbG93cGxheWVyIn0.YUoY8b2vl1Z15PikwgYeWQ8Cp85C-TvtmwIJ_UFxpfAYYH8yiiUrhmd3SaY_qb3AvVDz45xVV6R9wizYl-NRGQ"
        -  })
        -  
        -  var btn = document.querySelector('#ad-toggle');
        -
        -  btn.addEventListener('click', function() {
        -    if (player.ads.adPlaying) player.ads.pause();
        -    else player.ads.resume();
        -  })
        -
        -  function toggleDisabled(disabled) {
        -    return function() { btn.disabled = disabled }
        -  }
        -
        -  player.ads.on(flowplayer.AdEvents.AD_STARTED, toggleDisabled(false));
        -  player.ads.on(flowplayer.AdEvents.AD_COMPLETED, toggleDisabled(true));
        -  player.ads.on(flowplayer.AdEvents.AD_SKIPPED, toggleDisabled(true));
        -
        -</script>      
        -
        -
        -
        - -
        -
        - - - - - - - diff --git a/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html b/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html index 350fdfea7d..ee2caebd3a 100644 --- a/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html +++ b/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html @@ -1,182 +1,180 @@ --- layout: video_sample -title: Prebid Video | Instream Example with JW Player (Self-Hosted) -description: An example of an instream pre-roll ad using Prebid.js and JW Player (Hosted). +title: Prebid Video | Instream Example with JW Player (Self-Hosted) +description: An example of an instream pre-roll ad using Prebid.js and JW Player (Hosted). videoType: pb-is-jw02 isVideo: true sidebarType: 4 --- +
        +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        - -
        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script type="text/javascript" src="https://ssl.p.jwpcdn.com/player/v/7.2.4/jwplayer.js"></script>
        -<script type="text/javascript">
        -	jwplayer.key = "YOUR_JW_PLAYER_KEY"; //Test Key - replace this with your own valid JWPlayer license key
        -</script> -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - - // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - } - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13232361 // Add your own placement id here
        - } - }] - }; - - pbjs.que.push(function() { - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        - -
        -
        -
        -<!--player div-->
        -<div id="playerContainerJW" style='width:640px; height:480px; border:1px solid black;'></div>
        -<script>
        -	var jwPlayerInstance = jwplayer("playerContainerJW");
        -	
        -	invokeVideoPlayer = function(url) {
        -	    jwPlayerInstance.setup({
        -	        "file": "https://vjs.zencdn.net/v/oceans.mp4",
        -	        "width": 640,
        -	        "height": 480,
        -	        "autostart": true,
        -	        "mute": false,
        -	        "advertising": {
        -	            client: "vast",
        -	        }
        -	    });
        -	
        -	    jwPlayerInstance.on('beforePlay', function() {
        -	        jwPlayerInstance.playAd(url);
        -	    })
        -	}
        -	
        -	if (tempTag) {
        -	    invokeVideoPlayer(tempTag);
        -	    tempTag = false;
        -	}
        -
        -</script>
        -
        -
        -
        -
        - -
        + +
        + + + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +
        +  
        +  <script async src="//cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
        +  <script type="text/javascript" src="https://ssl.p.jwpcdn.com/player/v/7.2.4/jwplayer.js"></script>
        +  <script type="text/javascript">
        +    jwplayer.key = "YOUR_JW_PLAYER_KEY"; //Test Key - replace this with your own valid JWPlayer license key
        + </script> + <script> + var pbjs = pbjs || {}; + pbjs.que = pbjs.que || []; + + // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        + var tempTag = false; + var invokeVideoPlayer = function(url) { + tempTag = url; + } + + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [2], + skip: 1 + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361 // Add your own placement id here
        + } + }] + }; + + pbjs.que.push(function() { + pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        + pbjs.setConfig({ + debug: true, + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + + pbjs.requestBids({ + bidsBackHandler: function(bids) { + var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ + adUnit: videoAdUnit, + params: { + iu: '/19968336/prebid_cache_video_adunit', + cust_params: { + section: 'blog', + anotherKey: 'anotherValue' + }, + output: 'vast' + } + }); + invokeVideoPlayer(videoUrl); + } + }); + }); + + </script> +
        +
        + +

        Place this code in the page body.

        +
        + +
        +
        +  
        +  <!--player div-->
        +  <div id="playerContainerJW" style='width:640px; height:480px; border:1px solid black;'></div>
        +  <script>
        +    var jwPlayerInstance = jwplayer("playerContainerJW");
        +
        +    invokeVideoPlayer = function(url) {
        +        jwPlayerInstance.setup({
        +            "file": "https://vjs.zencdn.net/v/oceans.mp4",
        +            "width": 640,
        +            "height": 480,
        +            "autostart": true,
        +            "mute": false,
        +            "advertising": {
        +                client: "vast",
        +            }
        +        });
        +
        +        jwPlayerInstance.on('beforePlay', function() {
        +            jwPlayerInstance.playAd(url);
        +        })
        +    }
        +
        +    if (tempTag) {
        +        invokeVideoPlayer(tempTag);
        +        tempTag = false;
        +    }
        +
        +  </script>
        +
        +
        +        
        +
        +
        - + - - - - - + diff --git a/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html b/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html index 3370763d1f..693aea6b2f 100644 --- a/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html +++ b/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html @@ -1,186 +1,181 @@ --- layout: video_sample -title: Prebid Video | Instream Example with JW Player (Platform) -description: An example of an instream pre-roll ad using Prebid.js and JW Player (Platform). +title: Prebid Video | Instream Example with JW Player (Platform) +description: An example of an instream pre-roll ad using Prebid.js and JW Player (Platform). videoType: pb-is-jw01 isVideo: true sidebarType: 4 --- - +
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        - -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<!--Prebid.js and video player code-->
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - } - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + + +
        + + + + +
        + +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +  
        +  <!--Prebid.js and video player code-->
        +  <script async src="//cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
        +  <script>
        +      var pbjs = pbjs || {};
        +      pbjs.que = pbjs.que || [];
        +
        +      // define invokeVideoPlayer in advance in case we get the bids back from prebid before the entire page loads
        + var tempTag = false; + var invokeVideoPlayer = function(url) { + tempTag = url; + } + + var videoAdUnit = { + code: 'video1', + mediaTypes: { + video: { + context: 'instream', + playerSize: [640, 480], + mimes: ['video/mp4'], + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [2], + skip: 1 + } + }, + bids: [{ + bidder: 'appnexus', + params: { + placementId: 13232361 //put your placement id here
        + } + }] + }; + + pbjs.que.push(function() { + //put your adunits here
        + pbjs.addAdUnits(videoAdUnit); + + pbjs.setConfig({ + debug: true, + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }); + + pbjs.requestBids({ + bidsBackHandler: function(bids) { + var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ + adUnit: videoAdUnit, + params: { + iu: '/19968336/prebid_cache_video_adunit', + cust_params: { + section: 'blog', + anotherKey: 'anotherValue' + }, + output: 'vast' + } + }); + invokeVideoPlayer(videoUrl); + } + }); + }); + + </script> +
        +
        + +

        Place this code in the page body.

        +
        + +
        +    
        +  <div id="myElement1"></div>
        +
        +  <!-- Replace this with the correct url for your player -->
        +  <script src="YOUR_JW_URL"></script>
        +  <script>
        +      // we initialize our player instance, specifying the div to load it into
        + var playerInstance = jwplayer('myElement1'); + + function invokeVideoPlayer(url) { + // this calls setup on the player we initialized   + // this will use the settings defined in the player we loaded above unless you override them here
        + playerInstance.setup({ + "file": "https://vjs.zencdn.net/v/oceans.mp4", + // or "file" could be replaced with "playlist" and a URL + // from your JW Platform account in either json or rss format. + "width": 640, + "height": 480, + // we enable vast advertising for this player
        + "advertising": { + "client": "vast", + // url is the vast tag url that we passed in when we called invokeVideoPlayer in the header
        + "tag": url + }, + }); + } + + if (tempTag) { + invokeVideoPlayer(tempTag); + tempTag = false; + } + + </script> + +
        +
        +
        + +
        - - - - - - - - - - diff --git a/examples/video/instream/kaltura/pb-ve-kaltura.html b/examples/video/instream/kaltura/pb-ve-kaltura.html deleted file mode 100644 index a5ce534724..0000000000 --- a/examples/video/instream/kaltura/pb-ve-kaltura.html +++ /dev/null @@ -1,286 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Kaltura -description: An example of an instream pre-roll ad using Prebid.js and Kaltura. -videoType: pb-is-kl -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -    Because we have no way of knowing when all the bids will be
        -    returned from Prebid we can't be sure that the browser will
        -    reach the point where `invokeVideoPlayer` is defined before
        -    `bidsBackHandler` fires and tries to call it.
        -
        -    To prevent an "`invokeVideoPlayer` not defined" error, we
        -    pre-define it before we make the call to Prebid, and redefine
        -    it later on with the code to create the player and play the
        -    ad.
        -
        -    In this first version it simply stores the winning VAST to use
        -    later. */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    }
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361  // Add your own placement ID here
        - } - }] - }; - - pbjs.que.push(function() { - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="myPlayer" style="width:640px; height:480px;"></div>
        -<!-- INCLUDE KALTURA PLAYER SCRIPT
        -
        - Add the script for your Kaltura player. This will be part of
        - the code you will copy-paste from Kaltura. -->
        -
        -<script src="https://cdnapi.kaltura.com/p/2222001/sp/222200100/embedIframeJs/uiconf_id/37440401/partner_id/2222001"></script>
        -
        -<script>
        -    invokeVideoPlayer = function(url) {
        -
        -        /* EMBED KALTURA PLAYER
        -
        -           Call `kWidget.embed()` and pass in a JSON object of your
        -           player settings. Most of this JSON object will be part of
        -           the code you will copy paste from Kaltura.
        -
        -           Documentation for kWidget available here:
        -           https://player.kaltura.com/docs/kwidget */
        -
        -        kWidget.embed({
        -            "targetId": "myPlayer",
        -            "wid": "_2222001",
        -            "uiconf_id": 37440401,
        -
        -            /* ADD VAST SETTINGS TO THE PLAYER SETTINGS
        -
        -               Inside `flashVars`, add another key called `"vast"` and
        -               pass in a JSON object with:
        -
        -               - the position where you want your ad to play
        -
        -               - the URL of the ad (which in this case will be the `url`
        -               we got back from Prebid) */
        -
        -            "flashvars": {
        -                "streamerType": "auto",
        -                "vast": {
        -                    "plugin": true,
        -                    "prerollUrl": url,
        -                }
        -            },
        -            "entry_id": "1_k4eka7er",
        -
        -            /* ADD A READY CALLBACK AND GET A REFERENCE TO THE PLAYER
        -
        -               Add a ready callback to the player settings. This allows
        -               us to get a reference to the player (stored in the
        -               variable `kdp`) in order to interact with it later. */
        -
        -            readyCallback: function(playerId) {
        -                console.log("Kaltura player " + playerId + " is ready.");
        -            }
        -        });
        -    }
        -
        -    /* ACCOUNT FOR PAGE SPEED
        -
        -       If Prebid returned bids before the browser reached the end of
        -       the page, the first version of `invokeVideoPlayer` will have
        -       been called from `bidsBackHandler` so the winning VAST tag
        -       will be stored in the `tempTag` variable.
        -
        -       If that's the case, we want to call the 'real' version of
        -       `invokeVideoPlayer` with the stored URL to create the player
        -       and play the ad.
        -
        -       If `tempTag` is not defined, that means the browser reached
        -       the end of the page before the bids came back from Prebid,
        -       meaning the 'real' version of `invokeVideoPlayer` was already
        -       called. */
        -
        -    if (tempTag) {
        -        invokeVideoPlayer(tempTag);
        -        tempTag = false;
        -    }
        -
        -</script>  
        -
        -
        - -
        -
        - - - - - - - - - - diff --git a/examples/video/instream/ooyala/pb-ve-ooyala.html b/examples/video/instream/ooyala/pb-ve-ooyala.html deleted file mode 100644 index efa39ea99d..0000000000 --- a/examples/video/instream/ooyala/pb-ve-ooyala.html +++ /dev/null @@ -1,358 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Ooyala player -description: An example of an instream pre-roll ad using Prebid.js and Ooyala player . -videoType: pb-is-ol -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        - -
        
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<!-- LOAD OOYALA PLUGINS
        -
        - Load the Ooyala player scripts you plan to use.
        -
        - You must load the core player script, the scripts for
        - whatever video formats you want to support, and the scripts
        - for the ad manager you want to use.
        -
        - The scripts themselves and a guide for choosing which ones
        - you need can be found here:
        -
        - https://help.ooyala.com/video-platform/documentation/concepts/pbv4_plugins.html
        --->
        -
        -<!-- CORE PLAYER REQUIRED -->
        -<script src="//player.ooyala.com/static/v4/production/latest/core.min.js"></script>
        -
        -<!-- VIDEO PLUGINS -->
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/main_html5.min.js"></script>
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/bit_wrapper.min.js"></script>
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/osmf_flash.min.js"></script>
        -
        -<!-- HTML5 SKIN -->
        -<script src="//player.ooyala.com/static/v4/production/latest/skin-plugin/html5-skin.min.js"></script>
        -
        -<!-- SKIN ASSET -->
        -<link rel="stylesheet" href="//player.ooyala.com/static/v4/production/latest/skin-plugin/html5-skin.min.css" />
        -
        -<!-- IMA PLUGIN -->
        -<script src="//player.ooyala.com/static/v4/production/latest/ad-plugin/google_ima.js"></script>
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -    iosDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
        -    console.log("|||| Start of prebid: " + performance.now());
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -       Because we have no way of knowing when all the bids will be
        -       returned from prebid we can't be sure that the browser will
        -       reach the point where `invokeVideoPlayer` is defined before
        -       bidsBackHandler fires and tries to call it.
        -
        -       To prevent a `invokeVideoPlayer not defined` error, we
        -       pre-define it before we make the call to prebid, and redefine
        -       it later on with the code to create the player and play the
        -       ad. In this first version it simply stores the winning VAST to
        -       use later.  */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    }
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -		context: 'instream',
        -		playerSize: [640, 480],
        -		mimes: ['video/mp4'],
        -		protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -		playbackmethod: [2],
        -		skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: iosDevice ? 13239390 : 13232361 // Add your own placement id here. 
        -            }
        -        }]
        -    };
        -
        -    pbjs.que.push(function() {
        -        pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - /* Use the Prebid Cache - required for video ads */ - - pbjs.setConfig({ - debug: true, - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - } - }); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - - /* Build the DFP video URL */ - - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - - - -
        -

        Place this code in the page body.

        -
        -
        -<script>
        -    var invokeVideoPlayer = function(url) {
        -        console.log("invoking video player with url " + url);
        -
        -        /* DEFINE PLAYER SETTINGS
        -
        -           Define the settings you want for your player in a JSON
        -           object. These lines will be part of the embed code you
        -           copy-paste from Ooyala Backlot, we just need to add the ad
        -           parameters.  */
        -
        -        var playerParam = {
        -            'pcode': 'lsbWkyOjtI6LOjmlqk2o5I-TsWRA',
        -            'playerBrandingId': '45b8294c6ad14265b2b47586c911cb07',
        -            'debug': true,
        -            'autoplay': true,
        -            'initialVolume': 0.0,
        -            'skin': {
        -                'config': '//player.ooyala.com/static/v4/stable/4.6.9/skin-plugin/skin.json',
        -                'inline': {
        -                    'adScreen': {
        -                        'showAdMarquee': true,
        -                        'showAdCountDown': true,
        -                        'showControlBar': true,
        -                        'useGoogleAdUI': true
        -                    }
        -                }
        -            },
        -
        -            /* ADD THE AD PARAMETERS TO THE PLAYER SETTINGS
        -
        -               Create a new JSON object in the player parameters. The key
        -               should be the ad manager you're using (in our case we're
        -               using the Google IMA ads manager, so the key is
        -               `"google-ima-ads-manager"`). The IMA ads manager requires
        -               an ad set (which we've named `"all_ads"`).
        -
        -               For more information see the Ooyala docs:
        -
        -               https://help.ooyala.com/video-platform/concepts/pbv4_ads_dev_google_ima.html:
        -
        -               Make sure the ad parameters are properly formatted JSON.
        -             */
        -            "google-ima-ads-manager": {
        -                "all_ads": [{
        -                    "position": "0",
        -                    "position_type": "t",
        -                    "tag_url": url
        -                }],
        -                'showAdControls': true
        -            }
        -        };
        -
        -        /* INITIALIZE THE PLAYER
        -
        -           Use the `OO.ready()` event to make sure that all the
        -           necessary Ooyala plugins have loaded before attempting to
        -           create the player. Once it has, call `create()` and pass
        -           in:
        -
        -           - the div you're creating the player in
        -
        -           - the ID of the content video
        -
        -           - the player settings we created above */
        -
        -        OO.ready(function() {
        -            console.log("OO is ready, invoking");
        -            console.dir(playerParam);
        -            window.pp = OO.Player.create('container', 'ltcG54NzE6Bxk08Mqs1_KMcQZDN7lH8N', playerParam);
        -        });
        -    }
        -
        -    /* ACCOUNT FOR PAGE SPEED
        -
        -       If Prebid returned bids before the browser reached the end of
        -       the page, the first version of `invokeVideoPlayer` will have
        -       been called from `bidsBackHandler`, so the winning VAST tag will
        -       be stored in `tempTag`.
        -
        -       If that's the case, we want to call the "real" version of
        -       `invokeVideoPlayer` with the stored URL to create the player and
        -       play the ad.
        -
        -       If `tempTag` is not defined, that means the browser reached the
        -       end of the page before the bids came back from Prebid, meaning
        -       the "real" version of `invokeVideoPlayer` was already called.
        -     */
        -
        -    if (tempTag) {
        -        invokeVideoPlayer(tempTag);
        -        tempTag = false;
        -    }
        -
        -</script> 
        -
        -
        - -
        -
        - - - - - diff --git a/examples/video/instream/radiant/pb-ve-radiant.html b/examples/video/instream/radiant/pb-ve-radiant.html deleted file mode 100644 index 30426eb6e2..0000000000 --- a/examples/video/instream/radiant/pb-ve-radiant.html +++ /dev/null @@ -1,329 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Instream Example with Radiant Media Player -description: An example of an instream pre-roll ad using Prebid.js and Radiant Media Player . -videoType: pb-is-rd -isVideo: true -sidebarType: 4 ---- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        - -
        
        -
        -<!--production version of prebid.js-->
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -
        -<!-- Radiant Media Player core library - debug browser console mode (use rmp.min.js for production) -->
        -<script src="https://cdn.radiantmediatechs.com/rmp/5.5.6/js/rmp.debug.js"></script>
        -
        -
        - - - -
        -

        Place this code in the page body.

        -
        -
        -<script>
        -		/* our app where we run player
        -			 our app variables */
        -		var pbApp = {};
        -		pbApp.playerSetup = false;
        -		pbApp.prebidTempTag = false;
        -		pbApp.debug = true;
        -		/* in case pre-bidding takes too long or fails we provide a playerSetupTimeout and fallbackAdTagUrl
        -			 to insure player setup happens - this is optional */
        -		pbApp.playerSetupTimeout = 5000;
        -		pbApp.fallbackAdTagUrl = 'https://www.radiantmediaplayer.com/vast/tags/inline-linear-1.xml';
        -		/* no console - no logs */
        -		if (typeof window.console === 'undefined' || typeof window.console.log === 'undefined' || typeof window.console.dir === 'undefined') {
        -			pbApp.debug = false;
        -		}
        -
        -		/* invokeVideoPlayer may not be defined when bidsBackHandler runs
        -			 we pre-defined it here so as to capture the returned adTagUrl to be passed to the player */
        -		pbApp.invokeVideoPlayer = function (adTagUrl) {
        -			pbApp.prebidTempTag = adTagUrl;
        -		};
        -
        -		/* prebid.js variables */
        -		var pbjs;
        -		pbjs = pbjs || {};
        -		pbjs.que = pbjs.que || [];
        -
        -		/* Prebid video ad unit
        -			 This is a working example but you must use your own settings/bidders for production
        -			 More docs at https://prebid.org/prebid-video/video-overview.html */
        -		var videoAdUnit = {
        -			code: 'video1',
        -			mediaTypes: {
        -				video: {
        -				  context: 'instream',
        -				  playerSize: [640, 480],
        -				  mimes: ['video/mp4'],
        -				  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -				  playbackmethod: [2],
        -				  skip: 1
        -				}
        -			},
        -			bids: [{
        -				bidder: 'appnexus',
        -				params: {
        -					placementId: 13232361
        -				}
        -			}]
        -		};
        -
        -		pbjs.que.push(function () {
        -			pbjs.addAdUnits(videoAdUnit);
        -
        -			pbjs.setConfig({
        -				debug: true,
        -				cache: {
        -					url: 'https://prebid.adnxs.com/pbc/v1/cache'
        -				}
        -			});
        -
        -			pbjs.requestBids({
        -				bidsBackHandler: function (bids) {
        -					if (pbApp.debug) {
        -						window.console.dir(bids);
        -					}
        -					var videoUrl = pbjs.adServers.dfp.buildVideoUrl({
        -						adUnit: videoAdUnit,
        -						params: {
        -							iu: '/19968336/prebid_cache_video_adunit',
        -							cust_params: {
        -								section: 'blog',
        -								anotherKey: 'anotherValue'
        -							},
        -							output: 'vast'
        -						}
        -					});
        -					pbApp.invokeVideoPlayer(videoUrl);
        -				}
        -			});
        -		});
        -
        -		/* here we re-define invokeVideoPlayer with Radiant Media Player set-up */
        -		pbApp.invokeVideoPlayer = function (adTagUrl) {
        -			if (pbApp.playerSetup) {
        -				return;
        -			}
        -			pbApp.playerSetup = true;
        -			if (pbApp.debug) {
        -				window.console.log('invokeVideoPlayer with Prebid VAST url = ' + adTagUrl);
        -			}
        -			var src = {
        -				mp4: [
        -					'https://www.rmp-streaming.com/media/bbb-360p.mp4'
        -				]
        -			};
        -			var settings = {
        -				licenseKey: 'Kl8lZ292K3N6MmVvZD9yb201ZGFzaXMzMGRiMEElXyo=',
        -				src: src,
        -				width: 640,
        -				height: 360,
        -				/*we enabled ads for our player
        -				 note that we requested a winning bid for skippable auto_play_sound_off so player starts muted autoplay*/
        -				ads: true,
        -				autoplay: true,
        -				muted: true,
        -				// we use Google IMA in this demo, but you can use rmp-vast as well depending on your requirements
        - adParser: 'ima', - // since we may request a skippable ads we set adDisableCustomPlaybackForIOS10Plus: true to allow rendering of skippable ads on iOS
        - adDisableCustomPlaybackForIOS10Plus: true, - // here is our winner VAST adTagUrl
        - adTagUrl: adTagUrl, - poster: 'https://www.radiantmediaplayer.com/images/poster-rmp-showcase.jpg' - }; - var elementID = 'rmpPlayer'; - var rmp = new RadiantMP(elementID); - rmp.init(settings); - - }; - - /* in case we already have a winning bid let's use the returned adTagUrl to run player */ - if (pbApp.prebidTempTag) { - pbApp.invokeVideoPlayer(pbApp.prebidTempTag); - pbApp.prebidTempTag = false; - } - - /* in case something went wrong (latency, network errors, bid issues ...) and we have no winning bid we still need to run the player - this is done after pbApp.playerSetupTimeout ms and we use fallbackAdTagUrl as adTagUrl to pass to the player */ - setTimeout(function () { - if (pbApp.playerSetup) { - return; - } - pbApp.invokeVideoPlayer(pbApp.fallbackAdTagUrl); - }, pbApp.playerSetupTimeout); - </script> -
        -
        - -
        -
        - - - - diff --git a/examples/video/instream/videoModule/videojs/video-module-videojs.html b/examples/video/instream/videoModule/videojs/video-module-videojs.html new file mode 100644 index 0000000000..739c783568 --- /dev/null +++ b/examples/video/instream/videoModule/videojs/video-module-videojs.html @@ -0,0 +1,281 @@ +--- +layout: video_sample +title: Prebid Video Module | Instream Example with VideoJS Submodule +description: An example of an instream pre-roll ad using the Prebid.js Video Module and the VideoJS submodule. +videoType: pb-vm-vjs +isVideo: true +sidebarType: 4 +--- + +
        +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + + +
        + +
        + + + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +          
        +          <script async src="//cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
        +          <link href="https://vjs.zencdn.net/7.20.2/video-js.css" rel="stylesheet" />
        +          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-ads/6.9.0/videojs-contrib-ads.css"
        +                  integrity="sha512-0gIqgiX1dWTChdWUl8XGIBDFvLo7aTvmd6FAhJjzWx5bzYsCJTiPJLKqLF3q31IN4Kfrc0NbTO+EthoT6O0olQ=="
        +                  crossorigin="anonymous" referrerpolicy="no-referrer" />
        +          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/videojs-ima/1.11.0/videojs.ima.css"
        +                  integrity="sha512-vvsEsf+dZDp6wbommO1Jbb2bpFhVQjw6pIzfE5fUY5Fgkmsgn/16sQWegqrd236T69kK5F1SbGZ+yK46a9il5A=="
        +                  crossorigin="anonymous" referrerpolicy="no-referrer" />
        +          <script src="https://vjs.zencdn.net/7.20.2/video.min.js"></script>
        +          <script src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
        +          <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-ads/6.9.0/videojs-contrib-ads.js"
        +                        integrity="sha512-XjyyAijQGlXZET35toG8igvVs8HvfVgKXGnbfAs2EpZ0o8vjJoIrxL9RBBQbQjzAODIe0jvWelFfZOA3Z/vdWg=="
        +                        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        +          <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-ima/1.11.0/videojs.ima.js"
        +                        integrity="sha512-9ocW9fl8CKJhZp4cmDpLDGPuTQ93gvw1iIS6daMYc5Y0Xh1all8iwdoI+iNmZpiydpdDGyKMTriXDX0wfs2OEg=="
        +                        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        +
        +          <script async src="../../../build/dev/prebid.js"></script>
        +
        +
        +        <!--This demo configures the video provider to use GAM Ad Server as mediation. Listens to Video events that are fired when an ad impression or ad error came from a bid. -->
        +
        +        <script>
        +            // Setup ad units
        +            var adUnits = [{
        +                code: 'div-gpt-ad-51545-0',
        +                mediaTypes: {
        +                    video: {}
        +                },
        +                video: {
        +                    divId: 'player', // required to indicate which player is being used to render this ad unit.
        +                },
        +                bids: [{
        +                    bidder: 'ix',
        +                    params: {
        +                        siteId: '300',
        +                    }
        +                }]
        +            }];
        +
        +            var pbjs = pbjs || {};
        +            pbjs.que = pbjs.que || [];
        +
        +            pbjs.que.push(function () {
        +                pbjs.setConfig({
        +                    video: {
        +                        providers: [{
        +                            divId: 'player',
        +                            vendorCode: 2, // videojs vendorCode
        +                            playerConfig: {
        +                                params: {
        +                                    adPluginConfig: {
        +                                        numRedirects: 10,
        +                                        adLabel: "Using Prebid Video Module!"
        +                                    },
        +                                    vendorConfig: {
        +                                        controls: true,
        +                                        autoplay: true,
        +                                        preload: "auto",
        +                                    }
        +                                }
        +                            },
        +                            // Configure your Ad Server Integration
        +                            adServer: {
        +                                vendorCode: 'gam',
        +                                baseAdTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator='
        +                            },
        +                        },]
        +                    },
        +                    cache: {
        +                        url: 'https://prebid.adnxs.com/pbc/v1/cache'
        +                    },
        +                    targetingControls: {
        +                        allowTargetingKeys: ['BIDDER', 'AD_ID', 'PRICE_BUCKET', 'SIZE', 'DEAL', 'SOURCE', 'FORMAT', 'UUID', 'CACHE_ID', 'CACHE_HOST', 'ADOMAIN']
        +                    },
        +                });
        +
        +                pbjs.addAdUnits(adUnits);
        +
        +                pbjs.onEvent('videoSetupComplete', e => {
        +                    // Load media with its Metadata when the video player is done instantiating.
        +                    videojs('player').loadMedia({
        +                        id: 'XYXYXYXY',
        +                        src: 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/SubaruOutbackOnStreetAndDirt.mp4',
        +                        title: 'Subaru Outback On Street And Dirt',
        +                        description: 'Smoking Tire takes the all-new Subaru Outback to the highest point we can find in hopes our customer-appreciation Balloon Launch will get some free T-shirts into the hands of our viewers.',
        +                        type: 'video/mp4'
        +                    });
        +                });
        +
        +                pbjs.onEvent('videoSetupFailed', e => {
        +                    console.log('The player setup failed: ', e);
        +                });
        +
        +                pbjs.onEvent('videoAdRequest', (e) => {
        +                    console.log('An ad request was made: ', e);
        +                });
        +
        +                pbjs.onEvent('videoBidError', e => {
        +                    console.log('An Ad Error came from a Bid: ', e);
        +                });
        +
        +                pbjs.onEvent('videoBidImpression', e => {
        +                    console.log('An Ad Impression came from a Bid: ', e);
        +                });
        +
        +                pbjs.requestBids(adUnits);
        +            });
        +        </script>
        +
        +                
        +
        + +

        Place this code in the page body.

        +
        + +
        +                  
        +                  <div class="example-video-container">
        +                    <video id="player" class="vjs-big-play-centered"></video>
        +                  </div>
        +                
        +
        +
        +
        + + + diff --git a/examples/video/instream/videojs/pb-ve-videojs.html b/examples/video/instream/videojs/pb-ve-videojs.html index 4a5f96e4ac..9d9daa2c4e 100644 --- a/examples/video/instream/videojs/pb-ve-videojs.html +++ b/examples/video/instream/videojs/pb-ve-videojs.html @@ -1,251 +1,263 @@ --- layout: video_sample -title: Prebid Video | Instream Example with VideoJS -description: An example of an instream pre-roll ad using Prebid.js and VideoJS. +title: Prebid Video | Instream Example with VideoJS +description: An example of an instream pre-roll ad using Prebid.js and VideoJS. videoType: pb-is-vjs isVideo: true sidebarType: 4 --- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<!-- use recent version of videojs to ensure proper functioning with the iOS devices -->
        -<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video-js.css">
        -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video.js"></script>
        -<!-- videojs-vast-vpaid -->
        -<link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs.vast.vpaid.min.css" rel="stylesheet">
        -<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs_5.vast.vpaid.min.js"></script>
        -
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -
        -    /* Prebid video ad unit */
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361
        -            }
        -        }]
        -    };
        -
        -    pbjs.que.push(function() {
        -        pbjs.addAdUnits(videoAdUnit);
        -
        -        pbjs.setConfig({
        -            debug: true,
        -            cache: {
        -                url: 'https://prebid.adnxs.com/pbc/v1/cache'
        -            }
        -        });
        +  
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + + +
        + +
        + + + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +  
        +  <script async src="//cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
        +  <!-- use recent version of videojs to ensure proper functioning with the iOS devices -->
        +  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video-js.css">
        +  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video.js"></script>
        +  <!-- videojs-vast-vpaid -->
        +  <link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs.vast.vpaid.min.css" rel="stylesheet">
        +  <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs_5.vast.vpaid.min.js"></script>
        +
        +  <script>
        +      var pbjs = pbjs || {};
        +      pbjs.que = pbjs.que || [];
        +
        +
        +      /* Prebid video ad unit */
        +
        +      var videoAdUnit = {
        +          code: 'video1',
        +          mediaTypes: {
        +              video: {
        +                  context: 'instream',
        +                  playerSize: [640, 480],
        +                  mimes: ['video/mp4'],
        +                  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        +                  playbackmethod: [2],
        +                  skip: 1
        +              }
        +          },
        +          bids: [{
        +              bidder: 'appnexus',
        +              params: {
        +                  placementId: 13232361
        +              }
        +          }]
        +      };
        +
        +      pbjs.que.push(function() {
        +          pbjs.addAdUnits(videoAdUnit);
        +
        +          pbjs.setConfig({
        +              debug: true,
        +              cache: {
        +                  url: 'https://prebid.adnxs.com/pbc/v1/cache'
        +              }
        +          });
        +
        +          pbjs.requestBids({
        +              bidsBackHandler: function(bids) {
        +                  var videoUrl = pbjs.adServers.dfp.buildVideoUrl({
        +                      adUnit: videoAdUnit,
        +                      params: {
        +                          iu: '/19968336/prebid_cache_video_adunit',
        +                          cust_params: {
        +                              section: 'blog',
        +                              anotherKey: 'anotherValue'
        +                          },
        +                          output: 'vast'
        +                      }
        +                  });
        +                  invokeVideoPlayer(videoUrl);
        +              }
        +          });
        +      });
        +
        +  </script>
        +        
        +
        + +

        Place this code in the page body.

        +
        + +
        +  
        +  <div class="example-video-container">
        +    <video id="vid1" class="video-js vjs-default-skin vjs-big-play-centered" controls data-setup='{}' width='640' height='480'>
        +      <source src="https://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'/>
        +      <source src="https://vjs.zencdn.net/v/oceans.webm" type='video/webm'/>
        +      <source src="https://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'/>
        +    </video>
        +  </div>
        +
        +
        +  <script>
        +      var page_load_time;
        +
        +      page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +      console.log(page_load_time + "ms -- Player loading!");
        +
        +      var vid1 = videojs('vid1');
        +
        +      page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +      console.log(page_load_time + "ms -- Player loaded!");
        +
        +      function invokeVideoPlayer(url) {
        +
        +          page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +          console.log(page_load_time + "ms -- Prebid VAST url = " + url);
        +
        +          /* Access the player instance by calling videojs() and passing
        +             in the player's ID. Add a ready listener to make sure the
        +             player is ready before interacting with it. */
        +
        +          videojs("vid1").ready(function() {
        +
        +              page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +              console.log(page_load_time + "ms -- Player is ready!");
        +
        +              /* PASS SETTINGS TO VAST PLUGIN
        +
        +                 Pass in a JSON object to the player's vastClient (defined
        +                 by the VAST/VPAID plugin we're using). The requires an
        +                 adTagUrl, which will be the URL returned by Prebid. You
        +                 can view all the options available for the vastClient
        +                 here:
        +
        +                 https://github.com/MailOnline/videojs-vast-vpaid#options */
        +
        +              var player = this;
        +              var vastAd = player.vastClient({
        +                  adTagUrl: url,
        +                  playAdAlways: true,
        +                  verbosity: 4,
        +                  vpaidFlashLoaderPath: "https://github.com/MailOnline/videojs-vast-vpaid/blob/RELEASE/bin/VPAIDFlash.swf?raw=true",
        +                  autoplay: true
        +              });
        +
        +              page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +              console.log(page_load_time + "ms -- Prebid VAST tag inserted!");
        +
        +              player.muted(true);
        +              player.play();
        +
        +              page_load_time = new Date().getTime() - performance.timing.navigationStart;
        +              console.log(page_load_time + "ms -- invokeVideoPlayer complete!");
        +
        +          });
        +      }
        +
        +  </script>
        +        
        +
        +
        +
        - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - - - - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div class="example-video-container">
        -	<video id="vid1" class="video-js vjs-default-skin vjs-big-play-centered" controls data-setup='{}' width='640' height='480'>
        -		<source src="https://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'/>
        -		<source src="https://vjs.zencdn.net/v/oceans.webm" type='video/webm'/>
        -		<source src="https://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'/>
        -	</video>
        -</div>
        -        
        -
        -<script>
        +
        +	
        -	
        -	
        +        page_load_time =
        +          new Date().getTime() - performance.timing.navigationStart;
        +        console.log(page_load_time + "ms -- invokeVideoPlayer complete!");
        +      });
        +    };
        +    window.resolveVideoJS();
        +  }
        +
        diff --git a/examples/video/long-form/long-form-video-with-freewheel.html b/examples/video/long-form/long-form-video-with-freewheel.html
        index faba737d37..5d9324187d 100644
        --- a/examples/video/long-form/long-form-video-with-freewheel.html
        +++ b/examples/video/long-form/long-form-video-with-freewheel.html
        @@ -3,7 +3,7 @@
           
             Prebid Freewheel Integration Demo
             
        -    
        +    
             
             
             
        @@ -15,11 +15,11 @@
             
             
             
        +{% include prebidjs-non-prod.html %}s
        +
        +
        +
        +

        {{ page.title }}

        +

        {{ page.description }}

        +
        + + +
        +

        Important: + This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        +
        + + +
        +

        Warning: + Do not forget to exchange the placementId in the code examples with your own placementId!

        +
        + +
        + +
        +
        + +
        +
        +
        
        +             
        +
        +
        +
        + + + diff --git a/examples/video/outstream/pb-ve-outstream-app.html b/examples/video/outstream/pb-ve-outstream-app.html deleted file mode 100644 index 34524e8540..0000000000 --- a/examples/video/outstream/pb-ve-outstream-app.html +++ /dev/null @@ -1,205 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Outstream Example with AdPlayer.Pro Player -description: An example of an outstream video using Prebid.js and AdPlayer.Pro player. -videoType: pb-os-app -isVideo: true -sidebarType: 4 ---- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - -
        - -
        -

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

        -
        - - -
        - -
        -

        Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

        -
        -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -<script src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<!--AdPlayer.Pro code-->
        -<script src="https://static.adplayer.pro/player/demo.js"></script>
        -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id='playerContainerADP'></div>
        -<script>
        -	/* our app where we run player
        -   our app variables */
        -		var pbjs;
        -		pbjs = pbjs || {};
        -		pbjs.que = pbjs.que || [];
        -		var debug = false;
        -		if (typeof window.console === 'undefined' || typeof window.console.log === 'undefined' || typeof window.console.dir === 'undefined') {
        -		  debug = false;
        -		}
        -		var videoId = 'video1';
        -
        -		/* Prebid video ad unit
        -		   This is a working example but you must use your own settings/bidders for production
        -		   More docs at https://prebid.org/prebid-video/video-overview.html */
        -		var adUnits = [{
        -		  code: videoId,
        -		  mediaTypes: {
        -		    video: {
        -		      context: 'outstream',
        -                      playerSize: [640, 480],
        -                      mimes: ['video/mp4'],
        -                      protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                      playbackmethod: [2],
        -                      skip: 1
        -		    }
        -		  },
        -		  bids: [{
        -		    bidder: 'appnexus',
        -		    params: {
        -		      placementId: 13232385
        -		    }
        -		  }]
        -		}];
        -
        -		pbjs.que.push(function () {
        -		  pbjs.addAdUnits(adUnits);
        -		  pbjs.requestBids({
        -		    timeout: 1000,
        -		    bidsBackHandler: function (bids) {
        -		      if (debug) {
        -		        window.console.dir(bids);
        -		      }
        -		      // we get the VAST XML from bids adResponse and pass it to our outstream player
        - if (bids && bids[videoId] && bids[videoId].bids && bids[videoId].bids[0] && bids[videoId].bids[0].adResponse) { - var adResponse = bids[videoId].bids[0].adResponse; - if (adResponse.ad && adResponse.ad.video && typeof adResponse.ad.video.content === 'string') { - var vastXml = bids[videoId].bids[0].adResponse.ad.video.content; - if (vastXml !== '') { - if (debug) { - window.console.log(vastXml); - } - AdPlayerPro('playerContainerADP').setup({ - "file": "https://static.adplayer.pro/video/640.mp4", - "width": 640, - "height": 360, - "autoStart": true, - "muted": true, - "advertising": { - "tag": vastXml - } - }); - } - } - } - } - }); - }); -</script> -
        -
        - -
        -
        - - - - - diff --git a/examples/video/outstream/pb-ve-outstream-dfp.html b/examples/video/outstream/pb-ve-outstream-dfp.html index 0a62332454..25f2130937 100644 --- a/examples/video/outstream/pb-ve-outstream-dfp.html +++ b/examples/video/outstream/pb-ve-outstream-dfp.html @@ -1,151 +1,165 @@ --- layout: video_sample -title: Prebid Video | Video Outstream Example with Google Ad Manager -description: An example of an outstream video with a pre-roll ad using Prebid.js and Google Ad Manager. +title: Prebid Video | Video Outstream Example with Google Ad Manager +description: An example of an outstream video with a pre-roll ad using Prebid.js and Google Ad Manager. videoType: pb-os-dfp isVideo: true sidebarType: 4 --- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - -
        - -
        -

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

        -
        - -
        -

        Prebid Outstream Video Ad

        - -
        - -
        -

        Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

        -
        -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//www.googletagservices.com/tag/js/gpt.js"></script>
        -
        -<script>
        -
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    var googletag = googletag || {};
        -    googletag.cmd = googletag.cmd || [];
        -
        -    var PREBID_TIMEOUT = 1000;
        -
        -    var adUnits = [{
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'outstream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [
        -            {
        -                bidder: 'appnexus',
        -                params: {
        -                    placementId: 13232385
        -                }
        -            }
        -        ]
        -    }];
        -
        -    pbjs.que.push(function() {
        -        pbjs.addAdUnits(adUnits);
        -        pbjs.requestBids({
        -            bidsBackHandler: initAdserver
        -        });
        -    });
        -
        -    function initAdserver() {
        -        if (pbjs.initAdserverSet) return;
        -        pbjs.initAdserverSet = true;
        -        googletag.cmd.push(function() {
        -            pbjs.que.push(function() {
        -                pbjs.setTargetingForGPTAsync();
        -                googletag.pubads().refresh();
        -            });
        -        });
        -    }
        -
        -    setTimeout(function() {
        -        initAdserver();
        -    }, PREBID_TIMEOUT);
        -
        -    googletag.cmd.push(function() {
        -        var slot1 = googletag.defineSlot('/19968336/prebid_outstream_adunit_1', [[1, 1]], 'video1').addService(googletag.pubads());
        -        googletag.pubads().disableInitialLoad();
        -        googletag.pubads().enableSingleRequest();
        -        googletag.enableServices();
        -    });
        -
        -</script>
        -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id='video1'>
        -    <p>Prebid Outstream Video Ad</p>
        -    <script type='text/javascript'>
        -        googletag.cmd.push(function() {
        -            googletag.display('video1');
        -        });
        -
        -    </script>
        -</div>
        -
        -
        -
        - -
        +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + +
        +
        +

        + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. +

        +
        + +
        +

        Prebid Outstream Video Ad

        +
        + +
        +

        + Sed ut perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae + ab illo inventore veritatis et quasi architecto beatae vitae dicta + sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit + aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos + qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui + dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed + quia non numquam eius modi tempora incidunt ut labore et dolore magnam + aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex + ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in + ea voluptate velit esse quam nihil molestiae consequatur, vel illum + qui dolorem eum fugiat quo voluptas nulla pariatur? +

        +
        +
        + + + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +  
        +  <script async src="//securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
        +
        +  <script>
        +
        +      var pbjs = pbjs || {};
        +      pbjs.que = pbjs.que || [];
        +
        +      var googletag = googletag || {};
        +      googletag.cmd = googletag.cmd || [];
        +
        +      var PREBID_TIMEOUT = 1000;
        +
        +      var adUnits = [{
        +          code: 'video1',
        +          mediaTypes: {
        +              video: {
        +                  context: 'outstream',
        +                  playerSize: [640, 480],
        +                  mimes: ['video/mp4'],
        +                  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        +                  playbackmethod: [2],
        +                  skip: 1
        +              }
        +          },
        +          bids: [
        +              {
        +                  bidder: 'appnexus',
        +                  params: {
        +                      placementId: 13232385
        +                  }
        +              }
        +          ]
        +      }];
        +
        +      pbjs.que.push(function() {
        +          pbjs.addAdUnits(adUnits);
        +          pbjs.requestBids({
        +              bidsBackHandler: initAdserver
        +          });
        +      });
        +
        +      function initAdserver() {
        +          if (pbjs.initAdserverSet) return;
        +          pbjs.initAdserverSet = true;
        +          googletag.cmd.push(function() {
        +              pbjs.que.push(function() {
        +                  pbjs.setTargetingForGPTAsync();
        +                  googletag.pubads().refresh();
        +              });
        +          });
        +      }
        +
        +      setTimeout(function() {
        +          initAdserver();
        +      }, PREBID_TIMEOUT);
        +
        +      googletag.cmd.push(function() {
        +          var slot1 = googletag.defineSlot('/19968336/prebid_outstream_adunit_1', [[1, 1]], 'video1').addService(googletag.pubads());
        +          googletag.pubads().disableInitialLoad();
        +          googletag.pubads().enableSingleRequest();
        +          googletag.enableServices();
        +      });
        +
        +  </script>
        +        
        +
        + + +

        Place this code in the page body.

        +
        +
        +  
        +  <div id='video1'>
        +      <p>Prebid Outstream Video Ad</p>
        +      <script type='text/javascript'>
        +          googletag.cmd.push(function() {
        +              googletag.display('video1');
        +          });
        +
        +      </script>
        +  </div>
        +
        +        
        +
        +
        - - - - + diff --git a/examples/video/outstream/pb-ve-outstream-no-server-specify-renderer.html b/examples/video/outstream/pb-ve-outstream-no-server-specify-renderer.html new file mode 100644 index 0000000000..8321849a81 --- /dev/null +++ b/examples/video/outstream/pb-ve-outstream-no-server-specify-renderer.html @@ -0,0 +1,170 @@ +--- +layout: video_sample +title: Prebid Video | Video Outstream Example with No Ad Server using Specified Renderer +description: An example of an outstream video ad using Prebid.js and no ad server but with a specified renderer. +videoType: pb-os-nas-renderer +isVideo: true +sidebarType: 4 +--- + +
        +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + +
        +
        +

        + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. +

        +
        + +
        +

        Prebid Outstream Video Ad

        +
        + +
        +

        + Sed ut perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae + ab illo inventore veritatis et quasi architecto beatae vitae dicta + sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit + aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos + qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui + dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed + quia non numquam eius modi tempora incidunt ut labore et dolore magnam + aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex + ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in + ea voluptate velit esse quam nihil molestiae consequatur, vel illum + qui dolorem eum fugiat quo voluptas nulla pariatur? +

        +
        +
        + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +  
        +  <script>
        +      var pbjs = pbjs || {};
        +      pbjs.que = pbjs.que || [];
        +
        +      function callANRenderer(bid, ad) {
        +        const adResponse = {
        +            ad: {
        +                video: {
        +                    content: ad,
        +                    player_width: 640,
        +                    player_height: 480,
        +                }
        +            }
        +        }
        +
        +        bid.renderer.push(() => {
        +            window.ANOutstreamVideo.renderAd({
        +                targetId: bid.adUnitCode,
        +                adResponse,
        +            });
        +        });
        +      }
        +
        +      function render(bid) {
        +          let ad = bid.ad || bid.vastXml;
        +
        +          if (ad) {
        +              callANRenderer(bid, ad)
        +          } else {
        +              if (bid.vastUrl) {
        +                (async () => {
        +                    ad = await fetch(resp).then(resp => resp.text());
        +
        +                    if (typeof ad === 'string') {
        +                        callANRenderer(bid, ad);
        +                    } else {
        +                        console.log('Invalid VAST');
        +                    }
        +                })();
        +              } else {
        +                  console.log('Invalid ad');
        +              }
        +          }
        +      }
        +
        +      const adUnits = [{
        +          code: 'video1',
        +          mediaTypes: {
        +              video: {
        +                  context: 'outstream',
        +                  playerSize: [640, 480],
        +                  mimes: ['video/mp4'],
        +                  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        +                  playbackmethod: [2],
        +                  skip: 1,
        +                  renderer: {
        +                      render,
        +                      url: "https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js"
        +                  },
        +              }
        +          },
        +          bids: [{
        +              bidder: 'appnexus',
        +              params: {
        +                  placementId: 13232385
        +              }
        +          }]
        +      }];
        +
        +      pbjs.que.push(function() {
        +          pbjs.addAdUnits(adUnits);
        +          pbjs.requestBids({
        +              timeout: 1000,
        +              bidsBackHandler: function(bids) {
        +                  const highestCpmBids = pbjs.getHighestCpmBids('video1');
        +                  pbjs.renderAd(document, highestCpmBids[0].adId);
        +              }
        +          });
        +      });
        +  </script>
        +              
        + +

        Place this code in the page body.

        +
        + +
        +  
        +  <div id='video1'>
        +    <p>Prebid Outstream Video Ad</p>
        +  </div>
        +              
        +
        +
        +
        +
        diff --git a/examples/video/outstream/pb-ve-outstream-no-server.html b/examples/video/outstream/pb-ve-outstream-no-server.html index bb78701f5e..f33601f3d3 100644 --- a/examples/video/outstream/pb-ve-outstream-no-server.html +++ b/examples/video/outstream/pb-ve-outstream-no-server.html @@ -7,110 +7,123 @@ sidebarType: 4 --- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - -
        - -
        - -

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

        -
        - -
        -

        Prebid Outstream Video Ad

        -
        - -
        -

        Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

        -
        -
        - - - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    var adUnits = [{
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'outstream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232385
        -            }
        -        }]
        -    }];
        -
        -    pbjs.que.push(function() {
        -        pbjs.addAdUnits(adUnits);
        -        pbjs.requestBids({
        -            timeout: 1000,
        -            bidsBackHandler: function(bids) {
        -                var highestCpmBids = pbjs.getHighestCpmBids('video1');
        -                pbjs.renderAd(document, highestCpmBids[0].adId);
        -            }
        -        });
        -    });
        -
        -</script>
        -
        -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id='video1'>
        -	<p>Prebid Outstream Video Ad</p>
        -</div>
        -
        -
        - -
        +
        +
        +

        {{ page.title }}

        +

        {{page.description }}

        +
        + + +
        +

        + Important: This example uses a test version of Prebid.js hosted + on our CDN that is not recommended for production use. It includes all + available adapters. Production implementations should build from source + or customize the build using the Download page to make sure only the + necessary bidder adapters are included. +

        +
        + +
        +
        +

        + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. +

        +
        + +
        +

        Prebid Outstream Video Ad

        +
        + +
        +

        + Sed ut perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae + ab illo inventore veritatis et quasi architecto beatae vitae dicta + sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit + aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos + qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui + dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed + quia non numquam eius modi tempora incidunt ut labore et dolore magnam + aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex + ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in + ea voluptate velit esse quam nihil molestiae consequatur, vel illum + qui dolorem eum fugiat quo voluptas nulla pariatur? +

        +
        +
        + + + + +
        +

        + Warning: Do not forget to exchange the placementId in the code + examples with your own placementId! +

        +
        + +

        Place this code in the page header.

        +
        +
        +  
        +  <script>
        +      var pbjs = pbjs || {};
        +      pbjs.que = pbjs.que || [];
        +
        +      var adUnits = [{
        +          code: 'video1',
        +          mediaTypes: {
        +              video: {
        +                  context: 'outstream',
        +                  playerSize: [640, 480],
        +                  mimes: ['video/mp4'],
        +                  protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        +                  playbackmethod: [2],
        +                  skip: 1
        +              }
        +          },
        +          bids: [{
        +              bidder: 'appnexus',
        +              params: {
        +                  placementId: 13232385
        +              }
        +          }]
        +      }];
        +
        +      pbjs.que.push(function() {
        +          pbjs.addAdUnits(adUnits);
        +          pbjs.requestBids({
        +              timeout: 1000,
        +              bidsBackHandler: function(bids) {
        +                  var highestCpmBids = pbjs.getHighestCpmBids('video1');
        +                  pbjs.renderAd(document, highestCpmBids[0].adId);
        +              }
        +          });
        +      });
        +
        +  </script>
        +
        +        
        +
        + +

        Place this code in the page body.

        +
        + +
        +  
        +  <div id='video1'>
        +    <p>Prebid Outstream Video Ad</p>
        +  </div>
        +          
        +
        +
        - - -
        ; -

        Prebid Outstream Video Ad

        -

        - - diff --git a/examples/video/outstream/pb-ve-outstream-radiant.html b/examples/video/outstream/pb-ve-outstream-radiant.html deleted file mode 100644 index 60315adaa6..0000000000 --- a/examples/video/outstream/pb-ve-outstream-radiant.html +++ /dev/null @@ -1,217 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Video Outstream Example with Radiant Media Player -description: An example of an outstream video with a pre-roll ad using Prebid.js and Radiant Media Player. -videoType: pb-os-rd -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - -
        - -
        -

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

        -
        - - -
        - -
        -

        Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

        -
        -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<!--radiant code-->
        -<script src="https://cdn.radiantmediatechs.com/rmp/5.5.6/js/rmp.debug.js"></script>
        -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<script>
        -	/* our app where we run player
        -   our app variables */
        -		var pbjs;
        -		pbjs = pbjs || {};
        -		pbjs.que = pbjs.que || [];
        -		var debug = false;
        -		if (typeof window.console === 'undefined' || typeof window.console.log === 'undefined' || typeof window.console.dir === 'undefined') {
        -		  debug = false;
        -		}
        -		var videoId = 'video1';
        -
        -		/* Prebid video ad unit
        -		   This is a working example but you must use your own settings/bidders for production
        -		   More docs at https://prebid.org/prebid-video/video-overview.html */
        -		var adUnits = [{
        -		  code: videoId,
        -		  mediaTypes: {
        -		    video: {
        -		      context: 'outstream',
        -                      playerSize: [640, 480],
        -                      mimes: ['video/mp4'],
        -                      protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                      playbackmethod: [2],
        -                      skip: 1
        -		    }
        -		  },
        -		  bids: [{
        -		    bidder: 'appnexus',
        -		    params: {
        -		      placementId: 13232385
        -		    }
        -		  }]
        -		}];
        -
        -		pbjs.que.push(function () {
        -		  pbjs.addAdUnits(adUnits);
        -		  pbjs.requestBids({
        -		    timeout: 1000,
        -		    bidsBackHandler: function (bids) {
        -		      if (debug) {
        -		        window.console.dir(bids);
        -		      }
        -		      // we get the VAST XML from bids adResponse and pass it to our outstream player
        -		      if (bids && bids[videoId] && bids[videoId].bids && bids[videoId].bids[0] && bids[videoId].bids[0].adResponse) {
        -		        var adResponse = bids[videoId].bids[0].adResponse;
        -		        if (adResponse.ad && adResponse.ad.video && typeof adResponse.ad.video.content === 'string') {
        -		          var vastXml = bids[videoId].bids[0].adResponse.ad.video.content;
        -		          if (vastXml !== '') {
        -		            if (debug) {
        -		              window.console.log(vastXml);
        -		            }
        -		            var settings = {
        -		              licenseKey: 'Kl8lZ292K3N6MmVvZD9yb201ZGFzaXMzMGRiMEElXyo=',
        -		              width: 640,
        -		              height: 360,
        -		              autoplay: true,
        -		              adOutStreamMutedAutoplay: true,
        -		              ads: true,
        -		              adsResponse: vastXml,
        -		              adOutStream: true,
        -		              skin: 'outstream'
        -		            };
        -		            var elementID = 'rmpPlayer';
        -		            var rmp = new RadiantMP(elementID);
        -		            rmp.init(settings);
        -		          }
        -		        }
        -		      }
        -		    }
        -		  });
        -		});
        -</script>
        -
        -
        - -
        -
        - - - - - diff --git a/examples/video/pb-video-template.html b/examples/video/pb-video-template.html deleted file mode 100644 index 1d1f9e5ef8..0000000000 --- a/examples/video/pb-video-template.html +++ /dev/null @@ -1,305 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Video Outstream Example with Google Ad Manager -description: An example of an outstream video with a pre-roll ad using Prebid.js and Google Ad Manager. -videoType: pb-os-dfp -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        - - - - - -

        {{page.title}}

        - - -
        {{page.description}}
        - - - - - -
        -

        - In scelerisque sem sed tortor posuere sagittis. Fusce scelerisque odio at tincidunt ultricies. Fusce egestas, erat non finibus dictum, nulla arcu viverra nibh, at bibendum ligula nisi egestas magna. Nulla eu finibus nulla. Pellentesque at mi eget turpis - consequat scelerisque. Sed lacinia, nisi sit amet egestas vestibulum, elit odio iaculis leo, et lacinia risus enim non lacus. Cras nec neque eget nunc gravida maximus. Ut hendrerit convallis sollicitudin. Donec cursus erat vel metus gravida, - et pretium justo iaculis. Curabitur condimentum blandit augue, quis interdum leo. Vivamus dapibus est nec dui efficitur, eu imperdiet nulla sollicitudin. Suspendisse laoreet velit vitae arcu mollis, ac interdum lorem venenatis. Aenean - nec purus varius, accumsan ex at, luctus arcu. Quisque consectetur tortor eros, placerat lacinia eros aliquam a. Proin non porttitor libero. -

        -

        - Proin eget vulputate est. Nunc sit amet neque a tortor ullamcorper suscipit non eu neque. Quisque at massa in metus feugiat rutrum. Nulla et orci orci. Aliquam erat volutpat. Cras tincidunt metus lectus, sed suscipit augue mollis vitae. Sed quis condimentum - tortor, sit amet consectetur erat. Nulla pellentesque turpis lacus, eu venenatis massa fringilla at. Duis sed pharetra turpis. Maecenas vel porttitor neque. Praesent quis felis sapien. Donec suscipit euismod dui, vitae fermentum nisi ornare - in. -

        -

        - Suspendisse tempor felis accumsan orci finibus, imperdiet mollis arcu imperdiet. In eu dolor condimentum, pulvinar nisl a, sollicitudin nunc. Ut vel lectus libero. Praesent rhoncus leo tortor, at mollis nulla sagittis eget. Quisque tempus tempor augue - sed rutrum. Sed vitae volutpat quam. Proin vestibulum eros metus, a luctus erat condimentum eu. Vivamus ullamcorper ultricies dui, ac malesuada leo finibus semper. Cras diam augue, imperdiet sed efficitur id, aliquam sed purus. Praesent - eget turpis quis sapien interdum sagittis. Vivamus placerat nunc a tempus fermentum. Praesent laoreet leo at tellus porta, ut viverra tortor pharetra. Quisque elit velit, eleifend eget imperdiet vel, suscipit ac nisi. Aliquam egestas mauris - ut massa fringilla laoreet. -

        -
        -

        Prebid Outstream Video Ad

        - -
        - - -

        - Quisque ac luctus nisi, vitae ornare arcu. Proin fermentum sapien vitae odio vestibulum porta. Suspendisse faucibus sapien enim, et faucibus urna tempus et. Integer porttitor justo sed faucibus blandit. Morbi semper lectus vitae semper facilisis. Quisque - molestie accumsan arcu, eget bibendum dui euismod et. Sed in mattis lacus, nec lacinia sem. Fusce sed tortor posuere, iaculis justo varius, elementum est. -

        -

        - Etiam condimentum, eros commodo semper tristique, lorem leo pharetra massa, eget cursus justo enim id urna. Sed imperdiet mauris vitae ante bibendum elementum. Etiam eu dui porttitor leo imperdiet cursus. Maecenas consequat, neque a dapibus viverra, nunc - velit volutpat nibh, ut cursus sem tortor ac arcu. Praesent convallis lacus vel nisi aliquam, in posuere libero scelerisque. Curabitur et lacinia nisl. Nunc id ligula neque. Phasellus non eros et leo ultrices ultricies. Nulla facilisi. - Donec ut augue urna. Suspendisse sodales nisi at ex faucibus, et tempus magna fermentum. Proin non arcu interdum, pulvinar est at, vehicula odio. Morbi nec maximus sem. Ut eu tristique urna. -

        -

        - Pellentesque eget quam sem. Nam interdum eleifend leo, mattis sagittis metus ornare tristique. Cras pretium odio lectus, vitae viverra massa consequat eget. Suspendisse porttitor pretium lectus in scelerisque. Phasellus euismod porta lectus eget pharetra. - Ut et viverra mi, ut imperdiet lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc tempus sapien sit amet tortor rhoncus dignissim. Sed at augue et sem lacinia feugiat. Nulla vitae convallis - urna. Morbi scelerisque erat quis nibh pretium, non elementum elit consectetur. Proin in feugiat nisl. -

        -

        - Morbi et ipsum purus. Integer ut pulvinar metus. Fusce maximus ex nec purus sollicitudin gravida. Vivamus dapibus volutpat erat nec tristique. Aliquam mi dolor, pretium non elementum quis, viverra non est. Pellentesque egestas, lectus a posuere imperdiet, - nisi sem elementum neque, eu volutpat arcu turpis venenatis magna. Curabitur non neque consectetur, vulputate urna sed, vestibulum lacus. Aenean mollis, risus non pulvinar egestas, lectus lectus finibus dui, sit amet pretium metus mauris - vitae nibh. In non ultricies odio. -

        -

        - Donec dictum sem ac risus molestie lobortis. Maecenas at justo vehicula, iaculis orci eget, eleifend nunc. In non justo imperdiet, blandit leo in, interdum mi. Proin feugiat libero et erat dictum efficitur. Nunc auctor lacus feugiat erat euismod cursus. - Sed vehicula ante vel quam pretium blandit. Maecenas congue quis mauris vitae efficitur. Cras sit amet justo at sem dictum ornare vitae eu ex. Nunc ornare odio nec leo consectetur cursus. Mauris eu dolor tellus. Etiam dignissim ut nunc - et mollis. Cras at pulvinar velit, ut tincidunt velit. Cras vitae fermentum ante. Aenean interdum dolor in scelerisque consectetur. -

        -

        - Curabitur auctor leo sit amet massa faucibus ultrices. Maecenas dignissim libero ac cursus cursus. Curabitur eget sapien leo. Phasellus pretium blandit facilisis. Proin egestas urna a sagittis tempus. Donec in nibh ex. Vestibulum efficitur felis aliquam - urna ultrices, at gravida nibh pretium. Morbi dictum vulputate pretium. Donec at nisi rutrum, pharetra nunc a, placerat felis. Quisque rhoncus congue fermentum. Quisque pharetra est at nisl sagittis suscipit. Maecenas scelerisque porta - eleifend. Mauris nulla leo, consectetur at eros vel, elementum pretium diam. -

        -

        - In nisi libero, porta ut ullamcorper a, dapibus nec velit. Vestibulum congue rhoncus congue. Nulla a libero sit amet risus feugiat hendrerit id placerat ex. In hac habitasse platea dictumst. Pellentesque ut ullamcorper risus. Nunc et ipsum nisi. Vivamus - a interdum diam, hendrerit pellentesque orci. -

        -

        - Vestibulum ut massa blandit, maximus sem vitae, vulputate mauris. Nam condimentum velit a facilisis dignissim. Nunc venenatis pharetra dapibus. Praesent ullamcorper risus sit amet molestie consectetur. Cras mauris felis, consequat et enim a, ultricies - pretium enim. Nulla porttitor nunc mi, sed posuere magna venenatis non. Donec lobortis consectetur mauris, fermentum auctor dui dignissim sed. Sed vel venenatis urna. Donec velit velit, imperdiet non vulputate non, eleifend sed nisi. -

        -

        - Proin et turpis velit. Donec tempus dictum dolor, eget eleifend lacus. Donec eu felis in ante iaculis ultrices. Mauris varius, turpis quis venenatis convallis, enim dolor ornare justo, in dictum ipsum purus quis dolor. Ut condimentum feugiat lectus ut - auctor. Maecenas luctus consequat erat, nec pretium urna pulvinar in. Donec gravida rhoncus aliquet. Cras aliquet odio eget orci hendrerit, non posuere velit dignissim. Nunc tempus aliquam iaculis. Nunc viverra lobortis mauris et malesuada. - Donec congue suscipit mauris. Phasellus efficitur, leo at mollis maximus, lorem mauris pretium urna, nec scelerisque ante neque eu erat. Nam rhoncus malesuada velit nec ultricies. -

        -

        - Proin blandit in arcu sed porttitor. Morbi in erat vel risus mollis interdum. Proin vel odio semper, porttitor risus sed, tristique odio. Donec viverra massa et dui scelerisque, ac sagittis odio viverra. Aliquam lacinia enim sit amet dapibus ultrices. - Nulla mollis, massa eget interdum egestas, lectus eros pretium eros, vel consectetur velit odio vel odio. Proin euismod aliquam finibus. Phasellus facilisis mollis est, non consequat lectus volutpat nec. -

        -

        - Ut vel ultricies erat. Pellentesque non ipsum quis odio ornare tempus in cursus ex. In a turpis non quam pulvinar tincidunt. Maecenas tortor neque, dapibus a quam aliquet, dictum pellentesque leo. Sed aliquet tellus est, in tempus magna congue ut. Phasellus - at tincidunt lorem, id fringilla risus. Nunc vel pulvinar massa. Aliquam erat volutpat. Phasellus semper interdum justo at eleifend. Curabitur feugiat quam sed mollis facilisis. -

        -

        - Quisque consectetur sem a elit aliquet facilisis. Quisque dignissim velit at quam rhoncus dignissim. Proin feugiat sem at turpis ultrices imperdiet. Integer vel eros vel ante ultricies dapibus vitae eget dui. Fusce sollicitudin semper tortor at molestie. - Pellentesque nec metus sed mauris aliquet iaculis. Mauris malesuada tortor nec mi dictum, feugiat euismod enim gravida. Vestibulum dapibus ut nulla vel euismod. Nunc lobortis, mauris at pretium faucibus, ligula diam venenatis nulla, in - mattis sapien arcu feugiat dolor. In at dui leo. Cras elementum condimentum turpis. -

        -

        - Donec eget dolor ac nulla lobortis bibendum. Praesent commodo accumsan ligula eget commodo. Suspendisse sit amet dignissim metus. Sed ut eros viverra, viverra lectus eget, ornare eros. Mauris elementum lacinia dapibus. Donec magna nisl, suscipit quis - mattis eget, tincidunt sed sapien. Curabitur elementum nulla eget lorem gravida dapibus. Nunc vel dolor et libero pretium interdum vitae eget mauris. Vestibulum et erat in nulla sollicitudin luctus ut quis nulla. -

        -

        - Maecenas iaculis pellentesque quam at fringilla. Donec dui elit, suscipit eget varius id, suscipit efficitur metus. Nulla rutrum ultrices tempor. Vivamus hendrerit justo ac fermentum euismod. Vestibulum tempus pulvinar tempus. Curabitur congue neque luctus - dolor vehicula, non efficitur metus fringilla. Nam a imperdiet ex. Integer at est hendrerit, rutrum justo eu, ornare odio. Etiam convallis sapien a purus vehicula, eget gravida purus semper. Fusce ex enim, volutpat ac feugiat et, rhoncus - vel tortor. Aenean ultrices libero sed neque fermentum tempor. Morbi tincidunt dui turpis, non mollis est dignissim at. Suspendisse molestie convallis interdum. Donec sit amet fermentum purus. -

        -

        - Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam et ex orci. Vivamus rutrum est vel porta imperdiet. Cras ultricies tortor dolor, nec mollis felis ullamcorper vel. Praesent scelerisque vehicula sem, nec feugiat - mauris tempus ac. Donec at enim non sem commodo sodales. Ut sit amet risus sit amet ante viverra venenatis. Aliquam sodales mollis est eget ultricies. Etiam pulvinar sapien et ipsum elementum pharetra. -

        -

        - Nam blandit metus erat, sit amet congue ipsum cursus sed. In a commodo ante, sit amet tincidunt quam. Aenean lobortis et nibh in venenatis. Aliquam faucibus purus quis neque consectetur, quis consequat risus maximus. Proin mollis imperdiet felis, eget - tempus ipsum scelerisque ut. Sed euismod interdum augue sed varius. Sed volutpat tellus ut risus porta accumsan. -

        -

        - Mauris aliquet eu arcu sed pharetra. Duis nec leo volutpat libero finibus malesuada in eget velit. Aliquam facilisis urna mauris, et aliquam ipsum dictum finibus. Donec eget mi fermentum, vehicula odio at, molestie orci. In a hendrerit lectus. Aenean - congue ipsum ac imperdiet suscipit. Maecenas eleifend pretium metus id mollis. -

        -

        - Ut vel ultricies erat. Pellentesque non ipsum quis odio ornare tempus in cursus ex. In a turpis non quam pulvinar tincidunt. Maecenas tortor neque, dapibus a quam aliquet, dictum pellentesque leo. Sed aliquet tellus est, in tempus magna congue ut. Phasellus - at tincidunt lorem, id fringilla risus. Nunc vel pulvinar massa. Aliquam erat volutpat. Phasellus semper interdum justo at eleifend. Curabitur feugiat quam sed mollis facilisis. -

        -

        - Quisque consectetur sem a elit aliquet facilisis. Quisque dignissim velit at quam rhoncus dignissim. Proin feugiat sem at turpis ultrices imperdiet. Integer vel eros vel ante ultricies dapibus vitae eget dui. Fusce sollicitudin semper tortor at molestie. - Pellentesque nec metus sed mauris aliquet iaculis. Mauris malesuada tortor nec mi dictum, feugiat euismod enim gravida. Vestibulum dapibus ut nulla vel euismod. Nunc lobortis, mauris at pretium faucibus, ligula diam venenatis nulla, in - mattis sapien arcu feugiat dolor. In at dui leo. Cras elementum condimentum turpis. -

        -

        - Donec eget dolor ac nulla lobortis bibendum. Praesent commodo accumsan ligula eget commodo. Suspendisse sit amet dignissim metus. Sed ut eros viverra, viverra lectus eget, ornare eros. Mauris elementum lacinia dapibus. Donec magna nisl, suscipit quis - mattis eget, tincidunt sed sapien. Curabitur elementum nulla eget lorem gravida dapibus. Nunc vel dolor et libero pretium interdum vitae eget mauris. Vestibulum et erat in nulla sollicitudin luctus ut quis nulla. -

        -

        - Maecenas iaculis pellentesque quam at fringilla. Donec dui elit, suscipit eget varius id, suscipit efficitur metus. Nulla rutrum ultrices tempor. Vivamus hendrerit justo ac fermentum euismod. Vestibulum tempus pulvinar tempus. Curabitur congue neque luctus - dolor vehicula, non efficitur metus fringilla. Nam a imperdiet ex. Integer at est hendrerit, rutrum justo eu, ornare odio. Etiam convallis sapien a purus vehicula, eget gravida purus semper. Fusce ex enim, volutpat ac feugiat et, rhoncus - vel tortor. Aenean ultrices libero sed neque fermentum tempor. Morbi tincidunt dui turpis, non mollis est dignissim at. Suspendisse molestie convallis interdum. Donec sit amet fermentum purus. -

        -
        - - - - - - - - -
        -

        Place this code in the page header.

        -
        -	
        -	<script async src="//www.googletagservices.com/tag/js/gpt.js"></script>
        -		<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -		<script type="text/javascript" src="https://ssl.p.jwpcdn.com/player/v/8.0.5/jwplayer.js"></script>
        -        <script type="text/javascript">
        -            jwplayer.key = "ssbF6k0i9BPe87xfG/s0ipdp5gwbLoZaDON/GQvuwPU9nVJy"; //Test Key - replace this with your own valid JWPlayer license key
        -        </script>
        -
        -        <script>
        -
        -            var pbjs = pbjs || {};
        -            pbjs.que = pbjs.que || [];
        -
        -            var googletag = googletag || {};
        -            googletag.cmd = googletag.cmd || [];
        -
        -            var PREBID_TIMEOUT = 1000;
        -
        -            var adUnits = [{
        -                code: 'video1',
        -                mediaTypes: {
        -                    video: {
        -                        playerSize: [640, 480],
        -                        context: 'outstream',
        -			mimes: ['video/mp4'],
        -			protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -			playbackmethod: [2],
        -			skip: 1
        -                    }
        -                },
        -                bids: [
        -                    {
        -                        bidder: 'appnexus',
        -                        params: {
        -                            placementId: 13232385
        -                        }
        -                    }
        -                ]
        -            }];
        -
        -            pbjs.que.push(function() {
        -                pbjs.addAdUnits(adUnits);
        -                pbjs.requestBids({
        -                    bidsBackHandler: initAdserver
        -                });
        -            });
        -
        -            function initAdserver() {
        -                if (pbjs.initAdserverSet) return;
        -                pbjs.initAdserverSet = true;
        -                googletag.cmd.push(function() {
        -                    pbjs.que.push(function() {
        -                        pbjs.setTargetingForGPTAsync();
        -                        googletag.pubads().refresh();
        -                    });
        -                });
        -            }
        -
        -            setTimeout(function() {
        -                initAdserver();
        -            }, PREBID_TIMEOUT);
        -
        -            googletag.cmd.push(function() {
        -                var slot1 = googletag.defineSlot('/19968336/prebid_outstream_adunit_1', [[1, 1]], 'video1').addService(googletag.pubads());
        -                googletag.pubads().disableInitialLoad();
        -                googletag.pubads().enableSingleRequest();
        -                googletag.enableServices();
        -            });
        -
        -        </script>
        -
        -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -	
        -	<div id='video1'>
        -		<p>Prebid Outstream Video Ad</p>
        -		<script type='text/javascript'>
        -			googletag.cmd.push(function() {
        -				googletag.display('video1');
        -			});
        -		</script>
        -	</div>  
        -
        -
        -
        - -
        -
        - - - - - - - - diff --git a/examples/video/server/brid/pbs-ve-brid.html b/examples/video/server/brid/pbs-ve-brid.html deleted file mode 100644 index 93b89d953b..0000000000 --- a/examples/video/server/brid/pbs-ve-brid.html +++ /dev/null @@ -1,185 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with Brid player -description: An example of a pre-roll ad using Prebid Server and Brid player. -videoType: pbs-br -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -
        -<script type="text/javascript" src="//services.brid.tv/player/build/brid.min.js"></script>
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -    Because we have no way of knowing when all the bids will be
        -    returned from Prebid we can't be sure that the browser will
        -    reach the point where `invokeVideoPlayer` is defined before
        -    `bidsBackHandler` fires and tries to call it.
        -
        -    To prevent an "`invokeVideoPlayer` not defined" error, we
        -    pre-define it before we make the call to Prebid, and redefine
        -    it later on with the code to create the player and play the
        -    ad.
        -
        -    In this first version, it simply stores the winning VAST to
        -    use later. */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    };
        -
        -    /* Prebid video ad unit */
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361 // Add your own placement id here
        - } - }] - }; - - pbjs.que.push(function() { - - // configure prebid to use prebid cache and prebid server   - // make sure to add your own accountId to your s2sConfig object
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - enableSendAllBids: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', - bidders: ['appnexus'] - } - }); - - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - console.log("got some bids"); - console.log(bids); - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="myDiv" class="brid" style="width:640px; height:360;"></div>
        -
        -<script type="text/javascript">
        -  invokeVideoPlayer = function(url) {
        -    $bp("myDiv", {"id":"17041","width":"640","height":"360","video":"400684",
        -    "Ad": [
        -            {
        -                "mobile": url, // Array of url's will get called in succession
        - "desktop": null, // Array of url's will get called in succession
        - "adType": "0", // Type 0 for pre roll
        - "adTimeType": "s", - "overlayStartAt": null, - "overlayDuration": null, - "cuepoints": null - } - ] - }); - } -</script> -
        -
        - -
        -
        - - - - - - diff --git a/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html b/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html deleted file mode 100644 index 62e4108e2e..0000000000 --- a/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html +++ /dev/null @@ -1,208 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with JW Player (Self-Hosted) -description: An example of a pre-roll ad using Prebid Server and JW Player (Hosted). -videoType: pbs-jw02 -isVideo: true -sidebarType: 4 ---- - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -	
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -<script type="text/javascript" src="https://ssl.p.jwpcdn.com/player/v/8.0.5/jwplayer.js"></script>
        -<script type="text/javascript">
        -    jwplayer.key = "YOUR_JW_PLAYER_KEY"; //Test Key - replace this with your own valid JWPlayer license key
        -</script> - -<script> - var pbjs = pbjs || {}; - pbjs.que = pbjs.que || []; - - /* PRE-DEFINE `invokeVideoPlayer` - - Because we have no way of knowing when all the bids will be - returned from Prebid we can't be sure that the browser will - reach the point where `invokeVideoPlayer` is defined before - `bidsBackHandler` fires and tries to call it. - - To prevent an "`invokeVideoPlayer` not defined" error, we - pre-define it before we make the call to Prebid, and redefine - it later on with the code to create the player and play the - ad. - - In this first version, it simply stores the winning VAST to - use later. */ - - var tempTag = false; - var invokeVideoPlayer = function(url) { - tempTag = url; - }; - - /* Prebid video ad unit */ - - var videoAdUnit = { - code: 'video1', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - mimes: ['video/mp4'], - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13232361 // Add your own placement id here
        - } - }] - }; - - pbjs.que.push(function() { - - // configure prebid to use prebid cache and prebid server
        - // make sure to add your own accountId to your s2sConfig object
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - enableSendAllBids: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', - bidders: ['appnexus'] - } - }); - - - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - console.log("got some bids"); - console.log(bids); - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="playerContainerJW" style='width:640px; height:480px; border:1px solid black;'></div>
        -
        -<script>
        -    var jwPlayerInstance = jwplayer("playerContainerJW");
        -
        -    invokeVideoPlayer = function(url) {
        -        console.log("starting player with url " + url);
        -        jwPlayerInstance.setup({
        -           
        -           "file": "https://vjs.zencdn.net/v/oceans.mp4",
        -            "width": 640,
        -            "height": 480,
        -            "autostart": true,
        -            "mute": true,
        -            "advertising": {
        -                client: "vast",
        -            }
        -        });
        -
        -        jwPlayerInstance.on('beforePlay', function() {
        -            jwPlayerInstance.playAd(url);
        -        })
        -    }
        -
        -    if (tempTag) {
        -        invokeVideoPlayer(tempTag);
        -        tempTag = false;
        -    }
        -
        -</script>
        -
        -
        -
        - -
        -
        - - - - - diff --git a/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html b/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html deleted file mode 100644 index f5a15deb27..0000000000 --- a/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html +++ /dev/null @@ -1,205 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with JW Player (Platform) -description: An example of a pre-roll ad using Prebid Server and JW Player (Platform). -videoType: pbs-jw01 -isVideo: true -sidebarType: 4 ---- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -      <script>
        -	    var pbjs = pbjs || {};
        -	    pbjs.que = pbjs.que || [];
        -	
        -	    /* PRE-DEFINE `invokeVideoPlayer`
        -	
        -	    Because we have no way of knowing when all the bids will be
        -	    returned from Prebid we can't be sure that the browser will
        -	    reach the point where `invokeVideoPlayer` is defined before
        -	    `bidsBackHandler` fires and tries to call it.
        -	
        -	    To prevent an "`invokeVideoPlayer` not defined" error, we
        -	    pre-define it before we make the call to Prebid, and redefine
        -	    it later on with the code to create the player and play the
        -	    ad.
        -	
        -	    In this first version, it simply stores the winning VAST to
        -	    use later. */
        -	
        -	    var tempTag = false;
        -	    var invokeVideoPlayer = function(url) {
        -	        tempTag = url;
        -	    };
        -	
        -	    var videoAdUnit = {
        -	        code: 'video1',
        -	        mediaTypes: {
        -	            video: {
        -			context: 'instream',
        -			playerSize: [640, 480],
        -			mimes: ['video/mp4'],
        -			protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -			playbackmethod: [2],
        -			skip: 1
        -	            }
        -	        },
        -	        bids: [{
        -	            bidder: 'appnexus',
        -	            params: {
        -	                placementId: 13232361  // Add your own placement id here.
        - } - }] - }; - - pbjs.que.push(function() { - - // configure prebid to use prebid cache and prebid server  - // make sure to add your own accountId to your s2sConfig object
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', - bidders: ['appnexus'] - } - }); - - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - - </script> -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<!-- This line loads a player without loading any video content -->
        -<!-- Replace this with the correct url for your player -->
        -<script src="YOUR_JW_URL"></script>
        -<script>
        -    // we initialize our player instance, specifying the div to load it into
        - var playerInstance = jwplayer('myElement1'); - - function invokeVideoPlayer(url) { - // this calls setup on the player we initialized  - // this will use the settings defined in the player we loaded above unless you override them here
        - playerInstance.setup({ - "file": "https://vjs.zencdn.net/v/oceans.mp4", - // or "file" could be replaced with "playlist" and a URL - // from your JW Platform account in either json or rss format. - "width": 640, - "height": 480, - "autostart": true, - "mute": true, - // we enable vast advertising for this player
        - "advertising": { - "client": "vast", - // url is the vast tag url that we passed in when we called invokeVideoPlayer in the header
        - "tag": url - } - }); - } - - if (tempTag) { - invokeVideoPlayer(tempTag); - tempTag = false; - } - -</script> - -
        -
        - -
        -
        - - - - - - - - diff --git a/examples/video/server/kaltura/pbs-ve-kaltura.html b/examples/video/server/kaltura/pbs-ve-kaltura.html deleted file mode 100644 index 5bf385058e..0000000000 --- a/examples/video/server/kaltura/pbs-ve-kaltura.html +++ /dev/null @@ -1,303 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with Kaltura -description: An example of a pre-roll ad using Prebid Server and Kaltura. -videoType: pbs-kl -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -	
        -		
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -    Because we have no way of knowing when all the bids will be
        -    returned from Prebid we can't be sure that the browser will
        -    reach the point where `invokeVideoPlayer` is defined before
        -    `bidsBackHandler` fires and tries to call it.
        -
        -    To prevent an "`invokeVideoPlayer` not defined" error, we
        -    pre-define it before we make the call to Prebid, and redefine
        -    it later on with the code to create the player and play the
        -    ad.
        -
        -    In this first version, it simply stores the winning VAST to
        -    use later. */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    };
        -
        -    /* Prebid video ad unit */
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361  // Add your own placement id here.
        - } - }] - }; - - pbjs.que.push(function() { - - // configure prebid to use prebid cache and prebid server   - // make sure to add your own accountId to your s2sConfig object
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', - bidders: ['appnexus'] - } - }); - - pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id="myPlayer" style="width:640px; height:480px;"></div>
        -
        -<!-- INCLUDE KALTURA PLAYER SCRIPT
        -
        - Add the script for your Kaltura player. This will be part of
        - the code you will copy-paste from Kaltura. -->
        -
        -<script src="https://cdnapi.kaltura.com/p/2222001/sp/222200100/embedIframeJs/uiconf_id/37440401/partner_id/2222001"></script>
        -
        -<script>
        -    invokeVideoPlayer = function(url) {
        -
        -        /* EMBED KALTURA PLAYER
        -
        -        Call `kWidget.embed()` and pass in a JSON object of your
        -        player settings. Most of this JSON object will be part of
        -        the code you will copy paste from Kaltura.
        -
        -        Documentation for kWidget available here:
        -        https://player.kaltura.com/docs/kwidget */
        -
        -        kWidget.embed({
        -            "targetId": "myPlayer",
        -            "wid": "_2222001",
        -            "uiconf_id": 37440401,
        -
        -            /* ADD VAST SETTINGS TO THE PLAYER SETTINGS
        -
        -            Inside `flashVars`, add another key called `"vast"` and
        -            pass in a JSON object with:
        -
        -            - the position where you want your ad to play
        -
        -            - the URL of the ad (which in this case will be the `url`
        -            we got back from Prebid) */
        -
        -            "flashvars": {
        -                "streamerType": "auto",
        -                "vast": {
        -                    "plugin": true,
        -                    "prerollUrl": url,
        -                }
        -            },
        -            "entry_id": "1_k4eka7er",
        -
        -            /* ADD A READY CALLBACK AND GET A REFERENCE TO THE PLAYER
        -
        -            Add a ready callback to the player settings. This allows
        -            us to get a reference to the player (stored in the
        -            variable `kdp`) in order to interact with it later. */
        -
        -            readyCallback: function(playerId) {
        -                console.log("Kaltura player " + playerId + " is ready.");
        -            }
        -        });
        -    };
        -
        -    /* ACCOUNT FOR PAGE SPEED
        -
        -    If Prebid returned bids before the browser reached the end of
        -    the page, the first version of `invokeVideoPlayer` will have
        -    been called from `bidsBackHandler` so the winning VAST tag
        -    will be stored in the `tempTag` variable.
        -
        -    If that's the case, we want to call the 'real' version of
        -    `invokeVideoPlayer` with the stored URL to create the player
        -    and play the ad.
        -
        -    If `tempTag` is not defined, that means the browser reached
        -    the end of the page before the bids came back from Prebid,
        -    meaning the 'real' version of `invokeVideoPlayer` was already
        -    called. */
        -
        -    if (tempTag) {
        -        invokeVideoPlayer(tempTag);
        -        tempTag = false;
        -    }
        -
        -</script>
        -
        -
        -
        - -
        -
        - - - - - - - - - - - diff --git a/examples/video/server/ooyala/pbs-ve-ooyala.html b/examples/video/server/ooyala/pbs-ve-ooyala.html deleted file mode 100644 index 6bbe7c407e..0000000000 --- a/examples/video/server/ooyala/pbs-ve-ooyala.html +++ /dev/null @@ -1,372 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with Ooyala -description: An example of a pre-roll ad using Prebid Server and Ooyala. -videoType: pbs-oy -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -	
        -	
        -<!-- LOAD OOYALA PLUGINS
        -
        - Load the Ooyala player scripts you plan to use.
        -
        - You must load the core player script, the scripts for
        - whatever video formats you want to support, and the scripts
        - for the ad manager you want to use.
        -
        - The scripts themselves and a guide for choosing which ones
        - you need can be found here:
        -
        - https://help.ooyala.com/video-platform/documentation/concepts/pbv4_plugins.html
        --->
        -
        -<!-- CORE PLAYER REQUIRED -->
        -<script src="//player.ooyala.com/static/v4/production/latest/core.min.js"></script>
        -
        -<!-- VIDEO PLUGINS -->
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/main_html5.min.js"></script>
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/bit_wrapper.min.js"></script>
        -<script src="//player.ooyala.com/static/v4/production/latest/video-plugin/osmf_flash.min.js"></script>
        -
        -<!-- HTML5 SKIN -->
        -<script src="//player.ooyala.com/static/v4/production/latest/skin-plugin/html5-skin.min.js"></script>
        -
        -<!-- SKIN ASSET -->
        -<link rel="stylesheet" href="//player.ooyala.com/static/v4/production/latest/skin-plugin/html5-skin.min.css" />
        -
        -<!-- IMA PLUGIN -->
        -<script src="//player.ooyala.com/static/v4/production/latest/ad-plugin/google_ima.js"></script>
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -    Because we have no way of knowing when all the bids will be
        -    returned from Prebid we can't be sure that the browser will
        -    reach the point where `invokeVideoPlayer` is defined before
        -    `bidsBackHandler` fires and tries to call it.
        -
        -    To prevent an "`invokeVideoPlayer` not defined" error, we
        -    pre-define it before we make the call to Prebid, and redefine
        -    it later on with the code to create the player and play the
        -    ad.
        -
        -    In this first version, it simply stores the winning VAST to
        -    use later. */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    };
        -
        -    /* Prebid video ad unit */
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361  // Add your own placement id here.
        - } - }] - }; - - pbjs.que.push(function() { - - // configure prebid to use prebid cache and prebid server   - // make sure to add your own accountId to your s2sConfig object
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', // replace this with your account id
        - bidders: ['appnexus'] - } - }); - - // add your ad units to the bid request
        - pbjs.addAdUnits(videoAdUnit); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - console.log(bids); - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div id='container' style='width:640px;height:480px;'></div>
        -
        -<script>
        -    var invokeVideoPlayer = function(url) {
        -        console.log("invoking video player with url " + url);
        -
        -        /* DEFINE PLAYER SETTINGS
        -
        -        Define the settings you want for your player in a JSON
        -        object. These lines will be part of the embed code you
        -        copy-paste from Ooyala Backlot, we just need to add the ad
        -        parameters.  */
        -
        -        var playerParam = {
        -            'pcode': 'lsbWkyOjtI6LOjmlqk2o5I-TsWRA',
        -            'playerBrandingId': '45b8294c6ad14265b2b47586c911cb07',
        -            'debug': true,
        -            'autoplay': true,
        -            'initialVolume': 0.0,
        -            'skin': {
        -                'config': '//player.ooyala.com/static/v4/stable/4.6.9/skin-plugin/skin.json',
        -                'inline': {
        -                    'adScreen': {
        -                        'showAdMarquee': true,
        -                        'showAdCountDown': true,
        -                        'showControlBar': true,
        -                        'useGoogleAdUI': true
        -                    }
        -                }
        -            },
        -
        -            /* ADD THE AD PARAMETERS TO THE PLAYER SETTINGS
        -
        -            Create a new JSON object in the player parameters. The key
        -            should be the ad manager you're using (in our case we're
        -            using the Google IMA ads manager, so the key is
        -            `"google-ima-ads-manager"`). The IMA ads manager requires
        -            an ad set (which we've named `"all_ads"`).
        -
        -            For more information see the Ooyala docs:
        -
        -            https://help.ooyala.com/video-platform/concepts/pbv4_ads_dev_google_ima.html:
        -
        -            Make sure the ad parameters are properly formatted JSON.
        -            */
        -            "google-ima-ads-manager": {
        -                "all_ads": [{
        -                    "position": "0",
        -                    "position_type": "t",
        -                    "tag_url": url
        -                }],
        -                'showAdControls': true
        -            }
        -        };
        -
        -        /* INITIALIZE THE PLAYER
        -
        -        Use the `OO.ready()` event to make sure that all the
        -        necessary Ooyala plugins have loaded before attempting to
        -        create the player. Once it has, call `create()` and pass
        -        in:
        -
        -        - the div you're creating the player in
        -
        -        - the ID of the content video
        -
        -        - the player settings we created above */
        -
        -        OO.ready(function() {
        -            console.log("OO is ready, invoking");
        -            console.dir(playerParam);
        -            window.pp = OO.Player.create('container', 'ltcG54NzE6Bxk08Mqs1_KMcQZDN7lH8N', playerParam);
        -        });
        -    };
        -
        -    /* ACCOUNT FOR PAGE SPEED
        -
        -    If Prebid returned bids before the browser reached the end of
        -    the page, the first version of `invokeVideoPlayer` will have
        -    been called from `bidsBackHandler`, so the winning VAST tag will
        -    be stored in `tempTag`.
        -
        -    If that's the case, we want to call the "real" version of
        -    `invokeVideoPlayer` with the stored URL to create the player and
        -    play the ad.
        -
        -    If `tempTag` is not defined, that means the browser reached the
        -    end of the page before the bids came back from Prebid, meaning
        -    the "real" version of `invokeVideoPlayer` was already called.
        -    */
        -
        -    if (tempTag) {
        -        invokeVideoPlayer(tempTag);
        -        tempTag = false;
        -    }
        -
        -</script>
        -
        -
        -
        - -
        -
        - - - - - - - - diff --git a/examples/video/server/radiant/pbs-ve-radiant.html b/examples/video/server/radiant/pbs-ve-radiant.html deleted file mode 100644 index d64d43b0ec..0000000000 --- a/examples/video/server/radiant/pbs-ve-radiant.html +++ /dev/null @@ -1,344 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with Radiant Media Player -description: An example of an instream pre-roll ad using Prebid Server and Radiant Media Player . -videoType: pbs-rd -isVideo: true -sidebarType: 4 ---- - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        - -
        
        -
        -<!--production version of prebid.js-->
        -<script async src="//acdn.adnxs.com/prebid/not-for-prod/prebid.js"></script>
        -
        -<!-- Radiant Media Player core library - debug browser console mode (use rmp.min.js for production) -->
        -<script src="https://cdn.radiantmediatechs.com/rmp/5.5.6/js/rmp.debug.js"></script>
        -
        -
        - - - -
        -

        Place this code in the page body.

        -
        -
        -/* our app where we run player
        -   our app variables */
        -var pbApp = {};
        -pbApp.playerSetup = false;
        -pbApp.prebidTempTag = false;
        -pbApp.debug = true;
        -/* in case pre-bidding takes too long or fails we provide a playerSetupTimeout and fallbackAdTagUrl
        -   to insure player setup happens - this is optional */
        -pbApp.playerSetupTimeout = 5000;
        -pbApp.fallbackAdTagUrl = 'https://www.radiantmediaplayer.com/vast/tags/inline-linear-1.xml';
        -/* no console - no logs */
        -if (typeof window.console === 'undefined' || typeof window.console.log === 'undefined' || typeof window.console.dir === 'undefined') {
        -  pbApp.debug = false;
        -}
        -
        -/* invokeVideoPlayer may not be defined when bidsBackHandler runs
        -   we pre-defined it here so as to capture the returned adTagUrl to be passed to the player */
        -pbApp.invokeVideoPlayer = function (adTagUrl) {
        -  pbApp.prebidTempTag = adTagUrl;
        -};
        -
        -/* prebid.js variables */
        -var pbjs;
        -pbjs = pbjs || {};
        -pbjs.que = pbjs.que || [];
        -
        -/* Prebid video ad unit
        -   This is a working example but you must use your own settings/bidders for production
        -   More docs at https://prebid.org/prebid-video/video-overview.html */
        -var videoAdUnit = {
        -  code: 'video1',
        -  mediaTypes: {
        -    video: {
        -	context: 'instream',
        -	playerSize: [640, 480],
        -	mimes: ['video/mp4'],
        -	protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -	playbackmethod: [2],
        -	skip: 1
        -    }
        -  },
        -  bids: [{
        -    bidder: 'appnexus',
        -    params: {
        -      placementId: 13232361  // Add your own placement id here.
        -    }
        -  }]
        -};
        -
        -pbjs.que.push(function () {
        -  // configure prebid to use prebid cache and prebid server
        -  // make sure to add your own accountId to your s2sConfig object
        -  pbjs.setConfig({
        -    cache: {
        -      url: 'https://prebid.adnxs.com/pbc/v1/cache'
        -    },
        -    debug: true,
        -    enableSendAllBids: true,
        -    s2sConfig: {
        -      endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction',
        -      enabled: true,
        -      accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e',
        -      bidders: ['appnexus']
        -    }
        -  });
        -
        -  pbjs.addAdUnits(videoAdUnit); // add your ad units to the bid request
        -
        -  pbjs.requestBids({
        -    bidsBackHandler: function (bids) {
        -      if (pbApp.debug) {
        -        window.console.dir(bids);
        -      }
        -      var videoUrl = pbjs.adServers.dfp.buildVideoUrl({
        -        adUnit: videoAdUnit,
        -        params: {
        -          iu: '/19968336/prebid_cache_video_adunit',
        -          cust_params: {
        -            section: 'blog',
        -            anotherKey: 'anotherValue'
        -          },
        -          output: 'vast'
        -        }
        -      });
        -      pbApp.invokeVideoPlayer(videoUrl);
        -    }
        -  });
        -});
        -
        -/* here we re-define invokeVideoPlayer with Radiant Media Player set-up */
        -pbApp.invokeVideoPlayer = function (adTagUrl) {
        -  if (pbApp.playerSetup) {
        -    return;
        -  }
        -  pbApp.playerSetup = true;
        -  if (pbApp.debug) {
        -    window.console.log('invokeVideoPlayer with Prebid VAST url = ' + adTagUrl);
        -  }
        -  var src = {
        -    mp4: [
        -      'https://www.rmp-streaming.com/media/bbb-360p.mp4'
        -    ]
        -  };
        -  var settings = {
        -    licenseKey: 'Kl8lZ292K3N6MmVvZD9yb201ZGFzaXMzMGRiMEElXyo=',
        -    src: src,
        -    width: 640,
        -    height: 360,
        -    //*we enabled ads for our player
        -    note that we requested a winning bid for skippable auto_play_sound_off so player starts muted autoplay*/
        -    ads: true,
        -    autoplay: true,
        -    muted: true,
        -    // we use Google IMA in this demo, but you can use rmp-vast as well depending on your requirements
        - adParser: 'ima', - // since we may request a skippable ads we set adDisableCustomPlaybackForIOS10Plus: true to allow rendering of skippable ads on iOS
        - adDisableCustomPlaybackForIOS10Plus: true, - // here is our winner VAST adTagUrl
        - adTagUrl: adTagUrl, - poster: 'https://www.radiantmediaplayer.com/images/poster-rmp-showcase.jpg' - }; - var elementID = 'rmpPlayer'; - var rmp = new RadiantMP(elementID); - rmp.init(settings); - -}; - -/* in case we already have a winning bid let's use the returned adTagUrl to run player */ -if (pbApp.prebidTempTag) { - pbApp.invokeVideoPlayer(pbApp.prebidTempTag); - pbApp.prebidTempTag = false; -} - -/* in case something went wrong (latency, network errors, bid issues ...) and we have no winning bid we still need to run the player - this is done after pbApp.playerSetupTimeout ms and we use fallbackAdTagUrl as adTagUrl to pass to the player */ -setTimeout(function () { - if (pbApp.playerSetup) { - return; - } - pbApp.invokeVideoPlayer(pbApp.fallbackAdTagUrl); -}, pbApp.playerSetupTimeout); -
        -
        - -
        -
        - - - - diff --git a/examples/video/server/videojs/pbs-ve-videojs.html b/examples/video/server/videojs/pbs-ve-videojs.html deleted file mode 100644 index cb3172c5eb..0000000000 --- a/examples/video/server/videojs/pbs-ve-videojs.html +++ /dev/null @@ -1,286 +0,0 @@ ---- -layout: video_sample -title: Prebid Video | Prebid Server Example with VideoJS -description: An example of a pre-roll ad using Prebid Server and VideoJS. -videoType: pbs-vjs -isVideo: true -sidebarType: 4 ---- - - - -
        -
        -
        -

        {{ page.title }}

        -

        {{page.description }}

        -
        - - -
        -

        Important: - This example uses a test version of Prebid.js hosted on our CDN that is not recommended for production use. It includes all available adapters. Production implementations should build from source or customize the build using the Download page to make sure only the necessary bidder adapters are included.

        -
        - - -
        - -
        - - - - - -
        -

        Warning: - Do not forget to exchange the placementId in the code examples with your own placementId!

        -
        - -
        -

        Place this code in the page header.

        -
        -
        -<!-- videojs -->
        -<!-- use recent version of videojs to ensure proper functioning with the iOS devices -->
        -<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video-js.css">
        -<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.4.0/video.js"></script>
        -<!-- videojs-vast-vpaid -->
        -<link href="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs.vast.vpaid.min.css" rel="stylesheet">
        -<script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-vast-vpaid/2.0.2/videojs_5.vast.vpaid.min.js"></script>
        -
        -<script>
        -    var pbjs = pbjs || {};
        -    pbjs.que = pbjs.que || [];
        -
        -    /* PRE-DEFINE `invokeVideoPlayer`
        -
        -    Because we have no way of knowing when all the bids will be
        -    returned from Prebid we can't be sure that the browser will
        -    reach the point where `invokeVideoPlayer` is defined before
        -    `bidsBackHandler` fires and tries to call it.
        -
        -    To prevent an "`invokeVideoPlayer` not defined" error, we
        -    pre-define it before we make the call to Prebid, and redefine
        -    it later on with the code to create the player and play the
        -    ad.
        -
        -    In this first version, it simply stores the winning VAST to
        -    use later. */
        -
        -    var tempTag = false;
        -    var invokeVideoPlayer = function(url) {
        -        tempTag = url;
        -    };
        -
        -    /* Prebid video ad unit */
        -
        -    var videoAdUnit = {
        -        code: 'video1',
        -        mediaTypes: {
        -            video: {
        -                context: 'instream',
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        -                protocols: [1, 2, 3, 4, 5, 6, 7, 8],
        -                playbackmethod: [2],
        -                skip: 1
        -            }
        -        },
        -        bids: [{
        -            bidder: 'appnexus',
        -            params: {
        -                placementId: 13232361  // Add your own placement id here.
        -            }
        -        }]
        -    };
        -
        -    pbjs.que.push(function() {
        -
        -        // configure prebid to use prebid cache and prebid server  
        -        // make sure to add your own accountId to your s2sConfig object 
        - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - }, - debug: true, - s2sConfig: { - endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction', - enabled: true, - accountId: 'c9d412ee-3cc6-4b66-9326-9f49d528f13e', // replace this with your account id
        - bidders: ['appnexus'] - } - }); - - // add your ad units to the bid request
        - pbjs.addAdUnits(videoAdUnit); - - pbjs.requestBids({ - bidsBackHandler: function(bids) { - var videoUrl = pbjs.adServers.dfp.buildVideoUrl({ - adUnit: videoAdUnit, - params: { - iu: '/19968336/prebid_cache_video_adunit', - cust_params: { - section: 'blog', - anotherKey: 'anotherValue' - }, - output: 'vast' - } - }); - invokeVideoPlayer(videoUrl); - } - }); - }); - -</script> - -
        - - -
        - - -
        -

        Place this code in the page body.

        -
        -
        -<div class="example-video-container">
        -    <video id="vid1" class="video-js vjs-default-skin vjs-big-play-centered" controls data-setup='{}' width='640' height='480'>
        -        <source src="https://vjs.zencdn.net/v/oceans.mp4" type='video/mp4'/>
        -        <source src="https://vjs.zencdn.net/v/oceans.webm" type='video/webm'/>
        -        <source src="https://vjs.zencdn.net/v/oceans.ogv" type='video/ogg'/>
        -    </video>
        -</div>
        -
        -<script>
        -    var page_load_time;
        -
        -    page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -    console.log(page_load_time + "ms -- Player loading!");
        -
        -    var vid1 = videojs('vid1');
        -
        -    page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -    console.log(page_load_time + "ms -- Player loaded!");
        -
        -    function invokeVideoPlayer(url) {
        -
        -        page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -        console.log(page_load_time + "ms -- Prebid VAST url = " + url);
        -
        -        /* Access the player instance by calling `videojs()` and passing
        -         in the player's ID. Add a `ready` listener to make sure the
        -         player is ready before interacting with it. */
        -
        -        videojs("vid1").ready(function() {
        -
        -            page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -            console.log(page_load_time + "ms -- Player is ready!");
        -
        -            /* PASS SETTINGS TO VAST PLUGIN
        -
        -            Pass in a JSON object to the player's `vastClient` (defined
        -            by the VAST/VPAID plugin we're using). The requires an
        -            `adTagUrl`, which will be the URL returned by Prebid. You
        -            can view all the options available for the `vastClient`
        -            here:
        -
        -            https://github.com/MailOnline/videojs-vast-vpaid#options */
        -
        -            var player = this;
        -            var vastAd = player.vastClient({
        -                adTagUrl: url,
        -                prerollTimeout: 500,
        -                playAdAlways: true,
        -                verbosity: 4,
        -                vpaidFlashLoaderPath: "https://github.com/MailOnline/videojs-vast-vpaid/blob/RELEASE/bin/VPAIDFlash.swf?raw=true",
        -                autoplay: true
        -            });
        -
        -            page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -            console.log(page_load_time + "ms -- Prebid VAST tag inserted!");
        -
        -            player.muted(true);
        -            player.play();
        -
        -            page_load_time = new Date().getTime() - performance.timing.navigationStart;
        -            console.log(page_load_time + "ms -- invokeVideoPlayer complete!");
        -
        -        });
        -    }
        -
        -</script>
        -
        -
        - -
        -
        - - - - - - - - diff --git a/faq/faq.md b/faq/faq.md index de57ee611b..0b47d9cc56 100644 --- a/faq/faq.md +++ b/faq/faq.md @@ -6,23 +6,30 @@ sidebarType: 7 --- # Frequently Asked Questions + {:.no_toc} Everyone has questions. We have answers - at least to some of the most frequently asked questions. -## [Prebid.js](/dev-docs/faq.html) +## Prebid.js Check out the [Prebid.js FAQ](/dev-docs/faq.html). If you don't find what you need there, here are some additional resources: - [Troubleshooting](/troubleshooting/troubleshooting.html) - [About Prebid.js](/prebid/prebidjs.html) -- [Training Videos](/videos/index.html) -- [Resources](/support/index.html) +- [Support Resources](/support/index.html) -## [Prebid Server](/faq/prebid-server-faq.html) +## Prebid Server If you don't find answers to your questions in the [Prebid Server FAQ](/faq/prebid-server-faq.html), you can learn more here: - [Troubleshooting](/troubleshooting/troubleshooting.html) - [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) -- [Resources](/support/index.html) +- [Support Resources](/support/index.html) + +## Prebid Mobile SDK + +Please see the [Prebid Mobile FAQ](/faq/prebid-mobile-faq.html). You can learn more at: + +- [Prebid Mobile home page](/prebid-mobile/prebid-mobile.html) +- [Support Resources](/support/index.html) diff --git a/faq/prebid-mobile-faq.md b/faq/prebid-mobile-faq.md new file mode 100644 index 0000000000..95e6a33d77 --- /dev/null +++ b/faq/prebid-mobile-faq.md @@ -0,0 +1,230 @@ +--- +layout: page_v2 +title: Prebid Mobile FAQ | Prebid +description: Prebid Mobile FAQ +sidebarType: 2 +--- + +# Prebid Mobile FAQ + +{:.no_toc} + +This page has answers to some frequently asked questions about Prebid Mobile. If you don't find what you're looking for here, there are other ways to [get help](/support/index.html). + +- TOC +{:toc} + +## General + +### What size is the SDK? + +Compiled sizes: + +- Android: 800 KB +- iOS: 3.2 Mb + +Note: these sizes will go down as several assets will be pulled out into a CDN over the coming months. + +### Does the SDK have UI components? If so, are they localized? + +The Prebid SDK has no localized UI components. + +Most probably you will use an integration approach that doesn’t utilize UI component at all, as they are used only with the Rendering API. + +### Is the SDK compressed using any compression tools? + +No. + +### Is the SDK encrypted or obfuscated in any way? + +No. + +### Is the SDK synchronous? + +Prebid SDK is always async. The completion handler for the main fetchDemand() method is called asynchronously when the bid response (or timeout, network error, etc.) is received. The app defines the desired timeout. + +### How long do bids remain valid? + +Prebid SDK does not support a [limited bid cache](/dev-docs/faq.html#does-prebidjs-cache-bids) like Prebid.js does. Which means it's up to the app to build any kind of pre-fetch or bid-cache feature. Notes: + +1. If Prebid Cache is being utilized, the Time-To-Live for that cache should be understood. By default, the TTL for Prebid Cache is 5 minutes for banners and 15 minutes for video, but this can be changed. +2. No matter what the Cache TTL is set to, it's important that any pre-fetch or bid-cache feature built into the app should respect the OpenRTB `seatbid.bid.exp` field for each bid, which is the expiration of the bid in seconds. + +### Does Prebid SDK support integration into the Unity SDK? + +Prebid does not support Unity directly and no one in the community has recent experience with it. We believe that it may be possible to call for bids using the [custom bidding integration(/prebid-mobile/modules/rendering/ios-sdk-integration-pb.html) approach. + +Contributions from the community (whether code or documentation) would be welcome. + +## Dependencies + +### Does the SDK use third-party libraries? + +Prebid Mobile SDK is bundled with the Open Measurement (OM) SDK. If you will be using Prebid Mobile SDK to render ads, then the Open Measurement signals are available and are passed in the ad request. If you are using different SDK (e.g. GAM) to render ads, then the OM signals should be checked with the respective SDK (e.g. if there is OM SDK dependency there). + +### Is Prebid Certified for the Open Measurement SDK? + +No, the Prebid SDK is currently not certified with the IAB. The open-source nature of the Prebid SDK means that app developers can modify the code, which means that publishers requiring certification need to reach out to the IAB and get their particular implementation of the Prebid + OM SDK dependency certified. + +Advertisers can leverage 3rd party vendors of their choice when measuring viewability using OM SDK. Majority of the vendors are providing viewability scores for all types of the OM SDK integrations allowing advertisers to independently measure viewability across any publisher independently of their certifications. The only known exception currently is MOAT. This vendor is known to nullify the viewability scores if the integration is not certified. In this case, publishers can directly reach out to the IAB and get their own version of the Prebid SDK integration with OM SDK dependency certified. + +More details available at: + +- [IAB OM SDK](https://iabtechlab.com/standards/open-measurement-sdk/) +- [Prebid iOS OM SDK](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html#open-measurement-sdk-omsdk-api) +- [Prebid Android OM SDK](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html#open-measurement-sdk-omsdk-api) + +### Does it have external dependencies? + +No. + +### Does it use open-source libraries? If so, which licenses are used? + +No. The Prebid SDK is itself a library open sourced under the Apache 2 license. + +### Are there any back-end dependencies to this SDK? + +Yes - the app developer must have a [Prebid Server](/prebid-server/overview/prebid-server-overview.html) at their disposal. This is open source software that they may run themselves, or they may contract with a [Managed Service](https://prebid.org/product-suite/managed-services/). + +## Communication + +### Does the SDK make network requests and how often and how heavy? + +Yes. Its main job is to formulate requests to [Prebid Server](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html) to obtain bids for ad units. + +The frequency of HTTPS network calls is up to the app developer. It depends on whether and how frequently ad units are refreshed. The payload size will depend on how many ad units are present in the app and what kind of consent strings are present. For one ad unit, the size should be under 2KB, with each ad unit adding a couple hundred bytes. + +## Maintenance + +### How often is the SDK updated? + +It varies, but on average, it's updated about once per month. + +The open source repos have a list of releases: + +- +- + +### How does one update the Prebid Mobile version? + +The best way is to integrate SDK via dependency managers - CocoaPods (iOS) and Maven (Android). You can specify the particular version or point the dependency manager to the latest SDK version. In the second case, the new version of SDK will be added to the app as soon as released. + +### If a bug is found in the SDK, what is the process for reporting it? + +Please open a github issue: + +- +- + +### Is there a support forum where we can monitor issues and resolutions? + +Yes, you may monitor github issues and pull requests at the repositories noted above. + +### Are there debug/logging options that can be toggled on/off? + +Yes. + +1. You can change app console log verbose level via PrebiMobile.shared.logLevel +2. You can set the OpenRtb 'test' flag for Prebid Server to return additional server-side information. See 'debug' in and + +## Privacy/Security + +### Does the SDK store any data locally on the device? If so, what is it? + +If the developer calls certain functions, the SDK will store the results for future auctions. See the "Local Storage" section of + + +In all other cases SDK plays a transport role. It collects information from API (if it’s allowed by privacy settings) and sends it in the bid requests to the server. SDK uses the following datasources: + +- TCF API - SDK reads data from UserDefaults +- Configuration / Targeting API - publishers provide data to SDK in runtime +- Device API - SDK collects device info using public OS API, like user agent, OS version, location + +### Does the SDK send any Personal Information over the network? + +The Prebid SDK sends information provided by the publisher using the Targeting API. We recommend that publishers avoid targeting to personal information unless reviewed by their own legal teams. + +The SDK will send IP address and device latitude/longitude information. Prebid Server will anonymize requests as required by regulations, including GDPR, COPPA, CCPA. See the [Prebid Server privacy features](/prebid-server/features/pbs-privacy.html) for more details. + +### Is the SDK GDPR compliant? + +Yes - the SDK will forward TCF consent strings to Prebid Server where requests may be anonymized or restricted. It is up to the entity hosting Prebid Server to configure the server properly. + +Also note that Prebid.org is committed to other privacy initiatives such as the IAB's Global Privacy Platform, including US National Privacy and TCF-Canada. + +### How does the SDK allow for deletion of user private data? + +SDK does’t commit any action on managing user data. Only publishers using SDK’s API can provide/store/remove user data. + +### Does SDK Provide an Apple Privacy Manifest? + +No, because the Prebid SDK is an open-source SDK, that doesn't have a single domain to send bid requests. + +However, here is the list of items that the app developer can add to the application's privacy manifest to cover Prebid SDK activity and data consumption: + +- `NSPrivacyTracking` - true. Because Prebid SDK collects IDFA. +- `NSPrivacyTrackingDomains` - the tracking domain for the PBS. + +Pay attention - if `NSPrivacyTracking` is true, the tracking domain is provided, and the user doesn't allow the app to track him or her, iOS will block the bid requests. Prebid SDK doesn't support tracking and non-tracking endpoints yet. Follow the [issue](https://github.com/prebid/prebid-mobile-ios/issues/954) for the details. + +- `NSPrivacyCollectedDataTypes` array should contain the following `NSPrivacyCollectedDataType` items: `NSPrivacyCollectedDataTypePreciseLocation`, `NSPrivacyCollectedDataTypeCoarseLocation`,`NSPrivacyCollectedDataTypeDeviceID`, `NSPrivacyCollectedDataTypeProductInteraction`, `NSPrivacyCollectedDataTypeAdvertisingData`. + +The values for `NSPrivacyCollectedDataTypeLinked` and `NSPrivacyCollectedDataTypeTracking` in each entry depend on your demand partners, you should consult with them to provide proper info. Neither SDK nor Server uses these data for tracking or linking. + +The `NSPrivacyCollectedDataTypePurposes` array should contain `NSPrivacyCollectedDataTypePurposeThirdPartyAdvertising` and/or other purposes your demand partners require. + +- `NSPrivacyAccessedAPITypes` array should contain the `NSPrivacyAccessedAPICategoryUserDefaults` item. The `NSPrivacyAccessedAPITypeReasons` for this item should contain `CA92.1` value. + +## Performance + +### Does the SDK do any work in the background? If so, what is it? + +The SDK will receive responses from Prebid Server in the background and call the application-defined callbacks. + +The developer may set up auto-refresh for ad units. If in the background, Prebid SDK will not perform bid requests. + +### Has power usage related to this SDK been tested? + +No. We'd welcome any community member to help us with requirements, code, and/or results. + +### How long does it take to initialize? + +Is not measured, but very fast. Because it makes only initialization of internal classes and optional health check calls to PBS. The result of the health check call does not influence the SDK behavior, so publishers may not wait for its result during the initialization. + +## API Questions + +### What is the difference between Original API and Rendering API? + +The main difference is that with Original API, the Prebid demand is rendered by the Ad Server SDK (Google Mobile Ads SDK) using Prebid Universal Creative. But with Rendering API, Prebid SDK renders the winning bid in its own Web or Video views. + +## iOS Specifics + +### Does the SDK support Swift 3+? + +Yes. Prebid SDK is developed with latest Xcode version. + +### Does it ship as a CocoaPod? + +Yes - + +### Is it bit code enabled? + +Starting with 2.1.0: No + +### Does it support 64-bit? + +Yes. + +## Android Specifics + +### What are the targeted APIs? + +Android API 32. + +### Does it include Broadcast Receivers in the Manifest? + +No. + +## Further Reading + +- [Prebid Mobile home page](/prebid-mobile/prebid-mobile.html) diff --git a/faq/prebid-server-faq.md b/faq/prebid-server-faq.md index 8ae4ce15de..26d7946c36 100644 --- a/faq/prebid-server-faq.md +++ b/faq/prebid-server-faq.md @@ -10,7 +10,7 @@ sidebarType: 5 This page has answers to some frequently asked questions about Prebid Server. If you don't find what you're looking for here, there are other ways to [get help](/support/index.html). -* TOC +- TOC {:toc} ## Do we need to be a member of Prebid.org to submit a bidder adapter? @@ -25,17 +25,19 @@ but it's not necessary for contributing code as a community member. ## How can I debug Prebid Server requests? -+ When invoking Prebid Server through Prebid.js, this can be done just by adding `?pbjs_debug=true` to the page URL. -+ Through AMP, you can put `test: 1` in the stored request, or add `debug=1` to the query string of Prebid Server's AMP endpoint. -+ If calling directly, add `test: 1` to the JSON. +- When invoking Prebid Server through Prebid.js, this can be done just by adding `?pbjs_debug=true` to the page URL. +- Through AMP, you can put `ext.prebid.debug: true` in the stored request, or add `debug=1` to the query string of Prebid Server's AMP endpoint. +- If calling directly, add `ext.prebid.debug: true` to the JSON. + +The OpenRTB `test:1` flag will also turn on debugging, and for true test requests, is the most appropriate thing to do, depending on your scenario. SSPs may not respond or log `test` requests. ## Why are there two versions of Prebid Server? Are they kept in sync? The original version of Prebid Server was the Go-Lang version. Rubicon Project ported it to Java because they had more Java talent than Go. -+ [Prebid Server - Go](https://github.com/prebid/prebid-server) -+ [Prebid Server - Java](https://github.com/prebid/prebid-server-java) +- [Prebid Server - Go](https://github.com/prebid/prebid-server) +- [Prebid Server - Java](https://github.com/prebid/prebid-server-java) Both versions are live in production, and they are kept identical in external APIs and reasonably close in functionality. See the [Prebid Server feature list](/prebid-server/features/pbs-feature-idx.html) for the list of differences. @@ -43,6 +45,7 @@ and reasonably close in functionality. See the [Prebid Server feature list](/pre For demand partners, we recommend building new bid adapters in Go - the team will port it to Java for you within a couple of months. For those looking to host a Prebid Server: + - If you plan to use long-form video, we recommend the Go version of the server. - Look over the features and see if there's any important to you. - Otherwise, just choose the language you're most comfortable with. @@ -55,10 +58,10 @@ Just schedule a [post-bid creative]({{site.baseurl}}/dev-docs/examples/postbid.h 1. Set up the AdUnit 1. Set the app and device objects with setConfig(). e.g. -``` +```javascript pbjs.setConfig({ s2sConfig: { - ... + // ... }, app: { bundle: "com.test.app" @@ -68,6 +71,7 @@ pbjs.setConfig({ } }); ``` + ## How do user ID cookies and ID syncing work in Prebid Server? For Prebid SDK there's no concept of cookies, so no syncing takes place in that scenario. ID in mobile is based on IDFA. @@ -83,7 +87,7 @@ See the [Prebid Server Privacy Feature Page](/prebid-server/features/pbs-privacy For Prebid.js-initated server requests, we've found that cookie match rates are about what can be expected given the constraints: - The [/cookie_sync](/prebid-server/developers/pbs-cookie-sync.html) process is initiated by Prebid.js the moment the [s2sConfig](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Server-to-Server) is parsed. -- A limited number of bidders will be synced at once. PBS-Go will sync all the bidders listed in the `bidders` array. PBS-Java will sync all of them and possibly additional bidders. Publishers can change the number of syncs by specifying `userSyncLimit` on the s2sConfig. +- A limited number of bidders will be synced at once. Prebid Server will sync all bidders listed in the `bidders` array and possibly additional bidders. Publishers can change the number of syncs by specifying `userSyncLimit` on the s2sConfig. - Privacy settings (e.g. GDPR) can affect sync rate. e.g. If a lot of your traffic is in the EEA, it's going to be harder to set cookies. [AMP](/prebid-server/use-cases/pbs-amp.html) is a different story. There are several things you should check: @@ -99,8 +103,8 @@ For Prebid.js-initated server requests, we've found that cookie match rates are If a bidder adapter supplies 'nurl' in the bidResponse object, there are two paths: -1) If it's cached in Prebid Cache (e.g. AMP and App), then the 'nurl' is cached along with the 'adm' and utilized by the Prebid Universal Creative. -2) If it's not cached, the Prebid.js PrebidServerBidAdapter will append the 'nurl' to the bottom of the creative in a new div. +1. If it's cached in Prebid Cache (e.g. AMP and App), then the 'nurl' is cached along with the 'adm' and utilized by the Prebid Universal Creative. +2. If it's not cached, the Prebid.js PrebidServerBidAdapter will append the 'nurl' to the bottom of the creative in a new div. **Video** @@ -195,10 +199,70 @@ may choose to disable your adapter if it uses a dynamically configured domain. e.g. this config is not allowed because the entire domain name is a variable: -``` +```text endpoint: "https://{host}/path" ``` + but this would be ok: -``` + +```text endpoint: "https://{host}.example.com/path" ``` + +## Did the location of the bidder parameters change? + +Why yes, glad you noticed. The original 2017 OpenRTB extension where bidders +and parameters were placed was imp[].ext.BIDDER. Since 2020, the recommended location +is imp[].ext.prebid.bidder.BIDDER. This change was driven by the existence of +other fields in imp[].ext that aren't bidders, like `skadn`, `data`, etc. + +Bidders are copied from imp[].ext to imp[].ext.prebid.bidder, and they will be copied for years to come, but we would ask that new implementations of stored requests +utilize the new location. + +## Does PBS do a geo-lookup? + +PBS-Go does not currently support integration with a geo-lookup service. + +PBS-Java supports MaxMind and Netacuity. It performs the geo-lookup on every request **unless**: + +1. The config `gdpr.consent-string-means-in-scope` is true and provided `user.consent` string is valid +2. `regs.gdpr` is specified in the request +3. `device.geo.country` is specified in the request +4. It is unable to determine the IP address from the header or `device.ip` +5. There's no geo-location service configured + +## Does PBS support SSL? + +No, Prebid Server is intended to run behind a load balancer or proxy, so it does not currently support defining a security certificate. + +## How can we rename our bid adapter? + +If you have a company name change and need to add a new bidder code for the updated branding, here's the recommended approach: + +1. Keep the existing filenames and make the new name a hard-coded alias. There are separate instructions for this for [PBS-Go](/prebid-server/developers/add-new-bidder-go.html#aliasing-an-adapter) and [PBS-Java](/prebid-server/developers/add-new-bidder-java.html#create-bidder-alias). +2. Update the contact email in your YAML file as needed ([PBS-Go](https://github.com/prebid/prebid-server/tree/master/static/bidder-info), [PBS-Java](https://github.com/prebid/prebid-server-java/tree/master/src/main/resources/bidder-config)) +3. **Copy** your bidder documentation file in [https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders) so both names are available. + +In the long run, if you'd prefer to change the filenames too, that's ok - but our rule is that the old name needs to be available until the next major release to give time for publishers to transition. In that case: + +1. Submit a PR that changes the filenames and makes the old name a hard-coded alias. +2. Keep both bidder documentation files. + +## Should Prebid bidders be in ads.txt? + +Publishers should be careful to list all their bidding partners in their ads.txt file. Bidders without an entry in ads.txt may be +perceived by DSPs as unauthorized sources of your inventory. The domain for any ads.txt [inventory partners](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/dc71586842e648e89c1bbe6c666ffac8ff010a96/2.6.md?plain=1#L1752), if one exists, should be specified with a `setConfig({ortb2.site.inventorypartnerdomain})` call. For details of the specification of ads.txt entries, see [ads.txt v1.1](https://iabtechlab.com/wp-content/uploads/2022/04/Ads.txt-1.1.pdf) + +## How can I help with Prebid Server? + +Generally, people and companies will work on features and bug fixes that directly affect them. The process is: + +1. If there's not already an issue tracking the work, create an issue in the PBS-Go repo [here](https://github.com/prebid/prebid-server/issues/new). Note: we track enhancement requests in the PBS-Go repo. If it's a bug that affects PBS-Java only, then you can open the issue [here](https://github.com/prebid/prebid-server-java/issues/new). +2. The issue should describe what you're planning to build/fix. We'll want to review any interfaces, config options, or metrics for consistency. +3. After getting approval (if needed), you'll make a Pull Request against the appropriate repo, whether PBS-Go or PBS-Java. Be sure to have read the contribution guidelines for [PBS-Go](https://github.com/prebid/prebid-server/tree/master/docs/developers) or [PBS-Java](https://github.com/prebid/prebid-server-java/tree/master/docs/developers). +4. The core team will review your PR. + +If you're looking to help but don't have a specific item in mind, there are two approaches: + +- You can scan the [issue list](https://github.com/prebid/prebid-server/issues) and add a note to one offering to take it. Someone will add your github handle as the `assignee`. A prioritized set of issues is available on our [project board](https://github.com/orgs/prebid/projects/4/views/1). +- You can attend the Prebid Server committee meeting and ask about the issues currently ranked as most desirable by the group. Contact to get an invite to that meeting. diff --git a/features/InterstitialAds.md b/features/InterstitialAds.md index 67a68304fe..3505900010 100644 --- a/features/InterstitialAds.md +++ b/features/InterstitialAds.md @@ -6,12 +6,13 @@ sidebarType: 1 --- # Interstitial Ads - Prebid.js + {: .no_toc} -* TOC +- TOC {:toc} -Interstitial ads are often placed at natural transition points of the user's experience, such as moving from one page to the next. These ads are generally center-aligned overlaying user content. +Interstitial ads are often placed at natural transition points of the user's experience, such as moving from one page to the next. These ads are generally center-aligned overlaying user content. This document covers how to setup interstitial ad units. @@ -19,10 +20,10 @@ This document covers how to setup interstitial ad units. Please check with each of this AdUnit's bidders to ensure they're reading the interstitial flag from the standard Prebid location. If the bidder doesn't specifically support interstitials, results may be unexpected. - ## How It Works The flow for publishers is the following: + - Publisher traffics an interstitial line item with appropriate size(s) ([GAM example](https://support.google.com/admanager/answer/9840201?hl=en)) - Publisher defines ad server interstitial slot on the page ([GAM Example](https://developers.google.com/publisher-tag/samples/display-web-interstitial-ad)) - Publisher creates a PBJS AdUnit and defines the appropriate interstitial ad sizes, adUnit.mediaType, and a special interstitial flag @@ -30,11 +31,13 @@ The flow for publishers is the following: - Prebid requests bids for interstitial adUnits and invokes the ad server call from the requestBids callback ## Ad Sizes -Publishers must set the desired size in the respective adUnit. + +Publishers must set the desired size in the respective adUnit. The below sizes are specials sizes to indicate the ad will be full screen for mobile or tablet devices: + - 320x480: Fullscreen mobile phone portrait ad -- 480x320: Fullscreen mobile phone landscape ad +- 480x320: Fullscreen mobile phone landscape ad - 768x1024: Fullscreen tablet portrait ad - 1024x768: Fullscreen tablet landscape ad @@ -46,7 +49,7 @@ The Prebid Interstitial flag reflects the OpenRTB standard, specifying it at the If an attribute is specific to an AdUnit, it can be passed this way: -{% highlight js %} +```javascript pbjs.addAdUnits({ code: "test-div", mediaTypes: { @@ -61,21 +64,28 @@ pbjs.addAdUnits({ ... bidders that support interstitials ... ] }); -{% endhighlight %} - - +``` ## How Bid Adapters Should Read Interstitial Flag To access global data, a Prebid.js bid adapter needs only to retrieve the interstitial flag from the adUnit like this: -{% highlight js %} +```javascript utils.deepAccess(bidRequest.ortb2Imp, 'instl') -{% endhighlight %} - +``` The assumption is that bid adapters will copy the values to the appropriate protocol location for their endpoint. +## Billing Deferral + +Optimizing when billing occurs for an interstitial ad can sometimes be tricky. The following built-in Prebid.js functionality can help assist with this: + +- Bid adapters can provide a method called `onBidBillable(bid)` which will be invoked by Prebid.js when it deems a bid to be billable (Note: A bid adapter must have the onBidBillable method configured for this to work). +- When a bid wins, it is by default also billable. That is, by default, Prebid.js will invoke the bid adapter methods onBidWon and onBidBillable one after the other. +- A publisher can flag individual adUnits as being separately billable with the following configuration: `pbjs.addAdUnits({deferBilling: true, ...})` +- Winning bids for adUnits with deferBilling set to true will trigger a bid adapters onBidWon method but not their onBidBillable method. +- Finally, when appropriate (e.g. an interstitial is displayed), the publisher may call `pbjs.triggerBilling(winningBidObjectToBill)` with the winning bid to be billed, which would trigger a bid adapters onBidBillable method. + ## Related Topics - The [AdUnit Reference](/dev-docs/adunit-reference.html) diff --git a/features/ac-quebec.md b/features/ac-quebec.md new file mode 100644 index 0000000000..8adeb46692 --- /dev/null +++ b/features/ac-quebec.md @@ -0,0 +1,141 @@ +--- +layout: page_v2 +title: Prebid Quebec Privacy Support +description: Prebid Quebec Privacy Support +sidebarType: 7 +--- + +# Prebid Quebec Privacy Support +{: .no_toc} + +- TOC +{:toc} + +{% include legal-warning.html %} + +## Overview + +Starting September 2023, new privacy regulations came into effect in Quebec, a province of Canada, which governs about a quarter of Canada's population. + +IAB Canada has offered a modified version of the Transparency and Consent Framework (TCF) as a solution to cover user consent preferences in Quebec. However, as of Feb 2024, guidance from regulators, TCF Canada, and major advertising entities in Canada is still in flux. The Canadian [vendor list](https://iabcanada.com/tcf-canada/vendor-list/) does not have enough vendors for meaningful adoption of the framework by any publisher, as it does not include the primary publisher ad server nor many large DSPs. These CMPs are [registered as CMPs with TCF Canada](https://iabcanada.com/tcf-canada/cmp-list/). + +Here is guidance from IAB Canada dated February 2024: + +{: .alert.alert-info :} +CAI released new guidance in October 2023 but unfortunately, it did not clear up the confusion around whether or not expressed consent is required for personalized advertising. Conflicting interpretations of the statute remain and as a result, we are left with organizations taking different approaches based on their analysis. TCF Canada has the flexibility built in to allow for either approach and for it to be used across our market regardless of the form of consent you are collecting. + +Given this context, Prebid has identified publisher concern that many will not be able to transact programmatically in Quebec until broader adoption of the IAB TCF-Canada spec is achieved. This document is intended to provide guidance on conveying user notification and consent signals as gathered by the publisher to Prebid software independent of the GPP signals in Section 5 and the lack of a consensus consent string framework from IAB Canada. + +References: + +- [TCF Canada Infographic on Quebec Privacy Law](https://iabcanada.com/content/uploads/2022/04/IAB-Canada_Quebec-Privacy-Law-Inforgraphic.pdf) +- [IAB Canada TCF Canada policies](https://iabcanada.com/tcf-canada/for-publishers/) +- [IABTL's GPP Canada section spec](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/Canada/GPPExtension%3A%20IAB%20Canada%20TCF.md) + +## TCF Canada and GPP Support in Prebid.js + +Prebid.js supports a [GPP module](/dev-docs/modules/consentManagementGpp.html), but it does not interpret the strings in Section 5 (Canada). It simply takes the GPP signal from the CMP and includes it in outgoing network requests if those vendors initiating network requests have added support for GPP in their modules. It isn't clear if TCF Purpose 2 (consent to 'basic ad serving') or a vendor list will be critical parts of a Quebec consent framework. Also, it isn't clear if publishers will be required to seek vendor-level consent as one does for TCF-EU. + +Prebid.js is planning a TCF Canada module to react to the contents of the string, but it is not yet available as of March 2024. Instead, publishers may access their CMP or the consent preferences that their website visitors have expressed to them directly, and control Prebid.js activity. Below is an example of how the Prebid.js [Activity Control system](/dev-docs/activity-controls.html) could be used to implement an interim solution for ad serving in Quebec: + +```javascript +function isQuebecPersonConsentDenied() { +### a __gpp getSection command might be useful here, but generally, the publisher can implement this however they choose + if(someCondition) { return true } else { return false }}); +} + +pbjs.setConfig({ + allowActivities: { + enrichUfpd: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + }, + enrichEids: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + }, + syncUser: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + }, + transmitEids: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + }, + transmitPreciseGeo: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + }, + transmitUfpd: { + rules: [{ + condition: isQuebecPersonConsentDenied, + allow: false + }] + } + + } +}) +``` + +In addition, according to [Google Ad Manager documentation](https://support.google.com/admanager/answer/7678538) a publisher should call `googletag.pubads().setPrivacySettings({nonPersonalizedAds: true})` when consent for personalized advertising is not available. + +## Quebec and Prebid Server + +Like Prebid.js, there is a TCF Canada module planned for Prebid Server, but given the uncertainties +in implmentation, it may not be complete by the end of September. + +One option for supporting Quebec in Prebid Server (including mobile apps and AMP pages) would be +to simply let if pass GPP strings containing Section 5 through to bidders, trusting that they +will interpret the string in alignment with Quebec law. Prebid cannot provide guidance on which +bidders are in such alignment. + +An alternate solution would utilize the Prebid Server version of the [Activity Control system](/prebid-server/features/pbs-activitycontrols.html). + +{: .alert.alert-info :} +Only the Java version of Prebid Server currently supports targeting Activity Controls to geographic regions. + +Here's an example account configuration that utilizes the user's geographic region to determine +whether to allow or deny the named activities. Publishers will need to confirm the details with +their Prebid Server host company. + +```javascript +{ + privacy: { + allowactivities: { + syncUser: { + rules: [{ + gpp_sid: 5 + }], + allow: false + }, + transmitUfpd: { + rules: [{ + gpp_sid: 5 + }], + allow: false + }, + transmitPreciseGeo: { + rules: [{ + gpp_sid: 5 + }], + allow: false + } + } + } +} +``` + +## Related Topics + +- Prebid.js: [Activity Controls](/dev-docs/activity-controls.html), [GPP module](/dev-docs/modules/consentManagementGpp.html), [GPP USNat module](/dev-docs/modules/gppControl_usnat.html) +- Prebid Server: [Activity Controls](/prebid-server/features/pbs-activitycontrols.html) diff --git a/features/adServerKvps.md b/features/adServerKvps.md index 0f16c932cf..3cae2f32cc 100644 --- a/features/adServerKvps.md +++ b/features/adServerKvps.md @@ -6,19 +6,19 @@ sidebarType: 1 --- # Prebid.js and Ad Server Key Values + {: .no_toc} -* TOC +- TOC {:toc} - The point of header bidding is to supply bids into the regular ad server calls. -Prebid.js provides many ways to do this. This document describes the -controls for obtaining auction results. +Prebid.js provides many ways to do this. This document describes the controls for obtaining auction results. ## Overview Here's the general way PBJS is integrated into the page: + 1. Define AdUnits so they can be linked to existing ad server ad slots in the page 1. Set auction parameters 1. Initiate the auction @@ -27,6 +27,7 @@ Here's the general way PBJS is integrated into the page: This last step has historically been called "targeting" in Prebid.js, but really what's sent to the adserver is a set of Key Value Pairs (KVPs) that serve several purposes: + - **Ad server line item targeting**. These values are used to pick out which line items match the request. Generally targets depend on the hb_pb attribute, but could also include hb_deal and hb_format. - **Display**. Some of these values are needed for rendering the creative properly when the Prebid line item is chosen, including hb_adid, hb_uuid, hb_size, and for AMP/app hb_cache_host. - **Reporting**. Some publishers rely on ad server key-values for important business reporting. The keys used for reporting could be any of the above, along with hb_source. @@ -37,26 +38,26 @@ How a publisher should configure Prebid.js to report auction results will depend on how the final ad decision will be made. These approaches need to be in sync. -There are four main scenarios that follow. +There are four main scenarios, described in the following sections. ### Ad Server Line Items are Created Per-Bidder In order to have header bidding compete with direct-sold demand, a publisher can set up placeholder line items in their ad server. -Prebid.org recommends setting up separate line items -for each bidder. Benefits: -- use ad server reporting to get a view of which bidders are performing well -- control ad decisions with the ad server -- video bids have a fallback available +Prebid.org recommends setting up separate line items for each bidder. Benefits to this approach include: -There are more details on this scenario in the [Ad Ops section](/adops/before-you-start.html#one-set-of-line-items-for-each-bidder). +- You can use ad server reporting to get a view of which bidders are performing well. +- You can control ad decisions with the ad server. +- Video bids have a fallback available. + +There are more details on this scenario in the [Ad Ops section](/adops/send-all-vs-top-price.html). Once implemented in the ad server, setting this up in Prebid.js is simple, as it is the default [Send All Bids](#send-all-kvps) mode. However to limit the number of values sent to the ad server, some flavor of this solution like the [Top Two Bids and Deals](#top-two-bids-and-deals) -may be of interest. +may be of interest. {: .alert.alert-info :} Note that `enableSendAllBids` mode can send a lot of keys to your @@ -65,11 +66,11 @@ publishers monitor the key traffic and [control](#controls) as necessary. ### Only One Set of Ad Server Line Items are Created -However, there are reasons a publisher may not want to create -separate line items for each bidder: -- some ad servers have a limit on how many line items can be created -- it takes work to set up line items -- the volume of key-value pairs can be a factor +There are reasons a publisher may not want to create separate line items for each bidder. For example: + +- Some ad servers have a limit on how many line items can be created. +- It takes work to set up line items. +- The volume of key-value pairs (KVPs) can be a factor. So the other ad-server based solution is to create one set of line items that is used by all bidders. @@ -77,6 +78,8 @@ items that is used by all bidders. Setting this mode up in Prebid.js is done by setting [enableSendAllBids](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-All-Bids) to false. See the [Bare Minimum solution](#the-bare-minimum-for-display-ads) for reference. +See [Send All Bids vs Top Price](/adops/send-all-vs-top-price.html) for ad ops details on this scenario. + ### Post-Bid Sometimes Prebid.js is used as a fallback. This mode is called [PostBid](/overview/what-is-post-bid.html) @@ -97,7 +100,7 @@ In early versions of Prebid.js, there were a couple of basic functions publishers could use to get the auction results: - [pbjs.setTargetingForGPTAsync](/dev-docs/publisher-api-reference/setTargetingForGPTAsync.html) - matches Google Publisher Toolkit ad slots to Prebid.js AdUnits, obtains the auction results for that adunit, and adds "targeting" values using GPT-provided functions. -- [pbjs.getAdserverTargeting](/dev-docs/publisher-api-reference/getAdserverTargeting.html) - a more generic interface for obtaining KVPs +- [pbjs.getAdserverTargeting](/dev-docs/publisher-api-reference/getAdserverTargeting.html) - a more generic interface for obtaining KVPs. All of the other functions available in the [publisher API](/dev-docs/publisher-api-reference.html) for obtaining auction bids came later. @@ -110,7 +113,7 @@ That approach has been deprecated -- all implementations should now use [one of ### Video Video's always been a different implementation than banners because -it's the video player that controls the ad call, not in-page javascript like +it's the video player that controls the ad call, not in-page JavaScript like the GPT library. So the [Google Ad Manager Video module](/dev-docs/modules/dfp_video.html) includes the [buildVideoUrl](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html) function. Publishers using other ad servers need to integrate on their own @@ -128,10 +131,7 @@ targeting configuration](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction. ## Controls -Over the years, quite a few options have been added to to Prebid.js to adjust the number of bids and the exact set of KVPs sent to the ad server. This is an overlapping-but-powerful set of controls. There are often - -multiple ways to implement the same requirements, and there's no "wrong" -way to do it. +Over the years, quite a few options have been added to to Prebid.js to adjust the number of bids and the exact set of KVPs sent to the ad server. This is an overlapping-but-powerful set of controls. There are often multiple ways to implement the same requirements, and there's no "wrong" way to do it. The list is ordered by those functions that Prebid recommends starting with: @@ -141,20 +141,22 @@ The list is ordered by those functions that Prebid recommends starting with: 1. [targetingControls.allowTargetingKeys](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) - this resets the default keys defined by Prebid.js, defining which KVPs are sent for the winning set. (e.g. hb_pb) 1. [targetingControls.allowSendAllBidsTargetingKeys](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) - similar to allowTargetingKeys but works on the bidder-specific KVPs. (e.g. hb_pb_BIDDER) 1. [bidderSettings.standard.adserverTargeting](/dev-docs/publisher-api-reference/bidderSettings.html) - completely redefine what Prebid produces for the winning bid's KVPs. +1. [bidderSettings.standard.sendStandardTargeting](/dev-docs/publisher-api-reference/bidderSettings.html) - turn off the sending of the standard winning KVPs 1. [bidderSettings.BIDDER.adserverTargeting](/dev-docs/publisher-api-reference/bidderSettings.html) - completely redefine what Prebid produces for the bidder-specific KVPs. +1. [bidderSettings.BIDDER.sendStandardTargeting](/dev-docs/publisher-api-reference/bidderSettings.html) - turn off the sending of the standard bidder-specific KVPs 1. [targetingControls.addTargetingKeys](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) - This is similar to allowTargetingKeys but adds KVPs to the default set rather than replacing them. 1. [targetingControls.auctionKeyMaxChars](/dev-docs/publisher-api-reference/setConfig.html#setConfig-targetingControls) - This limits the number of characters Prebid is allowed to add to the KVPs. The function will count the number of characters used and will limit to the integer number of bids that won't exceed this count. 1. [sendBidsControl.dealPrioritization](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Send-Bids-Control) - This changes the sort order used by 'bidLimit' to put deals first. It's not useful when alwaysIncludeDeals is specified. ### Examples -Here are a few scenarios to give you a sense of the configurability. +Here are a few scenarios to give you a sense of the configurability. #### Send All KVPs If the number of KVPs sent to the ad server is not a concern, then the recommended approach is to Send All Bids and all deals: -``` +```javascript pbjs.setConfig({ enableSendAllBids: true, targetingControls: { @@ -167,7 +169,7 @@ pbjs.setConfig({ The opposite approach is to send only the winning set of KVPs directly needed for targeting line items and rendering. -``` +```javascript pbjs.setConfig({ enableSendAllBids: false, targetingControls: { @@ -176,11 +178,11 @@ pbjs.setConfig({ }); ``` -Note: this example lacks video support, deal support, and doesn't even tell you which bidder won. +Note: This example lacks video support, deal support, and doesn't even tell you which bidder won. #### Top Two Bids and Deals -``` +```javascript pbjs.setConfig({ sendBidsControl: { bidLimit: 2 }, targetingControls: { @@ -192,15 +194,15 @@ pbjs.setConfig({ } }); ``` -Notes: -- this assumes that video creatives are set up refering to HB_UUID rather than bidder-specific UUID values. + +Note: This assumes that video creatives are set up refering to HB_UUID rather than bidder-specific UUID values. #### Completely Custom KVPs Publishers that don't want to use KVPs prefixed with "hb_" can change them with bidderSettings: -``` +```javascript pbjs.setConfig({ enableSendAllBids: false }); @@ -209,8 +211,8 @@ pbjs.bidderSettings={ adserverTargeting: [{ key: "pb_price", // note the price granularity assumption below is Medium Granularity - // other options are pbAg (auto), pbCg (custom), pbDg (dense), - // pbHg (high), pbLg (low) + // other options are pbAg (auto), pbCg (custom), pbDg (dense), + // pbHg (high), pbLg (low) val: function(bidResponse) { return bidResponse.pbMg; } },{ key: "pb_size", @@ -235,7 +237,7 @@ pbjs.bidderSettings={ }; ``` -## Related Topics +## Further Reading - [Prebid.js Publisher API setConfig() routine](/dev-docs/publisher-api-reference/setConfig.html) - [Ad Ops and Prebid](/adops/before-you-start.html) diff --git a/features/firstPartyData.md b/features/firstPartyData.md index 12118d9aa6..2d8f0abc3d 100644 --- a/features/firstPartyData.md +++ b/features/firstPartyData.md @@ -6,9 +6,10 @@ sidebarType: 1 --- # First Party Data - Prebid.js + {: .no_toc} -* TOC +- TOC {:toc} Prebid allows publishers to supply attributes related to their content @@ -31,90 +32,202 @@ which can be used for more than just First Party Data. Publishers supply First Party Data (FPD) by specifying attributes as configuration or on a Prebid.js AdUnit: -- Global site or user data that applies to all AdUnits and all bidders. Use [`setConfig()`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd) -- AdUnit-specific data that applies to all bidders. Define [AdUnit.ortb2Imp](/dev-docs/adunit-reference.html#first-party-data) -- Bidder-specific site or user data that applies to all AdUnits. Use [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html) +- Global site or user data that applies to all AdUnits, bidders, and auctions. Use [`setConfig()`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-fpd) +- Auction-specific site or user data that applies to all AdUnits and bidders in that auction. Use the `ortb2` parameter of [`requestBids()`](/dev-docs/publisher-api-reference/requestBids.html) +- AdUnit-specific data that applies to all bidders and auctions. Define [AdUnit.ortb2Imp](/dev-docs/adunit-reference.html#first-party-data) +- Bidder-specific site or user data that applies to all AdUnits and auctions. Use [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html) ## In-Page Examples The Prebid First Party Data JSON structure reflects the OpenRTB standard. + - Arbitrary attributes should go in `ortb2.site.ext.data` or `ortb2.user.data`. - Fields that are meant to be standard [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) should be in `ortb2.site` or `ortb2.user`. Specfically, the standard values for 'site' are: name, domain, cat, sectioncat, pagecat, page, ref, search, keywords. For 'user' these are: yob, gender, keywords. - Segment taxonomy values go in `ortb2.site.content.data` or `ortb2.user.data` using the IAB standard representation. +### Automatically collected first party data + +If not specified through any of the methods above, Prebid.js attempts to automatically fill a number of fields: + +{: .table .table-bordered .table-striped } +| Field | Value | Notes | +|-----------+--------------| +| `site.page` | Site URL, from `pageUrl` falling back to `location.href` | [`pageUrl` config](/dev-docs/publisher-api-reference/setConfig.md#setConfig-Page-URL) | +| `site.ref` | `document.referrer` | | +| `site.domain` | Domain portion of `site.page` | | +| `site.keywords` | Contents of ``, if such a tag is present on the page | | +| `site.publisher.domain` | Second level domain portion of `site.domain` | The second-level domain portion of `sub.example.publisher.com` is `publisher.com`| +| `device.w` | Viewport width | +| `device.h` | Viewport height | +| `device.dnt` | Do Not Track setting | [Navigator.doNotTrack](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack) | +| `device.language` | User's language | [Navigator.language](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language) | +| `device.ua` | User agent | [Navigator.userAgent](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent) | +| `device.sua` | User agent client hints | [uaHints config](#uaHints) | +| `device.ext.webdriver`| `true` if the browser declares to be an automation tool | [Navigator.webdriver](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver) | +| `device.ext.cdep`| Google Chrome cookie deprecation label | [Chrome-facilitated testing](https://developers.google.com/privacy-sandbox/setup/web/chrome-facilitated-testing) | +| `regs.coppa` | COPPA Regulation flag | [COPPA config](/dev-docs/publisher-api-reference/setConfig.md#setConfig-coppa) +| `regs.ext.gpc` | Global Privacy Control setting | [Navigator.globalPrivacyControl](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/globalPrivacyControl) | + +Publisher-provided first party data always takes precedence for all fields; you can also set `null` to disable them. For example, the following discards the automatically collected `device.keywords`: + +```javascript +pbjs.setConfig({ + ortb2: { + device: { + keywords: null + } + } +}) +``` + + + +#### User Agent client hints + +`device.sua` is populated with UA client hints retrieved from [`navigator.userAgentData`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData). You can specify the list of hints using the `uaHints` option with [any available high entropy hint](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData#returning_high_entropy_values): + +```javascript +pbjs.setConfig({ + firstPartyData: { + uaHints: [ + 'platform', + // ... + ] + } +}) +``` + +If `uaHints` is set to an empty array or is not set, only low-entropy hints are used. + ### Supplying Global Data Here's how a publisher can let all bid adapters have access to first party data that might be useful in ad targeting that's good in PBJS 4.30 and later: -{% highlight js %} + +```javascript pbjs.setConfig({ - ortb2: { - site: { - name: "example", - domain: "page.example.com", - cat: ["IAB2"], - sectioncat: ["IAB2-2"], - pagecat: ["IAB2-2"], - page: "https://page.example.com/here.html", - ref: "https://ref.example.com", - keywords: "power tools, drills", - search: "drill", - content: { - userrating: "4", - data: [{ - name: "www.dataprovider1.com", - ext: { - segtax: 4, - cids: [ "iris_c73g5jq96mwso4d8" ] - }, - segment: [ - { id: "687" }, - { id: "123" } - ] + ortb2: { + // this is where the contextual data is placed + site: { + name: "example", + domain: "page.example.com", + + // OpenRTB 2.5 spec / Content Taxonomy + cat: ["IAB2"], + sectioncat: ["IAB2-2"], + pagecat: ["IAB2-2"], + + page: "https://page.example.com/here.html", + ref: "https://ref.example.com", + keywords: "power tools, drills", + search: "drill", + + content: { + userrating: "4", + data: [{ + name: "www.dataprovider1.com", // who resolved the segments + ext: { + segtax: 7, // taxonomy used to encode the segments + cids: ["iris_c73g5jq96mwso4d8"] + }, + // the bare minimum are the IDs. These IDs are the ones from the new IAB Content Taxonomy v3 + segment: [{ id: "687" }, { id: "123" } ] }] - }, - ext: { - data: { // fields that aren't part of openrtb 2.5 - pageType: "article", - category: "repair" - } - } + }, + ext: { + data: { // fields that aren't part of openrtb 2.6 + pageType: "article", + category: "repair" + } + } }, + + // this is where the user data is placed user: { - yob: 1985, - gender: "m", - keywords: "a,b", - data: [{ - name: "dataprovider.com", - ext: { segtax: 4 }, - segment: [ - { id: "1" } - ] - }], - ext: { - data: { - registered: true, - interests: ["cars"] - } - } + keywords: "a,b", + data: [{ + name: "dataprovider.com", + ext: { + segtax: 4 + }, + segment: [{ + id: "1" + }] + }], + ext: { + data: { + registered: true, + interests: ["cars"] + } + } + }, + regs: { + gpp: "abc1234", + gpp_sid: [7], + ext: { + dsa: { + dsarequired: 3, + pubrender: 0, + datatopub: 2, + transparency: [ + { + domain: 'platform1domain.com', + dsaparams: [1] + }, + { + domain: 'platform2domain.com', + dsaparams: [1, 2] + } + ] + } + } } } }); -{% endhighlight %} +``` {: .alert.alert-warning :} Note that supplying first party **user** data may require special -consent in certain regions. Prebid.js does **not** police the passing -of user data as part of its GDPR or CCPA modules. +consent in certain regions. By default, Prebid's [gdprEnforcement](/dev-docs/modules/gdprEnforcement.html) module does **not** police the passing +of user data, but can optionally do so if the `personalizedAds` rule is enabled. {: .alert.alert-warning :} If you're using PBJS version 4.29 or before, replace the following in the example above: 'ortb' with 'fpd', 'site' with 'context' and 'site.ext.data' with 'context.data'. +### Supplying Auction-Specific Data + +In some situations the same page may wish to supply different `site` data for some of its sections, +for example in infinite scroll or instream video scenarios where multiple pieces of content that would benefit from different contexts are served together. + +To support this use case, Prebid version 7 and above accepts auction-specific first-party data as a parameter to `requestBids`. For example: + +```javascript +pbjs.requestBids({ + ortb2: { + site: { + content: { + data: [{ + name: 'www.iris.com', + ext: { + segtax: 500, + cids: ['iris_c73g5jq96mwso4d8'] + }, + segment: [ + {id: '687'}, + {id: '123'} + ] + }] + } + } + } +}); +``` + ### Supplying AdUnit-Specific Data If an attribute is specific to an AdUnit, it can be passed this way: -{% highlight js %} +```javascript pbjs.addAdUnits({ code: "test-div", mediaTypes: { @@ -124,7 +237,7 @@ pbjs.addAdUnits({ }, ortb2Imp: { ext: { - data: { + data: { pbadslot: "homepage-top-rect", adUnitSpecificAttribute: "123" } @@ -132,7 +245,48 @@ pbjs.addAdUnits({ }, ... }); -{% endhighlight %} +``` + +Another case is [declaring rewarded](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/422eedb76e8730c89dcac75c7427c18cfa10e8c4/2.6.md?plain=1#L993). Here is how one might do that: + +```javascript +pbjs.addAdUnits({ + code: "test-div-rewarded", + mediaTypes: { + banner: { + sizes: [[300,250]] + } + }, + ortb2Imp: { + rwdd: 1, + ext: { + data: { + pbadslot: "my-rewarded-rectangle", + adUnitSpecificAttribute: "123" + } + } + }, + ... +}); +``` + +You may also specify adUnit-specific transaction IDs using `ortb2Imp.ext.tid`, and Prebid will use them instead of generating random new ones. This is useful if you are auctioning the same slots through multiple header bidding libraries. Note: you must take care to not re-use the same transaction IDs across different ad units or auctions. Here's a simplified example passing a tid through the [requestBids](/dev-docs/publisher-api-reference/requestBids.html) function: + +```javascript +const tid = crypto.randomUUID(); +pbjs.requestBids({ + adUnits: [{ + code: 'test-div', + // ... + ortb2Imp: { + ext: { + tid: tid + } + } + }] +}); +// reuse `tid` when auctioning `test-div` through some other header bidding wrapper +``` {: .alert.alert-info :} Prebid does not support AdUnit-specific **user** data, nor does it support @@ -147,7 +301,7 @@ If you're using PBJS version 4.29 or before, replace the following in the exampl Use the [`setBidderConfig()`](/dev-docs/publisher-api-reference/setBidderConfig.html) function to supply bidder-specific data. In this example, only bidderA and bidderB will get access to the supplied global data. -{% highlight js %} +```javascript pbjs.setBidderConfig({ bidders: ['bidderA', 'bidderB'], config: { @@ -178,13 +332,13 @@ pbjs.setBidderConfig({ // different bidders can receive different data ortb2: { ... } } }); -{% endhighlight %} +``` -### Supplying App Content Data +### Supplying App or DOOH ORTB Objects -Occasionally, an app which embeds a webview might run Prebid.js. In this case, the app object is often specified for OpenRTB, and the site object would be invalid. When this happens, one should specify app.content.data in place of site.content.data. +Occasionally, an app which embeds a webview might run Prebid.js. In this case, the app object is often specified for OpenRTB, and the site object would be invalid. When this happens, one should specify app.content.data in place of site.content.data. We can also imagine scenarios where billboards or similar displays are running Prebid.js. In the case of a DOOH object existing, both the site object and the app object are considered invalid. -{% highlight js %} +```javascript pbjs.setConfig({ ortb2: { app: { @@ -226,13 +380,14 @@ pbjs.setConfig({ } ) -{% endhighlight %} +``` ### Supplying OpenRTB Content Data + OpenRTB `content` object describes specific (mostly audio/video) content information, and it is useful for targeting. For website ad, the content object should be defined in `ortb2.site.content`, for non-browser ad, it should be defined in `ortb2.app.content` -{% highlight js %} +```javascript pbjs.setConfig({ ortb2: { site: { @@ -248,30 +403,28 @@ pbjs.setConfig({ url: "http://foo_url.de", cat: ["IAB1-1", "IAB1-2", "IAB2-10"], context: "7", - keywords: ["k1", "k2"], + keywords: "k1,k2", live: "0" } } } }); -{% endhighlight %} +``` ## Segments and Taxonomy -The [IAB](https://iab.com) offers standard content and audience taxonomies for categorizing sites and users. Prebid supports defining these values as first party data in `site.content.data` or `user.data` as shown in the examples above. - -{: .alert.alert-warning :} -Segment support is still under development. You can follow the [Prebid.js discussion](https://github.com/prebid/Prebid.js/issues/6057) if you'd like. +The [IAB](https://iab.com) offers standard content and audience taxonomies for categorizing sites and users. Prebid supports defining these values as first party data in `site.content.data` or `user.data` as shown in examples above and below. -``` - user: { - data: [{ - name: "dataprovider.com", // who resolved the segments - ext: { segtax: 4 }, // taxonomy used to encode the segments - segment: [ - { id: "1" } - ] - }], +```javascript +user: { + data: [{ + name: "dataprovider.com", // who resolved the segments + ext: { segtax: 4 }, // taxonomy used to encode the segments + segment: [ + { id: "1" } + ] + }], +} ``` The new extension is `segtax`, which identifies the specific taxonomy used to @@ -283,9 +436,12 @@ here to their page. For now, here's the beta table defining the segtax values: {: .table .table-bordered .table-striped } | Segtax ID | Taxonomy Type | Version | Description | |-----------+---------------+---------+-------------| -| 1 | Content | 1.x | IAB - Content Taxonomy version 1 | -| 2 | Content | 2.x | [IAB - Content Taxonomy version 2](https://iabtechlab.com/wp-content/uploads/2020/12/IABTechLab_Content_Taxonomy_2-2_Final.xlsx) | +| 1 | Content | 1.0 | IAB - Content Taxonomy version 1 - deprecated| +| 2 | Content | 2.0 | IAB - Content Taxonomy version 2) - deprecated | | 4 | Audience | 1.1 | [IAB - Audience Taxonomy version 1.1](https://iabtechlab.com/wp-content/uploads/2020/07/IABTL-Audience-Taxonomy-1.1-Final.xlsx) | +| 5 | Content | 2.1 | [IAB - Content Taxonomy version 2.1](https://iabtechlab.com/standards/content-taxonomy/) | +| 6 | Content | 2.2 | [IAB - Content Taxonomy version 2.2](https://iabtechlab.com/standards/content-taxonomy/) | +| 7 | Content | 3.0 | [IAB - Content Taxonomy version 3.0](https://iabtechlab.com/standards/content-taxonomy/) | {: .alert.alert-info :} The [IAB version of this table](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--category-taxonomies-) is associated with ADCOM. Publishers should check with their SSPs and DSPs to confirm which @@ -293,11 +449,13 @@ segment taxonomies they support. ## How Bid Adapters Should Read First Party Data -To access global data, a Prebid.js bid adapter needs only to call [`getConfig()`](/dev-docs/publisher-api-reference/getConfig.html), like this: +Prebid.js bid adapters are supplied global data in the `ortb2` property of [bid requests](/dev-docs/bidder-adaptor.html#building-the-request): -{% highlight js %} -config.getConfig('ortb2')) -{% endhighlight %} +```javascript +buildRequests: function(validBidRequests, bidderRequest) { + const firstPartyData = bidderRequest.ortb2; +} +``` AdUnit-specific values must be parsed out of the AdUnit object. diff --git a/features/mspa-usnat.md b/features/mspa-usnat.md new file mode 100644 index 0000000000..f488fd3a06 --- /dev/null +++ b/features/mspa-usnat.md @@ -0,0 +1,310 @@ +--- +layout: page_v2 +title: Prebid MSPA Support +description: Prebid MSPA Support +sidebarType: 7 +--- + +# Prebid Multi-State Privacy Agreement Support +{: .no_toc} + +- TOC +{:toc} + +{% include legal-warning.html %} + +## Overview + +Starting July 1st 2023, several US states started enforcing new privacy regulations. + +The IAB released the "Multi-State Privacy Agreement" (MSPA) as its proposal for how the advertising ecosystem can support these and future US State regulations. References: + +- [IAB's MSPA](https://www.iab.com/news/multi-state-privacy-agreement-mspa/) +- IAB Guidance on the [MSPA Decision Tree](https://www.iab.com/wp-content/uploads/2022/12/IAB_MSPA_Decision_Tree.pdf) +- IAB's [US National technical protocols](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections) + +### Glossary + +1. **Global Privacy Platform (GPP)** - A technical IAB framework that defines a container format for communicating multiple privacy protocols. e.g. GPP can contain existing Transparency and Consent Framework (TCF) strings, various US privacy string formats, and other future implementations. +1. **GPP Section ID (SID)** - the GPP container may contain multiple encoded privacy protocol strings. Each protocol gets its own SID in the overall GPP container. e.g. TCF-EU is assigned SID 2. +1. **Multi-State Privacy Agreement (MSPA)** - the IAB's contractual framework for publishers to manage various US state privacy laws. +1. **MSPA Covered Transaction** - Whether a given ad auction falls legally under the MSPA's privacy requirements. For MSPA-covered 'transactions' (ad auctions), publishers must declare themselves in one of two modes: "Service Provider Mode" or "Opt-Out Mode". +1. **MSPA Service Provider Mode** - "Service Provider Mode is for First Parties who do not Sell or Share Personal Information, and do not Process Personal Information for Targeted Advertising". This means that personal information is never sent to downstream entities. +1. **MSPA Opt-Out Mode** - For First Parties that may engage in targeted advertising activities or disclose personal information for such purposes. This means that user consent is gathered before privacy-sensitive data is sent to downstream entities. +1. **US National Privacy Technical Specification (USNat)** - the IAB's technical framework for encoding MSPA publisher policies and user consents. Stored in the GPP container as SID 7. +1. **US State Privacy Technical Specifications** - the IAB has defined technical frameworks for 5 states based on their interpretation of state privacy laws. These protocols are similar to the US National protocol and are stored in the GPP container as SIDs 8 through 12. +1. **Global Privacy Control (GPC)** - a browser-level control for end users. Some US states have referred to a global control so that users don't have to state their preferences on each website they visit. The USNat protocol strings also contain the GPC flag. +1. **US Privacy** - this is the IAB's original version of a US privacy protocol, meant to address CCPA only. It's active during a transition period until September 30, 2023. +1. **Prebid Activity Controls** - Prebid.js and Prebid Server have identified a set of behaviors for activities that may be in scope for privacy concerns such as transmitting user IDs. These activities may be allowed or suppressed with flexible conditions and exceptions as defined by the publisher. + - [Prebid.js Activity Controls](/dev-docs/activity-controls.html) were released with PBJS 7.52 + - [Prebid Server Activity Controls](/prebid-server/features/pbs-activitycontrols.html) were released with PBS-Java 1.118 + +### Assumptions + +Prebid.org cannot advise publishers on how to conform to privacy laws that affect their business. Instead, publishers should be aware of what privacy-related features Prebid supports so that their legal, product, and engineering teams can define a privacy implementation. + +Prebid's assumptions about the MSPA and the US National Privacy specification: + +1. Most Publishers will initially declare ad units in their CMP as "Not covered by MSPA." (MspaCoveredTransaction=2) This is because many major SSPs, DSPs, and Ad Servers have not signed the MSPA and some of these parties are dropping MSPA-covered transactions. + - At some point in the future when more major players have signed the MSPA, the Prebid community and legal counsel will re-evaluate the state of the industry. +1. For requests that are in-scope for SIDs 7 through 12 that are not "covered" by MSPA, Prebid treats them as being in "Opt-Out Mode". This implies that CMPs have prompted users for consent and encoded the results in the relevant section of the GPP container. +1. Prebid never changes the GPP string. This means that all downstream vendors will see whatever the CMP set. +1. Prebid has implemented a default way to interpret the US National string (SID 7) in the context of each Prebid Activity. +1. US state privacy rules do not mandate the cancellation of contextual advertising, but rather are focused on protecting user privacy. Therefore, Prebid's MSPA module may anonymize different aspects of a header bidding auction, but will never outright cancel an auction. +1. There are differences in the US state-level protocols and the US National protocol as defined by the IAB. (e.g. child consent for targeted advertising is somewhat different across SIDs 7 through 12.) +1. Rather than implementing several very similar modules and forcing publishers to include separate modules for each US state, Prebid handles state differences through a normalization process. The differences for each state are mapped onto the US National (SID 7) string, and that string is interpreted for which activities are allowed or suppressed. As with the rest of Prebid’s approach, this is a default intended to ease publishers’ ability to comply with the state laws, but publishers should make their own determinations about state law obligations and consult legal counsel to ensure that they feel comfortable that this approach allows them to meet their legal obligations. +1. Publishers that do not agree with Prebid's default behavior may override the behavior. This includes the interpretation of the USNat string as well as the normalization of state protocols. +1. The Global Privacy Control (GPC) flag is interpreted as a strong user signal that ad requests should be anonymized. +1. There's no need to support a data-deletion activity for MSPA. +1. Prebid doesn't need to explicitly support mapping US National Privacy SID 6 (legacy US Privacy) for anonymization activities. This is covered by a feature on Prebid Server where SID 6 is pulled out into regs.us_privacy and is covered by documentation in Prebid.js. + +## USNat Support in Prebid Products + +### Prebid.js + +Here's a summary of the privacy features in Prebid.js that publishers may use to align with the guidance of their legal counsel: + +{: .table .table-bordered .table-striped } +| Prebid.js Version | USNat-Related Features | Notes | +| ----------------- | ---------------------- | ----- | +| before 7.30 | None | If you operate in the US, you should consider upgrading. | +| 7.30-7.51 | **GPP module** | The [GPP module](/dev-docs/modules/consentManagementGpp.html) reads the GPP string from a compliant CMP and passes to compliant bid adapters. Not many bid adapters supported GPP in earlier versions. | +| 7.52-8.1 | GPP module
        **Activity Controls** | [Activity Controls](/dev-docs/activity-controls.html) provide the ability for publishers to allow or restrict certain privacy-sensitive activities for particular bidders and modules. See examples in that document for supporting CCPA directly. | +| 8.2-8.x | GPP module
        Activity Controls
        **USNat module** | The [USNat module](/dev-docs/modules/gppControl_usnat.html) processes SID 7. | +| After 8.x | GPP module
        Activity Controls
        USNat module
        **US State module** | The US State module processes SIDs 8 through 12 after normalizing protocol differences. | +| After 8.10 | **GPP Module** | The [GPP module](/dev-docs/modules/consentManagementGpp.html) now understands GPP 1.1 which makes it incompatible with GPP 1.0. Publishers **MUST** upgrade for continued GPP support. | + +### Prebid Server + +Here's a summary of the privacy features in Prebid Server that publishers may use to align with the guidance of their legal counsel: + +{: .table .table-bordered .table-striped } +| Prebid Server Version | USNat-Related Features | Notes | +| --------------------- | ---------------------- | ----- | +| PBS-Go before 0.236
        PBS-Java before 1.110 | None | If you operate in the US, you should consider upgrading. | +| PBS-Go 0.236
        PBS-Java 1.110 | **GPP passthrough** | PBS reads the GPP string from the ORTB request and passes to compliant bid adapters. Not many bid adapters supported GPP in earlier versions. | +| PBS‑Go 0.248 and later
        PBS‑Java 1.113 and later | GPP passthrough
        **GPP US Privacy** | PBS will read SID 6 out of the GPP string and process it as if regs.us_privacy were present on the request. | +| PBS-Go 2.2
        PBS-Java 1.118 | GPP passthrough
        GPP US Privacy
        **Activity Controls** | [Activity Controls](/prebid-server/features/pbs-activitycontrols.html) grant the ability for publishers to allow or restrict certain privacy-sensitive activities for particular bidders and modules. | +| PBS-Go TBD
        PBS-Java 1.122 | GPP passthrough
        GPP US Privacy
        **Enhanced Activity Controls** | Activity controls support additional conditions for defining USNat-related rules: gppSid, geo, and gpc. | +| PBS-Go TBD
        PBS-Java 1.126 | GPP passthrough
        GPP US Privacy
        Enhanced Activity Controls
        **USGen Module** | The [USGen module](/prebid-server/features/pbs-usgen.html) processes SIDs 7 through 12 after normalizing protocol differences. | +| PBS-Go TBD
        PBS-Java 1.130 | GPP passthrough
        GPP US Privacy
        Enhanced Activity Controls
        USNat Module
        **US Custom Logic module** | Allows publishers to provide alternate interpretations of the USNat string as it applies to Activity Controls. | + +### Prebid SDK + +SDK v2.0.8 (both iOS and Android) supports reading mobile app GPP data and passing it to Prebid Server. + +## Interpreting USNat Strings + +This section details the default for how Prebid code interprets GPP SIDs 7 through 12. It applies to both Prebid.js and Prebid Server. + +### Requirements + +When normalizing state-specific strings to the US National string, Prebid adds an additional "NULL" value which means that value was not present in the original string. + +To make sense of the specific values below, please refer to the [IAB's USNat technical specifications](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/tree/main/Sections). + +1. The US National privacy module should be able to translate state-level differences into the US National (SID 7) sense of the flags using this mapping: + 1. KnownChild normalizations follow these rules: + 1. SID 7 has two 'KnownChild' values: ages 13-16 and under 13. The goal is to map SIDs 8-12 behavior to SID 7's structure. + 1. Prebid does not distinguish between "selling", "sharing", or "processing" data. + 1. If the state-level KnownChild values are all 0 (N/A), then the normalized output values are also 0. The assumption is that a KnownChild value of 0 means the user is not a child as defined by the various laws. + 1. If the state-specific values do not distinguish between ages 13-16 and under 13, Prebid will set the normalized values to be the same and will never report consent because we will not recognize consent from under 13. We've mapped information in the state-specific protocols in a conservative way. + 1. Normalization for California (CA) (SID 8) + 1. CA sensitive data 1 maps to US national sensitive data 9 + 1. CA sensitive data 2 maps to US national sensitive data 10 + 1. CA sensitive data 3 maps to US national sensitive data 8 + 1. CA sensitive data 4 maps to US national sensitive data 1 and 2 + 1. CA sensitive data 5 maps to US national sensitive data 12 + 1. CA sensitive data 6 and 7 maps straight through to US national sensitive data 6 and 7 + 1. CA sensitive data 8 maps to US national sensitive data 3 + 1. CA sensitive data 9 maps to US national sensitive data 4 + 1. Set these fields to NULL: SharingNotice, TargetedAdvertisingOptOutNotice, TargetedAdvertisingOptOut, SensitiveDataProcessingOptOutNotice, SensitiveDataProcessing[5 and 11] + 1. KnownChild - SID 8 does not distinguish between consent for ages 13-16 and under 13, so Prebid will never normalize a positive KnownChild consent. + 1. If CA string KnownChildSensitiveDataConsents[1]=0 and state string KnownChildSensitiveDataConsents[2]=0, then no change – these can be treated as the normalized KnownChildSensitiveDataConsents[1]=KnownChildSensitiveDataConsents[2]=0 (i.e. not a 'known child') + 1. Otherwise, the SID 8 protocol does not allow Prebid to know if the user is aged 13-16 or under 13, so simply set KnownChildSensitiveDataConsents[1] or [2] both to 1 (no consent) + 1. All other fields pass through. + 1. Normalization for Virginia (SID 9) + 1. Set these fields to NULL: SharingOptOutNotice, SharingOptOut, SensitiveDataLimitUseNotice, SensitiveDataProcessingOptOutNotice, SensitiveDataProcessing[9-12], PersonalDataConsents, GPC. + 1. KnownChild: - SID 9 does not distinguish between consent for ages 13-16 and under 13, and the VA state laws define a child as being under 13, so Prebid will never normalize a positive KnownChild consent. + 1. If the SID 9 KnownChildSensitiveDataConsents value is 1 or 2, normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=1 (no consent) + 1. If the SID 9 KnownChildSensitiveDataConsents value is 0, assume the user is not a child and normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=0 (N/A) + 1. All other fields pass through. + 1. Normalization for Colorado (SID 10) + 1. Set these fields to NULL: SharingOptOutNotice, SharingOptOut, SensitiveDataLimitUseNotice, SensitiveDataProcessingOptOutNotice, SensitiveDataProcessing[8-12], PersonalDataConsents + 1. KnownChild - SID 10 does not distinguish between consent for ages 13-16 and under 13, so Prebid will never normalize a positive KnownChild consent. + + 1. If the SID 10 KnownChildSensitiveDataConsents value is 1 or 2, normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=1 (no consent) + 1. If the SID 10 KnownChildSensitiveDataConsents value is 0, assume the user is not a child and normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=0 (N/A) + 1. All other fields pass through. + 1. Normalization for Utah (UT) (SID 11) + 1. UT sensitive data 1,2 maps straight through to US National 1,2 + 1. UT sensitive data 3 maps to US National 4 + 1. UT sensitive data 4 maps to US National 5 + 1. UT sensitive data 5 maps to US National 3 + 1. UT sensitive data 6,7,8 maps straight through to US National 6,7,8 + 1. Set these fields to NULL: SharingOptOutNotice, SharingOptOut, SensitiveDataLimitUseNotice, SensitiveDataProcessing[9-12], PersonalDataConsents, GPC + 1. KnownChild - SID 11 does not distinguish between consent for ages 13-16 and under 13, so Prebid will never normalize a positive KnownChild consent. + 1. If the SID11 KnownChildSensitiveDataConsents value is 1 or 2, normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=1 (no consent) + 1. If the SID11 KnownChildSensitiveDataConsents value is 0, assume the user is not a child and normalize to SID 7 KnownChildSensitiveDataConsents[1 and 2]=0 (N/A) + 1. All other fields pass through. + 1. Normalization for Connecticut (SID 12) + 1. Set these fields to NULL: SharingOptOutNotice, SharingOptOut, SensitiveDataLimitUseNotice, SensitiveDataProcessingOptOutNotice, SensitiveDataProcessing[9-12], PersonalDataConsents + 1. KnownChild - SID 12 does distinguish ages aligned with SID 7 + 1. If SID 12 string KnownChildSensitiveDataConsents[1, 2, and 3] are all 0 then assume the user is not a child and set the normalized SID 7 KnownChildSensitiveDataConsents[1 and 2]=0 (N/A) + 1. SID 12 age ranges align with SID 7, so let ages 13-16 state their consent. If SID 12 string KnownChildSensitiveDataConsents[2]=2 and SID 12 string KnownChildSensitiveDataConsents[3]=2, then set the normalized KnownChildSensitiveDataConsents[1]=2 (Ages 13-16 consented) and the normalized KnownChildSensitiveDataConsents[2]=1 (under 13 not consented) + 1. Otherwise, set the normalized SID 7 KnownChildSensitiveDataConsents[1 and 2] to 1 (no consent) + 1. All other fields pass through. + 1. If the CMP provides a non-zero value for any of the following sensitive data categories, the module should suppress the activity. In other words, if there's any hint that data from these categories is associated with advertising, Prebid should anonymize first-party data. + 1. Genetic (6) + 1. Biometric (7) + 1. Personal Info (9) + 1. Login/Credit Card (10) + 1. Email content (12) + 1. The publisher should be able to override the default activity restriction logic with fine-grained control over all of the flags, including the ability to refine the conditions separately for ServiceProvider and OptOut modes, and for the MspaCoveredTransaction flag. + 1. The overrides should support the ability for the platform to understand whether it should be looking at the native SID state flags or the 'normalized' flags mapped from the process above. + 1. It should be possible for a publisher to override the USNat logic differently for different states. + 1. Prebid's default restrictions should be tight. Restrict the potential for syncing and/or ad targeting when + 1. in ServiceProvider mode + 1. the GPC flag is set + 1. in OptOut mode and any of the following are true + 1. notice was not provided + 1. opt-out was chosen + 1. consent for sensitive or 'known child' was not provided + 1. invalid data was provided by the CMP + +### USNat Activity Restrictions + +This table documents the default blocks of boolean logic that indicate whether a given privacy activity is allowed or suppressed. + +{: .table .table-bordered .table-striped } +| Activity | USNat Disallow Logic | Notes | +| -------- | ---------------------- | ----- | +| deviceAccess | n/a | Default to 'allow'. Publisher Activity Control config may cause it to 'restrict'. | +| fetchBid | n/a | Header bidding auctions are always allowed, but aspects of them may be anonymized. | +| reportAnalytics | n/a | Analytics always allowed, but may be anonymized. | +| syncUser | MspaServiceProviderMode=1 OR
        GPC=1 OR
        SaleOptOut=1 OR
        SaleOptOutNotice=2 OR
        (SaleOptOutNotice=0 AND SaleOptOut=2) OR
        SharingNotice=2 OR
        SharingOptOutNotice=2 OR
        (SharingOptOutNotice=0 AND SharingOptOut=2) OR
        (SharingNotice=0 AND SharingOptOut=2) OR
        SharingOptOut=1 OR
        TargetedAdvertisingOptOutNotice=2 OR
        TargetedAdvertisingOptOut=1 OR
        (TargetedAdvertisingOptOutNotice=0 AND TargetedAdvertisingOptOut=2) OR
        KnownChildSensitiveDataConsents[2]==1 OR
        KnownChildSensitiveDataConsents[2]==2 OR
        KnownChildSensitiveDataConsents[1]=1 OR
        PersonalDataConsents=2 | Suppress usersyncs when activity is not allowed:
        - Service Provider Mode
        - GPC flag
        - Lack of notice
        - Any opt-out
        - Allow kids 13-16 to consent, but always anonymize under age 13.
        - Notice was considered unnecessary yet permission to engage in targeted advertising is somehow considered valid.
        - Do not trust a CMP that claims to have 'personal data consent' for something that's logically impossible. | +| enrichEids | (same as syncUser) | Suppress the addition of EIDs when activity is not allowed. | +| enrichUfpd | (same as syncUser) | Suppress the addition of User First Party Data when activity is not allowed. | +| transmitEids | (same as syncUser) | Suppress the transmission of user.eids when activity is not allowed. | +| transmitUfpd | MspaServiceProviderMode=1 OR
        GPC=1 OR
        SaleOptOut=1 OR
        SaleOptOutNotice=2 OR
        SharingNotice=2 OR
        (SaleOptOutNotice=0 AND SaleOptOut=2) OR
        SharingOptOutNotice=2 OR
        SharingOptOut=1 OR
        (SharingOptOutNotice=0 AND SharingOptOut=2) OR
        (SharingNotice=0 AND SharingOptOut=2) OR
        TargetedAdvertisingOptOutNotice=2 OR
        TargetedAdvertisingOptOut=1 OR
        (TargetedAdvertisingOptOutNotice=0 AND TargetedAdvertisingOptOut=2) OR
        SensitiveDataProcessingOptOutNotice=2 OR
        SensitiveDataLimitUseNotice=2 OR
        ((SensitiveDataProcessingOptOutNotice=0 OR SensitiveDataLimitUseNotice=0) AND SensitiveDataProcessing[1-7,9-12]=2)
        SensitiveDataProcessing[1-5,11]=1 OR
        SensitiveDataProcessing[6,7,9,10,12]=1 OR
        SensitiveDataProcessing[6,7,9,10,12]=2 OR
        KnownChildSensitiveDataConsents[2]==1 OR
        KnownChildSensitiveDataConsents[2]==2 OR
        KnownChildSensitiveDataConsents[1]=1 OR
        PersonalDataConsents=2 | Suppress the transmission or user.ext.data.*, user.data.*, and device IDs when the activity is not allowed.

        The difference in this logic compared to syncUser is that it includes 'sensitive data' flags. See the requirements above and the commentary below. | +| transmitPreciseGeo | MspaServiceProviderMode=1 OR
        GPC=1 OR
        SensitiveDataProcessingOptOutNotice=2 OR
        SensitiveDataLimitUseNotice=2 OR
        ((SensitiveDataProcessingOptOutNotice=0 OR SensitiveDataLimitUseNotice=0) AND SensitiveDataProcessing[8]=2)
        SensitiveDataProcessing[8]=1 OR
        KnownChildSensitiveDataConsents[2]==1 OR
        KnownChildSensitiveDataConsents[2]==2 OR
        KnownChildSensitiveDataConsents[1]=1 OR
        PersonalDataConsents=2 | Round IP address and lat/long in both device.geo and user.geo when the activity is not allowed.

        The difference in this logic is that it includes "sensitive data 8" (geo) and does not include the UFPD- and ID-related fields. | +| transmitTid | n/a | Sending transaction IDs is not an aspect of USNat. | + +NOTE -- Here's what the numbers in the logic above indicate in the [IAB GPP USNat specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md): + +MspaServiceProviderMode: + +- 0 - Not Applicable +- 1 - Yes +- 2 - No + +SaleOptOut, SharingOptOut, TargetedAdvertisingOptOut: + +- 0 - Not Applicable +- 1 - Opted-Out +- 2 - Did not Opt-Out + +SaleOptOutNotice, SharingNotice, TargetedAdvertisingOptOutNotice, SensitiveDataProcessingOptOutNotice, SensitiveDataLimitUseNotice: + +- 0 - Not Applicable +- 1 - Notice was provided +- 2 - Notice was not provided + +KnownChildSensitiveDataConsents, PersonalDataConsents, SensitiveDataProcessing: + +- 1 - No Consent +- 2 - Consent + +### Commentary + +Prebid arrived at this logic through community discussions and in conjunction with legal counsel. First, we established the requirements and then translated them into boolean logic. Here's a commentary on the default logic for the `transmitUfpd` activity: + +```javascript +// In ServiceProvider mode, a publisher has declared they don't use personal data, +// so Prebid can anonymize all aspects of the request +MspaServiceProviderMode=1 OR + +// The Global Privacy Control flag means to anonymize everything +GPC=1 OR + +// Notice was not given to the user about opting out of the sale of their data +SaleOptOutNotice=2 OR + +// The user opted out of the sale of their data +SaleOptOut=1 OR + +// Notice was not given to the user about the sharing of their data +SharingNotice=2 OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +(SaleOptOutNotice=0 AND SaleOptOut=2) OR + +// Notice was not given to the user about opting out of the sharing of their data +SharingOptOutNotice=2 OR + +// The user opted out of the sharing of their data +SharingOptOut=1 OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +(SharingOptOutNotice=0 AND SharingOptOut=2) OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +(SharingNotice=0 AND SharingOptOut=2) OR + +// Notice was not given to the user about opting out of ad targeting +TargetedAdvertisingOptOutNotice=2 OR + +// The user opted out of ad targeting +TargetedAdvertisingOptOut=1 OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +(TargetedAdvertisingOptOutNotice=0 AND TargetedAdvertisingOptOut=2) OR + +// Notice was not given to the user about opting out of processing sensitive data +SensitiveDataProcessingOptOutNotice=2 OR + +// Notice was not given to the user about limiting the use of their sensitive data +SensitiveDataLimitUseNotice=2 OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +// Note that SensitiveDataProcessing[8] is the geographic location and covered in the `transmitPreciseGeo` activity +((SensitiveDataProcessingOptOutNotice=0 OR SensitiveDataLimitUseNotice=0) AND SensitiveDataProcessing[1-7,9-12]=2) + +// The user has not consented to share data of categories 1-5 and 11 +SensitiveDataProcessing[1-5,11]=1 OR + +// Data of the following categories should never be present in ad calls. +// So whether consented or not consented, anonymize UFPD if the CMP says they're present +SensitiveDataProcessing[6,7,9,10,12]=1 OR +SensitiveDataProcessing[6,7,9,10,12]=2 OR + +// If a child 13-16 has not granted consent +KnownChildSensitiveDataConsents[1]=1 OR + +// Do not accept consent from a child younger than 13 +KnownChildSensitiveDataConsents[2]==1 OR +KnownChildSensitiveDataConsents[2]==2 OR + +// The CMP claims to have consent for an 'unrelated' activity. +// Prebid views this as a logical impossibility and an invalid CMP response +PersonalDataConsents=2 +``` + +{: .alert.alert-info :} +If a publisher's legal team disagrees with any of these interpretations, both Prebid.js and Prebid Server +support overriding this default logic. + +The `transmitPreciseGeo` activity has a couple of clauses not already mentioned: + +```javascript +// Consent was not given for the use of "precise geographic" information +SensitiveDataProcessing[8]=1 OR + +// The CMP claims that notice was not needed, but at the same time claims consent was given +((SensitiveDataProcessingOptOutNotice=0 OR SensitiveDataLimitUseNotice=0) AND SensitiveDataProcessing[8]=2) +``` + +## Related Topics + +- Prebid.js: [Activity Controls](/dev-docs/activity-controls.html), [GPP module](/dev-docs/modules/consentManagementGpp.html), [GPP USNat module](/dev-docs/modules/gppControl_usnat.html) +- Prebid Server: [Activity Controls](/prebid-server/features/pbs-activitycontrols.html) diff --git a/features/pbAdSlot.md b/features/pbAdSlot.md index 8da35d6380..c67054b0c1 100644 --- a/features/pbAdSlot.md +++ b/features/pbAdSlot.md @@ -6,14 +6,15 @@ sidebarType: 1 --- # The Prebid Ad Slot and the GPID + {:.no_toc} -* TOC +- TOC {:toc} Prebid Ad Slot and the Global Placement ID (GPID) are overlapping conventions that allow publishers to identify ad inventory on their pages so bidders and reporting systems can better deal with their sites. -## Background +## Background It all starts with how publishers decide to label their ad slots: the places on their pages where ads can be served. In some ad servers like GAM, these things are called "ad units". @@ -40,9 +41,10 @@ when the publisher uses the same ad slot name multiple times. The original suggestion for GPID was to simply append the HTML div element id (aka the 'div-id') to the ad slot name. But some publishers generate div-ids randomly, so the definition of GPID has become: -``` +```javascript imp[].ext.gpid: ADSLOTNAME#UNIQUIFIER ``` + Where ADSLOTNAME is the ad server's slot name (e.g. /1111/homepage) and UNIQUIFIER is something that makes the ADSLOTNAME different from others. Normally it's a div-id, but if div-ids are random, it can be something else. The "#UNIQUIFIER" is only required if the ADSLOTNAME isn't unique enough on its own. @@ -54,23 +56,25 @@ someday we'll deprecate it in favor of the more standard GPID. There are two ways a publisher can inject these values into the header bidding auctions: -1. Supply them manually on the PBJS AdUnits -2. Install the [GPT Pre-Auction module](/dev-docs/modules/gpt-pre-auction.html) +1. Supply them manually on the PBJS AdUnits. This is required for in-stream video and for publishers not using GAM. +2. If you're using GPT, install the [GPT Pre-Auction module](/dev-docs/modules/gpt-pre-auction.html) ### Defining them on the PBJS Ad Unit +This approach what you'll have to use for in-stream video and for publishers not using GAM. + #### Example 1 - unique ad slot names In this example, there's no need for the "UNIQUIFIER" string because every ad slot on the publisher page is already unique. -``` +```javascript pbjs.addAdUnits({ code: '/1111/homepage-leftnav', ortb2Imp: { ext: { gpid: "/1111/homepage-leftnav", - data: { + data: { pbadslot: "/1111/homepage-leftnav" } } @@ -85,13 +89,13 @@ pbjs.addAdUnits({ In this example, the publisher's ad slots all have the same name, but at least the div-ids are unique. -``` +```javascript pbjs.addAdUnits({ code: 'div-leftnav', ortb2Imp: { ext: { gpid: "/1111/homepage#div-leftnav", - data: { + data: { pbadslot: "/1111/homepage#div-leftnav" } } @@ -104,16 +108,17 @@ pbjs.addAdUnits({ #### Example 3 - duplicate ad slots, random div IDs In this example, the publisher utilizes the same 'slotname' in the page for multiple holes-in-the-page, differentiating in the ad server by size. They also use random div-ids. e.g. + - defineSlot('/1111/homepage', [[300,250]], 'div-293rj893p9wje9we9fj'); - defineSlot('/1111/homepage', [[728,90]], 'div-j98s9u9usj987665da'); -``` +```javascript pbjs.addAdUnits({ code: 'div-293rj893p9wje9we9fj', ortb2Imp: { ext: { gpid: "/1111/homepage#300x250", - data: { + data: { pbadslot: "/1111/homepage#300x250" } } @@ -125,7 +130,7 @@ pbjs.addAdUnits({ ortb2Imp: { ext: { gpid: "/1111/homepage#728x90", - data: { + data: { pbadslot: "/1111/homepage#728x90" } } @@ -138,6 +143,7 @@ pbjs.addAdUnits({ ## Prebid Server The Prebid Server Bid Adapter just sends the values to the conventional OpenRTB locations: + - Prebid Ad Slot is `imp[].ext.data.pbadslot` - GPID is `imp[].ext.gpid` diff --git a/features/timeouts.md b/features/timeouts.md index d3d592b91b..35e55b4d51 100644 --- a/features/timeouts.md +++ b/features/timeouts.md @@ -38,7 +38,7 @@ ad server call, Prebid Server shaves off a safety buffer and responds to the cli configurable values (`auction.timeout-adjustment-ms` and `auction.cache.expected-request-time-ms`), which can be expected to shave 30-100ms off of `tmax`. For example, if tmax=1000 and the Prebid Server host company has 40ms of safety margin configured, bidders will actually timeout at 960ms. -### Prebid SDK Timeouts +## Prebid SDK Timeouts The SDK `setTimeoutMillis()` function is a "failsafe" timeout on the app side. @@ -47,14 +47,14 @@ The Prebid Server timeout value comes from `tmax` in the top level stored reques There is no "Timeout Buffer" in the SDK scenario, but Prebid Server will shave off the Timeout Adjustment. -### AMP Timeouts +## AMP Timeouts AMP pages may pass a timeout attribute on the query string. This value will override the default that's set in the stored request. There is no "Timeout Buffer" in the AMP scenario, but Prebid Server will shave off the Timeout Adjustment. -## Related Resources +# Related Resources - [Prebid.js timeoutBuffer](/dev-docs/publisher-api-reference/setConfig.html#setConfig-timeoutBuffer) - [FAQ: What should I set my timeouts to?](/dev-docs/faq.html#what-should-my-timeouts-be) diff --git a/formats/amp.md b/formats/amp.md index 484b14b34c..a19576c014 100644 --- a/formats/amp.md +++ b/formats/amp.md @@ -19,14 +19,12 @@ At a high level, setting up AMP pages for header bidding with Prebid has these s 1. Ad server line items for header bidding are established. 1. The publisher sets up and tests the AMP pages. - ## Ad Ops -+ [Setting up Prebid for AMP in Google Ad Manager]({{site.baseurl}}/adops/setting-up-prebid-for-amp-in-dfp.html) ++ [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) ## Developers + [How Prebid on AMP works](/prebid-server/use-cases/pbs-amp.html) + [Prebid AMP Implementation Guide](/dev-docs/show-prebid-ads-on-amp-pages.html) + [Prebid Server AMP endpoint documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-amp.html) - diff --git a/formats/display.md b/formats/display.md index 66eb7d4588..8e7cdcc369 100644 --- a/formats/display.md +++ b/formats/display.md @@ -7,6 +7,7 @@ sidebarType: 6 --- # Prebid Display Ads + {:.no_toc} Display (banner) ads are supported by Prebid.js and Prebid Mobile. The [IAB](https://www.iab.com/) has created a set of [standards](https://www.iab.com/newadportfolio/) for the different types of display ads. @@ -15,19 +16,19 @@ Here are some resources to help you work with the display ad format in Prebid. ## Prebid.js -- [What is Prebid.js?]({{site.baseurl}}/prebid/prebidjs.html) +- [What is Prebid.js?](/prebid/prebidjs.html) ### Adops -- [Adops Getting Started]({{site.baseurl}}/overview/getting-started.html) +- [Adops Getting Started](/adops/before-you-start.html) ### Developer -- [Developer Getting Started]({{site.baseurl}}/dev-docs/getting-started.html) -- [Basic Prebid.js Example]({{site.baseurl}}/dev-docs/examples/basic-example.html) -- [Ad Unit Refresh/Infinite Scroll Example]({{site.baseurl}}/dev-docs/examples/adunit-refresh.html) +- [Developer Getting Started](/dev-docs/getting-started.html) +- [Basic Prebid.js Example](/dev-docs/examples/basic-example.html) +- [Ad Unit Refresh/Infinite Scroll Example](/dev-docs/examples/adunit-refresh.html) ## Prebid Mobile -- [Overview]({{site.baseurl}}/prebid-mobile/prebid-mobile.html) -- [Prebid Mobile Getting Started]({{site.baseurl}}/prebid-mobile/prebid-mobile-pbs.html) +- [Overview](/prebid-mobile/prebid-mobile.html) +- [Prebid Mobile Getting Started](/prebid-mobile/prebid-mobile-getting-started.html) diff --git a/formats/formats.md b/formats/formats.md index dff4503cf2..9311f35a3b 100644 --- a/formats/formats.md +++ b/formats/formats.md @@ -6,44 +6,46 @@ sidebarType: 6 --- # Prebid Formats + {:.no_toc} -Prebid supports header bidding for many ad formats. This page outlines the available formats and where to find more information. (Note: At this time, only display and interstitial are available on Prebid Mobile.) +Prebid supports header bidding for many ad formats. This page outlines the available formats and where to find more information. ## Display Standard display, or banner, is an available format for all Prebid products. Learn more with the following resources: -- [Adops Getting Started]({{site.baseurl}}/adops/before-you-start.html) -- [Developer Getting Started]({{site.baseurl}}/dev-docs/getting-started.html) -- [Basic Prebid.js Example]({{site.baseurl}}/dev-docs/examples/basic-example.html) -- [Ad Unit Refresh/Infinite Scroll Example]({{site.baseurl}}/dev-docs/examples/adunit-refresh.html) +- [Adops Getting Started](/adops/before-you-start.html) +- [Developer Getting Started](/dev-docs/getting-started.html) +- [Basic Prebid.js Example](/dev-docs/examples/basic-example.html) +- [Ad Unit Refresh/Infinite Scroll Example](/dev-docs/examples/adunit-refresh.html) ## Video Prebid.js provides access to video demand for both instream and outstream video ad slots. -- [Overview]({{site.baseurl}}/prebid-video/video-overview.html) -- [Getting Started]({{site.baseurl}}/prebid-video/video-getting-started.html) -- [Examples]({{site.baseurl}}/examples/video) -- [Bidders with Video Demand]({{site.baseurl}}/dev-docs/bidders.html#bidders-with-video-and-native-demand) +- [Overview](/prebid-video/video-overview.html) +- [Getting Started](/prebid-video/video-getting-started.html) +- [Examples](/examples/video) +- [Bidders with Video Demand](/dev-docs/bidders.html#bidders-with-video-and-native-demand) ## Native Many of the Prebid.js bidder adaptors support delivery of native ads. -- [Overview]({{site.baseurl}}/dev-docs/show-native-ads.html#how-native-ads-work) -- [Developer Walkthrough]({{site.baseurl}}/dev-docs/show-native-ads.html) -- [Setting Up Your Ad Server for Native]({{site.baseurl}}/adops/setting-up-prebid-native-in-dfp.html) -- [Bidders with Native Demand]({{site.baseurl}}/dev-docs/bidders.html#bidders-with-video-and-native-demand) +- [Overview](/dev-docs/show-native-ads.html#how-native-ads-work) +- [Developer Walkthrough](/dev-docs/show-native-ads.html) +- [GAM Step by Step - Native Creatives](/adops/gam-native.html) +- [Bidders with Native Demand](/dev-docs/bidders.html#bidders-with-video-and-native-demand) ## AMP You can implement header bidding on your AMP pages. -- [How It Works]({{site.baseurl}}/dev-docs/how-prebid-on-amp-works.html) -- [Show Prebid Ads on AMP Pages]({{site.baseurl}}/dev-docs/show-prebid-ads-on-amp-pages.html) -- [Setting Up Your Ad Server for AMP]({{site.baseurl}}/adops/setting-up-prebid-for-amp-in-dfp.html) +- [How It Works](/dev-docs/show-prebid-ads-on-amp-pages.html) +- [Show Prebid Ads on AMP Pages](/dev-docs/show-prebid-ads-on-amp-pages.html) +- [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) +- [GAM Step by Step - Banner/Outstream/AMP Creatives](/adops/gam-creative-banner-sbs.html) For general information on the AMP Project, see [ampproject.org](https://www.ampproject.org/). @@ -51,16 +53,16 @@ For general information on the AMP Project, see [ampproject.org](https://www.amp A multi-format ad unit supports at least two of the following types: banner, native, and video. -- [Overview]({{site.baseurl}}/dev-docs/show-multi-format-ads.html#how-multi-format-ads-work) -- [Show Multi-Format Ads]({{site.baseurl}}/dev-docs/show-multi-format-ads.html) -- [Setting Up Your Ad Server for Multi-Format]({{site.baseurl}}/adops/setting-up-prebid-multi-format-in-dfp.html) -- [Example]({{site.baseurl}}/dev-docs/examples/multi-format-example.html) +- [Overview](/dev-docs/show-multi-format-ads.html#how-multi-format-ads-work) +- [Show Multi-Format Ads](/dev-docs/show-multi-format-ads.html) +- [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) +- [Example](/dev-docs/examples/multi-format-example.html) ## Interstitial Interstitial ads appear as full screen ads in mobile apps that must be dismissed for interaction with the app to continue. Prebid Mobile supports header bidding for interstitial ads. -- [Prebid Mobile Overview]({{site.baseurl}}/prebid-mobile/prebid-mobile.html) -- [Getting Started with Prebid Mobile]({{site.baseurl}}/prebid-mobile/prebid-mobile-pbs.html) -- [iOS Code Integration]({{site.baseurl}}/prebid-mobile/pbm-api/ios/code-integration-ios.html) -- [Android Code Integration]({{site.baseurl}}/prebid-mobile/pbm-api/android/code-integration-android.html) +- [Prebid Mobile Overview](/prebid-mobile/prebid-mobile.html) +- [Getting Started with Prebid Mobile](/prebid-mobile/prebid-mobile-getting-started.html) +- [iOS Code Integration](/prebid-mobile/pbm-api/ios/code-integration-ios.html) +- [Android Code Integration](/prebid-mobile/pbm-api/android/code-integration-android.html) diff --git a/formats/multiformat.md b/formats/multiformat.md index e62c45720e..b99eda71b4 100644 --- a/formats/multiformat.md +++ b/formats/multiformat.md @@ -6,17 +6,26 @@ sidebarType: 6 --- # Prebid Multi-Format -{:.no_toc} -Ad Units that support multiple formats are supported by Prebid.js. Prebid Server support is coming soon. +Ad Units that support multiple formats are supported by Prebid.js and Prebid Server. + +How precisely multiformat is supported is defined by each bid adapter on their parameter page in the "Multi Format Support" field. These are the possible values: + +- will-bid-on-any: the adapter will consider all supported formats and bid on one or more. +- will-bid-on-one: the adapter will consider only one of the supported formats for each auction. +- will-not-bid: the adapter will not bid on any adunits with more than one format. ## Prebid.js +[Bid adapters](/dev-docs/bidders.html) declare which formats (banner, video, and/or native) they're ready to receive. ### Adops -- [Setting up Multi-Format in Google Ad Manager](/adops/setting-up-prebid-multi-format-in-dfp.html) +- [Google Ad Manager with Prebid Step by Step](/adops/step-by-step.html) ### Developers - [Show Multi-Format Ads with Prebid.js](/dev-docs/show-multi-format-ads.html) +## Prebid Server + +[Bid adapters](/dev-docs/pbs-bidders.html) declare which formats (banner, video, and/or native) they're ready to receive. diff --git a/formats/native.md b/formats/native.md index aecf26f0a4..d181691d13 100644 --- a/formats/native.md +++ b/formats/native.md @@ -8,12 +8,25 @@ sidebarType: 6 # Prebid Native Ads + {:.no_toc} -Native ads are supported by Prebid.js for mobile web. Prebid Server support is coming soon. +## Prebid Server + +At a high level, Prebid Server just passes native parameters through to +bid adapters. See [Prebid Server Native](/prebid-server/features/pbs-native.html) for more information. + +## Prebid SDK + +See the separate pages for + +- [iOS](/prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.html) +- [Android](/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html#native-api) ## Prebid.js +Native ads are supported by Prebid.js for mobile web. + ### Adops - [Setting up Prebid Native in Google Ad Manager](/adops/gam-native.html) diff --git a/formats/video.md b/formats/video.md index 00e6391101..13bac2ce47 100644 --- a/formats/video.md +++ b/formats/video.md @@ -5,67 +5,31 @@ description: Prebid Video sidebarType: 6 --- - - # Prebid Video Ads -{:.no_toc} - -Video ads are supported by both Prebid.js and Prebid Server. - -## Prebid.js - -### Adops - -- [Prebid.js video overview](/prebid-video/video-overview.html) -- [Show video ads in Google Ad Manager](/dev-docs/show-video-with-a-dfp-video-tag.html) -### Developers +Welcome to Prebid video ad support. This is a collection of resources covering +how Prebid can help you monetize video. If you're new to Prebid video, a +good place to start would be the [Prebid.js-focused training video overview](/prebid-video/video-overview-video.html). -- [Getting started with video](/prebid-video/video-getting-started.html) -- [Outstream video ads](/dev-docs/show-outstream-video-ads.html) -- [Prebid Server video ads](/prebid-server/use-cases/pbs-pbjs.html) -- [Prebid Server Long Form Video](/prebid-server/use-cases/pbs-lfv.html) +## Instream -### Prebid.js bid adapters that support instream and outstream video ads +Instream ads are for short-form video content within a player generally has simple video ad requirements, e.g. a single pre-roll ad. -
        +1. [Prebid.js instream video overview](/prebid-video/video-overview.html#instream-video) +1. [Prebid.js: Getting started with Prebid video](/prebid-video/video-getting-started.html) +1. [Prebid Server video ad support](/prebid-server/use-cases/pbs-pbjs.html) - - +'Outstream' ads are packaged with a separate player, or the publisher provides a special player for them. They aren't embedded within video content, but rather exist as standalone video players somewhere on the page. +1. [Prebid.js outstream video overview](/prebid-video/video-overview.html#outstream-video) +1. [Prebid.js: Getting started with Prebid video](/prebid-video/video-getting-started.html) +1. [Prebid Server video ad support](/prebid-server/use-cases/pbs-pbjs.html) -### Prebid.js bid adapters that support only outstream video ads +## CTV-OTT -
        - - +1. [Prebid CTV+OTT white paper](https://files.prebid.org/docs/Prebid_for_CTV-OTT.pdf) +1. [Prebid Server long-form video ad support](/prebid-server/use-cases/pbs-lfv.html) diff --git a/fourofour.html b/fourofour.html index 634f17cfa9..6d4ee18bdb 100644 --- a/fourofour.html +++ b/fourofour.html @@ -2,8 +2,8 @@ {% include nav.html %} -
        -
        - {{ content }} -
        -
        \ No newline at end of file +
        +
        + {{ content }} +
        +
        \ No newline at end of file diff --git a/guide.md b/guide.md index d358c4d4cc..aae389fadb 100644 --- a/guide.md +++ b/guide.md @@ -9,10 +9,28 @@ sidebarType: 0 # Prebid Website Maintenance Guide -v 1.2 -Sept 24, 2021 +{:.no_toc} -*** +Updated Feb 9, 2023 + +- TOC +{:toc} + +## Getting started + +The easiest way to setup an environment to contribute to the docs or review pull requests is [Github Codespaces](https://github.com/features/codespaces). + +1. Open [github.com/prebid/prebid.github.io](https://github.com/prebid/prebid.github.io) +2. Click on the `Code` drop down menu and select "create new codespace from master". If you have no access to prebid.github.io, then you should do this on your fork of the repository +3. Install the [markdownlint extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) + 1. go to _Extensions_ + 2. search for _markdownlint_ and hit install + 3. now you get direct feedback on linting errors +4. Start the jekyll build as described in the `TERMINAL` of your codespace + 1. `bundle install` + 2. `JEKYLL_ENV=production bundle exec jekyll serve --watch --incremental` + 3. Codespaces will display a notification to open the running instance in the browser. +5. In the `PORTS` tab you find the running instance ## Reviewing Pull Requests and Issues @@ -38,7 +56,7 @@ The Prebid website is developed using [GitHub pages](https://pages.github.com/) **Markdown**: The majority of the content is written in Markdown language. Jekyll transform this into raw HTML. -Learn more about Markdown](https://www.markdownguide.org/) +Learn more about [Markdown](https://www.markdownguide.org/) **Bootstrap**: A CSS template for responsive site design. Bootstrap provides the base formatting for the site. @@ -63,7 +81,7 @@ On the rare occasions where we need to use the 'dev' or 'stage' sites, we just c ## Site Config -The _config.yml file (note underscore prefix) sets the base configuration for the site. Refer to [Jekyll](https://jekyllrb.com/docs/configuration/) documentation on which properties can be set in the _config.yml file. +The `_config.yml` file (note underscore prefix) sets the base configuration for the site. Refer to [Jekyll](https://jekyllrb.com/docs/configuration/) documentation on which properties can be set in the `_config.yml` file. *** @@ -76,20 +94,18 @@ Jekyll requires adherence to a certain directory structure to generate the site. For the Prebid.org site the following directories are used: **_data** -Jekyll was originally designed specifically for creation of blogging websites and not for dynamic, data-driven sites. However, by including the _data directory we can mimic a database structure to create a more robust site. Files in this directory can be saved in either *json*, *yml* or *csv* format. For Prebid.org they have been saved in *yml*. +Jekyll was originally designed specifically for creation of blogging websites and not for dynamic, data-driven sites. However, by including the _data directory we can mimic a database structure to create a more robust site. Files in this directory can be saved in either _json_, _yml_ or _csv_ format. For Prebid.org they have been saved in _yml_. Learn more about YML [here](https://yaml.org/start.html) There are several YML files in the Prebid _data directory -- [dropdown_v2](#Dropdown) -- [sidebar](#Sidebar) -- [messages](#Messages) -- [partners](#Partners) +- [dropdown_v2](#dropdown) +- [sidebar](#sidebar) +- [partners](#partners) The contents of these files are used throughout the Prebid.org site for dynamically creating the navigation and displaying messages. See the [Data Model](#data-models) section for a review of how the data is structured and to see sample code. - **_layouts** The layout directory contains HTML files that, in conjunction with CSS and JS files, format the layout of pages throughout the site. @@ -106,32 +122,33 @@ The bidders directory is not a standard part of Jekyll; it’s a special use dir The sites directory is created by Jekyll. It contains the live site generated from the collected files and data listed above, combined with the CSS, JS and image assets and the Markdown files for individual pages. - *** ## Assets The assets directory contains the CSS, Javascript, images and other assets used to create the site. -The base CSS file used is Bootstrap (version 3.7.1) Custom CSS and modifications to Bootstrap classes are contained in the style.css file. +The base CSS file used is Bootstrap (version 4.6.3) Custom CSS and modifications to Bootstrap classes are contained in the [_sass/vendor/_bootstrap.scss](_sass/vendor/_bootstrap.scss) file. The JS directory contains the Javascript files required for the Prebid.org site. It includes JQuery and Bootstrap javascript frameworks as well as other third party libraries and custom javascript written specifically for the Prebid site. For JQuery and Bootstrap both the expanded and minified versions of the javascript files are included but only the minified files are linked from the site header. +### CSS -#### CSS - -1. Styles all come from /assets/css/main-bundle.css -1. These are generated from /_assets/sass +1. Styles all come from `/assets/css/main-bundle.scss` +1. These are generated from [_sass/main.scss](_sass/main.scss) 1. To make a change, edit the relevant sass file -1. Generate the css file from sass with 'npm run dev/prod' -1. Commit all the changes including assets/css/main-bundle.css -1. the _assets directory is not part of the _site tree + +If you want to upgrade bootstrap + +1. Upgrade bootstrap in the [package.json](package-lock) +1. Run `npm install`. This will update the node_modules commited in [_sass/node_modules](_sass/node_modules) +1. Commit the updated node module source files ## Data Models The data files are stored in the __data directory. - ### Dropdown @@ -139,13 +156,13 @@ The dropdown_v2 YML file is used to construct the top nav when the site is viewe The YML map is divided into collections of menu sections. Menu sections are commented when they begin, for example; -```Markdown +```markdown #----------Product SubNav------------ ``` Each menu item is represented in the YML map as a collection of key value pairs and begins with a dash (-) symbol. An indented collection indicates it is a child of the collection above it. Example: -```Markdown +```markdown #-----------Overview--------------- - sectionId: 0 @@ -183,13 +200,13 @@ The collection with the title property "What Is Prebid?" is a child of the colle | isSubsectionStart | bool | 0 | Indicates if the item is the start of a subsection. **Deprecated** | **Code Use** -This data file is read in the nav.html file using Liquid. (__includes/nav.html). +This data file is read in the nav.html file using Liquid. (_`_includes/nav.html`). - ### Sidebar -The sidebar YML file is used to construct the left side navigation when the site is viewed on desktops and tablets and the top navigation when viewed on phones. +The sidebar YML file is used to construct the left side navigation when the site is viewed on desktops and tablets and the top navigation when viewed on phones. The YML map is divided into collections of menu sections. Menu sections are commented when they begin, for example; @@ -243,17 +260,28 @@ Each menu item is represented in the YML map as a collection of key value pairs | sbCollapseId | string | overview | Required if isSectionHeader = 1. Used to identify which div object is being toggled. | **Code Use** -This data file is read in the page_v2.html file using Liquid. +This data file is read in the left_nav.html file using Liquid. (__includes/left_nav.html) -**Code Use** -This data file is read in the home.html file using Liquid. +**Files Not in the Sidebar** +If a page is open that is not listed in the sidebar.yml file, by default the sidebar will display only top-level options, with no options expanded or selected. + +In certain cases, it is helpful to the user to highlight a page in the left navigation that is not currently open. For example, when a bidder page is open (such as [docs.prebid.org/dev-docs/bidders/1ad4good.html](https://docs.prebid.org/dev-docs/bidders/1ad4good.html)), we don't want hundreds of bidders displayed in the left nav, but we want the user to be oriented to where they are in the documentation. In this case, that would be under Prebid.js > Reference > Bidder Params. To accomplish this, you must do two things: + +- Add `sidebarType: 1` to all bidder pages. This opens the Prebid.js menu. (If you want to extend this functionality to other pages, use the sbSecId in the sidebar.yml file of the top-level menu as the value for sidebarType.) +- Modified the left_nav.html file's Liquid code to highlight Reference > Bidder Params anytime a page with layout=bidder is open. + +This has been done for both bidders pages (pages with `layout: bidder`) and the Publisher API Reference (`layout: api_prebidjs` and highlighting Prebid.js > Reference > Publish API Reference in the left nav), but can be extended to other pages as needed. + +## Partners + +TBD ## Bidder Files There are 200+ bidder files in the /dev-docs/bidders directory describing the parameters for each Prebid.js bidder. There are two unfortunately identical pieces of code that process them: -- /\_layouts/bidder.html - this is used to generate the single-bidder version of the page like https://prebid.org/dev-docs/bidders/rubicon.html -- /dev-docs/bidders.md - this is used to generate the (large) combined page at https://prebid.org/dev-docs/bidders.html +- /\_layouts/bidder.html - this is used to generate the single-bidder version of the page like +- /dev-docs/bidders.md - this is used to generate the (large) combined page at The attributes in the Jekyll 'front matter' drive various behaviors and dynamic tables elsewhere on the site. @@ -265,9 +293,11 @@ The attributes in the Jekyll 'front matter' drive various behaviors and dynamic | pbs | sorta | true or false | defines whether this is a Prebid Server bidder | | description | no | - | Not used | | biddercode | yes | preferred bidder code | Used as the default ad server targeting suffix and the default download filename | -| aliasCode | no | download filename | Overrides the filename used to build the PBJS package on the download page | +| aliasCode | no | bid adapter that actually implements this adapter | Overrides the filename used to build the PBJS package on the download page. Will be suffixed with "BidAdapter". This is also intended to be a valid bidder code. | +| filename | no | bid adapter that actually implements this adapter | Used when a bid adapter is created with a filename that is not the bidder code. This completely overrides what is passed into the gulp build command, so needs to be fully specified. e.g. bidderaBidAdapter | | prevBiddercode | no | secondary bidder code | Adds a note about an alternate code that may have been used. | | pbjs_version_notes | no | string | Displays on the download page | +| sidebarType | yes | `1` | Used for navigation. This opens the Prebid.js portion of the menu so the sidebar can display the Reference/Prebid Params menu option when a bidder page is open. | | ANYTHING ELSE | no | string | There are many pieces of metadata (e.g. GDPR support, user IDs supported) that bid adapters can disclose. They're displayed on the bidder's parameter page. | The bidderCode, aliasCode, and prevBiddercode parameters bear some description. @@ -276,15 +306,30 @@ there's only one documentation file and of course one PBJS adapter file. An rela long bidderCode, but found it awkward to set up ad server targeting variables because GAM limits you to 20 chars, which is easy to exceed with a prefix like `hb_cache_host`. So they wanted to have shorter bidderCode for new customers while supporting the legacy targeting variables. In that scenario, they: -1) add the shorter code as an alias in their PBJS file, which can stay the old longer name -2) change the biddercode to the shorter name as it's the new preferred code -3) add aliasCode so the Download page will pull in the right module -4) optionally add prevBiddercode to add a note to the page about the legacy value +1. add the shorter code as an alias in their PBJS file, which can stay the old longer name +2. change the biddercode to the shorter name as it's the new preferred code +3. add aliasCode so the Download page will pull in the right module +4. optionally add prevBiddercode to add a note to the page about the legacy value +5. optionally add filename if the bid adapter was created using a filename that's different than their bidder code. e.g. if the biddercode is "biddera" but they named the file "bidderABidAdapter", set the biddercode to "biddera" and the filename to "bidderABidAdapter". ## Algolia Search -We use Algolia for site search. +We use Algolia for site search. -- The configuration defining the search parameters is at https://github.com/algolia/docsearch-configs/blob/master/configs/prebid.json +- The configuration defining the search parameters is at - Only elements p, th, td, li, code, and h1-h3 are indexed - Code implementation in _includes/body-end.html and a the 'site-search' div in the header. + +## Cookie Privacy + +Prebid websites don't set their own cookies, but vendor products we use do. So we use the consentmanager.net to pop up a cookie banner. If the user hasn't consented to setting cookies, they will find reduced functionality on the site -- they won't be able to view JSFiddle examples or example videos. + +This is implemented with the [consentmanager third party blocking feature](https://help.consentmanager.net/books/cmp/page/how-to-block-third-party-codes-cookies-if-no-consent-is-given). See layout/example.md for an example implementation. + +The test case for vendor code that drops cookies is simple: + +- clear your prebid.org cookies +- reload the page +- confirm the cookie banner appears +- confirm the vendor's functionality doesn't appear +- confirm that the vendor didn't set any cookies diff --git a/guide/pb-guide-alerts.md b/guide/pb-guide-alerts.md index 3934631252..50f7b5a2fe 100644 --- a/guide/pb-guide-alerts.md +++ b/guide/pb-guide-alerts.md @@ -6,16 +6,17 @@ title: Prebid Website Documentation Guide | Alerts --- # Prebid Style Guide | Alerts + {: .no_toc } -This page provides instructions on how to display alerts within prebid.org documentation. +This page provides instructions on how to display alerts within prebid.org documentation. -* TOC +- TOC {:toc} ## Alerts -Alerts are callouts that provide emphasis, tips, important information or warnings. They are distinguished from regular text by being displayed in a colored box. There are four types of alerts that can be displayed on prebid.org: +Alerts are callouts that provide emphasis, tips, important information or warnings. They are distinguished from regular text by being displayed in a colored box. There are four types of alerts that can be displayed on prebid.org: - [Note](#note) - [Tip](#tip) @@ -24,12 +25,13 @@ Alerts are callouts that provide emphasis, tips, important information or warnin ## Composing an alert -Alerts have two components, the content and the type. +Alerts have two components, the content and the type. ### Creating alert content -Alert content is assigned to a Liquid variable by using the `capture` tag. This variable is then passed on to the alert HTML include file. In the example below we are 'capturing' the content between the opening and closing `capture` tags and assigining it to the `tipAlert` variable. -``` +Alert content is assigned to a Liquid variable by using the `capture` tag. This variable is then passed on to the alert HTML include file. In the example below we are 'capturing' the content between the opening and closing `capture` tags and assigining it to the `tipAlert` variable. + +```text { % capture tipAlert % } Follow the Prebid.org style guide to ensure all your documentation is consistent! { % endcapture % } @@ -37,31 +39,32 @@ Follow the Prebid.org style guide to ensure all your documentation is consistent ### Displaying an alert -To display an alert, use the Liquid `include` command to include one of the alert HTML files and pass the 'captured' content to it. The include files provide the HTML and CSS references to correctly format the alert. There are four include files: +To display an alert, use the Liquid `include` command to include one of the alert HTML files and pass the 'captured' content to it. The include files provide the HTML and CSS references to correctly format the alert. There are four include files: - alert_note.html - alert_tip.html - alert_important.html - alert_warning.html -In the example below we are including the tip alert, `alert_tip.html` and passing the value of `tipAlert` to the page's `content` variable. +In the example below we are including the tip alert, `alert_tip.html` and passing the value of `tipAlert` to the page's `content` variable. -``` +```text { % include alerts/alert_tip.html content=tipAlert % } ``` -In the `alert_tip.html` file the `content` variable is displayed by Liquid wrapping it in double braces. +In the `alert_tip.html` file the `content` variable is displayed by Liquid wrapping it in double braces. ```html { { content } } ``` -The full HTML from the `alert_note.html` file: + +The full HTML from the `alert_note.html` file: ```html ``` -Using the examples above would render this alert: +Using the examples above would render this alert: {% capture tipAlert %} Follow the Prebid.org style guide to ensure all your documentation is consistent! @@ -73,7 +76,7 @@ Follow the Prebid.org style guide to ensure all your documentation is consistent ### Note -A note presents important information in relation to the page topic. The content of the note is deemed important enough that it needs to be distinguished from the regular content on the page. Notes are displayed in a blue box. +A note presents important information in relation to the page topic. The content of the note is deemed important enough that it needs to be distinguished from the regular content on the page. Notes are displayed in a blue box. *Example* @@ -85,24 +88,24 @@ This is some very important information. ### Tip -A tip provides a shortcut or more efficient way of performing a task or writing some code. Tips should not be used for general comments. For general comments or to give added emphasis use a note. +A tip provides a shortcut or more efficient way of performing a task or writing some code. Tips should not be used for general comments. For general comments or to give added emphasis use a note. *Example* {% capture tipAlert %} -A tip helps the user do something. +A tip helps the user do something. {% endcapture %} {% include alerts/alert_tip.html content=tipAlert %} ### Important -Important alerts provide critical information to the user, such as to use caution when using an element in certain situations or that an API feature is scheduled to be deprecated and will not be available in future releases. +Important alerts provide critical information to the user, such as to use caution when using an element in certain situations or that an API feature is scheduled to be deprecated and will not be available in future releases. *Example* {% capture importantAlert %} -An important alert provides crititcal information to the user. +An important alert provides crititcal information to the user. {% endcapture %} {% include alerts/alert_important.html content=importantAlert %} @@ -111,24 +114,24 @@ An important alert provides crititcal information to the user. ### Warning -Warning indicate when an action can cause dire results for the user. For example, if API endpoints have been deprecated a warning should appear in the API docs to warn the user their code could break if they use the deprecated endpoints. +Warning indicate when an action can cause dire results for the user. For example, if API endpoints have been deprecated a warning should appear in the API docs to warn the user their code could break if they use the deprecated endpoints. {% capture warningAlert %} -A caution alert provides crititcal information to the user. +A caution alert provides crititcal information to the user. {% endcapture %} {% include alerts/alert_warning.html content=warningAlert %} ## Streamlined alerts -If the alert to be presented requires only a small amount of text there is no need to use the Liquid `capture` command, the text can be passed directly to the content value of the include file. +If the alert to be presented requires only a small amount of text there is no need to use the Liquid `capture` command, the text can be passed directly to the content value of the include file. -For example, if you had content such as "The adpod unit is only available for long-form video." you could pass that line of text directly to the `content` variable. -``` +For example, if you had content such as "The adpod unit is only available for long-form video." you could pass that line of text directly to the `content` variable. + +```text { % include alerts/alert_note.html content="The adpod unit is only available for long-form video." % } ``` -{% include alerts/alert_note.html content="The adpod unit is only available for long-form video." %} - -Use the Liquid `capture` command when you are creating an alert that is very long or contains HTML formating. +{% include alerts/alert_note.html content="The adpod unit is only available for long-form video." %} +Use the Liquid `capture` command when you are creating an alert that is very long or contains HTML formating. diff --git a/identity/prebid-identity-video.md b/identity/prebid-identity-video.md new file mode 100644 index 0000000000..4d5861ee31 --- /dev/null +++ b/identity/prebid-identity-video.md @@ -0,0 +1,56 @@ +--- +layout: page_v2 +title: Video Intro to Prebid Identity Solutions +description: A video overview of Prebid Identity Solutions +sidebarType: 9 +--- + +# A Video Overview of Prebid Identity Solutions + +An explanation of Prebid’s user identity and consent management tools. + +{% include vimeo-iframe.html id="826314346" title="Identity in Prebid.js" %} + +Further Content: + +- [User Identity Overview](/identity/prebid-identity.html) +- [SharedID](/identity/sharedid.html) +- [Prebid.js Modules](/dev-docs/modules/) +- [All Videos](/overview/all-videos.html) + +Related Videos: + +- [Introduction to Prebid.js](/prebid/prebidjs-video.html) +- [Components of Prebid.js](/prebid/prebidjs-components-video.html) + +## Transcript + +### Introduction + +Prebid offers a powerful set of tools that help publishers to integrate with user identity solutions in a way that follows their organization’s privacy strategy. + +Digital media sellers need to have sophisticated practices for handling the data that describes users and audiences. To increase the value of impression opportunities surfaced to buyers, publishers may wish to transmit a pseudonymous user identifier in Prebid.js bid requests. These identifiers are a form of ad request enrichment. They can help increase the value of impression opportunities to buyers by unlocking the buyer’s ability to perform actions like frequency capping and audience targeting. + +At the same time, all members of the digital advertising supply chain have a responsibility to protect the privacy of internet users and to comply with privacy and data laws. Therefore, all sellers must develop an identity and privacy strategy that is rooted in their approach to monetization, user experience, and regulatory compliance. Prebid’s tools can be used to integrate with identity solutions and execute on an identity and privacy strategy. Prebid does not provide legal advice and makes no guarantees about compliance with any law or regulation. + +### Identity Solutions: SharedId and User ID Module + +Sellers using Prebid.js can transmit identity signals using Prebid’s SharedId service or any other major identity solution. SharedId is an open-source identity solution developed and maintained by Prebid. It stores a unique user ID in the publisher’s domain and makes it accessible to Prebid auction bidders. Bidders may then use this identifier for ad targeting, frequency capping, or other purposes. In addition to SharedId, Prebid also supports dozens of other popular identity servies. The benefits and mechanics of each service vary, and it is up to the seller to decide which providers align best with their privacy and identity strategies. + +The Prebid.js User ID Module is used to integrate SharedId and other services into Prebid.js. The providers of identity solutions build submodules that are compatible with the User ID module. The submodules allow the provider’s service to get and set identifiers and expose the identifiers to bidders. + +Publishers have complete control over which user ID submodules are included in their Prebid.js wrappers. Prebid.js also allows publishers to establish controls over user IDs, such as restricting when and how user syncing can occur during the header bidding auction. + +### Privacy Solutions: Consent Modules + +Prebid.js also includes tools that allow publishers to execute on their privacy, consent, and regulatory compliance strategies. These tools work in close coordination with the User ID module and Prebid adapters to control whether, when, and how user identifiers are created or shared. + +Collectively, these tools are called Consent Management Modules. They connect to the publisher’s Consent Management Platform, or CMP to make the user’s preferences about data use available to Prebid.js and to Prebid bidders. + +Consent Management modules allow Publishers and bidders to use consent data to decide when to activate user ID modules, whether to allow bidders to perform cookie syncs, and whether or not to serve ads. + +These modules are designed to provide tools related to specific regulations, but do not guarantee compliance with any regulatory requirements. + +### Getting Started + +To learn more about the Prebid User ID Module, SharedID, and Prebid Consent Management Modules, visit docs.prebid.org diff --git a/identity/prebid-identity.md b/identity/prebid-identity.md index d83d63b126..2d0f277936 100644 --- a/identity/prebid-identity.md +++ b/identity/prebid-identity.md @@ -14,7 +14,17 @@ To do this, Prebid offers a number of identity-related products that encourage a - [Prebid.js User Identity Module](/dev-docs/modules/userId.html). This module supports more than 20 different flavors of global IDs with different features that publishers can work with. - [SharedID](/identity/sharedid.html). This native hosted ID offering from Prebid is simple, free, robust, and privacy-minded. -- **Coming soon:** [Unified ID 2.0](https://prebid.org/blog/prebid-org-to-serve-as-operator-of-unified-id-2-0/) + +## Overview + +An explanation of Prebid’s user identity and consent management tools. + +{% include vimeo-iframe.html id="826314346" title="Identity in Prebid.js" %} + +Further Reading: + +- [Transcript of this video overview](/identity/prebid-identity-video.html) +- [Prebid.js Modules](/dev-docs/modules/) ## Prebid.js and Identity diff --git a/identity/sharedid.md b/identity/sharedid.md index be8913d04a..cd25557eac 100644 --- a/identity/sharedid.md +++ b/identity/sharedid.md @@ -6,10 +6,11 @@ sidebarType: 9 --- # Prebid SharedID + {: .no_toc} -* TOC -{:toc} +- TOC + {:toc} {: .alert.alert-warning :} As of Prebid.js 5.0, PubCommon ID is no longer supported -- it's been merged into SharedId. Also, SharedId no longer syncs to sharedid.org like it did in Prebid.js 4.x. @@ -33,49 +34,56 @@ There are multiple ways to integrate SharedId on your site. See the table below The SharedID ID system sets a user id cookie in the publisher’s domain. Since the cookie is set in the publisher's first party domain it does not fall in scope of browser restrictions on third party cookies. Safari has restrictions on first party cookies set via document.cookie. For this reason we recommend considering a server endpoint installation for maximum effect. See the "Alternate Implementations" section below. -### Prebid.js 5.x +### Prebid.js 5 and later The SharedId module reads and/or sets a random ID in the cookie name defined by the publisher when initializing the module: Example 1: client-side cookie setting -``` + +```javascript pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'sharedId', //"pubCommonId" as a name is supported for backwards compatibility, - storage: { - name: '_sharedID', // name of the 1st party cookie, _pubcid is supported for backwards compatibility - type: 'cookie', - expires: 30 - } - }] - } + userSync: { + userIds: [ + { + name: "sharedId", //"pubCommonId" as a name is supported for backwards compatibility, + storage: { + name: "_sharedID", // name of the 1st party cookie, _pubcid is supported for backwards compatibility + type: "cookie", + expires: 30, + }, + }, + ], + }, }); ``` Example 2: setting the cookie with a first party endpoint -``` + +```javascript pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'sharedId', //"pubCommonId" as a name is supported for backwards compatibility, - params: { - pixelUrl: "/wp-json/pubcid/v1/extend/" // this parameter identifies your server-side endpoint that will set a first party cookie' - }, - storage: { - name: '_sharedID', // name of the 1st party cookie, _pubcid is supported for backwards compatibility - type: 'cookie', - expires: 30 - } - }] - } + userSync: { + userIds: [ + { + name: "sharedId", //"pubCommonId" as a name is supported for backwards compatibility, + params: { + pixelUrl: "/wp-json/pubcid/v1/extend/", // this parameter identifies your server-side endpoint that will set a first party cookie' + }, + storage: { + name: "_sharedID", // name of the 1st party cookie, _pubcid is supported for backwards compatibility + type: "cookie", + expires: 30, + }, + }, + ], + }, }); ``` The 'source' value transmitted through OpenRTB (user.ext.eids) is pubcid.org. For example: -``` + +```javascript user: { ext: { eids: { @@ -101,7 +109,8 @@ source value. In addition to setting a first party cookie, SharedId in Prebid.js 4.x also sets a third party cookie where possible, syncing the first and third party cookies (subject to browser capability and user opt-out). SharedId in Prebid.js 4.x was transmitted through the header-bidding ecosystem on user.ext.eids with a different 'source': -``` + +```javascript user: { ext: { eids: { @@ -139,12 +148,16 @@ In Prebid.js 4.x, when SharedId performed third-party syncing there was an extra step in the diagram between steps 3 and 4 where the module would connect to a server on sharedid.org. This step was removed in Prebid.js 5.0. +### Configuration + +You can find available configuration options for the SharedID module [here](https://docs.prebid.org/dev-docs/modules/userid-submodules/sharedid.html) + ### Privacy Discussion There are several privacy scenarios in which a user ID is not created or read: 1. The User ID module suppresses all cookie reading and setting activity -when the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html) is in place and there's no consent for Purpose 1. + when the [GDPR Enforcement Module](/dev-docs/modules/gdprEnforcement.html) is in place and there's no consent for Purpose 1. 2. The User ID module infrastructure supports a first-party opt-out, by setting the `_pbjs_id_optout` cookie or local storage to any value. No other cookies will be set if this one is set. 3. The SharedId module will suppress the ID when the COPPA flag is set. @@ -160,18 +173,20 @@ mechanisms like GDPR and CCPA, the use of first party cookies requires that opt- by the publisher. Publishers that decide to build a first-party opt-out workflow might follow a process like this: + - User is presented with an option to turn off ad targeting - If the user opts out, the page can do one of two things: - - set a `_pbjs_id_optout` first party cookie - - avoid calling pbjs.setConfig to initialize the user ID modules + - set a `_pbjs_id_optout` first party cookie + - avoid calling pbjs.setConfig to initialize the user ID modules ## Alternative Implementations -For those not using Prebid's header bidding solution, SharedId can deployed via in inline script reference or from a web server. +For those not using Prebid's header bidding solution, SharedId can deployed via in inline script reference or from a web server. ### SharedId Script -For those interested in implementing SharedId without prebid.js. +For those interested in implementing SharedId without prebid.js. + 1. Clone the [SharedId script repository](https://github.com/prebid/Shared-id-v2) 2. Implement the pubcid.js script on the desired page by following the build instructions in the [readme.md](https://github.com/prebid/Shared-id-v2#readme) @@ -179,15 +194,15 @@ Prebid also recommends implementing a method where users can easily opt-out of t If there are no custom configurations, then just include the script and it'll use the default values. -``` +```html ``` If custom configurations are needed, define the pubcid_options object before inclusion of the script. Below is an example to switch from using local storage to cookie: -``` +```html ``` @@ -197,20 +212,20 @@ If custom configurations are needed, define the pubcid_options object before inc Below are the available configuration options for the PubCID script. {: .table .table-bordered .table-striped } -| Parameter Name | Type | Description | | Example | +| Parameter Name | Type | Description | | Example | | --- | --- | --- | --- | --- | -| create | boolean | If true, then an id is created automatically by the script if it's missing. Default is true. If your server has a component that generates the id instead, then this should be set to false | | `true` | -| expInterval | decimal | Expiration interval in minutes. Default is 525600, or 1 year | | `525600` | -| extend | boolean | If true, the the expiration time is automatically extended whenever the script is executed even if the id exists already. Default is true. If false, then the id expires from the time it was initially created. | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` | -| pixelUrl | string (optional) | For publisher server support only. Where to call out to for a server cookie. | | `/wp-json/pubcid/v1/extend/` +| create | boolean | If true, then an id is created automatically by the script if it's missing. Default is true. If your server has a component that generates the id instead, then this should be set to false | | `true` | +| expInterval | decimal | Expiration interval in minutes. Default is 525600, or 1 year | | `525600` | +| extend | boolean | If true, the the expiration time is automatically extended whenever the script is executed even if the id exists already. Default is true. If false, then the id expires from the time it was initially created. | For publisher server support only. If true, the publisher's server will create the (pubcid) cookie. Default is true. | `true` | +| pixelUrl | string (optional) | For publisher server support only. Where to call out to for a server cookie. | | `/wp-json/pubcid/v1/extend/` | type | string | Type of storage. It's possible to specify one of the following: 'html5', 'cookie'. Default is 'html5' priority, aka local storage, and fall back to cookie if local storage is unavailable. | If true, the expiration time of the stored IDs will be refreshed during each page load. Default is false. | `cookie` | #### Example Configurations Always use cookies and create an ID that expires in 30 days after creation. -``` -{ +```javascript +{ type: 'cookie', extend: false, expInterval: 43200 @@ -219,8 +234,8 @@ Always use cookies and create an ID that expires in 30 days after creation. Using a SharedId Endpoint implementation, create the cookie once, which will be allowed to expire before it is created again. -``` -{ +```javascript +{ type: 'cookie', pixelUrl: '/wp-json/pubcid/v1/extend/', create: false, @@ -235,9 +250,9 @@ Add server-side support for SharedId to better handle the ever-increasing restri #### CMS -PubCID/SharedId plugins are available for Wordpress and Drupal. Because the CMS can cache pages to improve scalability, it's impractical to set unique cookies during page generation. Instead these plugins require a dynamic endpoint that serves back a blank pixel along with a unique cookie value. The client side script needs one additional parameter for this URL. Please consult the corresponding plugin documents for default values: +PubCID/SharedId plugins are available for Wordpress and Drupal. Because the CMS can cache pages to improve scalability, it's impractical to set unique cookies during page generation. Instead these plugins require a dynamic endpoint that serves back a blank pixel along with a unique cookie value. The client side script needs one additional parameter for this URL. Please consult the corresponding plugin documents for default values: -1. Wordpress : Install directly from the [Wordpress admin page](https://wordpress.org/plugins/publisher-common-id/). Install from [GITHUB](https://github.com/prebid/sharedid-wordpress) +1. Wordpress : Install directly from the [Wordpress admin page](https://wordpress.org/plugins/publisher-common-id/). Install from [GITHUB](https://github.com/prebid/sharedid-wordpress) 2. Drupal : Install from [Github](https://github.com/prebid/sharedid-drupal). #### Endpoint Implementations @@ -246,11 +261,12 @@ The Wordpress and Drupal plugins require that the host company integrate a new e Below are some examples for how to implement this function in various languages or platforms. It is up to the site owner to integrate an appropriate script for their specific scenario. ##### JAVA -```JAVA + +```java public class PubCid { private static final String pubcidCookieName = "_pubcid"; private static final int expireTime = (int) TimeUnit.DAYS.toSeconds(365); //store cookie for 1 year - + /** * Returns the pubcid cookie found in the user's list of cookies. * Always update the expire time to another year so that the cookie persists. @@ -259,14 +275,14 @@ public class PubCid { * @return the pubcid cookie if found, null otherwise */ public static Cookie getPubcidCookie(Cookie[] cookies) { - + Cookie pubcidCookie = fetchPubcidCookie(cookies); if (pubcidCookie != null) pubcidCookie.setMaxAge(expireTime); - + return pubcidCookie; } - + /** * Simple function to test if the user has a pubcid cookie * @@ -276,7 +292,7 @@ public class PubCid { public static boolean hasPubcidCookie(Cookie[] cookies) { return fetchPubcidCookie(cookies) != null; } - + /** * Local function to find the pubcid cookie within the user's list of cookie * @@ -292,25 +308,27 @@ public class PubCid { } } ``` + ##### PHP -```PHP + +```php $cookie_name = '_pubcid'; $cookie_path = '/'; $max_age = 365; - + $value = NULL; - + // See if the cookie exist already - + if (isset($_COOKIE[$cookie_name ])) $value = $_COOKIE[$cookie_name]; - + // Obtain site domain if defined if (defined(COOKIE_DOMAIN)) $cookie_domain = COOKIE_DOMAIN; else $cookie_domain = ""; - + // Update the cookie if (isset($value)) { setcookie( @@ -322,46 +340,55 @@ if (isset($value)) { ); } ``` + ##### Node.js -```Node -const express = require('express'); -const cookieParser = require('cookie-parser'); + +```javascript +const express = require("express"); +const cookieParser = require("cookie-parser"); const app = express(); const port = 3000; - + app.use(cookieParser()); - -app.get('/', function(req, res) { - - // Check for existence of _pubcid cookie - let value = req.cookies['_pubcid']; - - // If pubcid exists, then update its expiration time - if (value) { - res.cookie('_pubcid', value, {domain: '.example.com', path: '/', expires: new Date(Date.now() + 1000*60*60*24*365)}); - } - - res.render('index'); + +app.get("/", function (req, res) { + // Check for existence of _pubcid cookie + let value = req.cookies["_pubcid"]; + + // If pubcid exists, then update its expiration time + if (value) { + res.cookie("_pubcid", value, { + domain: ".example.com", + path: "/", + expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365), + }); + } + + res.render("index"); }); - -app.listen(port, ()=>console.log(`App listening on port ${port}`)); + +app.listen(port, () => console.log(`App listening on port ${port}`)); ``` + ##### Apache -```Apache + +```conf # Add to httpd.conf # Requires mod_headers and mod_env - + # Capture _pubcid cookie value if available SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" PUBCID_VALUE=$2 SetEnvIf Cookie "(^|;\ *)_pubcid=([^;\ ]+)" HAVE_PUBCID=1 - + # Add _pubcid cookie if it exists to the response with 1 year expiration time Header add Set-Cookie "_pubcid=%{PUBCID_VALUE}e;Domain=.example.com;Path=/;Max-Age=31536000" env=HAVE_PUBCID ``` + ##### Nginx -```Nginx + +```conf # Add to a location directive - + location /example { set $pubcid_value $cookie__pubcid; if ($pubcid_value) { diff --git a/lib/jquery/jquery.js b/lib/jquery/jquery.js index 7fc60fca78..8a835aa999 100644 --- a/lib/jquery/jquery.js +++ b/lib/jquery/jquery.js @@ -14,25 +14,25 @@ (function( global, factory ) { - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } // Pass this if window is not defined yet }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { @@ -65,483 +65,483 @@ var support = {}; var - version = "1.12.4", + version = "1.12.4", - // Define a local copy of jQuery - jQuery = function( selector, context ) { + // Define a local copy of jQuery + jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, - // Support: Android<4.1, IE<9 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, + // The current version of jQuery being used + jquery: version, - constructor: jQuery, + constructor: jQuery, - // Start with an empty selector - selector: "", + // Start with an empty selector + selector: "", - // The default length of a jQuery object is 0 - length: 0, + // The default length of a jQuery object is 0 + length: 0, - toArray: function() { - return slice.call( this ); - }, + toArray: function() { + return slice.call( this ); + }, - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - // Return all the elements in a clean array - slice.call( this ); - }, + // Return all the elements in a clean array + slice.call( this ); + }, - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; - // Return the newly-formed element set - return ret; - }, + // Return the newly-formed element set + return ret; + }, - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, - first: function() { - return this.eq( 0 ); - }, + first: function() { + return this.eq( 0 ); + }, - last: function() { - return this.eq( -1 ); - }, + last: function() { + return this.eq( -1 ); + }, - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, - end: function() { - return this.prevObject || this.constructor(); - }, + end: function() { + return this.prevObject || this.constructor(); + }, - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: deletedIds.sort, - splice: deletedIds.splice + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice }; jQuery.extend = jQuery.fn.extend = function() { - var src, copyIsArray, copy, name, options, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = jQuery.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; + var src, copyIsArray, copy, name, options, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; }; jQuery.extend( { - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type( obj ) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type( obj ) === "array"; - }, - - isWindow: function( obj ) { - /* jshint eqeqeq: false */ - return obj != null && obj == obj.window; - }, - - isNumeric: function( obj ) { - - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - // adding 1 corrects loss of precision from parseFloat (#15100) - var realStringObj = obj && obj.toString(); - return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - isPlainObject: function( obj ) { - var key; - - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call( obj, "constructor" ) && - !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { - return false; - } - } catch ( e ) { - - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if ( !support.ownFirst ) { - for ( key in obj ) { - return hasOwn.call( obj, key ); - } - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; - }, - - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && jQuery.trim( data ) ) { - - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); // jscs:ignore requireDotNotation - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android<4.1, IE<9 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - var len; - - if ( arr ) { - if ( indexOf ) { - return indexOf.call( arr, elem, i ); - } - - len = arr.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - - // Skip accessing in sparse arrays - if ( i in arr && arr[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - while ( j < len ) { - first[ i++ ] = second[ j++ ]; - } - - // Support: IE<9 - // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) - if ( len !== len ) { - while ( second[ j ] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var args, proxy, tmp; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: function() { - return +( new Date() ); - }, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type( obj ) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + // adding 1 corrects loss of precision from parseFloat (#15100) + var realStringObj = obj && obj.toString(); + return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call( obj, "constructor" ) && + !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + } catch ( e ) { + + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( !support.ownFirst ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); // jscs:ignore requireDotNotation + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[ j ] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support } ); // JSHint would error on this code due to the Symbol not being defined in ES5. @@ -550,31 +550,31 @@ jQuery.extend( { // three lines. /* jshint ignore: start */ if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ]; + jQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ]; } /* jshint ignore: end */ // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); + class2type[ "[object " + name + "]" ] = name.toLowerCase(); } ); function isArrayLike( obj ) { - // Support: iOS 8.2 (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = jQuery.type( obj ); + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; } var Sizzle = /*! @@ -590,337 +590,337 @@ var Sizzle = (function( window ) { var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // http://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }; + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; // Optimize for push.apply( _, NodeList ) try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; } function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, nidselect, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; - while ( i-- ) { - groups[i] = nidselect + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); + var m, i, elem, nid, nidselect, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; + while ( i-- ) { + groups[i] = nidselect + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry */ function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; } /** @@ -928,8 +928,8 @@ function createCache() { * @param {Function} fn The function to mark */ function markFunction( fn ) { - fn[ expando ] = true; - return fn; + fn[ expando ] = true; + return fn; } /** @@ -937,20 +937,20 @@ function markFunction( fn ) { * @param {Function} fn Passed the created div and expects a boolean result */ function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } } /** @@ -959,12 +959,12 @@ function assert( fn ) { * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; + var arr = attrs.split("|"), + i = arr.length; - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } } /** @@ -974,26 +974,26 @@ function addHandle( attrs, handler ) { * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; } /** @@ -1001,10 +1001,10 @@ function siblingCheck( a, b ) { * @param {String} type */ function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; } /** @@ -1012,10 +1012,10 @@ function createInputPseudo( type ) { * @param {String} type */ function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; } /** @@ -1023,21 +1023,21 @@ function createButtonPseudo( type ) { * @param {Function} fn */ function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); } /** @@ -1046,7 +1046,7 @@ function createPositionalPseudo( fn ) { * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; + return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience @@ -1058,10 +1058,10 @@ support = Sizzle.support = {}; * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** @@ -1070,436 +1070,436 @@ isXML = Sizzle.isXML = function( elem ) { * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, parent, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( (parent = document.defaultView) && parent.top !== parent ) { - // Support: IE 11 - if ( parent.addEventListener ) { - parent.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", unloadHandler ); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var m = context.getElementById( id ); - return m ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - docElem.appendChild( div ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibing-combinator selector` fails - if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return document; + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( (parent = document.defaultView) && parent.top !== parent ) { + // Support: IE 11 + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + return m ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + docElem.appendChild( div ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; }; Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); + return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; }; Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); + throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** @@ -1507,32 +1507,32 @@ Sizzle.error = function( msg ) { * @param {ArrayLike} results */ Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; }; /** @@ -1540,553 +1540,553 @@ Sizzle.uniqueSort = function( results ) { * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; }; Expr = Sizzle.selectors = { - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } }; Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); + Expr.pseudos[ i ] = createInputPseudo( i ); } for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); + Expr.pseudos[ i ] = createButtonPseudo( i ); } // Easy API for creating new setFilters @@ -2095,474 +2095,474 @@ setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); }; function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; } function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); - - if ( (oldCache = uniqueCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( (oldCache = uniqueCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; } function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; } function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; } function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; } function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); } function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context === document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; } compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; }; /** @@ -2575,74 +2575,74 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { * @param {Array} [seed] A set of elements to match against */ select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; }; // One-time assignments @@ -2660,52 +2660,52 @@ setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; }); // Support: IE<8 // Prevent attribute/property "interpolation" // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !assert(function( div ) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#" ; + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; }) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); } // Support: IE<9 // Use defaultValue in place of getAttribute("value") if ( !support.attributes || !assert(function( div ) { - div.innerHTML = ""; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; }) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; + return div.getAttribute("disabled") == null; }) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); } return Sizzle; @@ -2725,31 +2725,31 @@ jQuery.contains = Sizzle.contains; var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; }; var siblings = function( n, elem ) { - var matched = []; + var matched = []; - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } - return matched; + return matched; }; @@ -2763,92 +2763,92 @@ var risSimple = /^.[^:#\[\.,]*$/; // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - } ); + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + } ); - } + } - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); - } + } - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } - qualifier = jQuery.filter( qualifier, elements ); - } + qualifier = jQuery.filter( qualifier, elements ); + } - return jQuery.grep( elements, function( elem ) { - return ( jQuery.inArray( elem, qualifier ) > -1 ) !== not; - } ); + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) > -1 ) !== not; + } ); } jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; + var elem = elems[ 0 ]; - if ( not ) { - expr = ":not(" + expr + ")"; - } + if ( not ) { + expr = ":not(" + expr + ")"; + } - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); }; jQuery.fn.extend( { - find: function( selector ) { - var i, - ret = [], - self = this, - len = self.length; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } } ); @@ -2858,125 +2858,125 @@ jQuery.fn.extend( { // A central reference to the root jQuery(document) var rootjQuery, - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // init accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt( 0 ) === "<" && - selector.charAt( selector.length - 1 ) === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[ 2 ] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[ 0 ] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof root.ready !== "undefined" ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // init accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt( 0 ) === "<" && + selector.charAt( selector.length - 1 ) === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[ 2 ] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[ 0 ] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof root.ready !== "undefined" ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; // Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn; @@ -2987,169 +2987,169 @@ rootjQuery = jQuery( document ); var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; jQuery.fn.extend( { - has: function( target ) { - var i, - targets = jQuery( target, this ), - len = targets.length; - - return this.filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( pos ? - pos.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[ 0 ], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem, this ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( pos ? + pos.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[ 0 ], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } } ); function sibling( cur, dir ) { - do { - cur = cur[ dir ]; - } while ( cur && cur.nodeType !== 1 ); + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); - return cur; + return cur; } jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge( [], elem.childNodes ); - } + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } }, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } - if ( this.length > 1 ) { + if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - ret = jQuery.uniqueSort( ret ); - } + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.uniqueSort( ret ); + } - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - } + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } - return this.pushStack( ret ); - }; + return this.pushStack( ret ); + }; } ); var rnotwhite = ( /\S+/g ); @@ -3157,379 +3157,379 @@ var rnotwhite = ( /\S+/g ); // Convert String-formatted options into Object-formatted ones function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; + var object = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; } /* * Create a callback list using the following parameters: * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * - * once: will ensure the callback list can only be fired once (like a Deferred) + * once: will ensure the callback list can only be fired once (like a Deferred) * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) * - * unique: will ensure a callback can only be added once (no duplicate in the list) + * unique: will ensure a callback can only be added once (no duplicate in the list) * - * stopOnFalse: interrupt callings when a callback returns false + * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( options ) { - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( jQuery.isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = true; - if ( !memory ) { - self.disable(); - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = true; + if ( !memory ) { + self.disable(); + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; }; jQuery.extend( { - Deferred: function( func ) { - var tuples = [ - - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], - [ "notify", "progress", jQuery.Callbacks( "memory" ) ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this === promise ? newDefer.promise() : this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( function() { - - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || - ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. - // If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .progress( updateFunc( i, progressContexts, progressValues ) ) - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } + Deferred: function( func ) { + var tuples = [ + + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], + [ "notify", "progress", jQuery.Callbacks( "memory" ) ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this === promise ? newDefer.promise() : this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( function() { + + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || + ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. + // If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .progress( updateFunc( i, progressContexts, progressValues ) ) + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } } ); @@ -3538,69 +3538,69 @@ var readyList; jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); + // Add the callback + jQuery.ready.promise().done( fn ); - return this; + return this; }; jQuery.extend( { - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } } ); /** * Clean-up method for dom ready events */ function detach() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - - } else { - document.detachEvent( "onreadystatechange", completed ); - window.detachEvent( "onload", completed ); - } + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } } /** @@ -3608,81 +3608,81 @@ function detach() { */ function completed() { - // readyState === "complete" is good enough for us to call the dom ready in oldIE - if ( document.addEventListener || - window.event.type === "load" || - document.readyState === "complete" ) { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || + window.event.type === "load" || + document.readyState === "complete" ) { - detach(); - jQuery.ready(); - } + detach(); + jQuery.ready(); + } } jQuery.ready.promise = function( obj ) { - if ( !readyList ) { + if ( !readyList ) { - readyList = jQuery.Deferred(); + readyList = jQuery.Deferred(); - // Catch cases where $(document).ready() is called - // after the browser event has already occurred. - // Support: IE6-10 - // Older IE sometimes signals "interactive" too soon - if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + // Catch cases where $(document).ready() is called + // after the browser event has already occurred. + // Support: IE6-10 + // Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); - // Standards-based browsers support DOMContentLoaded - } else if ( document.addEventListener ) { + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); - // If IE event model is used - } else { + // If IE event model is used + } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", completed ); + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); - // A fallback to window.onload, that will always work - window.attachEvent( "onload", completed ); + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); - // If IE and not a frame - // continually check to see if the document is ready - var top = false; + // If IE and not a frame + // continually check to see if the document is ready + var top = false; - try { - top = window.frameElement == null && document.documentElement; - } catch ( e ) {} + try { + top = window.frameElement == null && document.documentElement; + } catch ( e ) {} - if ( top && top.doScroll ) { - ( function doScrollCheck() { - if ( !jQuery.isReady ) { + if ( top && top.doScroll ) { + ( function doScrollCheck() { + if ( !jQuery.isReady ) { - try { + try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll( "left" ); - } catch ( e ) { - return window.setTimeout( doScrollCheck, 50 ); - } + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll( "left" ); + } catch ( e ) { + return window.setTimeout( doScrollCheck, 50 ); + } - // detach all dom ready events - detach(); + // detach all dom ready events + detach(); - // and execute any waiting functions - jQuery.ready(); - } - } )(); - } - } - } - return readyList.promise( obj ); + // and execute any waiting functions + jQuery.ready(); + } + } )(); + } + } + } + return readyList.promise( obj ); }; // Kick off the DOM ready check even if the user does not @@ -3695,7 +3695,7 @@ jQuery.ready.promise(); // Iteration over object's inherited properties before its own var i; for ( i in jQuery( support ) ) { - break; + break; } support.ownFirst = i === "0"; @@ -3706,591 +3706,591 @@ support.inlineBlockNeedsLayout = false; // Execute ASAP in case we need to set body.style.zoom jQuery( function() { - // Minified: var a,b,c,d - var val, div, body, container; + // Minified: var a,b,c,d + var val, div, body, container; - body = document.getElementsByTagName( "body" )[ 0 ]; - if ( !body || !body.style ) { + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { - // Return for frameset docs that don't have a body - return; - } + // Return for frameset docs that don't have a body + return; + } - // Setup - div = document.createElement( "div" ); - container = document.createElement( "div" ); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild( container ).appendChild( div ); + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); - if ( typeof div.style.zoom !== "undefined" ) { + if ( typeof div.style.zoom !== "undefined" ) { - // Support: IE<8 - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; - support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; - if ( val ) { + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { - // Prevent IE 6 from affecting layout for positioned elements #11048 - // Prevent IE from shrinking the body in IE 7 mode #12869 - // Support: IE<8 - body.style.zoom = 1; - } - } + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } - body.removeChild( container ); + body.removeChild( container ); } ); ( function() { - var div = document.createElement( "div" ); - - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch ( e ) { - support.deleteExpando = false; - } - - // Null elements to avoid leaks in IE. - div = null; + var div = document.createElement( "div" ); + + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch ( e ) { + support.deleteExpando = false; + } + + // Null elements to avoid leaks in IE. + div = null; } )(); var acceptData = function( elem ) { - var noData = jQuery.noData[ ( elem.nodeName + " " ).toLowerCase() ], - nodeType = +elem.nodeType || 1; + var noData = jQuery.noData[ ( elem.nodeName + " " ).toLowerCase() ], + nodeType = +elem.nodeType || 1; - // Do not set data on non-element DOM nodes because it will not be cleared (#8335). - return nodeType !== 1 && nodeType !== 9 ? - false : + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : - // Nodes accept data unless otherwise specified; rejection can be conditional - !noData || noData !== true && elem.getAttribute( "classid" ) === noData; + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute( "classid" ) === noData; }; var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; + rmultiDash = /([A-Z])/g; function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - data = elem.getAttribute( name ); + data = elem.getAttribute( name ); - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch ( e ) {} + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch ( e ) {} - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); - } else { - data = undefined; - } - } + } else { + data = undefined; + } + } - return data; + return data; } // checks a cache object for emptiness function isEmptyDataObject( obj ) { - var name; - for ( name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[ name ] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[ name ] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; } function internalData( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !acceptData( elem ) ) { - return; - } - - var ret, thisCache, - internalKey = jQuery.expando, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) && - data === undefined && typeof name === "string" ) { - return; - } - - if ( !id ) { - - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - - // Avoid exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( typeof name === "string" ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; + if ( !acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) && + data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; } function internalRemoveData( elem, name, pvt ) { - if ( !acceptData( elem ) ) { - return; - } - - var thisCache, i, - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split( " " ); - } - } - } else { - - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = name.concat( jQuery.map( name, jQuery.camelCase ) ); - } - - i = name.length; - while ( i-- ) { - delete thisCache[ name[ i ] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( pvt ? !isEmptyDataObject( thisCache ) : !jQuery.isEmptyObject( thisCache ) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } - } - - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - /* jshint eqeqeq: false */ - } else if ( support.deleteExpando || cache != cache.window ) { - /* jshint eqeqeq: true */ - delete cache[ id ]; - - // When all else fails, undefined - } else { - cache[ id ] = undefined; - } + if ( !acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } else { + + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[ i ] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject( thisCache ) : !jQuery.isEmptyObject( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, undefined + } else { + cache[ id ] = undefined; + } } jQuery.extend( { - cache: {}, - - // The following elements (space-suffixed to avoid Object.prototype collisions) - // throw uncatchable exceptions if you attempt to set expando properties - noData: { - "applet ": true, - "embed ": true, - - // ...but Flash objects (which have this classid) *can* handle expandos - "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data ) { - return internalData( elem, name, data ); - }, - - removeData: function( elem, name ) { - return internalRemoveData( elem, name ); - }, - - // For internal use only. - _data: function( elem, name, data ) { - return internalData( elem, name, data, true ); - }, - - _removeData: function( elem, name ) { - return internalRemoveData( elem, name, true ); - } + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } } ); jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Special expections of .data basically thwart jQuery.access, - // so implement the relevant behavior ourselves - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); - - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - jQuery.data( this, key ); - } ); - } - - return arguments.length > 1 ? - - // Sets one value - this.each( function() { - jQuery.data( this, key, value ); - } ) : - - // Gets one value - // Try to fetch any internally stored data first - elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; - }, - - removeData: function( key ) { - return this.each( function() { - jQuery.removeData( this, key ); - } ); - } + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + jQuery.data( this, key ); + } ); + } + + return arguments.length > 1 ? + + // Sets one value + this.each( function() { + jQuery.data( this, key, value ); + } ) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each( function() { + jQuery.removeData( this, key ); + } ); + } } ); jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = jQuery._data( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, - // or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - jQuery._removeData( elem, type + "queue" ); - jQuery._removeData( elem, key ); - } ) - } ); - } + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = jQuery._data( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, + // or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + } ) + } ); + } } ); jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = jQuery._data( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } } ); ( function() { - var shrinkWrapBlocksVal; + var shrinkWrapBlocksVal; - support.shrinkWrapBlocks = function() { - if ( shrinkWrapBlocksVal != null ) { - return shrinkWrapBlocksVal; - } + support.shrinkWrapBlocks = function() { + if ( shrinkWrapBlocksVal != null ) { + return shrinkWrapBlocksVal; + } - // Will be changed later if needed. - shrinkWrapBlocksVal = false; + // Will be changed later if needed. + shrinkWrapBlocksVal = false; - // Minified: var b,c,d - var div, body, container; + // Minified: var b,c,d + var div, body, container; - body = document.getElementsByTagName( "body" )[ 0 ]; - if ( !body || !body.style ) { + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { - // Test fired too early or in an unsupported environment, exit. - return; - } + // Test fired too early or in an unsupported environment, exit. + return; + } - // Setup - div = document.createElement( "div" ); - container = document.createElement( "div" ); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild( container ).appendChild( div ); + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); - // Support: IE6 - // Check if elements with layout shrink-wrap their children - if ( typeof div.style.zoom !== "undefined" ) { + // Support: IE6 + // Check if elements with layout shrink-wrap their children + if ( typeof div.style.zoom !== "undefined" ) { - // Reset CSS: box-sizing; display; margin; border - div.style.cssText = + // Reset CSS: box-sizing; display; margin; border + div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;" + - "padding:1px;width:1px;zoom:1"; - div.appendChild( document.createElement( "div" ) ).style.width = "5px"; - shrinkWrapBlocksVal = div.offsetWidth !== 3; - } + // Support: Firefox<29, Android 2.3 + // Vendor-prefix box-sizing + "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + + "box-sizing:content-box;display:block;margin:0;border:0;" + + "padding:1px;width:1px;zoom:1"; + div.appendChild( document.createElement( "div" ) ).style.width = "5px"; + shrinkWrapBlocksVal = div.offsetWidth !== 3; + } - body.removeChild( container ); + body.removeChild( container ); - return shrinkWrapBlocksVal; - }; + return shrinkWrapBlocksVal; + }; } )(); var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; @@ -4302,130 +4302,130 @@ var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || - !jQuery.contains( elem.ownerDocument, elem ); - }; + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || + !jQuery.contains( elem.ownerDocument, elem ); + }; function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, - scale = 1, - maxIterations = 20, - currentValue = tween ? - function() { return tween.cur(); } : - function() { return jQuery.css( elem, prop, "" ); }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - do { - - // If previous iteration zeroed out, double until we get *something*. - // Use string for doubling so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - initialInUnit = initialInUnit / scale; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // Break the loop if scale is unchanged or perfect, or if we've just had enough. - } while ( - scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations - ); - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { return tween.cur(); } : + function() { return jQuery.css( elem, prop, "" ); }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; } // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - length = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < length; i++ ) { - fn( - elems[ i ], - key, - raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[ 0 ], key ) : emptyGet; + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( + elems[ i ], + key, + raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[ 0 ], key ) : emptyGet; }; var rcheckableType = ( /^(?:checkbox|radio)$/i ); @@ -4436,106 +4436,106 @@ var rscriptType = ( /^$|\/(?:java|ecma)script/i ); var rleadingWhitespace = ( /^\s+/ ); var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|" + - "details|dialog|figcaption|figure|footer|header|hgroup|main|" + - "mark|meter|nav|output|picture|progress|section|summary|template|time|video"; + "details|dialog|figcaption|figure|footer|header|hgroup|main|" + + "mark|meter|nav|output|picture|progress|section|summary|template|time|video"; function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; } ( function() { - var div = document.createElement( "div" ), - fragment = document.createDocumentFragment(), - input = document.createElement( "input" ); - - // Setup - div.innerHTML = "
        a"; - - // IE strips leading whitespace when .innerHTML is used - support.leadingWhitespace = div.firstChild.nodeType === 3; - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - support.tbody = !div.getElementsByTagName( "tbody" ).length; - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - support.html5Clone = - document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - input.type = "checkbox"; - input.checked = true; - fragment.appendChild( input ); - support.appendChecked = input.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE6-IE11+ - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - - // #11217 - WebKit loses check when the name is after the checked attribute - fragment.appendChild( div ); - - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input = document.createElement( "input" ); - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE<9 - // Cloned elements keep attachEvent handlers, we use addEventListener on IE9+ - support.noCloneEvent = !!div.addEventListener; - - // Support: IE<9 - // Since attributes and properties are the same in IE, - // cleanData must set properties to undefined rather than use removeAttribute - div[ jQuery.expando ] = 1; - support.attributes = !div.getAttribute( jQuery.expando ); + var div = document.createElement( "div" ), + fragment = document.createDocumentFragment(), + input = document.createElement( "input" ); + + // Setup + div.innerHTML = "
        a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input = document.createElement( "input" ); + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Cloned elements keep attachEvent handlers, we use addEventListener on IE9+ + support.noCloneEvent = !!div.addEventListener; + + // Support: IE<9 + // Since attributes and properties are the same in IE, + // cleanData must set properties to undefined rather than use removeAttribute + div[ jQuery.expando ] = 1; + support.attributes = !div.getAttribute( jQuery.expando ); } )(); // We have to close these tags to support XHTML (#13200) var wrapMap = { - option: [ 1, "" ], - legend: [ 1, "
        ", "
        " ], - area: [ 1, "", "" ], - - // Support: IE8 - param: [ 1, "", "" ], - thead: [ 1, "", "
        " ], - tr: [ 2, "", "
        " ], - col: [ 2, "", "
        " ], - td: [ 3, "", "
        " ], - - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
        ", "
        " ] + option: [ 1, "" ], + legend: [ 1, "
        ", "
        " ], + area: [ 1, "", "" ], + + // Support: IE8 + param: [ 1, "", "" ], + thead: [ 1, "", "
        " ], + tr: [ 2, "", "
        " ], + col: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
        ", "
        " ] }; // Support: IE8-IE9 @@ -4546,291 +4546,291 @@ wrapMap.th = wrapMap.td; function getAll( context, tag ) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( tag || "*" ) : - typeof context.querySelectorAll !== "undefined" ? - context.querySelectorAll( tag || "*" ) : - undefined; - - if ( !found ) { - for ( found = [], elems = context.childNodes || context; - ( elem = elems[ i ] ) != null; - i++ - ) { - if ( !tag || jQuery.nodeName( elem, tag ) ) { - found.push( elem ); - } else { - jQuery.merge( found, getAll( elem, tag ) ); - } - } - } - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], found ) : - found; + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? + context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; + ( elem = elems[ i ] ) != null; + i++ + ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; } // Mark scripts as having already been evaluated function setGlobalEval( elems, refElements ) { - var elem, - i = 0; - for ( ; ( elem = elems[ i ] ) != null; i++ ) { - jQuery._data( - elem, - "globalEval", - !refElements || jQuery._data( refElements[ i ], "globalEval" ) - ); - } + var elem, + i = 0; + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + jQuery._data( + elem, + "globalEval", + !refElements || jQuery._data( refElements[ i ], "globalEval" ) + ); + } } var rhtml = /<|&#?\w+;/, - rtbody = / from table fragments - if ( !support.tbody ) { - - // String was a , *may* have spurious - elem = tag === "table" && !rtbody.test( elem ) ? - tmp.firstChild : - - // String was a bare or - wrap[ 1 ] === "
        " && !rtbody.test( elem ) ? - tmp : - 0; - - j = elem && elem.childNodes.length; - while ( j-- ) { - if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) && - !tbody.childNodes.length ) { - - elem.removeChild( tbody ); - } - } - } - - jQuery.merge( nodes, tmp.childNodes ); - - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; - - // Fix #12392 for oldIE - while ( tmp.firstChild ) { - tmp.removeChild( tmp.firstChild ); - } - - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; - } - } - } - - // Fix #11356: Clear elements from fragment - if ( tmp ) { - safe.removeChild( tmp ); - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !support.appendChecked ) { - jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); - } - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a
        , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[ 1 ] === "
        " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) && + !tbody.childNodes.length ) { + + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); - // Append to fragment - tmp = getAll( safe.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - tmp = null; - - return safe; + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; } ( function() { - var i, eventName, - div = document.createElement( "div" ); + var i, eventName, + div = document.createElement( "div" ); - // Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events) - for ( i in { submit: true, change: true, focusin: true } ) { - eventName = "on" + i; + // Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events) + for ( i in { submit: true, change: true, focusin: true } ) { + eventName = "on" + i; - if ( !( support[ i ] = eventName in window ) ) { + if ( !( support[ i ] = eventName in window ) ) { - // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) - div.setAttribute( eventName, "t" ); - support[ i ] = div.attributes[ eventName ].expando === false; - } - } + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i ] = div.attributes[ eventName ].expando === false; + } + } - // Null elements to avoid leaks in IE. - div = null; + // Null elements to avoid leaks in IE. + div = null; } )(); var rformElems = /^(?:input|select|textarea)$/i, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { - return true; + return true; } function returnFalse() { - return false; + return false; } // Support: IE9 // See #13393 for more info function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } + try { + return document.activeElement; + } catch ( err ) { } } function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); } /* @@ -4839,774 +4839,774 @@ function on( elem, types, selector, data, fn, one ) { */ jQuery.event = { - global: {}, - - add: function( elem, types, handler, data, selector ) { - var tmp, events, t, handleObjIn, - special, eventHandle, handleObj, - handlers, type, namespaces, origType, - elemData = jQuery._data( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && - ( !e || jQuery.event.triggered !== e.type ) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - - // Add elem as a property of the handle fn to prevent a memory leak - // with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - var j, handleObj, tmp, - origCount, t, events, - special, handlers, type, - namespaces, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery._removeData( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - var handle, ontype, cur, - bubbleType, special, tmp, i, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && - jQuery._data( cur, "handle" ); - - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( - ( !special._default || - special._default.apply( eventPath.pop(), data ) === false - ) && acceptData( elem ) - ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - try { - elem[ type ](); - } catch ( e ) { - - // IE<9 dies on focus/blur to hidden element (#1486,#12518) - // only reproducible on winXP IE8 native, not IE9 in IE8 mode - } - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Support (at least): Chrome, IE9 - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // - // Support: Firefox<=42+ - // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) - if ( delegateCount && cur.nodeType && - ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { - - /* jshint eqeqeq: false */ - for ( ; cur != this; cur = cur.parentNode || this ) { - /* jshint eqeqeq: true */ - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push( { elem: cur, handlers: matches } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: IE<9 - // Fix target property (#1925) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Support: Safari 6-8+ - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Support: IE<9 - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) - event.metaKey = !!event.metaKey; - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + - "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split( " " ), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: ( "button buttons clientX clientY fromElement offsetX offsetY " + - "pageX pageY screenX screenY toElement" ).split( " " ), - filter: function( event, original ) { - var body, eventDoc, doc, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + - ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + - ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? - original.toElement : - fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - try { - this.focus(); - return false; - } catch ( e ) { - - // Support: IE<9 - // If we error on focus to hidden element (#1486, #12518), - // let .trigger() run the handlers - } - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - // Piggyback on a donor event to simulate a different one - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - - // Previously, `originalEvent: {}` was set here, so stopPropagation call - // would not be triggered on donor event, since in our own - // jQuery.event.stopPropagation function we had a check for existence of - // originalEvent.stopPropagation method, so, consequently it would be a noop. - // - // Guard for simulated events was moved to jQuery.event.stopPropagation function - // since `originalEvent` should point to the original event for the - // constancy with other events and for more focused logic - } - ); - - jQuery.event.trigger( e, null, elem ); - - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && + ( !e || jQuery.event.triggered !== e.type ) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + + // Add elem as a property of the handle fn to prevent a memory leak + // with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && + jQuery._data( cur, "handle" ); + + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( + ( !special._default || + special._default.apply( eventPath.pop(), data ) === false + ) && acceptData( elem ) + ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Support (at least): Chrome, IE9 + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // + // Support: Firefox<=42+ + // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) + if ( delegateCount && cur.nodeType && + ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push( { elem: cur, handlers: matches } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Safari 6-8+ + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + + "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split( " " ), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: ( "button buttons clientX clientY fromElement offsetX offsetY " + + "pageX pageY screenX screenY toElement" ).split( " " ), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - + ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - + ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? + original.toElement : + fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + // Piggyback on a donor event to simulate a different one + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + + // Previously, `originalEvent: {}` was set here, so stopPropagation call + // would not be triggered on donor event, since in our own + // jQuery.event.stopPropagation function we had a check for existence of + // originalEvent.stopPropagation method, so, consequently it would be a noop. + // + // Guard for simulated events was moved to jQuery.event.stopPropagation function + // since `originalEvent` should point to the original event for the + // constancy with other events and for more focused logic + } + ); + + jQuery.event.trigger( e, null, elem ); + + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } }; jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { + function( elem, type, handle ) { - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } - } : - function( elem, type, handle ) { - var name = "on" + type; + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; - if ( elem.detachEvent ) { + if ( elem.detachEvent ) { - // #8545, #7054, preventing memory leaks for custom events in IE6-8 - // detachEvent needed property on element, by name of that event, - // to properly expose it to GC - if ( typeof elem[ name ] === "undefined" ) { - elem[ name ] = null; - } + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, + // to properly expose it to GC + if ( typeof elem[ name ] === "undefined" ) { + elem[ name ] = null; + } - elem.detachEvent( name, handle ); - } - }; + elem.detachEvent( name, handle ); + } + }; jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: IE < 9, Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - if ( !e ) { - return; - } - - // If preventDefault exists, run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // Support: IE - // Otherwise set the returnValue property of the original event to false - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( !e || this.isSimulated ) { - return; - } - - // If stopPropagation exists, run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - - // Support: IE - // Set the cancelBubble property of the original event to true - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( !e || this.isSimulated ) { + return; + } + + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } }; // Create mouseenter/leave events using mouseover/out and event-time checks @@ -5618,155 +5618,155 @@ jQuery.Event.prototype = { // https://code.google.com/p/chromium/issues/detail?id=470258 // for the description of the bug (it existed in older Chrome versions as well). jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" }, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; } ); // IE submit delegation if ( !support.submit ) { - jQuery.event.special.submit = { - setup: function() { - - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? - - // Support: IE <=8 - // We use jQuery.prop instead of elem.form - // to allow fixing the IE8 delegated submit issue (gh-2332) - // by 3rd party polyfills/workarounds. - jQuery.prop( elem, "form" ) : - undefined; - - if ( form && !jQuery._data( form, "submit" ) ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submitBubble = true; - } ); - jQuery._data( form, "submit", true ); - } - } ); - - // return undefined since we don't need an event listener - }, - - postDispatch: function( event ) { - - // If form was submitted by the user, bubble the event up the tree - if ( event._submitBubble ) { - delete event._submitBubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event ); - } - } - }, - - teardown: function() { - - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; + jQuery.event.special.submit = { + setup: function() { + + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? + + // Support: IE <=8 + // We use jQuery.prop instead of elem.form + // to allow fixing the IE8 delegated submit issue (gh-2332) + // by 3rd party polyfills/workarounds. + jQuery.prop( elem, "form" ) : + undefined; + + if ( form && !jQuery._data( form, "submit" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submitBubble = true; + } ); + jQuery._data( form, "submit", true ); + } + } ); + + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + + // If form was submitted by the user, bubble the event up the tree + if ( event._submitBubble ) { + delete event._submitBubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event ); + } + } + }, + + teardown: function() { + + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; } // IE change delegation and checkbox/radio fix if ( !support.change ) { - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._justChanged = true; - } - } ); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._justChanged && !event.isTrigger ) { - this._justChanged = false; - } - - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate( "change", this, event ); - } ); - } - return false; - } - - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "change" ) ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event ); - } - } ); - jQuery._data( elem, "change", true ); - } - } ); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || - ( elem.type !== "radio" && elem.type !== "checkbox" ) ) { - - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return !rformElems.test( this.nodeName ); - } - }; + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._justChanged = true; + } + } ); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._justChanged && !event.isTrigger ) { + this._justChanged = false; + } + + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event ); + } ); + } + return false; + } + + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "change" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event ); + } + } ); + jQuery._data( elem, "change", true ); + } + } ); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || + ( elem.type !== "radio" && elem.type !== "checkbox" ) ) { + + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; } // Support: Firefox @@ -5778,659 +5778,659 @@ if ( !support.change ) { // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order // Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857 if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = jQuery._data( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = jQuery._data( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - jQuery._removeData( doc, fix ); - } else { - jQuery._data( doc, fix, attaches ); - } - } - }; - } ); + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + } ); } jQuery.fn.extend( { - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - }, - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + }, + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } } ); var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, + rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, - // Support: IE 10-11, Edge 10240+ - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) ); + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*\s*$/g, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) ); // Support: IE<8 // Manipulating tables requires a tbody function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - elem.getElementsByTagName( "tbody" )[ 0 ] || - elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) : - elem; + elem.getElementsByTagName( "tbody" )[ 0 ] || + elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) : + elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { - elem.type = ( jQuery.find.attr( elem, "type" ) !== null ) + "/" + elem.type; - return elem; + elem.type = ( jQuery.find.attr( elem, "type" ) !== null ) + "/" + elem.type; + return elem; } function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute( "type" ); - } - return elem; + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + return elem; } function cloneCopyEvent( src, dest ) { - if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { - return; - } - - var type, i, l, - oldData = jQuery._data( src ), - curData = jQuery._data( dest, oldData ), - events = oldData.events; - - if ( events ) { - delete curData.handle; - curData.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - - // make the cloned public data object a copy from the original - if ( curData.data ) { - curData.data = jQuery.extend( {}, curData.data ); - } + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } } function fixCloneNodeIssues( src, dest ) { - var nodeName, e, data; - - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } - - nodeName = dest.nodeName.toLowerCase(); - - // IE6-8 copies events bound via attachEvent when using cloneNode. - if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { - data = jQuery._data( dest ); - - for ( e in data.events ) { - jQuery.removeEvent( dest, e, data.handle ); - } - - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute( jQuery.expando ); - } - - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if ( nodeName === "script" && dest.text !== src.text ) { - disableScript( dest ).text = src.text; - restoreScript( dest ); - - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if ( nodeName === "object" ) { - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) { - dest.innerHTML = src.innerHTML; - } - - } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.defaultSelected = dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } } function domManip( collection, args, callback, ignored ) { - // Flatten any nested arrays - args = concat.apply( [], args ); - - var first, node, hasScripts, - scripts, doc, fragment, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android<4.1, PhantomJS<2 - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !jQuery._data( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( - ( node.text || node.textContent || node.innerHTML || "" ) - .replace( rcleanScript, "" ) - ); - } - } - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - } - } - - return collection; + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( + ( node.text || node.textContent || node.innerHTML || "" ) + .replace( rcleanScript, "" ) + ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return collection; } function remove( elem, selector, keepData ) { - var node, - elems = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; + var node, + elems = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; - for ( ; ( node = elems[ i ] ) != null; i++ ) { + for ( ; ( node = elems[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } - return elem; + return elem; } jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var destElements, node, clone, i, srcElements, - inPage = jQuery.contains( elem.ownerDocument, elem ); - - if ( support.html5Clone || jQuery.isXMLDoc( elem ) || - !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - - clone = elem.cloneNode( true ); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } - - if ( ( !support.noCloneEvent || !support.noCloneChecked ) && - ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - // Fix all IE cloning issues - for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) { - - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[ i ] ) { - fixCloneNodeIssues( node, destElements[ i ] ); - } - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) { - cloneCopyEvent( node, destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - destElements = srcElements = node = null; - - // Return the cloned set - return clone; - }, - - cleanData: function( elems, /* internal */ forceAcceptData ) { - var elem, type, id, data, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - attributes = support.attributes, - special = jQuery.event.special; - - for ( ; ( elem = elems[ i ] ) != null; i++ ) { - if ( forceAcceptData || acceptData( elem ) ) { - - id = elem[ internalKey ]; - data = id && cache[ id ]; - - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { - - delete cache[ id ]; - - // Support: IE<9 - // IE does not allow us to delete expando properties from nodes - // IE creates expando attributes along with the property - // IE does not have a removeAttribute function on Document nodes - if ( !attributes && typeof elem.removeAttribute !== "undefined" ) { - elem.removeAttribute( internalKey ); - - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://code.google.com/p/chromium/issues/detail?id=378607 - } else { - elem[ internalKey ] = undefined; - } - - deletedIds.push( id ); - } - } - } - } - } + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc( elem ) || + !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( ( !support.noCloneEvent || !support.noCloneChecked ) && + ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) { + + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[ i ] ) { + fixCloneNodeIssues( node, destElements[ i ] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) { + cloneCopyEvent( node, destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + cleanData: function( elems, /* internal */ forceAcceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + attributes = support.attributes, + special = jQuery.event.special; + + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + if ( forceAcceptData || acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // Support: IE<9 + // IE does not allow us to delete expando properties from nodes + // IE creates expando attributes along with the property + // IE does not have a removeAttribute function on Document nodes + if ( !attributes && typeof elem.removeAttribute !== "undefined" ) { + elem.removeAttribute( internalKey ); + + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://code.google.com/p/chromium/issues/detail?id=378607 + } else { + elem[ internalKey ] = undefined; + } + + deletedIds.push( id ); + } + } + } + } + } } ); jQuery.fn.extend( { - // Keep domManip exposed until 3.0 (gh-2225) - domManip: domManip, - - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().append( - ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) - ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - } - - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); - } - - // If this is a select, ensure that it displays empty (#12336) - // Support: IE<9 - if ( elem.options && jQuery.nodeName( elem, "select" ) ) { - elem.options.length = 0; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined ) { - return elem.nodeType === 1 ? - elem.innerHTML.replace( rinlinejQuery, "" ) : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - - // Remove element nodes and prevent memory leaks - elem = this[ i ] || {}; - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } + // Keep domManip exposed until 3.0 (gh-2225) + domManip: domManip, + + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( + ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) + ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + + // Remove element nodes and prevent memory leaks + elem = this[ i ] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } } ); jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" }, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; } ); var iframe, - elemdisplay = { + elemdisplay = { - // Support: Firefox - // We have to pre-define these values for FF (#10227) - HTML: "block", - BODY: "block" - }; + // Support: Firefox + // We have to pre-define these values for FF (#10227) + HTML: "block", + BODY: "block" + }; /** * Retrieve the actual display of a element @@ -6440,15 +6440,15 @@ var iframe, // Called only from within defaultDisplay function actualDisplay( name, doc ) { - var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - display = jQuery.css( elem[ 0 ], "display" ); + display = jQuery.css( elem[ 0 ], "display" ); - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); - return display; + return display; } /** @@ -6456,58 +6456,58 @@ function actualDisplay( name, doc ) { * @param {String} nodeName */ function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; + var doc = document, + display = elemdisplay[ nodeName ]; - if ( !display ) { - display = actualDisplay( nodeName, doc ); + if ( !display ) { + display = actualDisplay( nodeName, doc ); - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { - // Use the already-created iframe if possible - iframe = ( iframe || jQuery( " + +
        +

        +Data by Sincera +

        +
        + +Prebid is more than a product; it’s a product suite, a community, and an independent organization. + +- **Product Suite:** A free and open source suite of software products that enables publishers to implement header bidding on websites and mobile apps. +- **Community:** Our community is comprised of developers from companies across the ad tech industry who maintain and improve our products. +- **Organization:** Prebid.org is an active membership of leaders within the ad tech industry that promotes Prebid products and works with the ad tech community to define and implement enhanced solutions. For more about the organization, see Prebid.org. + +![Prebid organization](/assets/images/intros/prebid-intro.png){: .center-image } -## Benefits of Prebid Products +{: .alert.alert-info :} +Our flagship product, Prebid.js, is sometimes referred to as simply Prebid, but the Prebid product line supports header bidding for web, AMP, and mobile apps, using both client- and server-side components. + +## A Brief History of Prebid -The Prebid product suite offers publishers multiple benefits designed to foster a better header bidding experience, including: +The early days of header bidding were dominated by bad practices, proprietary tech, poor standards, and little to no cooperation between competing companies. Publishers were presented with the confusing and time-consuming process of having to manually patch together various solutions from different companies and processes. -- A free and open source set of solutions, enabling anyone to contribute or review code. -- The largest repository of working header bidding adapters. -- Asynchronous and single time-out to provide a better user experience. -- Prebid Server, to run faster auctions with more partners. -- Modules, tools, and analytics support to optimize publisher setup. -- Multiple options on formats (display, video, native) and channels (mobile, web). -- A well established and helpful community that can advise on best practices and, if needed, provide professional setup and services. +Launched in 2015 as a collaboration of several leading ad tech companies, Prebid.js was developed to make header bidding easy for publishers by bringing conformity and simplicity to the header bidding process. Prebid.js provided a simple, open tech layer upon which companies could add their code to a standard but optimized foundation, and connected publishers and advertisers to demand side partners. Over time, more ad tech companies and individual contributors joined the collaboration, making Prebid the most widely used header bidding “container” or “wrapper” available. Today the ecosystem supports more than 300 demand partners, about 50 analytics providers, and thousands of websites. ## Prebid Products +Since the launch of Prebid.js, the Prebid line or products has continued to grow. Our product line includes: + +- **Prebid.js:** Provides a powerful and easy-to-implement code set to improve header bidding for display and video ads on a publisher’s website and within OTT applications. +- **Prebid Server:** Provides a server-side solution for header bidding. Utilizing Prebid Server can support additional use cases such as mobile apps, reduce latency between bid request and ad selection, and speed the presentation of your site and ads. Can be used as an option for managing the number of bidders, with some calls to bidders through the client and some server-side. +- **Prebid Mobile:** Our native iOS and Android solutions to enable header bidding within a mobile app. +- **SharedID:** Native hosted ID offering that is simple, free, robust, and privacy-minded. + ### Prebid.js -Prebid.js is the core product of the Prebid suite. It supports multiple formats include display, video, and native, and provides a simple process for header bidding that can be ramped up to fit the complexity of your needs. +Prebid.js is a JavaScript library that runs in the browser, and is the core product of the Prebid suite. It supports multiple formats including display, video, and native, and provides a simple process for header bidding that can be ramped up to fit the complexity of your needs. -**Reducing Latency** +One of the many benefits to using Prebid.js as your header bidding solution is its ability to reduce latency. Latency - the delay between the bid requests being sent and the responses being returned - is one of the main concerns publishers have with header bidding. Prebid addresses this issue by concurrently calling the selected bidders within the set timeout. That setting is respected by Prebid.js, and any bidder not returning a result within the timeout duration is excluded from the auction. This dramatically decreases the page load time, providing a better user experience. (See [“Prebid and Latency”](#latency) below for more information on latency.) -One of the main problems publishers have experienced with other header bidding solutions is the delay between the bid requests being sent and the responses being returned. Some solutions use synchronous calls, meaning each bidder has to receive the request and return a response before the next bidder is called. This can lead to a long delay between when the web page is called and when it is actually loaded. -Prebid resolves this issue by concurrently calling the selected bidders within the set timeout. That setting is respected by Prebid.js, and any bidder not returning a result within the timeout duration is excluded from the auction. This dramatically decreases the page load time, providing a better user experience. +See [What is Prebid.js?](/prebid/prebidjs.html) for more information. -**Prebid.js process** +### Prebid Server -A simple Prebid.js process follows these steps: -1. The ad server's tag is paused by a timer while Prebid.js sends out bid requests to selected bidders. -2. Creatives and bids are returned from the bidders. -3. From the bid responses, Prebid.js finds a winner (if applicable) and caches the creatives. -4. Prebid passes the winning bid parameters to the ad server as key-values. -5. The ad server takes those key-values and finds a matching line item and compares to other line items that bid on this impression. -6. If the ad server determines Prebid wins the auction it returns a signal to Prebid.js, which then writes the creative to the page. +Prebid Server (PBS) provides a powerful framework for a server-side solution to header bidding. Built on the same core principles as Prebid.js, our server solution can reduce latency and improve page load time. A server-side solution to header bidding is required in environments that don’t have HTML header sections in which to put JavaScript, such as mobiles apps and Accelerated Mobile Pages (AMP) sites. -![Prebid.js Simple Flowchart](/assets/images/flowcharts/pb-js-simple.png) +When a publisher chooses to push auctions to the server side, they’re doing it to lighten the load that header bidding has on the browser. For instance, if five bidders are moved from the client side to the server side, the browser just makes one request to PBS, which delegates the actual auctions to the server, lightening the load on the user's device. -### Prebid Server +Several Prebid.org members provide [managed solutions](https://prebid.org/product-suite/managed-services/), enabling publishers to receive the benefits of server-side header bidding without the need to implement and manage the process themselves. -Prebid Server provides a server-side solution to header bidding. Built on the same core principles as Prebid.js, our server solution can reduce latency and improve page load time. +If a publisher would prefer to implement their own solution, source code in Go and Java is available from our Github page and instructions for configuring, deploying and testing your implementation can be found in the Prebid Server section of this site. -When a pub chooses to push auctions to the server-side, they're doing it to -lighten the load that header bidding has on the browser. For instance, if 5 -bidders are moved from the client-side to the server-side, the browser just makes -one request to PBS, which fans out the actual 5 auctions across server-to-server -connections. +See [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) for more information. -Several Prebid.org members provide [hosted solutions](https://prebid.org/product-suite/managed-services/), enabling publishers to receive the benefits of server-side header bidding without the need to implement and manage the process themselves. +### Prebid Mobile -If a publisher would prefer to implement their own solution, source code in [Go](https://github.com/prebid/prebid-server) or [Java](https://github.com/prebid/prebid-server-java) is available from our Github page and detailed instructions for configuring, deploying and testing your implementation can be found in the [Prebid Server section](/prebid-server/overview/prebid-server-overview.html) of this site. +For mobile apps, Prebid provides Prebid Mobile (PBM) SDK, an end-to-end header bidding solution for both iOS and Android. Working in conjunction with Prebid Server, PBM enables access to more mobile buyers and provides options for banner, interstitial, and native ad formats as well as video ads. -**Prebid Server process** +See [Prebid Mobile Overview](/prebid-mobile/prebid-mobile.html) for more information. -Prebid Server (PBS) provides multiple endpoints for auctions as well as data retrieval and supports the AMP (accelerated mobile pages) format. The primary endpoint is `/openrtb2/auction` and the process follows these steps: +### SharedID -1. An OpenRTB request is sent to Prebid Server. -2. Prebid Server conducts the auction with selected SSPs and ad exchanges. -3. PBS collects the bids and creatives. -4. PBS passes the winning bid parameters to Prebid.js the ad server. -5. The ad server takes the passed in key-values and finds a matching line item and then compares to other line items that bid on this impression. -6. If the ad server determines Prebid wins the auction it returns the Prebid Universal Creative -7. The Prebid Universal Creative displays the winning ad. +SharedId is a first party identifier. For more information, see [Prebid SharedID](/identity/sharedid.html). -![Prebid Server Flowchart](/assets/images/flowcharts/pb-server-display.png) +### Modules -See the [Prebid Server documentation](/prebid-server/overview/prebid-server-overview.html) for more use cases including [AMP](/prebid-server/use-cases/pbs-amp.html) and [Mobile App](/prebid-server/use-cases/pbs-sdk.html). +Along with our suite of products, Prebid comes with modules that enable you to implement the header bidding solution that’s right for you. A module is add-on code that is outside the core Prebid.js functionality, all of which have been provided by a thriving ecosystem of contributors. There are many different types of modules, including bid adapters, analytics adapters, real-time data modules, user ID modules, and others. -### Prebid Mobile +Bid adapter modules are used to communicate with the bidders (SSPs, DSPs, and exchanges) that will be participating in the header bidding auction. Bidders create these adapters and submit them to Prebid, where they’re reviewed and tested before being made publicly available. You choose your adapters when you build or download Prebid.js. (You can also add them in later.) To help you determine the adapters that are available and decide which are right for you, Prebid provides a spreadsheet that lists all Prebid bid adapters and information about them, including media formats, regulatory compliance, etc. Download the CSV spreadsheet. + +Analytics adapter modules allow you to gather analytics from Prebid.js and send them to your analytics provider (such as Google Analytics). See [Prebid.js Analytics Adapters](/overview/analytics.html) for more information. + +Additional modules are available that support identity, price floors, testing, currency, and much more. See [Prebid.js Module Overview](/dev-docs/modules/) for more information. + + + +
        +

        +Data by Sincera +

        +
        + +## Benefits of Using Prebid Products + +The Prebid product suite offers publishers multiple benefits designed to foster a better header bidding experience, including: + +- A free and open source set of solutions, enabling anyone to contribute or review code. +- Ongoing innovations across all products and channels, led by strategic working groups of Prebid.org members. +- The largest repository of working header bidding adapters. +- Asynchronous and single time-out to provide a better user experience. +- Prebid Server, to support non-JavaScript scenarios and to run faster auctions with more partners. +- Modules, tools, and analytics support to optimize publisher setup. +- Multiple options on formats (display, video, native) and channels (mobile, web). +- A well established and helpful community that can advise on best practices and, if needed, provide professional setup and services. +- Troubleshooting and support, where members answer questions through issues raised in Github. + +![Prebid Benefits](/assets/images/intros/prebid-benefits.png){: .center-image } + +## Prebid Integration and Maintenance + +Publishers who don’t have engineering and/or ad ops resources available can still implement header bidding with Prebid by working with a managed service company that can integrate and maintain Prebid for you. See the [list of Prebid.org members who provide managed services](https://prebid.org/product-suite/managed-services/) if this is the right option for your organization. + +If you decide to use in-house resources to implement Prebid, keep in mind that regular software upgrades are critical. Prebid is continually releasing bug fixes, performance improvements, new features, better regulation support, etc. We suggest you upgrade at least every six months. + + + +
        +

        +Data by Sincera +

        +
        + + + +## Prebid and Latency + +With header bidding, the publisher creates a short delay in their ad serving to obtain bids that might be used in the ad decisioning. Often a major concern with this process is the latency caused by this delay. By delaying the ad serving, you may lose impressions from users who bounce very quickly. Prebid provides several options for minimizing this issue. + +- Minimize the number of bidders that will be allowed to participate in the header bidding auction. The fewer demand partners that have the opportunity to bid, the fewer the bids, and therefore the faster the processing. But fewer demand partners also means fewer chances for an optimal bid. It might require some time and experimentation to determine the optimal number. Client-side implementations typically use 5 – 15 demand partners. Because of the faster processing speeds, server-side will often have more. +- Use Prebid Server to do the processing rather than the client browser. Passing the load of running auctions to the server can be faster than running them client-side from the browser. You can also use a combination of client and server processing to optimize your yield while still reducing latency. +- Set a time limit for receiving bids. Prebid provides the option for you to set a time limit. Any demand partner who hasn’t responded with a bid within the time allotted will not be included in the auction. See [Timeouts](/features/timeouts.html) for more information. +- Asynchronous Processing. Requests are sent to all bidders at once, rather than one at a time. + +We recommend that publishers do A/B testing on the number of bidders, timeout values, and client-vs-server for their specific pages. If your org doesn't do a lot of A/B testing, several of the managed services can help in this area. + +## Community Support + +If you ever need support, simply raise an issue on [one of our Github repositories](https://github.com/prebid). We also provide extensive documentation not only on our products but on how to integrate them with various ad servers. -For mobile apps, Prebid provides Prebid Mobile (PBM) SDK: an end-to-end header bidding solution for both iOS and Android. Working in conjunction with Prebid Server, PBM reduces latency and enables access to more mobile buyers, provides options for banner and interstitial ad formats, and enables user to set global targeting values for the bid request. +Prebid also has an active member community that ensures Prebid will continue to grow and evolve in a way that is beneficial to the header bidding ecosystem. Through a variety of committees, Prebid.org members continually decide on and prioritizes new features, updates, and fixes. -**Prebid Mobile process** +## Prebid Membership -The PBM header bidding process follows these steps: +The ad server you’re working with makes their money by taking a cut of the winning bid price, so you might be wondering if Prebid also takes a cut. The answer is NO. Prebid is free to anyone who wants to use it. So how does Prebid continue to evolve as a quality set of products (not to mention provide events and great documentation) without taking in fees? Through dedicated volunteers from member companies, alongside a small handful of employees and an occasional contractor paid through Prebid.org membership dues. All dues go into serving the Prebid community and providing a voice for our members in the world of header bidding. -1. Prebid Mobile sends a request to Prebid Server. This request consists of the Prebid Server account ID and config ID for each tag included in the request. -2. Prebid Server constructs an OpenRTB bid request and passes it to the demand partners. -3. Each demand partner returns a bid response to Prebid Server. The bid response includes the bid price and the creative content. -4. Prebid Server sends the bid responses to Prebid Mobile. -5. Prebid Mobile sets key-value targeting for each ad slot through the primary ad server mobile SDK. This targeting will activate one or more of Prebid line items that were previously configured in the primary ad server. -6. If the line item associated with the Prebid Mobile bid wins, the primary ad server returns the Prebid Universal Creative JavaScript to the ad server’s SDK. -7. The Prebid Universal Creative JavaScript will fetch and render the corresponding creative content from the winning Prebid Server demand partner. +You don’t have to be a Prebid.org member to use Prebid. However, we do highly encourage you to explore the benefits of membership and consider joining. No matter the size of your company, Prebid has membership options available that will provide value to anyone interested in header bidding today and in the future. For more information on Prebid.org membership, see [Prebid.org Membership Overview](https://prebid.org/membership/). -![Prebid Mobile Flowchart](/assets/images/flowcharts/pb-mobile.png) +## Related Reading -## Further Reading -+ [Prebid.js](/prebid/prebidjs.html) -+ [Prebid Server](/prebid-server/overview/prebid-server-overview.html) -+ [Prebid Mobile](/prebid-mobile/prebid-mobile.html) -+ [Managed Prebid Solutions](https://prebid.org/product-suite/managed-services/) +- [Introduction to Header Bidding](/overview/intro-to-header-bidding-video.html) +- [Prebid Product Suite](https://prebid.org/product-suite/) +- [What is Prebid.js](/prebid/prebidjs.html) diff --git a/overview/optimal-header-bidding-setup.md b/overview/optimal-header-bidding-setup.md index 64993e94f0..0d2b5382c5 100644 --- a/overview/optimal-header-bidding-setup.md +++ b/overview/optimal-header-bidding-setup.md @@ -1,6 +1,6 @@ --- layout: page_v2 -title: Optimal Header Bidding Setup +title: Analyze Header Bidding Setup description: What is the optimal header bidding setup and some common problems. pid: 10 @@ -13,10 +13,9 @@ sidebarType: 3 -# Optimal Header Bidding Setup +# Analyze Header Bidding Setup - -### What's a good header bidding auction: +## What's a good header bidding auction
        @@ -27,7 +26,6 @@ sidebarType: 3
        - This setup (captured using [Headerbid Expert](https://chrome.google.com/webstore/detail/headerbid-expert/cgfkddgbnfplidghapbbnngaogeldmop)) has demonstrated a few facts that made it an ideal header bidding auction. **1. Asynchronous Calls** @@ -44,10 +42,9 @@ The ad server sees the impression and header bidding info immediately after all
        -### Poor Header Bidding Setup Examples: - -#### Scenario 1 +## Poor Header Bidding Setup Examples +### Scenario
        @@ -67,8 +64,7 @@ The ad server sees the impression and header bidding info immediately after all
        - -#### Scenario 2 +### Scenario 2
        @@ -79,18 +75,16 @@ The ad server sees the impression and header bidding info immediately after all
        - **Problem**: This site is under monetized. **Cause**: Too many bidder's bids got ignored, because they responded later than the ad server request was sent out. **How to fix**: Load these bidders earlier in the header, or experiment with extending the timeout without causing impression loss. -
        -#### Scenario 3 +### Scenario 3
        @@ -110,8 +104,7 @@ The ad server sees the impression and header bidding info immediately after all
        -#### Scenario 4 - +### Scenario 4
        @@ -133,7 +126,7 @@ The ad server sees the impression and header bidding info immediately after all
        -### Analyze Your Own Site +## Analyze Your Own Site Add the Plugin [Headerbid Expert](https://chrome.google.com/webstore/detail/headerbid-expert/cgfkddgbnfplidghapbbnngaogeldmop) to your browser. @@ -141,9 +134,3 @@ Add the Plugin [Headerbid Expert](https://chrome.google.com/webstore/detail/head headerbid-expert-logo
        - - - - - - diff --git a/overview/prebid-management-committees.md b/overview/prebid-management-committees.md index 459d6b1a90..ff023edd62 100644 --- a/overview/prebid-management-committees.md +++ b/overview/prebid-management-committees.md @@ -6,11 +6,13 @@ sidebarType: 0 --- # Project Management Committees + {: .no_toc} -This page has moved to [https://prebid.org/project-management-committees/](https://prebid.org/project-management-committees/)! +This page has moved to [prebid.org/project-management-committees/](https://prebid.org/project-management-committees/)! ## Further Reading + {: .no_toc} * [What is Prebid.org?](/overview/what-is-prebid-org.html) diff --git a/overview/prebid-universal-creative.md b/overview/prebid-universal-creative.md index 29e28e06d2..522bd1b2b7 100644 --- a/overview/prebid-universal-creative.md +++ b/overview/prebid-universal-creative.md @@ -11,7 +11,7 @@ nav_section: intro # Prebid Universal Creative {:.no_toc} -* TOC +- TOC {:toc} ## Overview @@ -24,26 +24,38 @@ when a Prebid ad has won the auction. There are a number of use cases: {: .table .table-bordered .table-striped } | Use Case | PUC file | Alternate Approach | | --- | --- | --- | -| web banner: iframe | creative.js | [Banner and Outstream Video iframes](#banner-and-outstream-video-iframes) | -| web banner: safeframe | creative.js | [Banner Safeframes](#banner-safeframes) | -| web outstream video: iframe | creative.js | [Banner and Outstream Video iframes](#banner-and-outstream-video-iframes) | +| web banner: iframe | banner.js (or creative.js) | [Dynamic creatives](#alt-dyn), [Banner and Outstream Video iframes](#alt-iframes) | +| web banner: safeframe | banner.js (or creative.js) | [Dynamic creatives](#alt-dyn), [Banner Safeframes](#alt-safeframes) | +| web outstream video: iframe | video.js (or creative.js) | [Dynamic creatives](#alt-dyn), [Banner and Outstream Video iframes](#alt-iframes) | | web outstream video: safeframe | n/a | Outstream renderers each choose where to render differently, but none writes to the safeframe. | -| AMP banner: always safeframe | creative.js | n/a | -| native: iframe | native-render.js | n/a | -| native: safeframe | native-render.js | n/a | +| AMP banner: always safeframe | amp.js (or creative.js) | n/a | +| native: iframe | native.js (or native-render.js) | [Dynamic creatives](#alt-dyn) | +| native: safeframe | native.js (or native-render.js) | [Dynamic creatives](#alt-dyn) | -The Prebid Universal Creative is the simplest approach for publishers to configure Prebid in their ad server. The PUC provides a creative configuration that can be used across several formats, platforms, devices, and ad servers. +Note that as of PUC v1.15, the recommended way of loading the creative +in the ad server involves using the `hb_format` ad server key-value. Before 1.15, the ad server needed to load creative.js which covered banner and outstream video, or native-render.js for native. 1.15 simplifies this +by allowing the ad server creative to load banner.js, video.js, or native.js, which can be done programmatically using ad server macros. e.g. -Here are the features of the PUC in various scenarios: +```html + +``` + +This loads the PUC from the Prebid-maintained location. Your managed +service provider may have a different location. + +## Features of the PUC ### What the PUC does for Web iframe Banners/Outstream + 1. Simply calls the Prebid.js renderAd function ### What the PUC does for Web Safeframe Banners + 1. Calls PostMessage to get the winning ad from Prebid.js 1. Creates an iframe of the appropriate size and displays the winning ad within it ### What the PUC does for AMP and Mobile Apps + 1. Updates the size of the iframe to the size of the winning ad. 1. Retrieves the body of the creative from Prebid Cache based on the UUID 1. If the 'burl' parameter is present, creates a tracking pixel. Includes special support for triggering the viewable billing url for mobile MRAID creatives. @@ -52,6 +64,7 @@ Here are the features of the PUC in various scenarios: 1. Resolves any `${AUCTION_PRICE}` macro in the creative body. ### What the PUC does for Native + 1. Retrieves the native attributes from the winning ad. 1. Coordinates the rendering of the native ad using the template method specified by the publisher. @@ -64,46 +77,38 @@ While Prebid recommends the use of creative.js because we regularly add features and fix bugs, publishers may choose to hardcode the functionality into their ad server creatives. -They would do this differently for each of the scenarios below. + -### Alternate method for Banner and Outstream Video iframes +### Prebid.js dynamic creatives -If you only ever need to display non-safeframed banner and outstream-video creatives, you may use -the simple approach of just calling the Prebid.js `renderAd` function directly: +If you only need to display creatives rendered by Prebid.js (as opposed platforms like AMP or mobile SDKs), +you can avoid loading the PUC script - and the performance cost that entails - but still keep some of its advantages, such as regular updates, +by using [Prebid.js dynamic creatives](/adops/js-dynamic-creative.html). -``` - -``` + -### Alternate Method for Banner Safeframes +### Alternate methods for Banner and Outstream Video iframes -See the example at [https://github.com/prebid/Prebid.js/blob/master/integrationExamples/gpt/x-domain/creative.html](https://github.com/prebid/Prebid.js/blob/master/integrationExamples/gpt/x-domain/creative.html) +If you only ever need to display non-safeframed banner and outstream-video creatives, there are several ways to replace the `jsdelivr` call in your ad server creative: -This is basically just part of the PUC that's been isolated to be standalone. +1. Copy the contents of `https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js` into each creative. +1. Directly call the Prebid.js `renderAd` function: -## More Information - -### Google Ad Manager - -- [Step by Step Guide to Google Ad Manager Setup](/adops/step-by-step.html) - -### AMP - -- Adops: [Setting Up Prebid for AMP in Google Ad Manager](/adops/setting-up-prebid-for-amp-in-dfp.html) -- Developer: [Show Prebid Ads on AMP Pages](/dev-docs/show-prebid-ads-on-amp-pages.html) - -### Mobile App +```html + +``` -- [Step by Step Line Item Setup for Google Ad Manager](/prebid-mobile/adops-line-item-setup-dfp.html) -- [Step by Step Line Item Setup for MoPub](/prebid-mobile/adops-line-item-setup-mopub.html) + -### Native +### Alternate Method for Banner Safeframes -- [Setting up Prebid Native in GAM](/adops/gam-native.html) +If safeframe support is required, some options are: -### AppNexus Publisher Adserver +1. Copy the contents of `https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js` into each ad server creative. +2. [Prebid.js dynamic creatives](/adops/js-dynamic-creative.html) -- [Setting up Prebid with the AppNexus Publisher Ad Server](/adops/setting-up-prebid-with-the-appnexus-ad-server.html) +## Further Reading -### Other -- [Send All Bids to the Ad Server - Ad Ops Setup](/adops/send-all-bids-adops.html) +- [Step by Step Guide to Google Ad Manager Setup](/adops/step-by-step.html) +- [Setting up Prebid with the Xandr Monetize Ad Server](/adops/setting-up-prebid-with-the-appnexus-ad-server.html) +- [Prebid.js dynamic creatives](/adops/js-dynamic-creative.html) diff --git a/overview/what-is-post-bid.md b/overview/what-is-post-bid.md index 0bbd22b652..ab0ea3dadc 100644 --- a/overview/what-is-post-bid.md +++ b/overview/what-is-post-bid.md @@ -29,30 +29,29 @@ Steps: 2. The ad server chooses a winning line item among 'class 1' (direct-sold ads), exchanges, and the post-bid line items. In the case shown here, the post-bid line item wins. 3. The post-bid line item’s creative is served to the page. The creative runs an auction for the bidders using prebid.js, which then displays the highest price creative in that creative’s ad slot. - -### Why Post-Bid? +## Why Post-Bid? The main reasons we have seen publishers opt for post-bid (instead of header bidding) are: -#### 1. A post-bid setup does not need engineering resources. +### 1. A post-bid setup does not need engineering resources The post-bid creative is just a 3rd party tag. Once it’s served to the page, prebid.js runs an auction across all demand sources. The only technical work is to insert the tag Ids into the 3rd party tag’s JSON config for the demand sources. It’s trivial work. -#### 2. A post-bid setup adds no latency to standard ad delivery. +### 2. A post-bid setup adds no latency to standard ad delivery Because post-bid is just a 3rd party tag, the ad server receives the impressions as soon as the page loads. The post-bid setup does not affect other ad spend. Post-bid actually reduces latency compared to a daisy chain mediation setup, because in post-bid all demand sources are requested concurrently, instead of in a waterfall. Additionally, post-bid does not need as many line items, so initial setup is easier than header bidding. -### Disadvantages of Post-Bid +## Disadvantages of Post-Bid We’ve listed the advantages of post-bid over header bidding in the previous section. The disadvantages include: -#### 1. No dynamic allocation across all demand sources. +### 1. No dynamic allocation across all demand sources The bid price on the post-bid line item is static (based on historical price). It thus has the typical problems of a 3rd party tag line item. Due to this downside, the post-bid setup cannot make header bidding demand partners compete on an even footing with other types of demand. -#### 2. Prebid.js is loaded for each ad unit chosen for Post-Bid. +### 2. Prebid.js is loaded for each ad unit chosen for Post-Bid If there are multiple ad units on a page that fall into the post-bid scenario, each creative loads and runs Prebid.js separately. This can cause more work for the @@ -60,11 +59,11 @@ browser (or device) as it loads the code multiple times and runs separate auctio However, since this activity takes place after the ad calls, content is generally already loaded. -#### 3. Reporting is harder. +### 3. Reporting is harder In the ad server's post-bid line item report, you’d only get an aggregated report of all demand sources. You may need to rely on a 3rd party reporting service to record which demand partner wins how much inventory. -### Comparison of Monetization Solutions +## Comparison of Monetization Solutions {: .table .table-bordered .table-striped } | Feature | Mediation Solution | Post-Bid Solution | Pre-Bid Solution | @@ -76,18 +75,16 @@ In the ad server's post-bid line item report, you’d only get an aggregated rep | Monetization Capability | Low | Medium | High | | Block page content from loading? | No | No | No (with Prebid.js) | +## FAQ -### FAQ - -#### 1. If none of the post-bid demand sources fill, can I still passback to another tag, say from Adsense? +### 1. If none of the post-bid demand sources fill, can I still passback to another tag, say from Adsense? Yes. Check out the [example](/dev-docs/examples/postbid.html). -#### 2. Can post-bid be used for mobile apps? +### 2. Can post-bid be used for mobile apps? Yes, it works the same as for browsers. When utilizing a server-to-server architecture, the [app](/dev-docs/publisher-api-reference/setConfig.html#setConfig-app) config option can be used to forward the mobile app details. - -## Getting Started +# Getting Started Please refer to the [example](/dev-docs/examples/postbid.html). diff --git a/overview/what-is-prebid-org.md b/overview/what-is-prebid-org.md index ef0dfef76c..cfba8f7a0c 100644 --- a/overview/what-is-prebid-org.md +++ b/overview/what-is-prebid-org.md @@ -15,34 +15,40 @@ Prebid.org is open to all companies who are part of the programmatic ecosystem, [Learn more](https://prebid.org/membership/) about becoming a member of Prebid.org. -## Operations -Managed through Product Management Committees (PMCs) +## Operations + +Managed through Product Management Committees (PMCs) + - Each PMC has a Chair and Members. - The Chair manages the PMC process and facilitates how the members contribute. - PMCs drive open source software development as well as events and activities. -- To obtain more information about becoming a member of Prebid.org, email membership@prebid.org. +- To obtain more information about becoming a member of Prebid.org, email . + +## Focus on Value -## Focus on Value We focus on providing value-add to publishers and encourage the industry to deploy fair and efficient wrappers. Prebid takes two approaches to accomplish this: ### Wrapper Code of Conduct + Prebid members must agree to support the [Wrapper Code of Conduct](https://prebid.org/code-of-conduct/). This ensures that all wrapper providers are operating within the same principles. -### Trademark +### Trademark + We support wrappers based on Prebid technology with rights to the **Powered by Prebid** brand. ## Current Projects + All Prebid projects are open source and licensed under Apache License 2.0. + - [Prebid.js](/prebid/prebidjs.html), including [Prebid Video](/prebid-video/video-overview.html) and [Prebid Native](/dev-docs/examples/native-ad-example.html): Header bidding on desktop and mobile web. - [Prebid Server](/prebid-server/overview/prebid-server-overview.html): Server-to-server header bidding. - [Prebid Mobile](/prebid-mobile/prebid-mobile.html): SDK for mobile app header bidding on iOS and Android. Works in conjunction with Prebid Server. - Continuing work on our tools, website, and documentation. Prebid welcomes any contribution on these projects! - Read more here: -* [Prebid.org Members and Partners](https://prebid.org/membership/) -* [The Drum reporting on Prebid.org](https://www.thedrum.com/news/2017/09/11/appnexus-and-rubicon-project-launch-prebidorg-hailing-open-source-approach-header) -* [Current members of Prebid.org](https://prebid.org/membership/member-directory/) +- [Prebid.org Members and Partners](https://prebid.org/membership/) +- [The Drum reporting on Prebid.org](https://www.thedrum.com/news/2017/09/11/appnexus-and-rubicon-project-launch-prebidorg-hailing-open-source-approach-header) +- [Current members of Prebid.org](https://prebid.org/membership/member-directory/) diff --git a/package-lock.json b/package-lock.json index 36437ee5ff..4e95391780 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { "name": "prebid.github.io", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prebid.github.io", "version": "1.0.0", + "hasInstallScript": true, "license": "ISC", "dependencies": { "awesomplete": "^1.1.5", @@ -15,23858 +16,57 @@ "include-media": "^1.4.9", "popper.js": "^1.16.1" }, - "devDependencies": { - "browser-sync": "^2.26.13", - "browser-sync-webpack-plugin": "^2.0.1", - "cross-env": "^7.0.2", - "laravel-mix": "^5.0.7", - "resolve-url-loader": "^3.1.0", - "sass": "^1.27.0", - "sass-loader": "^8.0.2", - "vue-template-compiler": "^2.6.12" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.1.tgz", - "integrity": "sha512-725AQupWJZ8ba0jbKceeFblZTY90McUBWMwHhkFQ9q1zKPJ95GUktljFcgcsIVwRnTnRKlcYzfiNImg5G9m6ZQ==", - "dev": true - }, - "node_modules/@babel/core": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", - "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", - "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.1.tgz", - "integrity": "sha512-jtBEif7jsPwP27GPHs06v4WBV0KrE8a/P7n0N0sSvHn2hwUCYnolP/CLmz51IzAW4NlN+HuoBtb9QcwnRo9F/g==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.12.1", - "@babel/helper-validator-option": "^7.12.1", - "browserslist": "^4.12.0", - "semver": "^5.5.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", - "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz", - "integrity": "sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.1" - } - }, - "node_modules/@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", - "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", - "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz", - "integrity": "sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", - "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz", - "integrity": "sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==", - "dev": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", - "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.11.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", - "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==", - "dev": true - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", - "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helpers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz", - "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==", - "dev": true, - "dependencies": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" - } - }, - "node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", - "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", - "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", - "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", - "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", - "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", - "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", - "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", - "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.1.tgz", - "integrity": "sha512-MR7Ok+Af3OhNTCxYVjJZHS0t97ydnJZt/DbR4WISO39iDnhiD8XHrY12xuSJ90FFEGjir0Fzyyn7g/zY6hxbxA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", - "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", - "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", - "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", - "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - }, - "engines": { - "node": ">=4" - } + "devDependencies": {} }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", - "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", - "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", - "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", - "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", - "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", - "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", - "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", - "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", - "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", - "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", - "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", - "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", - "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", - "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", - "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", - "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", - "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", - "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", - "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.12.1", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", - "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-identifier": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", - "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", - "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", - "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", - "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", - "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", - "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } + "node_modules/awesomplete": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/awesomplete/-/awesomplete-1.1.5.tgz", + "integrity": "sha512-UFw1mPW8NaSECDSTC36HbAOTpF9JK2wBUJcNn4MSvlNtK7SZ9N72gB+ajHtA6D1abYXRcszZnBA4nHBwvFwzHw==" }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", - "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", - "dev": true, - "dependencies": { - "regenerator-transform": "^0.14.2" + "node_modules/bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", - "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } + "node_modules/bourbon": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/bourbon/-/bourbon-7.3.0.tgz", + "integrity": "sha512-u9ZUqmaX7K7nkarKODlFT4/XYfWafLRoadlv2Lye8hytrIA4Urg/50rav1eFdbdbO6o9GnK9a6qf7zwq808atA==" }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", - "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "resolve": "^1.8.1", - "semver": "^5.5.1" - } + "node_modules/include-media": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/include-media/-/include-media-1.4.10.tgz", + "integrity": "sha512-TymQzKF7oWHbItEcEHOCponZ90lRr1I9QbYeD+qCxXy4Z0/pSpS4Ocz2bq3FMOERlXXrY9Sawsh9GjiObVQA6A==" }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", - "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", - "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", - "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", - "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", - "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", - "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", - "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", - "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.12.1", - "@babel/helper-compilation-targets": "^7.12.1", - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-option": "^7.12.1", - "@babel/plugin-proposal-async-generator-functions": "^7.12.1", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-dynamic-import": "^7.12.1", - "@babel/plugin-proposal-export-namespace-from": "^7.12.1", - "@babel/plugin-proposal-json-strings": "^7.12.1", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-numeric-separator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.1", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.12.1", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-async-to-generator": "^7.12.1", - "@babel/plugin-transform-block-scoped-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.1", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-computed-properties": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-dotall-regex": "^7.12.1", - "@babel/plugin-transform-duplicate-keys": "^7.12.1", - "@babel/plugin-transform-exponentiation-operator": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-function-name": "^7.12.1", - "@babel/plugin-transform-literals": "^7.12.1", - "@babel/plugin-transform-member-expression-literals": "^7.12.1", - "@babel/plugin-transform-modules-amd": "^7.12.1", - "@babel/plugin-transform-modules-commonjs": "^7.12.1", - "@babel/plugin-transform-modules-systemjs": "^7.12.1", - "@babel/plugin-transform-modules-umd": "^7.12.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", - "@babel/plugin-transform-new-target": "^7.12.1", - "@babel/plugin-transform-object-super": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-property-literals": "^7.12.1", - "@babel/plugin-transform-regenerator": "^7.12.1", - "@babel/plugin-transform-reserved-words": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/plugin-transform-sticky-regex": "^7.12.1", - "@babel/plugin-transform-template-literals": "^7.12.1", - "@babel/plugin-transform-typeof-symbol": "^7.12.1", - "@babel/plugin-transform-unicode-escapes": "^7.12.1", - "@babel/plugin-transform-unicode-regex": "^7.12.1", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.1", - "core-js-compat": "^3.6.2", - "semver": "^5.5.0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "node_modules/@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - } - }, - "node_modules/@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/traverse": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", - "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.1", - "@babel/types": "^7.12.1", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/types": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", - "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "node_modules/@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "dependencies": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "14.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz", - "integrity": "sha512-jeYJU2kl7hL9U5xuI/BhKPZ4vqGM/OmK6whiFAXVhlstzZhVamWhDSmHyGLIp+RVyuF9/d0dqr2P85aFj4BvJg==", - "dev": true - }, - "node_modules/@types/q": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", - "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", - "dev": true - }, - "node_modules/@vue/component-compiler-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz", - "integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==", - "dev": true, - "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.14", - "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "optionalDependencies": { - "prettier": "^1.18.2" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "dependencies": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adjust-sourcemap-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz", - "integrity": "sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==", - "dev": true, - "dependencies": { - "assert": "1.4.1", - "camelcase": "5.0.0", - "loader-utils": "1.2.3", - "object-path": "0.11.4", - "regex-parser": "2.2.10" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "dependencies": { - "util": "0.10.3" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "node_modules/adjust-sourcemap-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "node_modules/ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "node_modules/alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "node_modules/ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/arity-n": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", - "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", - "dev": true - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ast-types": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", - "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "node_modules/async-each-series": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", - "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/autoprefixer": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", - "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", - "dev": true, - "dependencies": { - "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.32", - "postcss-value-parser": "^4.1.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - } - }, - "node_modules/awesomplete": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/awesomplete/-/awesomplete-1.1.5.tgz", - "integrity": "sha512-UFw1mPW8NaSECDSTC36HbAOTpF9JK2wBUJcNn4MSvlNtK7SZ9N72gB+ajHtA6D1abYXRcszZnBA4nHBwvFwzHw==" - }, - "node_modules/axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", - "dev": true, - "dependencies": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - } - }, - "node_modules/axios/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/axios/node_modules/follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "dependencies": { - "debug": "=3.1.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/axios/node_modules/is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axios/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "node_modules/babel-code-frame/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/babel-code-frame/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/babel-code-frame/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/babel-loader": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", - "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", - "dev": true, - "dependencies": { - "find-cache-dir": "^2.1.0", - "loader-utils": "^1.4.0", - "mkdirp": "^0.5.3", - "pify": "^4.0.1", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 6.9" - } - }, - "node_modules/babel-merge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-2.0.1.tgz", - "integrity": "sha512-puTQQxuzS+0JlMyVdfsTVaCgzqjBXKPMv7oUANpYcHFY+7IptWZ4PZDYX+qBxrRMtrriuBA44LkKpS99EJzqVA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.0.0-beta.49", - "deepmerge": "^2.1.0", - "object.omit": "^3.0.0" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "node_modules/base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "node_modules/better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "dependencies": { - "callsite": "1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "dependencies": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/bootstrap": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.3.tgz", - "integrity": "sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==" - }, - "node_modules/bourbon": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/bourbon/-/bourbon-7.0.0.tgz", - "integrity": "sha512-49kyBY+4gwnEvnez8H0TzFjfNZpUVdCmmS873S9nQ6YUuh2+qesbOh8lA+9gAuWlqtYlF+/3Etxm/13RhceOrg==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/braces/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/browser-sync": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.13.tgz", - "integrity": "sha512-JPYLTngIzI+Dzx+StSSlMtF+Q9yjdh58HW6bMFqkFXuzQkJL8FCvp4lozlS6BbECZcsM2Gmlgp0uhEjvl18X4w==", - "dev": true, - "dependencies": { - "browser-sync-client": "^2.26.13", - "browser-sync-ui": "^2.26.13", - "bs-recipes": "1.3.4", - "bs-snippet-injector": "^2.0.1", - "chokidar": "^3.4.1", - "connect": "3.6.6", - "connect-history-api-fallback": "^1", - "dev-ip": "^1.0.1", - "easy-extender": "^2.3.4", - "eazy-logger": "3.1.0", - "etag": "^1.8.1", - "fresh": "^0.5.2", - "fs-extra": "3.0.1", - "http-proxy": "^1.18.1", - "immutable": "^3", - "localtunnel": "^2.0.0", - "micromatch": "^4.0.2", - "opn": "5.3.0", - "portscanner": "2.1.1", - "qs": "6.2.3", - "raw-body": "^2.3.2", - "resp-modifier": "6.0.2", - "rx": "4.1.0", - "send": "0.16.2", - "serve-index": "1.9.1", - "serve-static": "1.13.2", - "server-destroy": "1.0.1", - "socket.io": "2.1.1", - "ua-parser-js": "^0.7.18", - "yargs": "^15.4.1" - }, - "bin": { - "browser-sync": "dist/bin.js" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/browser-sync-client": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.13.tgz", - "integrity": "sha512-p2VbZoYrpuDhkreq+/Sv1MkToHklh7T1OaIntDwpG6Iy2q/XkBcgwPcWjX+WwRNiZjN8MEehxIjEUh12LweLmQ==", - "dev": true, - "dependencies": { - "etag": "1.8.1", - "fresh": "0.5.2", - "mitt": "^1.1.3", - "rxjs": "^5.5.6" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/browser-sync-ui": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.13.tgz", - "integrity": "sha512-6NJ/pCnhCnBMzaty1opWo7ipDmFAIk8U71JMQGKJxblCUaGfdsbF2shf6XNZSkXYia1yS0vwKu9LIOzpXqQZCA==", - "dev": true, - "dependencies": { - "async-each-series": "0.1.1", - "connect-history-api-fallback": "^1", - "immutable": "^3", - "server-destroy": "1.0.1", - "socket.io-client": "^2.0.4", - "stream-throttle": "^0.1.3" - } - }, - "node_modules/browser-sync-webpack-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/browser-sync-webpack-plugin/-/browser-sync-webpack-plugin-2.0.1.tgz", - "integrity": "sha512-F9vkVErG4N1XCJb1OI+RD/5oAK1nMd1G5UDfNE/FmUVAyo24YItfXN+etzA8MBC4Z7oLjkuBKDeeLlbFa4NBGQ==", - "dev": true, - "dependencies": { - "lodash": "^4" - } - }, - "node_modules/browser-sync/node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/browser-sync/node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync/node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/browser-sync/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/browser-sync/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync/node_modules/fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", - "universalify": "^0.1.0" - } - }, - "node_modules/browser-sync/node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/browser-sync/node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/browser-sync/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/browser-sync/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/browser-sync/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/browser-sync/node_modules/jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/browser-sync/node_modules/micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-sync/node_modules/mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true, - "bin": { - "mime": "cli.js" - } - }, - "node_modules/browser-sync/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/browser-sync/node_modules/opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/browser-sync/node_modules/qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/browser-sync/node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/browser-sync/node_modules/send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/browser-sync/node_modules/serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/browser-sync/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/browser-sync/node_modules/statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/browser-sync/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-rsa/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "dependencies": { - "pako": "~1.0.5" - } - }, - "node_modules/browserslist": { - "version": "4.14.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", - "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001135", - "electron-to-chromium": "^1.3.571", - "escalade": "^3.1.0", - "node-releases": "^1.1.61" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-recipes": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", - "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", - "dev": true - }, - "node_modules/bs-snippet-injector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", - "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", - "dev": true - }, - "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacache": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", - "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", - "dev": true, - "dependencies": { - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "minipass": "^3.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "p-map": "^3.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^2.7.1", - "ssri": "^7.0.0", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001150", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001150.tgz", - "integrity": "sha512-kiNKvihW0m36UhAFnl7bOAv0i1K1f6wpfVtTF5O5O82XzgtBnb05V0XeV3oZ968vfg2sRNChsHw8ASH2hDfoYQ==", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dev": true, - "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/collect.js": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.28.4.tgz", - "integrity": "sha512-NJXATt6r+gtGOgDJOKLeooTY6QpGn8YQN/PkKnCmajJOguz/xGPgPrTyrBkmBBTHXnniPRIkUqjqt3AkjwCKlg==", - "dev": true - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", - "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.1", - "color-string": "^1.5.4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/color-string": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", - "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", - "dev": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "node_modules/compose-function": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", - "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", - "dev": true, - "dependencies": { - "arity-n": "^1.0.4" - } - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/concat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz", - "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=", - "dev": true, - "dependencies": { - "commander": "^2.9.0" - }, - "bin": { - "concat": "bin/concat" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/connect/node_modules/statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "node_modules/consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "dependencies": { - "bluebird": "^3.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "node_modules/copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "dependencies": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "dev": true, - "dependencies": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - } - }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-env": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", - "integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-env/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-env/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cross-env/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - } - }, - "node_modules/css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/css-declaration-sorter": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", - "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", - "dev": true, - "dependencies": { - "postcss": "^7.0.1", - "timsort": "^0.3.0" - }, - "engines": { - "node": ">4" - } - }, - "node_modules/css-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", - "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", - "dev": true, - "dependencies": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash": "^4.17.11", - "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" - }, - "engines": { - "node": ">= 6.9.0 <7.0.0 || >= 8.9.0" - } - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/css-loader/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/css-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", - "dev": true - }, - "node_modules/css-selector-tokenizer": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", - "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "fastparse": "^1.1.2" - } - }, - "node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", - "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", - "dev": true, - "dependencies": { - "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.7", - "is-resolvable": "^1.0.0", - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cssnano-preset-default": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", - "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", - "dev": true, - "dependencies": { - "css-declaration-sorter": "^4.0.1", - "cssnano-util-raw-cache": "^4.0.1", - "postcss": "^7.0.0", - "postcss-calc": "^7.0.1", - "postcss-colormin": "^4.0.3", - "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.2", - "postcss-discard-duplicates": "^4.0.2", - "postcss-discard-empty": "^4.0.1", - "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.11", - "postcss-merge-rules": "^4.0.3", - "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.2", - "postcss-minify-params": "^4.0.2", - "postcss-minify-selectors": "^4.0.2", - "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.2", - "postcss-normalize-positions": "^4.0.2", - "postcss-normalize-repeat-style": "^4.0.2", - "postcss-normalize-string": "^4.0.2", - "postcss-normalize-timing-functions": "^4.0.2", - "postcss-normalize-unicode": "^4.0.1", - "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.2", - "postcss-ordered-values": "^4.1.2", - "postcss-reduce-initial": "^4.0.3", - "postcss-reduce-transforms": "^4.0.2", - "postcss-svgo": "^4.0.2", - "postcss-unique-selectors": "^4.0.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cssnano-util-get-arguments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", - "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cssnano-util-get-match": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", - "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cssnano-util-raw-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", - "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cssnano-util-same-parent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", - "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/csso": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", - "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", - "dev": true, - "dependencies": { - "css-tree": "1.0.0-alpha.39" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", - "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.6", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", - "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", - "dev": true - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", - "dev": true, - "dependencies": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "node_modules/dev-ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", - "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", - "dev": true, - "bin": { - "dev-ip": "lib/dev-ip.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "node_modules/dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, - "dependencies": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "dependencies": { - "buffer-indexof": "^1.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", - "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", - "dev": true - }, - "node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true, - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/dotenv-expand": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", - "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", - "dev": true - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/easy-extender": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", - "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", - "dev": true, - "dependencies": { - "lodash": "^4.17.10" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/eazy-logger": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.1.0.tgz", - "integrity": "sha512-/snsn2JqBtUSSstEl4R0RKjkisGHAhvYj89i7r3ytNUKW12y178KDZwXLXIgwDqLW6E/VRMT9qfld7wvFae8bQ==", - "dev": true, - "dependencies": { - "tfunk": "^4.0.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.3.582", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.582.tgz", - "integrity": "sha512-0nCJ7cSqnkMC+kUuPs0YgklFHraWGl/xHqtZWWtOeVtyi+YqkoAOMGuZQad43DscXCQI/yizcTa3u6B5r+BLww==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - } - }, - "node_modules/engine.io-client": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", - "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", - "dev": true, - "dependencies": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - } - }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/engine.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dev": true, - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "node_modules/engine.io/node_modules/base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/engine.io/node_modules/cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/engine.io/node_modules/engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "node_modules/engine.io/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/engine.io/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enhanced-resolve/node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - }, - "node_modules/errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "dev": true, - "dependencies": { - "stackframe": "^1.1.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-templates": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", - "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", - "dev": true, - "dependencies": { - "recast": "~0.11.12", - "through": "~2.3.6" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", - "dev": true, - "dependencies": { - "original": "^1.0.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-text-webpack-plugin": { - "version": "4.0.0-beta.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", - "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", - "dev": true, - "dependencies": { - "async": "^2.4.1", - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5", - "webpack-sources": "^1.1.0" - }, - "engines": { - "node": ">= 6.9.0 || >= 8.9.0" - } - }, - "node_modules/extract-text-webpack-plugin/node_modules/schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "dependencies": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, - "node_modules/faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "node_modules/file-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", - "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", - "dev": true, - "dependencies": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" - }, - "engines": { - "node": ">= 6.9.0 < 7.0.0 || >= 8.9.0" - } - }, - "node_modules/file-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/friendly-errors-webpack-plugin": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", - "integrity": "sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "error-stack-parser": "^2.0.0", - "string-width": "^2.0.0" - } - }, - "node_modules/friendly-errors-webpack-plugin/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/friendly-errors-webpack-plugin/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/friendly-errors-webpack-plugin/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-modules/node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "node_modules/growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "dependencies": { - "isarray": "2.0.1" - } - }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "node_modules/hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hex-color-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", - "dev": true - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hsl-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", - "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", - "dev": true - }, - "node_modules/hsla-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", - "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", - "dev": true - }, - "node_modules/html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, - "node_modules/html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", - "dev": true - }, - "node_modules/html-loader": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", - "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", - "dev": true, - "dependencies": { - "es6-templates": "^0.2.3", - "fastparse": "^1.1.1", - "html-minifier": "^3.5.8", - "loader-utils": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "dependencies": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "bin": { - "html-minifier": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/html-minifier/node_modules/commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "dev": true, - "dependencies": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "node_modules/icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "dependencies": { - "postcss": "^6.0.1" - } - }, - "node_modules/icss-utils/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/icss-utils/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "node_modules/iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "node_modules/ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "node_modules/imagemin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-6.1.0.tgz", - "integrity": "sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A==", - "dev": true, - "dependencies": { - "file-type": "^10.7.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^4.0.1", - "replace-ext": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imagemin/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/imagemin/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/img-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-3.0.2.tgz", - "integrity": "sha512-rSriLKgvi85Km7ppSF+AEAM3nU4fxpvCkaXtC/IoCEU7jfks55bEANFs0bB9YXYkxY9JurZQIZFtXh5Gue3upw==", - "dev": true, - "dependencies": { - "loader-utils": "^1.1.0" - } - }, - "node_modules/immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "dependencies": { - "import-from": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "dependencies": { - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "dependencies": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/include-media": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/include-media/-/include-media-1.4.9.tgz", - "integrity": "sha1-0AILe+PrLVSGiiCUNZXOOA4LxDs=" - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", - "dev": true, - "dependencies": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "node_modules/ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-color-stop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", - "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", - "dev": true, - "dependencies": { - "css-color-names": "^0.0.4", - "hex-color-regex": "^1.1.0", - "hsl-regex": "^1.0.0", - "hsla-regex": "^1.0.0", - "rgb-regex": "^1.0.1", - "rgba-regex": "^1.0.0" - } - }, - "node_modules/is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", - "dev": true, - "dependencies": { - "lodash.isfinite": "^3.3.2" - } - }, - "node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", - "dev": true, - "dependencies": { - "html-comment-regex": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", - "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", - "dev": true, - "dependencies": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 8.3" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, - "node_modules/json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/laravel-mix": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-5.0.7.tgz", - "integrity": "sha512-TL5txnQkzcwM8DYckgzjISSPGyZN6znFYb4NgtTSi9aIvfzOIEC6p0eYM6wDa/BkEKv290Ru6HWmH6Q2XApogQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-transform-runtime": "^7.2.0", - "@babel/preset-env": "^7.2.0", - "@babel/runtime": "^7.2.0", - "autoprefixer": "^9.4.2", - "babel-loader": "^8.0.4", - "babel-merge": "^2.0.1", - "chokidar": "^2.0.3", - "clean-css": "^4.1.3", - "collect.js": "^4.12.8", - "concat": "^1.0.3", - "css-loader": "^1.0.1", - "dotenv": "^6.2.0", - "dotenv-expand": "^4.2.0", - "extract-text-webpack-plugin": "v4.0.0-beta.0", - "file-loader": "^2.0.0", - "friendly-errors-webpack-plugin": "^1.6.1", - "fs-extra": "^7.0.1", - "glob": "^7.1.2", - "html-loader": "^0.5.5", - "imagemin": "^6.0.0", - "img-loader": "^3.0.0", - "lodash": "^4.17.15", - "md5": "^2.2.1", - "optimize-css-assets-webpack-plugin": "^5.0.1", - "postcss-loader": "^3.0.0", - "style-loader": "^0.23.1", - "terser": "^3.11.0", - "terser-webpack-plugin": "^2.2.3", - "vue-loader": "^15.4.2", - "webpack": "^4.36.1", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.14", - "webpack-merge": "^4.1.0", - "webpack-notifier": "^1.5.1", - "yargs": "^15.4.1" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/last-call-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", - "dev": true, - "dependencies": { - "lodash": "^4.17.5", - "webpack-sources": "^1.1.0" - } - }, - "node_modules/limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/loader-utils/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/localtunnel": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.0.tgz", - "integrity": "sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg==", - "dev": true, - "dependencies": { - "axios": "0.19.0", - "debug": "4.1.1", - "openurl": "1.1.1", - "yargs": "13.3.0" - }, - "bin": { - "lt": "bin/lt.js" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/localtunnel/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/localtunnel/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/localtunnel/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/localtunnel/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/localtunnel/node_modules/yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "node_modules/lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "node_modules/loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", - "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "dependencies": { - "mime-db": "1.44.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "dependencies": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mitt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", - "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", - "dev": true - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "dependencies": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "dependencies": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "node_modules/nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true, - "optional": true - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "dev": true, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "dependencies": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "node_modules/node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, - "dependencies": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, - "node_modules/node-releases": { - "version": "1.1.64", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.64.tgz", - "integrity": "sha512-Iec8O9166/x2HRMJyLLLWkd0sFFLrFNy+Xf+JQfSQsdBJzPcHpNl3JQ9gD4j+aJxmCa25jNsIbM4bmACtSbkSg==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "node_modules/object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/object.getownpropertydescriptors/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.omit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz", - "integrity": "sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==", - "dev": true, - "dependencies": { - "is-extendable": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, - "node_modules/opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/optimize-css-assets-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", - "dev": true, - "dependencies": { - "cssnano": "^4.1.10", - "last-call-webpack-plugin": "^3.0.0" - } - }, - "node_modules/original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "dev": true, - "dependencies": { - "url-parse": "^1.4.3" - } - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", - "dev": true, - "dependencies": { - "retry": "^0.12.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "node_modules/parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "dependencies": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", - "dev": true - }, - "node_modules/parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" - }, - "node_modules/portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "dependencies": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/portscanner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", - "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", - "dev": true, - "dependencies": { - "async": "1.5.2", - "is-number-like": "^1.0.3" - }, - "engines": { - "node": ">=0.4", - "npm": ">=1.0.0" - } - }, - "node_modules/portscanner/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/postcss-calc": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", - "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", - "dev": true, - "dependencies": { - "postcss": "^7.0.27", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.2" - } - }, - "node_modules/postcss-colormin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", - "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-colormin/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-convert-values": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-discard-comments": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", - "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-discard-empty": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-load-config": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", - "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", - "dev": true, - "dependencies": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "dev": true, - "dependencies": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", - "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", - "dev": true, - "dependencies": { - "css-color-names": "0.0.4", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-merge-rules": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", - "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-minify-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", - "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", - "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-minify-params": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", - "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", - "dev": true, - "dependencies": { - "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-minify-selectors": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", - "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", - "dev": true, - "dependencies": { - "alphanum-sort": "^1.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", - "dev": true, - "dependencies": { - "postcss": "^6.0.1" - } - }, - "node_modules/postcss-modules-extract-imports/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-modules-extract-imports/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "dependencies": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "dependencies": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "node_modules/postcss-modules-scope/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-modules-scope/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "dependencies": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - } - }, - "node_modules/postcss-modules-values/node_modules/postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/postcss-modules-values/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", - "dev": true, - "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", - "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", - "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", - "dev": true, - "dependencies": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", - "dev": true, - "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-unicode": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", - "dev": true, - "dependencies": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-normalize-whitespace": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", - "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", - "dev": true, - "dependencies": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-ordered-values": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", - "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", - "dev": true, - "dependencies": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-reduce-initial": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", - "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", - "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", - "dev": true, - "dependencies": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", - "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "dev": true, - "dependencies": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-svgo/node_modules/postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "node_modules/postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", - "dev": true, - "dependencies": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "node_modules/postcss/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", - "dev": true, - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", - "dev": true, - "dependencies": { - "ast-types": "0.9.6", - "esprima": "~3.1.0", - "private": "~0.1.5", - "source-map": "~0.5.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-parser": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.10.tgz", - "integrity": "sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==", - "dev": true - }, - "node_modules/regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/regexp.prototype.flags/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - } - }, - "node_modules/resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "dependencies": { - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-dir/node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "node_modules/resolve-url-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz", - "integrity": "sha512-2QcrA+2QgVqsMJ1Hn5NnJXIGCX1clQ1F6QJTqOeiaDw9ACo1G2k+8/shq3mtqne03HOFyskAClqfxKyFBriXZg==", - "dev": true, - "dependencies": { - "adjust-sourcemap-loader": "2.0.0", - "camelcase": "5.0.0", - "compose-function": "3.0.3", - "convert-source-map": "1.6.0", - "es6-iterator": "2.0.3", - "loader-utils": "1.2.3", - "postcss": "7.0.14", - "rework": "1.0.1", - "rework-visit": "1.0.0", - "source-map": "0.6.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/resolve-url-loader/node_modules/camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/resolve-url-loader/node_modules/convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/resolve-url-loader/node_modules/emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/resolve-url-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/resolve-url-loader/node_modules/postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-url-loader/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/resp-modifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", - "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", - "dev": true, - "dependencies": { - "debug": "^2.2.0", - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/resp-modifier/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/resp-modifier/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/rework": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", - "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", - "dev": true, - "dependencies": { - "convert-source-map": "^0.3.3", - "css": "^2.0.0" - } - }, - "node_modules/rework-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", - "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", - "dev": true - }, - "node_modules/rework/node_modules/convert-source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", - "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", - "dev": true - }, - "node_modules/rgb-regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", - "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", - "dev": true - }, - "node_modules/rgba-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", - "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", - "dev": true - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "dependencies": { - "aproba": "^1.1.1" - } - }, - "node_modules/rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", - "dev": true - }, - "node_modules/rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", - "dev": true, - "dependencies": { - "symbol-observable": "1.0.1" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sass": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz", - "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==", - "dev": true, - "dependencies": { - "chokidar": ">=2.0.0 <4.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/sass-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", - "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "loader-utils": "^1.2.3", - "neo-async": "^2.6.1", - "schema-utils": "^2.6.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">= 8.9.0" - } - }, - "node_modules/sass-loader/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "node_modules/selfsigned": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", - "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", - "dev": true, - "dependencies": { - "node-forge": "^0.10.0" - } - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", - "dev": true - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "node_modules/slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", - "dev": true, - "dependencies": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", - "dev": true - }, - "node_modules/socket.io-client": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.1.tgz", - "integrity": "sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ==", - "dev": true, - "dependencies": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - } - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/socket.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", - "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", - "dev": true, - "dependencies": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/socket.io-parser/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io/node_modules/base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/socket.io/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "node_modules/socket.io/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/socket.io/node_modules/engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "dependencies": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - } - }, - "node_modules/socket.io/node_modules/engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "node_modules/socket.io/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "node_modules/socket.io/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io/node_modules/parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "dependencies": { - "better-assert": "~1.0.0" - } - }, - "node_modules/socket.io/node_modules/parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "dependencies": { - "better-assert": "~1.0.0" - } - }, - "node_modules/socket.io/node_modules/socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "dependencies": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - } - }, - "node_modules/socket.io/node_modules/socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "dependencies": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - }, - "node_modules/socket.io/node_modules/ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/sockjs": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", - "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.10.0", - "uuid": "^3.4.0", - "websocket-driver": "0.6.5" - } - }, - "node_modules/sockjs-client": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", - "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", - "dev": true, - "dependencies": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - } - }, - "node_modules/sockjs-client/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/sockjs-client/node_modules/faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/ssri": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", - "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", - "dev": true, - "dependencies": { - "figgy-pudding": "^3.5.1", - "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "node_modules/stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", - "dev": true - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "node_modules/stream-throttle": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", - "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", - "dev": true, - "dependencies": { - "commander": "^2.2.0", - "limiter": "^1.0.5" - }, - "bin": { - "throttleproxy": "bin/throttleproxy.js" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", - "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", - "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", - "dev": true, - "dependencies": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/style-loader/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/stylehacks": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", - "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/stylehacks/node_modules/postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", - "dev": true, - "dependencies": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "bin": { - "terser": "bin/uglifyjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", - "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==", - "dev": true, - "dependencies": { - "cacache": "^13.0.1", - "find-cache-dir": "^3.3.1", - "jest-worker": "^25.4.0", - "p-limit": "^2.3.0", - "schema-utils": "^2.6.6", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.6.12", - "webpack-sources": "^1.4.3" - }, - "engines": { - "node": ">= 8.9.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/terser-webpack-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/terser-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tfunk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-4.0.0.tgz", - "integrity": "sha512-eJQ0dGfDIzWNiFNYFVjJ+Ezl/GmwHaFTBTjrtqNPW0S7cuVDBrZrmzUz6VkMeCR4DZFqhd4YtLwsw3i2wYHswQ==", - "dev": true, - "dependencies": { - "chalk": "^1.1.3", - "dlv": "^1.1.3" - } - }, - "node_modules/tfunk/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tfunk/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tfunk/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/timers-browserify": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", - "dev": true, - "dependencies": { - "setimmediate": "^1.0.4" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "node_modules/to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/ua-parser-js": { - "version": "0.7.22", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", - "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "dependencies": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uglify-js/node_modules/commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "node_modules/uglify-js/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "node_modules/uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "node_modules/uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - } - }, - "node_modules/util.promisify/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vendors": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", - "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", - "dev": true - }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "node_modules/vue-loader": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.3.tgz", - "integrity": "sha512-Y67VnGGgVLH5Voostx8JBZgPQTlDQeOVBLOEsjc2cXbCYBKexSKEpOA56x0YZofoDOTszrLnIShyOX1p9uCEHA==", - "dev": true, - "dependencies": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - } - }, - "node_modules/vue-style-loader": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", - "integrity": "sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==", - "dev": true, - "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz", - "integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==", - "dev": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "node_modules/watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", - "dev": true, - "dependencies": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - }, - "optionalDependencies": { - "chokidar": "^3.4.1", - "watchpack-chokidar2": "^2.0.0" - } - }, - "node_modules/watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "dev": true, - "optional": true, - "dependencies": { - "chokidar": "^2.1.8" - }, - "engines": { - "node": "<8.10.0" - } - }, - "node_modules/watchpack/node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "optional": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/watchpack/node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/watchpack/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "optional": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/watchpack/node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "optional": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - } - }, - "node_modules/watchpack/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "optional": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/watchpack/node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/watchpack/node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "optional": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/watchpack/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/watchpack/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/watchpack/node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "optional": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/watchpack/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "optional": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/webpack": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", - "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/webpack-cli/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-cli/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-cli/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-cli/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-cli/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", - "dev": true, - "dependencies": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/webpack-dev-middleware/node_modules/mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/webpack-dev-server": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", - "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", - "dev": true, - "dependencies": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.8", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.3.1", - "http-proxy-middleware": "0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "is-absolute-url": "^3.0.3", - "killable": "^1.0.1", - "loglevel": "^1.6.8", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.26", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.7", - "semver": "^6.3.0", - "serve-index": "^1.9.1", - "sockjs": "0.3.20", - "sockjs-client": "1.4.0", - "spdy": "^4.0.2", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.2", - "webpack-log": "^2.0.0", - "ws": "^6.2.1", - "yargs": "^13.3.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 6.11.5" - } - }, - "node_modules/webpack-dev-server/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/webpack-dev-server/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/webpack-dev-server/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/string-width/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/webpack-dev-server/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "dependencies": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/webpack-notifier": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/webpack-notifier/-/webpack-notifier-1.8.0.tgz", - "integrity": "sha512-I6t76NoPe5DZCCm5geELmDV2wlJ89LbU425uN6T2FG8Ywrrt1ZcUMz6g8yWGNg4pttqTPFQJYUPjWAlzUEQ+cQ==", - "dev": true, - "dependencies": { - "node-notifier": "^5.1.2", - "object-assign": "^4.1.0", - "strip-ansi": "^3.0.1" - } - }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/webpack-sources/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "dependencies": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/webpack/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack/node_modules/ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "dependencies": { - "figgy-pudding": "^3.5.1" - } - }, - "node_modules/webpack/node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/webpack/node_modules/terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "dependencies": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "engines": { - "node": ">= 6.9.0" - } - }, - "node_modules/websocket-driver": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", - "dev": true, - "dependencies": { - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "dependencies": { - "errno": "~0.1.7" - } - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/yargs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/yargs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.1.tgz", - "integrity": "sha512-725AQupWJZ8ba0jbKceeFblZTY90McUBWMwHhkFQ9q1zKPJ95GUktljFcgcsIVwRnTnRKlcYzfiNImg5G9m6ZQ==", - "dev": true - }, - "@babel/core": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.3.tgz", - "integrity": "sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.1", - "@babel/parser": "^7.12.3", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", - "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.1.tgz", - "integrity": "sha512-jtBEif7jsPwP27GPHs06v4WBV0KrE8a/P7n0N0sSvHn2hwUCYnolP/CLmz51IzAW4NlN+HuoBtb9QcwnRo9F/g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.12.1", - "@babel/helper-validator-option": "^7.12.1", - "browserslist": "^4.12.0", - "semver": "^5.5.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", - "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz", - "integrity": "sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.1" - } - }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", - "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz", - "integrity": "sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-module-imports": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz", - "integrity": "sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", - "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-replace-supers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz", - "integrity": "sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", - "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.1" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", - "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", - "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helpers": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.1.tgz", - "integrity": "sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", - "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz", - "integrity": "sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", - "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", - "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", - "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", - "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", - "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", - "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.1.tgz", - "integrity": "sha512-MR7Ok+Af3OhNTCxYVjJZHS0t97ydnJZt/DbR4WISO39iDnhiD8XHrY12xuSJ90FFEGjir0Fzyyn7g/zY6hxbxA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", - "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.1.tgz", - "integrity": "sha512-c2uRpY6WzaVDzynVY9liyykS+kVU+WRZPMPYpkelXH8KBt1oXoI89kPbZKKG/jDT5UK92FTW2fZkZaJhdiBabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", - "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", - "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", - "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", - "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", - "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", - "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", - "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.1.tgz", - "integrity": "sha512-zJyAC9sZdE60r1nVQHblcfCj29Dh2Y0DOvlMkcqSo0ckqjiCwNiUezUKw+RjOCwGfpLRwnAeQ2XlLpsnGkvv9w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", - "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", - "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", - "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", - "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", - "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", - "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", - "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", - "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", - "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", - "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", - "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", - "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.12.1", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", - "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-identifier": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", - "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", - "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", - "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", - "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", - "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", - "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", - "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", - "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", - "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "resolve": "^1.8.1", - "semver": "^5.5.1" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", - "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", - "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.1.tgz", - "integrity": "sha512-CiUgKQ3AGVk7kveIaPEET1jNDhZZEl1RPMWdTBE1799bdz++SwqDHStmxfCtDfBhQgCl38YRiSnrMuUMZIWSUQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", - "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.1.tgz", - "integrity": "sha512-EPGgpGy+O5Kg5pJFNDKuxt9RdmTgj5sgrus2XVeMp/ZIbOESadgILUbm50SNpghOh3/6yrbsH+NB5+WJTmsA7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", - "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", - "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/preset-env": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.1.tgz", - "integrity": "sha512-H8kxXmtPaAGT7TyBvSSkoSTUK6RHh61So05SyEbpmr0MCZrsNYn7mGMzzeYoOUCdHzww61k8XBft2TaES+xPLg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.12.1", - "@babel/helper-compilation-targets": "^7.12.1", - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-option": "^7.12.1", - "@babel/plugin-proposal-async-generator-functions": "^7.12.1", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-dynamic-import": "^7.12.1", - "@babel/plugin-proposal-export-namespace-from": "^7.12.1", - "@babel/plugin-proposal-json-strings": "^7.12.1", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-numeric-separator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.1", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.12.1", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-async-to-generator": "^7.12.1", - "@babel/plugin-transform-block-scoped-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.1", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-computed-properties": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-dotall-regex": "^7.12.1", - "@babel/plugin-transform-duplicate-keys": "^7.12.1", - "@babel/plugin-transform-exponentiation-operator": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-function-name": "^7.12.1", - "@babel/plugin-transform-literals": "^7.12.1", - "@babel/plugin-transform-member-expression-literals": "^7.12.1", - "@babel/plugin-transform-modules-amd": "^7.12.1", - "@babel/plugin-transform-modules-commonjs": "^7.12.1", - "@babel/plugin-transform-modules-systemjs": "^7.12.1", - "@babel/plugin-transform-modules-umd": "^7.12.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", - "@babel/plugin-transform-new-target": "^7.12.1", - "@babel/plugin-transform-object-super": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-property-literals": "^7.12.1", - "@babel/plugin-transform-regenerator": "^7.12.1", - "@babel/plugin-transform-reserved-words": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/plugin-transform-sticky-regex": "^7.12.1", - "@babel/plugin-transform-template-literals": "^7.12.1", - "@babel/plugin-transform-typeof-symbol": "^7.12.1", - "@babel/plugin-transform-unicode-escapes": "^7.12.1", - "@babel/plugin-transform-unicode-regex": "^7.12.1", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.1", - "core-js-compat": "^3.6.2", - "semver": "^5.5.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", - "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.1", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.1", - "@babel/types": "^7.12.1", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, - "@babel/types": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", - "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/node": { - "version": "14.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz", - "integrity": "sha512-jeYJU2kl7hL9U5xuI/BhKPZ4vqGM/OmK6whiFAXVhlstzZhVamWhDSmHyGLIp+RVyuF9/d0dqr2P85aFj4BvJg==", - "dev": true - }, - "@types/q": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", - "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", - "dev": true - }, - "@vue/component-compiler-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz", - "integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==", - "dev": true, - "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.14", - "postcss-selector-parser": "^6.0.2", - "prettier": "^1.18.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "adjust-sourcemap-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz", - "integrity": "sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA==", - "dev": true, - "requires": { - "assert": "1.4.1", - "camelcase": "5.0.0", - "loader-utils": "1.2.3", - "object-path": "0.11.4", - "regex-parser": "2.2.10" - }, - "dependencies": { - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - } - }, - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - } - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arity-n": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", - "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", - "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", - "dev": true - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-each-series": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", - "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", - "dev": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autoprefixer": { - "version": "9.8.6", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", - "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", - "dev": true, - "requires": { - "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.32", - "postcss-value-parser": "^4.1.0" - } - }, - "awesomplete": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/awesomplete/-/awesomplete-1.1.5.tgz", - "integrity": "sha512-UFw1mPW8NaSECDSTC36HbAOTpF9JK2wBUJcNn4MSvlNtK7SZ9N72gB+ajHtA6D1abYXRcszZnBA4nHBwvFwzHw==" - }, - "axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", - "dev": true, - "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - } - }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-loader": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", - "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.1.0", - "loader-utils": "^1.4.0", - "mkdirp": "^0.5.3", - "pify": "^4.0.1", - "schema-utils": "^2.6.5" - } - }, - "babel-merge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/babel-merge/-/babel-merge-2.0.1.tgz", - "integrity": "sha512-puTQQxuzS+0JlMyVdfsTVaCgzqjBXKPMv7oUANpYcHFY+7IptWZ4PZDYX+qBxrRMtrriuBA44LkKpS99EJzqVA==", - "dev": true, - "requires": { - "@babel/core": "^7.0.0-beta.49", - "deepmerge": "^2.1.0", - "object.omit": "^3.0.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", - "dev": true - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "bonjour": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", - "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, - "requires": { - "array-flatten": "^2.1.0", - "deep-equal": "^1.0.1", - "dns-equal": "^1.0.0", - "dns-txt": "^2.0.2", - "multicast-dns": "^6.0.1", - "multicast-dns-service-types": "^1.1.0" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "bootstrap": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.3.tgz", - "integrity": "sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==" - }, - "bourbon": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/bourbon/-/bourbon-7.0.0.tgz", - "integrity": "sha512-49kyBY+4gwnEvnez8H0TzFjfNZpUVdCmmS873S9nQ6YUuh2+qesbOh8lA+9gAuWlqtYlF+/3Etxm/13RhceOrg==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-sync": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.13.tgz", - "integrity": "sha512-JPYLTngIzI+Dzx+StSSlMtF+Q9yjdh58HW6bMFqkFXuzQkJL8FCvp4lozlS6BbECZcsM2Gmlgp0uhEjvl18X4w==", - "dev": true, - "requires": { - "browser-sync-client": "^2.26.13", - "browser-sync-ui": "^2.26.13", - "bs-recipes": "1.3.4", - "bs-snippet-injector": "^2.0.1", - "chokidar": "^3.4.1", - "connect": "3.6.6", - "connect-history-api-fallback": "^1", - "dev-ip": "^1.0.1", - "easy-extender": "^2.3.4", - "eazy-logger": "3.1.0", - "etag": "^1.8.1", - "fresh": "^0.5.2", - "fs-extra": "3.0.1", - "http-proxy": "^1.18.1", - "immutable": "^3", - "localtunnel": "^2.0.0", - "micromatch": "^4.0.2", - "opn": "5.3.0", - "portscanner": "2.1.1", - "qs": "6.2.3", - "raw-body": "^2.3.2", - "resp-modifier": "6.0.2", - "rx": "4.1.0", - "send": "0.16.2", - "serve-index": "1.9.1", - "serve-static": "1.13.2", - "server-destroy": "1.0.1", - "socket.io": "2.1.1", - "ua-parser-js": "^0.7.18", - "yargs": "^15.4.1" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^3.0.0", - "universalify": "^0.1.0" - } - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "qs": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", - "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", - "dev": true - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - } - }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "browser-sync-client": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.13.tgz", - "integrity": "sha512-p2VbZoYrpuDhkreq+/Sv1MkToHklh7T1OaIntDwpG6Iy2q/XkBcgwPcWjX+WwRNiZjN8MEehxIjEUh12LweLmQ==", - "dev": true, - "requires": { - "etag": "1.8.1", - "fresh": "0.5.2", - "mitt": "^1.1.3", - "rxjs": "^5.5.6" - } - }, - "browser-sync-ui": { - "version": "2.26.13", - "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.13.tgz", - "integrity": "sha512-6NJ/pCnhCnBMzaty1opWo7ipDmFAIk8U71JMQGKJxblCUaGfdsbF2shf6XNZSkXYia1yS0vwKu9LIOzpXqQZCA==", - "dev": true, - "requires": { - "async-each-series": "0.1.1", - "connect-history-api-fallback": "^1", - "immutable": "^3", - "server-destroy": "1.0.1", - "socket.io-client": "^2.0.4", - "stream-throttle": "^0.1.3" - } - }, - "browser-sync-webpack-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/browser-sync-webpack-plugin/-/browser-sync-webpack-plugin-2.0.1.tgz", - "integrity": "sha512-F9vkVErG4N1XCJb1OI+RD/5oAK1nMd1G5UDfNE/FmUVAyo24YItfXN+etzA8MBC4Z7oLjkuBKDeeLlbFa4NBGQ==", - "dev": true, - "requires": { - "lodash": "^4" - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.14.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", - "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001135", - "electron-to-chromium": "^1.3.571", - "escalade": "^3.1.0", - "node-releases": "^1.1.61" - } - }, - "bs-recipes": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", - "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", - "dev": true - }, - "bs-snippet-injector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", - "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", - "dev": true - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-indexof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "cacache": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", - "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", - "dev": true, - "requires": { - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "minipass": "^3.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "p-map": "^3.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^2.7.1", - "ssri": "^7.0.0", - "unique-filename": "^1.1.1" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "caniuse-lite": { - "version": "1.0.30001150", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001150.tgz", - "integrity": "sha512-kiNKvihW0m36UhAFnl7bOAv0i1K1f6wpfVtTF5O5O82XzgtBnb05V0XeV3oZ968vfg2sRNChsHw8ASH2hDfoYQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dev": true, - "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - } - }, - "collect.js": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.28.4.tgz", - "integrity": "sha512-NJXATt6r+gtGOgDJOKLeooTY6QpGn8YQN/PkKnCmajJOguz/xGPgPrTyrBkmBBTHXnniPRIkUqjqt3AkjwCKlg==", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", - "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", - "dev": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.4" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", - "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compose-function": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", - "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=", - "dev": true, - "requires": { - "arity-n": "^1.0.4" - } - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "concat": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz", - "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=", - "dev": true, - "requires": { - "commander": "^2.9.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", - "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } - } - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "dev": true, - "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-env": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", - "integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-declaration-sorter": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", - "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", - "dev": true, - "requires": { - "postcss": "^7.0.1", - "timsort": "^0.3.0" - } - }, - "css-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", - "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash": "^4.17.11", - "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", - "dev": true - }, - "css-selector-tokenizer": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", - "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "fastparse": "^1.1.2" - } - }, - "css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "dev": true, - "requires": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cssnano": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", - "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.7", - "is-resolvable": "^1.0.0", - "postcss": "^7.0.0" - } - }, - "cssnano-preset-default": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", - "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", - "dev": true, - "requires": { - "css-declaration-sorter": "^4.0.1", - "cssnano-util-raw-cache": "^4.0.1", - "postcss": "^7.0.0", - "postcss-calc": "^7.0.1", - "postcss-colormin": "^4.0.3", - "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.2", - "postcss-discard-duplicates": "^4.0.2", - "postcss-discard-empty": "^4.0.1", - "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.11", - "postcss-merge-rules": "^4.0.3", - "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.2", - "postcss-minify-params": "^4.0.2", - "postcss-minify-selectors": "^4.0.2", - "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.2", - "postcss-normalize-positions": "^4.0.2", - "postcss-normalize-repeat-style": "^4.0.2", - "postcss-normalize-string": "^4.0.2", - "postcss-normalize-timing-functions": "^4.0.2", - "postcss-normalize-unicode": "^4.0.1", - "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.2", - "postcss-ordered-values": "^4.1.2", - "postcss-reduce-initial": "^4.0.3", - "postcss-reduce-transforms": "^4.0.2", - "postcss-svgo": "^4.0.2", - "postcss-unique-selectors": "^4.0.1" - } - }, - "cssnano-util-get-arguments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", - "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", - "dev": true - }, - "cssnano-util-get-match": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", - "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", - "dev": true - }, - "cssnano-util-raw-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", - "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "cssnano-util-same-parent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", - "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", - "dev": true - }, - "csso": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", - "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", - "dev": true, - "requires": { - "css-tree": "1.0.0-alpha.39" - }, - "dependencies": { - "css-tree": { - "version": "1.0.0-alpha.39", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", - "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", - "dev": true, - "requires": { - "mdn-data": "2.0.6", - "source-map": "^0.6.1" - } - }, - "mdn-data": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", - "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "dev": true - }, - "default-gateway": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", - "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "ip-regex": "^2.1.0" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "dev-ip": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", - "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true - }, - "dns-packet": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", - "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, - "requires": { - "ip": "^1.1.0", - "safe-buffer": "^5.0.1" - } - }, - "dns-txt": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", - "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, - "requires": { - "buffer-indexof": "^1.0.0" - } - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", - "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", - "dev": true - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==", - "dev": true - }, - "dotenv-expand": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", - "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "easy-extender": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", - "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "eazy-logger": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.1.0.tgz", - "integrity": "sha512-/snsn2JqBtUSSstEl4R0RKjkisGHAhvYj89i7r3ytNUKW12y178KDZwXLXIgwDqLW6E/VRMT9qfld7wvFae8bQ==", - "dev": true, - "requires": { - "tfunk": "^4.0.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.582", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.582.tgz", - "integrity": "sha512-0nCJ7cSqnkMC+kUuPs0YgklFHraWGl/xHqtZWWtOeVtyi+YqkoAOMGuZQad43DscXCQI/yizcTa3u6B5r+BLww==", - "dev": true - }, - "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - }, - "dependencies": { - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - } - } - }, - "engine.io-client": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.4.tgz", - "integrity": "sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ==", - "dev": true, - "requires": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-stack-parser": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", - "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "dev": true, - "requires": { - "stackframe": "^1.1.1" - } - }, - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-templates": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", - "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", - "dev": true, - "requires": { - "recast": "~0.11.12", - "through": "~2.3.6" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true - }, - "eventsource": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", - "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", - "dev": true, - "requires": { - "original": "^1.0.0" - } - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", - "dev": true - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "extract-text-webpack-plugin": { - "version": "4.0.0-beta.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", - "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", - "dev": true, - "requires": { - "async": "^2.4.1", - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "file-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", - "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "friendly-errors-webpack-plugin": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", - "integrity": "sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "error-stack-parser": "^2.0.0", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - } - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hex-color-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", - "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "hsl-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", - "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", - "dev": true - }, - "hsla-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", - "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", - "dev": true - }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, - "html-entities": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", - "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", - "dev": true - }, - "html-loader": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", - "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", - "dev": true, - "requires": { - "es6-templates": "^0.2.3", - "fastparse": "^1.1.1", - "html-minifier": "^3.5.8", - "loader-utils": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - } - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", - "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", - "dev": true, - "requires": { - "http-proxy": "^1.17.0", - "is-glob": "^4.0.0", - "lodash": "^4.17.11", - "micromatch": "^3.1.10" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "imagemin": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-6.1.0.tgz", - "integrity": "sha512-8ryJBL1CN5uSHpiBMX0rJw79C9F9aJqMnjGnrd/1CafegpNuA81RBAAru/jQQEOWlOJJlpRnlcVFF6wq+Ist0A==", - "dev": true, - "requires": { - "file-type": "^10.7.0", - "globby": "^8.0.1", - "make-dir": "^1.0.0", - "p-pipe": "^1.1.0", - "pify": "^4.0.1", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - } - } - }, - "img-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-3.0.2.tgz", - "integrity": "sha512-rSriLKgvi85Km7ppSF+AEAM3nU4fxpvCkaXtC/IoCEU7jfks55bEANFs0bB9YXYkxY9JurZQIZFtXh5Gue3upw==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0" - } - }, - "immutable": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", - "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", - "dev": true - }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "requires": { - "import-from": "^2.1.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "include-media": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/include-media/-/include-media-1.4.9.tgz", - "integrity": "sha1-0AILe+PrLVSGiiCUNZXOOA4LxDs=" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "internal-ip": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", - "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", - "dev": true, - "requires": { - "default-gateway": "^4.2.0", - "ipaddr.js": "^1.9.0" - } - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-color-stop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", - "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", - "dev": true, - "requires": { - "css-color-names": "^0.0.4", - "hex-color-regex": "^1.1.0", - "hsl-regex": "^1.0.0", - "hsla-regex": "^1.0.0", - "rgb-regex": "^1.0.1", - "rgba-regex": "^1.0.0" - } - }, - "is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", - "dev": true, - "requires": { - "lodash.isfinite": "^3.3.2" - } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-svg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", - "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jest-worker": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", - "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "laravel-mix": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-5.0.7.tgz", - "integrity": "sha512-TL5txnQkzcwM8DYckgzjISSPGyZN6znFYb4NgtTSi9aIvfzOIEC6p0eYM6wDa/BkEKv290Ru6HWmH6Q2XApogQ==", - "dev": true, - "requires": { - "@babel/core": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-transform-runtime": "^7.2.0", - "@babel/preset-env": "^7.2.0", - "@babel/runtime": "^7.2.0", - "autoprefixer": "^9.4.2", - "babel-loader": "^8.0.4", - "babel-merge": "^2.0.1", - "chokidar": "^2.0.3", - "clean-css": "^4.1.3", - "collect.js": "^4.12.8", - "concat": "^1.0.3", - "css-loader": "^1.0.1", - "dotenv": "^6.2.0", - "dotenv-expand": "^4.2.0", - "extract-text-webpack-plugin": "v4.0.0-beta.0", - "file-loader": "^2.0.0", - "friendly-errors-webpack-plugin": "^1.6.1", - "fs-extra": "^7.0.1", - "glob": "^7.1.2", - "html-loader": "^0.5.5", - "imagemin": "^6.0.0", - "img-loader": "^3.0.0", - "lodash": "^4.17.15", - "md5": "^2.2.1", - "optimize-css-assets-webpack-plugin": "^5.0.1", - "postcss-loader": "^3.0.0", - "style-loader": "^0.23.1", - "terser": "^3.11.0", - "terser-webpack-plugin": "^2.2.3", - "vue-loader": "^15.4.2", - "webpack": "^4.36.1", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.14", - "webpack-merge": "^4.1.0", - "webpack-notifier": "^1.5.1", - "yargs": "^15.4.1" - } - }, - "last-call-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", - "dev": true, - "requires": { - "lodash": "^4.17.5", - "webpack-sources": "^1.1.0" - } - }, - "limiter": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", - "dev": true - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "localtunnel": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.0.tgz", - "integrity": "sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg==", - "dev": true, - "requires": { - "axios": "0.19.0", - "debug": "4.1.1", - "openurl": "1.1.1", - "yargs": "13.3.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" - } - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "loglevel": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", - "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", - "dev": true - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mitt": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", - "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, - "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" - } - }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true - }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "dev": true - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, - "node-releases": { - "version": "1.1.64", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.64.tgz", - "integrity": "sha512-Iec8O9166/x2HRMJyLLLWkd0sFFLrFNy+Xf+JQfSQsdBJzPcHpNl3JQ9gD4j+aJxmCa25jNsIbM4bmACtSbkSg==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "requires": { - "boolbase": "~1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-is": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", - "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "object.omit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-3.0.0.tgz", - "integrity": "sha512-EO+BCv6LJfu+gBIF3ggLicFebFLN5zqzz/WWJlMFfkMyGth+oBkhxzDl0wx2W4GkLzuQs/FsSkXZb2IMWQqmBQ==", - "dev": true, - "requires": { - "is-extendable": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "optimize-css-assets-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", - "dev": true, - "requires": { - "cssnano": "^4.1.10", - "last-call-webpack-plugin": "^3.0.0" - } - }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", - "dev": true, - "requires": { - "url-parse": "^1.4.3" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true - }, - "p-retry": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", - "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", - "dev": true, - "requires": { - "retry": "^0.12.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==", - "dev": true - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" - }, - "portfinder": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", - "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", - "dev": true, - "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.5" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "portscanner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", - "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", - "dev": true, - "requires": { - "async": "1.5.2", - "is-number-like": "^1.0.3" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", - "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-calc": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", - "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", - "dev": true, - "requires": { - "postcss": "^7.0.27", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.0.2" - } - }, - "postcss-colormin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", - "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-convert-values": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-discard-comments": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", - "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-duplicates": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-empty": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-discard-overridden": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-load-config": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", - "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "postcss-merge-longhand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", - "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", - "dev": true, - "requires": { - "css-color-names": "0.0.4", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-merge-rules": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", - "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-minify-font-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-minify-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", - "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", - "dev": true, - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-minify-params": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", - "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.0", - "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-minify-selectors": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", - "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", - "dev": true, - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-normalize-charset": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-normalize-display-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", - "dev": true, - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", - "dev": true, - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", - "dev": true, - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", - "dev": true, - "requires": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", - "dev": true, - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-unicode": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-normalize-whitespace": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", - "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-ordered-values": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", - "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", - "dev": true, - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-reduce-initial": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", - "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" - } - }, - "postcss-reduce-transforms": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", - "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", - "dev": true, - "requires": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-selector-parser": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", - "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1", - "util-deprecate": "^1.0.2" - } - }, - "postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "dev": true, - "requires": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" - }, - "dependencies": { - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - } - } - }, - "postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", - "dev": true, - "optional": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", - "dev": true, - "requires": { - "ast-types": "0.9.6", - "esprima": "~3.1.0", - "private": "~0.1.5", - "source-map": "~0.5.0" - } - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regex-parser": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.10.tgz", - "integrity": "sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA==", - "dev": true - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", - "dev": true, - "requires": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "resolve-url-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz", - "integrity": "sha512-2QcrA+2QgVqsMJ1Hn5NnJXIGCX1clQ1F6QJTqOeiaDw9ACo1G2k+8/shq3mtqne03HOFyskAClqfxKyFBriXZg==", - "dev": true, - "requires": { - "adjust-sourcemap-loader": "2.0.0", - "camelcase": "5.0.0", - "compose-function": "3.0.3", - "convert-source-map": "1.6.0", - "es6-iterator": "2.0.3", - "loader-utils": "1.2.3", - "postcss": "7.0.14", - "rework": "1.0.1", - "rework-visit": "1.0.0", - "source-map": "0.6.1" - }, - "dependencies": { - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - } - }, - "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "resp-modifier": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", - "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", - "dev": true, - "requires": { - "debug": "^2.2.0", - "minimatch": "^3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true - }, - "rework": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", - "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", - "dev": true, - "requires": { - "convert-source-map": "^0.3.3", - "css": "^2.0.0" - }, - "dependencies": { - "convert-source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", - "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", - "dev": true - } - } - }, - "rework-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", - "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", - "dev": true - }, - "rgb-regex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", - "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", - "dev": true - }, - "rgba-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", - "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", - "dev": true - }, - "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", - "dev": true, - "requires": { - "symbol-observable": "1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sass": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz", - "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==", - "dev": true, - "requires": { - "chokidar": ">=2.0.0 <4.0.0" - } - }, - "sass-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", - "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "loader-utils": "^1.2.3", - "neo-async": "^2.6.1", - "schema-utils": "^2.6.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selfsigned": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", - "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", - "dev": true, - "requires": { - "node-forge": "^0.10.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - } - } - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", - "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "engine.io-client": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - } - }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - } - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", - "dev": true - }, - "socket.io-client": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.1.tgz", - "integrity": "sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.1.tgz", - "integrity": "sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ==", - "dev": true, - "requires": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "sockjs": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", - "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", - "dev": true, - "requires": { - "faye-websocket": "^0.10.0", - "uuid": "^3.4.0", - "websocket-driver": "0.6.5" - } - }, - "sockjs-client": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", - "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", - "dev": true, - "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - } - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "ssri": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", - "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "minipass": "^3.1.1" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stackframe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "stream-throttle": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", - "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", - "dev": true, - "requires": { - "commander": "^2.2.0", - "limiter": "^1.0.5" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", - "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "string.prototype.trimstart": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", - "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "stylehacks": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", - "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", - "dev": true, - "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" - }, - "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - } - }, - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", - "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==", - "dev": true, - "requires": { - "cacache": "^13.0.1", - "find-cache-dir": "^3.3.1", - "jest-worker": "^25.4.0", - "p-limit": "^2.3.0", - "schema-utils": "^2.6.6", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.6.12", - "webpack-sources": "^1.4.3" - }, - "dependencies": { - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - } - } - }, - "tfunk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-4.0.0.tgz", - "integrity": "sha512-eJQ0dGfDIzWNiFNYFVjJ+Ezl/GmwHaFTBTjrtqNPW0S7cuVDBrZrmzUz6VkMeCR4DZFqhd4YtLwsw3i2wYHswQ==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "dlv": "^1.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "timers-browserify": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "dev": true - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.22", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz", - "integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==", - "dev": true - }, - "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "vendors": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", - "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", - "dev": true - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true - }, - "vue-loader": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.3.tgz", - "integrity": "sha512-Y67VnGGgVLH5Voostx8JBZgPQTlDQeOVBLOEsjc2cXbCYBKexSKEpOA56x0YZofoDOTszrLnIShyOX1p9uCEHA==", - "dev": true, - "requires": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - } - }, - "vue-style-loader": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", - "integrity": "sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==", - "dev": true, - "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "vue-template-compiler": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz", - "integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==", - "dev": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "optional": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "optional": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "dev": true, - "optional": true, - "requires": { - "chokidar": "^2.1.8" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webpack": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", - "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "dependencies": { - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - } - } - } - }, - "webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - } - } - }, - "webpack-dev-middleware": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", - "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", - "dev": true, - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "dev": true - } - } - }, - "webpack-dev-server": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", - "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "bonjour": "^3.5.0", - "chokidar": "^2.1.8", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "debug": "^4.1.1", - "del": "^4.1.1", - "express": "^4.17.1", - "html-entities": "^1.3.1", - "http-proxy-middleware": "0.19.1", - "import-local": "^2.0.0", - "internal-ip": "^4.3.0", - "ip": "^1.1.5", - "is-absolute-url": "^3.0.3", - "killable": "^1.0.1", - "loglevel": "^1.6.8", - "opn": "^5.5.0", - "p-retry": "^3.0.1", - "portfinder": "^1.0.26", - "schema-utils": "^1.0.0", - "selfsigned": "^1.10.7", - "semver": "^6.3.0", - "serve-index": "^1.9.1", - "sockjs": "0.3.20", - "sockjs-client": "1.4.0", - "spdy": "^4.0.2", - "strip-ansi": "^3.0.1", - "supports-color": "^6.1.0", - "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.2", - "webpack-log": "^2.0.0", - "ws": "^6.2.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - } - } - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - }, - "webpack-merge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", - "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "webpack-notifier": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/webpack-notifier/-/webpack-notifier-1.8.0.tgz", - "integrity": "sha512-I6t76NoPe5DZCCm5geELmDV2wlJ89LbU425uN6T2FG8Ywrrt1ZcUMz6g8yWGNg4pttqTPFQJYUPjWAlzUEQ+cQ==", - "dev": true, - "requires": { - "node-notifier": "^5.1.2", - "object-assign": "^4.1.0", - "strip-ansi": "^3.0.1" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "websocket-driver": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", - "dev": true, - "requires": { - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true } } } diff --git a/package.json b/package.json index 320ee697a4..0e5281ff3a 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,8 @@ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "npm run development", - "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", "watch": "bundle exec jekyll serve", - "prod": "npm run production", - "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --nide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" + "postinstall": "./npm-postinstall.sh" }, "repository": { "type": "git", @@ -26,14 +24,6 @@ }, "homepage": "https://github.com/AtreNet/prebid.github.io#readme", "devDependencies": { - "browser-sync": "^2.26.13", - "browser-sync-webpack-plugin": "^2.0.1", - "cross-env": "^7.0.2", - "laravel-mix": "^5.0.7", - "resolve-url-loader": "^3.1.0", - "sass": "^1.27.0", - "sass-loader": "^8.0.2", - "vue-template-compiler": "^2.6.12" }, "dependencies": { "awesomplete": "^1.1.5", diff --git a/partners/partners.md b/partners/partners.md index 71a7cf6417..29f5ee461f 100644 --- a/partners/partners.md +++ b/partners/partners.md @@ -8,8 +8,9 @@ sidebarType: 0 --- # Prebid.Org Membership -This page has moved to [https://prebid.org/membership/](https://prebid.org/membership/)! +This page has moved to [prebid.org/membership/](https://prebid.org/membership/)! ## Related Reading + - [Why Prebid](https://prebid.org/why-prebid/) - [Code of Conduct](https://prebid.org/code-of-conduct/) diff --git a/policies/antitrust.md b/policies/antitrust.md new file mode 100644 index 0000000000..857bf65c00 --- /dev/null +++ b/policies/antitrust.md @@ -0,0 +1,72 @@ +--- + +layout: page_v2 +title: Antitrust Policy | Prebid +description: Contributing to Prebid.js +sidebarType: 0 + +--- + +# Antitrust Policy + +Prebid.Org, Inc. (the “Corporation”) is intended to promote cooperation in the development of certain open source technology and related materials. The Corporation is necessary to enable its members to develop an open standard for transparent and interoperable header bidding solutions. The Corporation is narrowly tailored to achieving this goal. The Corporation is not organized to and does not play any role in the competitive business decisions of its members or potential members, nor does it in any way restrict competition among members or potential members. The Corporation’s members shall not discuss or coordinate individual bidding activity, strategy, customers, costs, employee compensation, hiring, or pricing (including the development of price ceilings, floors, or ranges). It is the express Policy of the Corporation to comply with all applicable federal, state, and foreign antitrust laws. This Policy has been prepared to inform Corporation members, staff and participants of this obligation. + +It is the responsibility of each member, staff and participant to comply with the antitrust laws and this Policy. + +## 1. Antitrust Laws + +### 1.a. Prices, Bids, and Compensation + +Agreements among competitors to fix prices or coordinate bids are per se unlawful and can result in criminal liability. Corporation members shall not discuss, signal, or exchange information about member company bids, sales opportunities, customers, costs, employee compensation, hiring, prices, or other competitively sensitive information. Members **SHALL NOT** discuss any element of a company's operations which might influence pricing, bids or compensation decisions, such as: + +1. Cost of operations, supplies, services and technology; +1. Allowance for discounts or rebates; +1. Terms of sales and licensing, including credit arrangements; +1. Profit margins and mark ups; +1. Transaction-specific past, present or future prices or costs; +1. Requests For Proposal, bids, or bidding opportunities; +1. Business, product, or marketing plans; +1. Employee compensation, benefits, recruitment, or hiring; +1. Market shares for any product or for all products; and +1. Actual or projected changes in production, output, capacity, or inventory. + +### 1.b. Markets + +Antitrust laws expressly prohibit any agreement between competitors to divide or allocate markets, including by geography, distribution channel, product type, and customers. Even an informal agreement whereby one member merely implies that it will stay away from another member’s territory or customers in exchange for reciprocity may constitute a per se violation of the antitrust laws and must be avoided. Members **SHALL NOT** discuss who will and will not compete for business along any of these dimensions. Agreements not to compete in any fashion, including in the hiring or poaching of employees, is forbidden. + +### 1.c.Exclusion + +Agreements among Corporation members to “boycott” or exclude a competitor from a market or a competitive activity are unlawful. Illegal group boycotts include “blacklisting” or agreeing to refuse to deal with a particular distributor or supplier. Members **SHALL NOT** discuss excluding or discriminating against other companies from any product, geography, technical standard, customer, source of supply, or distribution channel. + +## 2. Membership + +Corporation membership is subject to conditions that are non-discriminatory and objective. Membership to the Corporation is voluntary and each member of the Corporation retains absolute commercial freedom. No member is required to apply Corporation-compliant standards. The Corporation **SHALL NOT**: + +1. Exclude qualified competitors from membership in the Corporation for any anticompetitive purpose; +1. Restrict Corporation members from dealing with non-members or +1. Limit access to information developed by the Corporation unless such limitation is firmly grounded upon the need to protect trade secrets or other intellectual property rights. + +## 3. General Operating Procedures + +a.Understanding and sharing information on industry trends and conditions will be important for the Corporation to succeed in achieving its purpose of enabling its members to develop an open standard for transparent and interoperable header bidding solutions. Fortunately, antitrust enforcers recognize that sharing some types of information with competitors can benefit markets, businesses, and consumers alike if done with “adequate safeguards.” + +b.Keeping your conversations within these simple guardrails will ensure that you stay within the lanes of the law: + +1. You **MUST** hold discussions in open settings and avoid situations that could be seen as secretive. +1. In order to ensure that Corporation activities are conducted fairly in a manner that does not unduly benefit some competitors to the detriment of others, an agenda MUST be distributed prior to meetings and meetings shall adhere to the agenda. Meeting minutes shall be prepared and MUST accurately reflect the matters that transpired and MUST comply with this Policy. +1. You CAN discuss high-level, aggregate information regarding industry trends and expectations, rather than transaction-specific or company-specific data. +1. Generally, you CAN discuss industry public relations, litigation, legislation, lobbying, and long-term trends are generally appropriate. + +c.Antitrust violations can be inferred from the parties’ conduct and so it is important to avoid even the appearance of improper discussions. + +1. If you believe a conversation is approaching an improper subject, you must report any violations of this Policy concerning Corporation activities to the Corporation’s counsel; and MUST clearly state that: + 1. You have concerns about the comment or suggestion; + 2. Discussion on that topic must stop; and + 3. You will discuss this with counsel before deciding if it can proceed. +1.If the request is ignored, the meeting SHOULD stop and counsel should be advised. + +d.**No** Corporation member, staff or participant **SHALL** have authority to communicate with government officials regarding matters related to the Corporation without prior approval of the Corporation’s counsel. + +e.This Policy and standards of conduct set forth above **SHALL** apply to Board meetings, committee meetings, informal member meetings, social events, such as luncheons, receptions, and dinners, and any other activity related to the Corporation. + +f.All Corporation members, staff and participants staff **SHALL** report any violation of this Policy to the Corporation’s counsel. diff --git a/contributing/contribute.md b/policies/contribute.md similarity index 78% rename from contributing/contribute.md rename to policies/contribute.md index 194cf84133..b7f49089be 100644 --- a/contributing/contribute.md +++ b/policies/contribute.md @@ -15,20 +15,19 @@ There are several ways to contribute to the Prebid project. The easiest way is t Pull requests must satisfy certain conditions before being considered for merge. All the repos require the following: -+ 80% unit test code coverage -+ accompanying documentation (as necessary) +* 80% unit test code coverage +* accompanying documentation (as necessary) ## Repositories * [Prebid.js](https://github.com/prebid/Prebid.js) - * [Additional Pull Request requirements](https://github.com/prebid/Prebid.js/blob/master/PR_REVIEW.md) - * [Adding a bid adapter]({{site.baseurl}}/dev-docs/bidder-adaptor.html) - * [Adding an analytics adapter]({{site.baseurl}}/dev-docs/integrate-with-the-prebid-analytics-api.html) + * [Additional Pull Request requirements](https://github.com/prebid/Prebid.js/blob/master/PR_REVIEW.md) + * [Adding a bid adapter]({{site.baseurl}}/dev-docs/bidder-adaptor.html) + * [Adding an analytics adapter]({{site.baseurl}}/dev-docs/integrate-with-the-prebid-analytics-api.html) * [Prebid Server](https://github.com/prebid/prebid-server) * [Prebid iOS SDK](https://github.com/prebid/prebid-mobile-ios) * [Prebid Android SDK](https://github.com/prebid/prebid-mobile-android) - ## Reporting An Issue This website contains information on common issues. If you cannot find the issue you are reporting there, check on the appropriate GitHub repo's issue page ([Prebid.js](https://github.com/prebid/Prebid.js/issues), [Android SDK](https://github.com/prebid/prebid-mobile-android/issues), [iOS SDK](https://github.com/prebid/prebid-mobile-ios/issues)). If you are unable to find the issue there then submit a new issue . diff --git a/policies/cookies.md b/policies/cookies.md new file mode 100644 index 0000000000..1099d2bc9d --- /dev/null +++ b/policies/cookies.md @@ -0,0 +1,16 @@ +--- +layout: page_v2 +title: Cookies Used on Prebid.org +description: Cookies Used on Prebid.org +sidebarType: 0 +--- + +# Cookie Declaration + +The docs.prebid.org website may store or retrieve information on your browser in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. The information does not usually directly identify you, but it can give you a more personalized web experience. Because we respect your right to privacy, you can choose not to allow some types of cookies. However, blocking cookies may impact your experience of the site and the services we are able to offer. + + + +
        + +
        diff --git a/overview/ip-policy.md b/policies/ip-policy.md similarity index 99% rename from overview/ip-policy.md rename to policies/ip-policy.md index ad05f70253..08e23f0a75 100644 --- a/overview/ip-policy.md +++ b/policies/ip-policy.md @@ -10,8 +10,6 @@ sidebarType: 0 --- - - # INTELLECTUAL PROPERTY POLICY *Version 1.0* @@ -41,4 +39,3 @@ of the Organization. patent ownership. Contributors and members will not be required as a condition of membership to grant any patent rights, except as required by the Apache 2.0 license or contribution agreements described in Section 3 above. - diff --git a/privacy.md b/policies/privacy.md similarity index 95% rename from privacy.md rename to policies/privacy.md index 74373d2556..28ea7c1c71 100644 --- a/privacy.md +++ b/policies/privacy.md @@ -5,17 +5,19 @@ description: Prebid.org Privacy Policy sidebarType: 0 --- -# Prebid.org Website Privacy Policy +# Prebid.org Privacy Policy + {:.no_toc} Last updated Aug 5, 2020 -Prebid.org, Inc. respects your right to privacy. This Privacy Notice explains who we are, how we collect, share and use personal information about you, and how you can exercise your privacy rights. This Privacy Notice applies to personal information that we collect through our website at [https://prebid.org/](https://prebid.org/) and its subdomains ("**Website**") and via our marketing activities and events. +Prebid.org, Inc. respects your right to privacy. This Privacy Notice explains who we are, how we collect, share and use personal information about you, and how you can exercise your privacy rights. This Privacy Notice applies to personal information that we collect through our website at [prebid.org](https://prebid.org/) and its subdomains ("**Website**") and via our marketing activities and events. This Privacy Notice does not apply to any information collected by third parties using our open source software. If you have any questions or concerns about our use of your personal information, then please contact us using the contact details provided at the bottom of this Privacy Notice. ## Quick Links + {:.no_toc} We recommend that you read this Privacy Notice in full to ensure you are fully informed. However, if you only want to access a particular section of this Privacy Notice, then you can click on the relevant link below to jump to that section. @@ -23,24 +25,25 @@ We recommend that you read this Privacy Notice in full to ensure you are fully i * TOC {:toc} -## What does Prebid.org do? +## What does Prebid.org do? Prebid.org is an industry consortium that provides free and open source solutions to implement header bidding. We’re utilized globally and headquartered in the United States. We seek to ensure and promote fair, transparent, and efficient header bidding across the ad tech industry, representing all parts of the programmatic ecosystem, from ad tech vendors to publishers and others. The open source software products we make available may be utilized by third parties for the purposes of serving online advertisements. These third parties may configure the software to enable pseudonymized data included in bid requests to be transmitted within the online advertising ecosystem. However, Prebid.org has no involvement in these transactions and does not itself transmit, store or otherwise process the pseudonymized data in these transactions.  Prebid.org is not responsible for the privacy practices of third parties that use our software and it is the responsibility of the third party concerned to handle data in accordance with applicable privacy laws.  -For more information about Prebid.org, please see the “About” section of our Website at [https://prebid.org/overview/what-is-prebid-org.html](/overview/what-is-prebid-org.html). +For more information about Prebid.org, please see the “About” section of our Website at [prebid.org/overview/what-is-prebid-org.html](/overview/what-is-prebid-org.html). + ## What personal information does Prebid.org collect and why? The personal information that we may collect from our Website or through our marketing activities broadly falls into the following categories: **Information that you provide voluntarily** -Certain parts of our Website may ask you to provide personal information voluntarily: for example, we may ask you to provide your name and contact details in order to download files or code from us, sign up for an email newsletter, register for or attend one of our events, contribute code, and/or to submit enquiries or emails to us. When you submit code to us, we may ask you to sign our Code Contributor Licensing Agreement. If you are contributing code on behalf of your employer, then we may ask your employer to sign a similar agreement too. +Certain parts of our Website may ask you to provide personal information voluntarily: for example, we may ask you to provide your name and contact details in order to download files or code from us, sign up for an email newsletter, register for or attend one of our events, contribute code, and/or to submit enquiries or emails to us. When you submit code to us, we may ask you to sign our Code Contributor Licensing Agreement. If you are contributing code on behalf of your employer, then we may ask your employer to sign a similar agreement too. -Our Website also includes links to third party sites such as GitHub, Stack, Slack, Reddit, Quora and Twitter to enable you to submit questions and requests to us on those third party sites if you so choose; for example, by using certain tags or by following our profiles on those sites. +Our Website also includes links to third party sites such as GitHub, Stack, Slack, Reddit, Quora and Twitter to enable you to submit questions and requests to us on those third party sites if you so choose; for example, by using certain tags or by following our profiles on those sites. From time-to-time, Prebid.org may also host events, online or offline, and invite people to register for these events. @@ -56,14 +59,15 @@ Specifically, the information we collect automatically may include information l Collecting this information enables us to better understand the visitors who come to our Website, where they come from, and what content on our Website is of interest to them. We use this information for our internal analytics purposes and to improve the quality and relevance of our Website to our visitors. -Some of this information may be collected using cookies and similar tracking technology, as explained further in our [Cookies Notice](/cookies.html). +Some of this information may be collected using cookies and similar tracking technology, as explained further in our [Cookies Notice](/policies/cookies.html). + ## Who does Prebid.org share my personal information with? We may disclose your personal information to the following categories of recipients: -* to our **third party services providers and partners** who provide data processing services to us (for example, to support the delivery of, provide functionality on, or help to enhance the security of our Website or email newsletters), or who otherwise process personal information for purposes that are described in this Privacy Notice or notified to you when we collect your personal information. +* to our **third party services providers and partners** who provide data processing services to us (for example, to support the delivery of, provide functionality on, or help to enhance the security of our Website or email newsletters), or who otherwise process personal information for purposes that are described in this Privacy Notice or notified to you when we collect your personal information. * to any **competent law enforcement body, regulatory, government agency, court or other third party** where we believe disclosure is necessary (i) as a matter of applicable law or regulation, (ii) to exercise, establish or defend our legal rights, or (iii) to protect your vital interests or those of any other person; @@ -85,15 +89,15 @@ If you have questions about or need further information concerning the legal bas ## Third-Party Websites -This Notice only applies to the Prebid.org Website. We are not responsible for the privacy practices or disclosures of third party websites which may be linked from our Website. Any access to and use of such linked websites is governed by the privacy policies of those third parties. We are not responsible for the information practices of such third parties. +This Notice only applies to the Prebid.org Website. We are not responsible for the privacy practices or disclosures of third party websites which may be linked from our Website. Any access to and use of such linked websites is governed by the privacy policies of those third parties. We are not responsible for the information practices of such third parties. ## How does Prebid.org keep my personal information secure? -We use appropriate technical and organisational measures to protect the personal information that we collect and process about you. The measures we use are designed to provide a level of security appropriate to the risk of processing your personal information. +We use appropriate technical and organisational measures to protect the personal information that we collect and process about you. The measures we use are designed to provide a level of security appropriate to the risk of processing your personal information. ## International data transfers -Your personal information may be transferred to, and processed in, countries other than the country in which you are resident. We are headquartered in the US, and our member companies and third party service providers and partners operate around the world. Therefore, when we collect your personal information, we may process it in countries that have data protection laws that are different to the laws of your country and in some cases, may not be as protective. +Your personal information may be transferred to, and processed in, countries other than the country in which you are resident. We are headquartered in the US, and our member companies and third party service providers and partners operate around the world. Therefore, when we collect your personal information, we may process it in countries that have data protection laws that are different to the laws of your country and in some cases, may not be as protective. We will take appropriate safeguards to ensure that your personal information will remain protected in accordance with this Privacy Notice, including signing standard contractual clauses with our third party service providers. Further details can be provided upon request – please write to us using the contact details further below. @@ -101,14 +105,15 @@ We will take appropriate safeguards to ensure that your personal information wil We retain personal information we collect from you where we have an ongoing legitimate business need to do so (for example, to provide you with a service you have requested or to comply with applicable legal requirements). -When we have no ongoing legitimate business need to process your personal information, we will either delete or anonymise it or, if this is not possible (for example, because your personal information has been stored in backup archives), then we will securely store your personal information and isolate it from any further processing until deletion is possible. +When we have no ongoing legitimate business need to process your personal information, we will either delete or anonymise it or, if this is not possible (for example, because your personal information has been stored in backup archives), then we will securely store your personal information and isolate it from any further processing until deletion is possible. + ## Your data protection rights If you are a resident of the European Economic Area or California, you have the right to request to access or request deletion of your personal information. You may exercise this right at any time by using the contact details provided under the ["How to contact us"](#contact) heading below. -In addition, if you are a resident of the European Economic Area, you have the following additional data protection rights: +In addition, if you are a resident of the European Economic Area, you have the following additional data protection rights: * You may object to processing of your personal information, ask us to restrict processing of your personal information or request portability or correction of your personal information. Again, you can exercise these rights by contacting us using the contact details provided under the ["How to contact us"](#contact) heading below. * If we have collected and processed your personal information with your consent, then you can withdraw your consent at any time. Withdrawing your consent will not affect the lawfulness of any processing we conducted prior to your withdrawal, nor will it affect processing of your personal information conducted in reliance on lawful processing grounds other than consent. @@ -122,10 +127,10 @@ out by using the contact details provided under the ["How to contact us"](#conta We respond to all requests we receive from individuals wishing to exercise their data protection rights in accordance with applicable data protection laws. ## Additional information for California residents - + If you are a California resident, please review the following additional privacy disclosures under the California Consumer Privacy Act ("CCPA"). -You have the right to understand how we collect, use, and disclose your personal information, to access your information, to request that we delete certain information, and to not be discriminated against for exercising your privacy rights. You may exercise these rights as described in the ["Your data protection rights"](#data-protection-rights) section above. +You have the right to understand how we collect, use, and disclose your personal information, to access your information, to request that we delete certain information, and to not be discriminated against for exercising your privacy rights. You may exercise these rights as described in the ["Your data protection rights"](#data-protection-rights) section above. You also have the right to understand what information we collect, for what purpose, and how we disclose personal information to third parties. As described in the [What personal information does Prebid.org collect and why?](#what-personal-info) section, we collect the categories of personal information listed below, and we use and disclose these categories of information for the business purposes described in that section. The categories are: @@ -136,10 +141,9 @@ You also have the right to understand what information we collect, for what purp We share these categories of personal information as described in the [Who does Prebid.org share my personal information with?](#share-personal-info) section. We never sell the personal information we collect. - ## Updates to this Privacy Notice -We may update this Privacy Notice from time to time in response to changing legal, technical or business developments. When we update our Privacy Notice, we will take appropriate measures to inform you, consistent with the significance of the changes we make. We will obtain your consent to any material Privacy Notice changes if and where this is required by applicable data protection laws. +We may update this Privacy Notice from time to time in response to changing legal, technical or business developments. When we update our Privacy Notice, we will take appropriate measures to inform you, consistent with the significance of the changes we make. We will obtain your consent to any material Privacy Notice changes if and where this is required by applicable data protection laws. You can see when this Privacy Notice was last updated by checking the "last updated" date displayed at the top of this Privacy Notice. @@ -147,7 +151,6 @@ You can see when this Privacy Notice was last updated by checking the "last upda ## How to contact us -If you have any questions or concerns about our use of your personal information, please contact privacy@prebid.org . +If you have any questions or concerns about our use of your personal information, please contact . The data controller of your personal information is Prebid.org, Inc. - diff --git a/prebid-mobile/add-an-ad-server-adapter.md b/prebid-mobile/add-an-ad-server-adapter.md deleted file mode 100644 index 380901859f..0000000000 --- a/prebid-mobile/add-an-ad-server-adapter.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: page_v2 -title: Add an Ad Server Adapter -description: Add an Ad Server Adapter -pid: 0 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-contributors -sidebarType: 2 ---- - - - -# Add an Ad Server Adapter -{:.no_toc} - -We are looking for contributors to add ad server adapters so that Prebid Mobile can be used with more ad server SDKs. - -Contributors should visit GitHub to learn how to contribute to Prebid Mobile. - -### For iOS - -[The iOS source code is hosted under the Prebid organization on GitHub](https://github.com/prebid/prebid-mobile-ios) - -### For Android - -[The Android source code is hosted under the Prebid organization on GitHub](https://github.com/prebid/prebid-mobile-android) - - - diff --git a/prebid-mobile/adops-line-item-setup-dfp.md b/prebid-mobile/adops-line-item-setup-dfp.md deleted file mode 100644 index 7412eb0721..0000000000 --- a/prebid-mobile/adops-line-item-setup-dfp.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: page_v2 -title: Setup Line items For Google Ad Manager -head_title: Step by step guide to Google Ad Manager Setup -description: Setting up GAM for Prebid.js -#note the sidebar type needs to reflect the section this file is displayed in. See _data/sidenav.yml for the side nav categories. -sidebarType: 2 ---- - -{% include /adops/adops-gam-setup.html %} diff --git a/prebid-mobile/adops-line-item-setup-mopub.md b/prebid-mobile/adops-line-item-setup-mopub.md deleted file mode 100644 index cd5d578c87..0000000000 --- a/prebid-mobile/adops-line-item-setup-mopub.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -layout: page_v2 -title: Setup Line Items for MoPub -description: Setup line items for MoPub -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-adops -sidebarType: 3 ---- - - - - -# Step-by-Step Line Item Setup for MoPub - -* TOC -{:toc } - -This page provides step-by-step instructions to set up Prebid Mobile line items for MoPub to serve ads on app with the Prebid SDK. It is using the Universal Prebid Creative. - -## Step 1. Add a line item - -- Set the **Type & Priority** to **Non-guaranteed** and **12**, respectively, so the line item will compete with all other demand -- Set the **Rate** to the price you want to target, for example $0.50, in the screenshot below - -![MoPub Line Item Setup]({{site.github.url}}/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub1.png "Example MoPub Line Item"){: .pb-md-img :} - -- In the **Advanced Targeting** section, in **Keywords** target **hb_pb:0.50** - -![MoPub Advanced Targeting Setup]({{site.github.url}}/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub2.png "Example MoPub Advanced Targeting"){: .pb-md-img :} - -For each level of pricing granularity you need, you will have to set up one line item/creative pair. - -Line items must be set up to target custom keywords that include bid price information. The bid price keywords tell you how much the buyer bid on the impression. - -By default, `Prebid Mobile` will send the highest bid price to Google Ad Manager using the keyword `hb_pb` but will also pass the keys `hb_pb_BIDDERCODE`. You can decide to create one set of line items for all bidders or one set of line items for each bidder. - -## Step 2. Add creatives to your line item - -Banner creatives must be HTML banners with the **Format** set to **Banner** that include the code shown below. - -![MoPub Creative Setup]({{site.github.url}}/assets/images/prebid-mobile/adops-line-item-setup-mopub/mopub3.png "Example MoPub Creative"){: .pb-md-img :} - -The **hb_cache_id** variable stands for the cache id that will load the ad markup from the bid from Prebid Cache. Within each line item, for each ad unit size there should be one creative with this content. - - -{: .alert.alert-success :} -You can always get the latest version of the creative code below from [the Mobile example creative file in our GitHub repo](https://github.com/prebid/prebid-universal-creative/blob/master/template/amp/dfp-creative.html). - -{% highlight javascript %} - - - - -{% endhighlight %} - -## Step 3. Duplicate line items - -Duplicate your line items according to your [price granularity]({{site.github.url}}/prebid-mobile/adops-price-granularity.html) setting. diff --git a/prebid-mobile/adops-native-setup.md b/prebid-mobile/adops-native-setup.md deleted file mode 100644 index 0c274fbb58..0000000000 --- a/prebid-mobile/adops-native-setup.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -layout: page_v2 -title: Setup Native Ads -head_title: Step by step guide for Native Ad Setup -description: Setting up Native ads in both Google Ad Manager and MoPub. -sidebarType: 3 ---- - -# Set Up Native - -Prebid Mobile enables publishers to display native ads within their apps. This page provides instructions for setting up ad ops for both Google Ad Manager and MoPub. - - -## Google Ad Manager - -The following instructions are for setting up a Native ad with HTML and CSS. For more detailed information refer to the [Google Ad Manager documentation.](https://support.google.com/admanager/answer/7661907) - -1. Sign in to your Google Ad Manager account. -2. Click Delivery > Native. -3. Click New Native Ad. -4. Click Select in the "HTML & CSS editor" box. The *Define ad settings* page will appear. - - a. Select an ad size of `fluid`. With the Fluid size, Ad Manager will automatically size the ad to match available space. - b. Select an existing format or create a new one. (Formats are the variables that make up the content of your ad.) - c. Style your ad with HTML and CSS. (See code sample below) - Add your styles in the CSS tab in Ad Manager. - - A native ad is made up of assets, image URL, titles, descriptions, icons, etc. that are plugged into the template we've just created. The template includes placeholder macros for those assets, and may be styled to match the form of the surrounding page. - - At a high level, Prebid Mobile's support for native ads works by requesting native demand from bidder adapters. The native ad responses get placed on specific keys that are sent into your ad server. - - The `native-trk.js` linked in the code example below will find `hb_native_keys` and replace them with native assets. For more detailed information and a list of available keys see our documentation that explains [how Native ads work](/dev-docs/show-native-ads.html#how-native-ads-work). - - d. Set the targeting to default and save. - -5. [Create a line item](/prebid-mobile/adops-line-item-setup-dfp.html) targeting this ad unit and a `hb_pb price`, for expected creatives, put in the ad format in step 4.b. -6. Create a native creative using the native styles (and the ad format created/used with the native styles), associating it with the line item - -
        -**Example** -
        -``` - - - -``` - -## MoPub - -The instructions below describe how to add a Native ad with the MoPub SDK. For more detailed information review the MoPub Native ad documentation for [iOS](https://developers.mopub.com/publishers/ios/native/) and [Android](https://developers.mopub.com/publishers/android/native/). - - 1. Create a `Medium rectangle` Ad Unit - 2. Create a non-guaranteed line item targeting this ad unit and a `hb_pb price` - 3. Create a creative with 300x250 Medium Rectangle format, choose HTML and put in the following code: - -```html - - - -``` - -{% capture noteAlert %} -Note not to check Mraid ad.z -{% endcapture %} - -{% include alerts/alert_note.html content=noteAlert %} - -## Further Reading -- [Setting Up Line Items for Google Ad Manager]({{site.baseurl}}/prebid-mobile/adops-line-item-setup-dfp.html) -- [Setting Up Line Items for MoPub]({{site.baseurl}}/prebid-mobile/adops-line-item-setup-mopub.html) -- [How Native Ads Work](/dev-docs/show-native-ads.html#how-native-ads-work) diff --git a/prebid-mobile/adops-price-granularity.md b/prebid-mobile/adops-price-granularity.md index 65d4d04e87..cabe259c11 100644 --- a/prebid-mobile/adops-price-granularity.md +++ b/prebid-mobile/adops-price-granularity.md @@ -11,52 +11,52 @@ With Prebid Mobile, you’ll need to setup line items to tell your ad server how Example: -* Prebid Mobile is going to call Prebid Server which calls your bidders for their price, then passes it into your ad server on the query-string. You want to target this bid price with a line item that earns you the same amount if it serves. +- Prebid Mobile is going to call Prebid Server which calls your bidders for their price, then passes it into your ad server on the query-string. You want to target this bid price with a line item that earns you the same amount if it serves. -* If you had 1-line item for every bid at a penny granularity of $0.01, $0.02, $0.03, ..., 1.23, ..., $4.56 you’d need 1,000 line items just to represent bids from $0-$10. We call this the “Exact” granularity option. +- If you had 1-line item for every bid at a penny granularity of $0.01, $0.02, $0.03, ..., 1.23, ..., $4.56 you’d need 1,000 line items just to represent bids from $0-$10. We call this the “Exact” granularity option. -* Creating 1,000 line items can be a hassle, so publishers typically use price buckets to represent price ranges that matter. For example, you could group bids into 10 cent increments, so bids of $1.06 or $1.02 would be rounded down into a single price bucket of $1.00. +- Creating 1,000 line items can be a hassle, so publishers typically use price buckets to represent price ranges that matter. For example, you could group bids into 10 cent increments, so bids of $1.06 or $1.02 would be rounded down into a single price bucket of $1.00. The SDK itself doesn't deal with granularity. Instead, these details are set up in Prebid Server and your ad server. The specific details about how to set up the price granularity will differ for each Prebid Mobile managed service company -- check with your provider to get details for their system. ## Accepted values for price granularity -+ `"low"`: $0.50 increments, capped at $5 CPM -+ `"med"`: $0.10 increments, capped at $20 CPM (the default) -+ `"high"`: $0.01 increments, capped at $20 CPM -+ `"auto"`: Applies a sliding scale to determine granularity as shown in the [Auto Granularity](#autoGranularityBucket) table below. -+ `"dense"`: Like `"auto"`, but the bid price granularity uses smaller increments, especially at lower CPMs. For details, see the [Dense Granularity](#denseGranularityBucket) table below. -+ `"custom"`: If none of the above apply, your service provider should provide a way to establish arbitrary price buckets. +- `"low"`: $0.50 increments, capped at $5 CPM +- `"med"`: $0.10 increments, capped at $20 CPM (the default) +- `"high"`: $0.01 increments, capped at $20 CPM +- `"auto"`: Applies a sliding scale to determine granularity as shown in the [Auto Granularity](#autoGranularityBucket) table below. +- `"dense"`: Like `"auto"`, but the bid price granularity uses smaller increments, especially at lower CPMs. For details, see the [Dense Granularity](#denseGranularityBucket) table below. +- `"custom"`: If none of the above apply, your service provider should provide a way to establish arbitrary price buckets. Notes: + - Banner and outstream video generally share the same ad server line items. - PBS-Java support the "mediatypepricegranularity" enhancement, which lets you define different granularities for banner and video -#### Auto Granularity +### Auto Granularity {: .table .table-bordered .table-striped } -| CPM | Granularity | Example | +| CPM | Granularity | Example | |---------------------+----------------------------------+--------| -| CPM <= $5 | $0.05 increments | $1.87 floored to $1.85 | -| CPM <= $10 and > $5 | $0.10 increments | $5.09 floored to $5.00 | -| CPM <= $20 and > $10 | $0.50 increments | $14.26 floored to $14.00 | -| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | +| CPM <= $5 | $0.05 increments | $1.87 floored to $1.85 | +| CPM <= $10 and > $5 | $0.10 increments | $5.09 floored to $5.00 | +| CPM <= $20 and > $10 | $0.50 increments | $14.26 floored to $14.00 | +| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | -#### Dense Granularity +### Dense Granularity {: .table .table-bordered .table-striped } -| CPM | Granularity | Example | +| CPM | Granularity | Example | |------------+-------------------------------+---------| -| CPM <= $3 | $0.01 increments | $1.87 floored to $1.87 | -| CPM <= $8 and >$3 | $0.05 increments | $5.09 floored to $5.05 | -| CPM <= $20 and >$8 | $0.50 increments | $14.26 floored to $14.00 | -| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | - +| CPM <= $3 | $0.01 increments | $1.87 floored to $1.87 | +| CPM <= $8 and >$3 | $0.05 increments | $5.09 floored to $5.05 | +| CPM <= $20 and >$8 | $0.50 increments | $14.26 floored to $14.00 | +| CPM > $20 | Caps the price bucket at $20 | $24.82 floored to $20.00 | Please contact your Prebid Mobile host company for details about how to implement granularity. diff --git a/prebid-mobile/adops-setup-full-screen-video-mopub.md b/prebid-mobile/adops-setup-full-screen-video-mopub.md deleted file mode 100644 index 429c0488d3..0000000000 --- a/prebid-mobile/adops-setup-full-screen-video-mopub.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -layout: page_v2 -title: Setup Rewarded Video for MoPub -description: Setup Full Screen Video for MoPub -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-adops -sidebarType: 3 ---- - -# Step-by-Step Line Item Setup for Full-screen Video on MoPub - -* TOC -{:toc } - -This page provides step-by-step instructions to set up full-screen video line items on MoPub to be used with the Prebid Mobile SDK. - -## Step 1. Create full screen adUnit -Under New ad unit, select Fullscreen.   - -## Step 2. Add a line item -In the *Add a Line Item* section: -1. For the *Type and Priority* settings, select *Non-Guaranteed* as the type and set the priority to *12*. This ensures the line item will compete with all other demand. -2. Set the Rate to the price you want to target.  -For the Type and Priority settings, select Non-Guaranteed as the type and set the priority to 12   -3. In the *Advanced Targeting* section, set the target for *Keywords* to `hb_pb:0.50`  -In the Advanced Targeting section, set the target for Keywords to hb_pb:0.50   - -For each level of pricing granularity required, one line item/creative pairing will need to be set up. - -Line items must be set up to target custom keywords that include bid price information. The bid price keywords will contain how much the buyer bid on the impression. - -Prebid Mobile, by default, will send the highest bid price to MoPub using the keyword `hb_pb` but will also submit the key `hb_pb_BIDDERCODE` for each bidder. You can decide to create one set of line items for all bidders or one set of line items for each bidder. - -## Step 3. Add creatives to your line item -Full-screen video creatives must have a *VAST tag* with the *Format* set to *Fullscreen* that includes the code below: -``` - - - - MoPub - - - - - -``` -
        -MoPub VAST tag code   - -The `hb_uuid` variable value is the cache id that will load the ad markup from the bid stored in Prebid Cache. Within each line item, for each ad unit size, there should be one creative with this content. - -The XML can be constructed by providing the VAST tag URL as: -`https://%%KEYWORD:hb_cache_host%%%%KEYWORD:hb_cache_path%%?uuid=%%KEYWORD:hb_uuid%%` - -## Step 4. Duplicate line items -Duplicate your line items according to your [price granularity](/prebid-mobile/adops-price-granularity.html) setting. diff --git a/prebid-mobile/adops-setup-rewarded-video-mopub.md b/prebid-mobile/adops-setup-rewarded-video-mopub.md deleted file mode 100644 index 839a8593e7..0000000000 --- a/prebid-mobile/adops-setup-rewarded-video-mopub.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -layout: page_v2 -title: Setup Rewarded Video for MoPub -description: Setup Rewarded Video for MoPub -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-adops -sidebarType: 3 ---- - -# Step-by-Step Line Item Setup for Rewarded Video on MoPub - -* TOC -{:toc } - -This page provides step-by-step instructions to set up rewarded-video line items on MoPub to be used with the Prebid Mobile SDK. - -## Step 1. Add a line item - - In the *Add a Line Item* section: - 1. For the *Type and Priority* settings, select *Non-Guaranteed* as the type and set the priority to *12*. This ensures the line item will compete with all other demand. - 2. Set the Rate to the price you want to target.  - For the Type and Priority settings, select Non-Guaranteed as the type and set the priority to 12   - 3. In the *Advanced Targeting* section, set the target for *Keywords* to `hb_pb:0.50`  - In the Advanced Targeting section, set the target for Keywords to hb_pb:0.50   - -For each level of pricing granularity required, one line item/creative pairing will need to be set up. - -Line items must be set up to target custom keywords that include bid price information. The bid price keywords will contain how much the buyer bid on the impression. - -Prebid Mobile, by default, will send the highest bid price to MoPub using the keyword `hb_pb` but will also submit the key `hb_pb_BIDDERCODE` for each bidder. You can decide to create one set of line items for all bidders or one set of line items for each bidder. - -## Step 2. Add creatives to your line item -Rewarded video creatives must have a *VAST tag* with the *Format* set to *Rewarded Video* that includes the code below: - -``` - - - - MoPub - - - - -``` - -
        -MoPub VAST tag code   -The `hb_uuid` variable value is the cache id that will load the ad markup from the bid stored in Prebid Cache. Within each line item, for each ad unit size, there should be one creative with this content. - -The XML can be constructed by providing the VAST tag URL as: -`https://%%KEYWORD:hb_cache_host%%%%KEYWORD:hb_cache_path%%?uuid=%%KEYWORD:hb_uuid%%` - -## Step 3. Duplicate line items -Duplicate your line items according to your [price granularity](/prebid-mobile/adops-price-granularity.html) setting. diff --git a/prebid-mobile/adops-video-setup-dfp.md b/prebid-mobile/adops-video-setup-dfp.md deleted file mode 100644 index acd6c0aecc..0000000000 --- a/prebid-mobile/adops-video-setup-dfp.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: page_v2 -title: Setting up Prebid Video in Google Ad Manager -head_title: Setting up Prebid Video in Google Ad Manager -description: Setting up Prebid Video in Google Ad Manager -top_nav_section: mobile -sidebarType: 2 ---- - -{% include adops/adops-gam-video-setup.html %} diff --git a/prebid-mobile/docs/Prebid_Mobile_3_0_0.pdf b/prebid-mobile/docs/Prebid_Mobile_3_0_0.pdf new file mode 100644 index 0000000000..a476e0faa8 Binary files /dev/null and b/prebid-mobile/docs/Prebid_Mobile_3_0_0.pdf differ diff --git a/prebid-mobile/download.md b/prebid-mobile/download.md deleted file mode 100644 index c463280f78..0000000000 --- a/prebid-mobile/download.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: page_v2 -title: Prebid Mobile -description: What is Prebid.js -sidebarType: 2 ---- - -# Downloading Prebid Mobile SDK - -For both Android and iOS, there are a couple of options for integrating the Prebid SDK. - -## Android - -+ Option 1: Maven org.prebid:prebid-mobile-sdk -+ Option 2: clone https://github.com/prebid/prebid-mobile-android - -Follow the full instructions for [integrating the Android SDK](/prebid-mobile/pbm-api/android/code-integration-android.html). - -## iOS - -+ Option 1: Cocoapod 'PrebidMobile' -+ Option 2: https://github.com/prebid/prebid-mobile-ios - -Follow the full instructions for [integrating the iOS SDK](/prebid-mobile/pbm-api/ios/code-integration-ios.html). diff --git a/prebid-mobile/dr-prebid-tou.md b/prebid-mobile/dr-prebid-tou.md index 6b4bd37284..6b59c0b7fb 100644 --- a/prebid-mobile/dr-prebid-tou.md +++ b/prebid-mobile/dr-prebid-tou.md @@ -18,22 +18,22 @@ Last updated October 15, 2018 Thank you for using Prebid.org, Inc.’s (“**Prebid**”, “**we**”, “**us**”, or “**our**”) “*Dr. Prebid*” application (the “**App**”). By downloading and using the App, you or the entity you represent, as the case may be (“**you**”), agree to be bound by these terms of use (the “**Terms**”). You may only use the App in accordance with these Terms. -1. **The App**. The App is provided by Prebid to help clients identify and address implementation issues for header bidding integrations on mobile properties. You may submit certain materials or data (e.g., information about your Prebid Server configuration or Account Information, as defined below) to the App (any such materials or data, the “**Data**”). You hereby grant to Prebid and its affiliates the non-exclusive, royalty-free, perpetual, irrevocable right to use or disclose your Data (i) as reasonably required by Prebid to provide or enhance the App, (ii) to create and make publicly available anonymous, aggregated statistics regarding Data and use of the App, provided that (a) we will not identify you as the source of the data for any such statistics, and (b) your Data will be aggregated with the Data of other users reasonably sufficient to mask the identity of any single source of the statistical data, (iii) to enforce Prebid’s rights under these Terms, and (iv) as required by court order, law, or regulatory agency. Prebid may also collect certain information regarding your use of, and the performance of, the App. +1. **The App**. The App is provided by Prebid to help clients identify and address implementation issues for header bidding integrations on mobile properties. You may submit certain materials or data (e.g., information about your Prebid Server configuration or Account Information, as defined below) to the App (any such materials or data, the “**Data**”). You hereby grant to Prebid and its affiliates the non-exclusive, royalty-free, perpetual, irrevocable right to use or disclose your Data (i) as reasonably required by Prebid to provide or enhance the App, (ii) to create and make publicly available anonymous, aggregated statistics regarding Data and use of the App, provided that (a) we will not identify you as the source of the data for any such statistics, and (b) your Data will be aggregated with the Data of other users reasonably sufficient to mask the identity of any single source of the statistical data, (iii) to enforce Prebid’s rights under these Terms, and (iv) as required by court order, law, or regulatory agency. Prebid may also collect certain information regarding your use of, and the performance of, the App. -2. **Confidentiality**. “**Confidential Information**” means any information that is disclosed, provided, or made accessible by, or on behalf of, Prebid to you in connection with these Terms or through the App, and which is identified as “confidential” or “proprietary” or which, given the nature of the information or material, or the circumstances surrounding the disclosure, reasonably should be understood to be confidential or proprietary, but does not include information that you already knew, becomes public through no fault of yours, or was independently developed by you without reference to our confidential information. You agree not to disclose Prebid Confidential Information without our prior written consent. You may only use Confidential Information to exercise your rights and fulfill your obligations under these Terms, or as otherwise specifically permitted by Prebid, and not for any other purpose, including, but not limited to, collusion against, advancement of competitive interests contrary to, or interference with the business plans of, Prebid. +2. **Confidentiality**. “**Confidential Information**” means any information that is disclosed, provided, or made accessible by, or on behalf of, Prebid to you in connection with these Terms or through the App, and which is identified as “confidential” or “proprietary” or which, given the nature of the information or material, or the circumstances surrounding the disclosure, reasonably should be understood to be confidential or proprietary, but does not include information that you already knew, becomes public through no fault of yours, or was independently developed by you without reference to our confidential information. You agree not to disclose Prebid Confidential Information without our prior written consent. You may only use Confidential Information to exercise your rights and fulfill your obligations under these Terms, or as otherwise specifically permitted by Prebid, and not for any other purpose, including, but not limited to, collusion against, advancement of competitive interests contrary to, or interference with the business plans of, Prebid. -3. **Representations and Obligations**. You represent, warrant, and agree that: (i) you have all rights and authority necessary to bind yourself, or your company, as applicable, to these Terms and perform your obligations hereunder, (ii) your performance under these Terms, your use of the App, and our exercise of any rights granted to us by you hereunder will not (a) violate any applicable law, rule, or regulation, (b) breach any agreement or other obligation that you have with or to any third party, (c) violate or infringe any intellectual property, proprietary, or other rights of any third party, or (d) require of Prebid any license, authorization, or other permission from a third party, (iii) nothing you use with the App will contain any viruses, spyware, or other types of malware, and will not cause injury to any person or damage to any property, and (iv) you will be solely responsible for your use of the App, including, but not limited to, your submission, use, and disclosure of Data. +3. **Representations and Obligations**. You represent, warrant, and agree that: (i) you have all rights and authority necessary to bind yourself, or your company, as applicable, to these Terms and perform your obligations hereunder, (ii) your performance under these Terms, your use of the App, and our exercise of any rights granted to us by you hereunder will not (a) violate any applicable law, rule, or regulation, (b) breach any agreement or other obligation that you have with or to any third party, (c) violate or infringe any intellectual property, proprietary, or other rights of any third party, or (d) require of Prebid any license, authorization, or other permission from a third party, (iii) nothing you use with the App will contain any viruses, spyware, or other types of malware, and will not cause injury to any person or damage to any property, and (iv) you will be solely responsible for your use of the App, including, but not limited to, your submission, use, and disclosure of Data. -4. **Your Account**. You may be required to provide us certain information about you or your company, or about your Prebid Server account, in order to register for and use the App (the “**Account Information**”). You are solely responsible for maintaining control over your account. +4. **Your Account**. You may be required to provide us certain information about you or your company, or about your Prebid Server account, in order to register for and use the App (the “**Account Information**”). You are solely responsible for maintaining control over your account. -5. **No Warranties**. Prebid provides the App “as is,” “with all faults,” and “as available.” You agree that use of the App is at your sole risk. To the fullest extent permitted by applicable law, Prebid disclaims all implied and statutory warranties, including without limitation implied warranties for non-infringement, merchantability, and fitness for any purpose. +5. **No Warranties**. Prebid provides the App “as is,” “with all faults,” and “as available.” You agree that use of the App is at your sole risk. To the fullest extent permitted by applicable law, Prebid disclaims all implied and statutory warranties, including without limitation implied warranties for non-infringement, merchantability, and fitness for any purpose. -6. **Limitation of Liability**. To the fullest extent permitted by applicable law, in no event will Prebid or its affiliates, or its or its affiliates’ employees, officers, agents, or licensors be held liable in connection with the App for any direct, indirect, special, punitive, exemplary, or consequential (including loss of use, data, business, or profits) damages, regardless of legal theory, even if Prebid is aware or should know that such damages are possible. To the fullest extent permitted under applicable law, Prebid’s maximum aggregate liability with respect to the App will not exceed fifty dollars ($50). +6. **Limitation of Liability**. To the fullest extent permitted by applicable law, in no event will Prebid or its affiliates, or its or its affiliates’ employees, officers, agents, or licensors be held liable in connection with the App for any direct, indirect, special, punitive, exemplary, or consequential (including loss of use, data, business, or profits) damages, regardless of legal theory, even if Prebid is aware or should know that such damages are possible. To the fullest extent permitted under applicable law, Prebid’s maximum aggregate liability with respect to the App will not exceed fifty dollars ($50). -7. **Indemnification**. You will indemnify, defend, and hold harmless Prebid and its affiliates, and its and its affiliates’ employees, officers, agents, and licensors, against any claim, loss, damage, settlement, cost, expense or other liability (including, without limitation, attorneys’ fees) related to your use of the App or your breach of any of the Terms or your Data including, but not limited to, its use within the App as contemplated hereunder (together, “**Claims**”). You will use counsel reasonably satisfactory to us to defend each Claim. If at any time we reasonably determine that any Claim might adversely affect us, we may take control of the defense at our expense. You may not consent to the entry of any judgment or enter into any settlement involving anything other than the payment of cash consideration solely by you without our prior written consent, which may not be unreasonably withheld. +7. **Indemnification**. You will indemnify, defend, and hold harmless Prebid and its affiliates, and its and its affiliates’ employees, officers, agents, and licensors, against any claim, loss, damage, settlement, cost, expense or other liability (including, without limitation, attorneys’ fees) related to your use of the App or your breach of any of the Terms or your Data including, but not limited to, its use within the App as contemplated hereunder (together, “**Claims**”). You will use counsel reasonably satisfactory to us to defend each Claim. If at any time we reasonably determine that any Claim might adversely affect us, we may take control of the defense at our expense. You may not consent to the entry of any judgment or enter into any settlement involving anything other than the payment of cash consideration solely by you without our prior written consent, which may not be unreasonably withheld. -8. **Termination**. Prebid may terminate or suspend your access to the App, in whole or in part, without notice at any time at its sole discretion. Upon any such termination or suspension, your right to use the App or access any information stored in your account will terminate immediately. Notwithstanding any such termination, any provisions of these Terms that by their nature are intended to survive, will survive termination. +8. **Termination**. Prebid may terminate or suspend your access to the App, in whole or in part, without notice at any time at its sole discretion. Upon any such termination or suspension, your right to use the App or access any information stored in your account will terminate immediately. Notwithstanding any such termination, any provisions of these Terms that by their nature are intended to survive, will survive termination. -9. **Updates to the Terms and App**. Prebid may change the Terms or App (including, without limitation, the removal or addition of features or functionality, including, for example, automatically downloaded updates or features) at its sole discretion at any time without notice to you by posting the updated version of these Terms in the App or updating the App, as applicable. Your continued use of the App after Prebid posts changes to the Terms constitutes your acceptance of the modified Terms. +9. **Updates to the Terms and App**. Prebid may change the Terms or App (including, without limitation, the removal or addition of features or functionality, including, for example, automatically downloaded updates or features) at its sole discretion at any time without notice to you by posting the updated version of these Terms in the App or updating the App, as applicable. Your continued use of the App after Prebid posts changes to the Terms constitutes your acceptance of the modified Terms. -10. **General**. These Terms are governed by New York law, excluding its conflicts of laws rules. The jurisdiction and venue for all disputes hereunder will be the state and federal courts in the county and state of New York, and the parties hereby consent to personal jurisdiction in those courts. Prebid may assign these Terms, in whole or in part, at any time without notice to you. You may not assign these Terms, or assign, transfer or sublicense your rights to use the App. Any notice or other communication to be given by you hereunder will be made in writing and sent to us at the following mailing address: 28 West 23rd Street, 4th Floor, New York, NY 10010. +10. **General**. These Terms are governed by New York law, excluding its conflicts of laws rules. The jurisdiction and venue for all disputes hereunder will be the state and federal courts in the county and state of New York, and the parties hereby consent to personal jurisdiction in those courts. Prebid may assign these Terms, in whole or in part, at any time without notice to you. You may not assign these Terms, or assign, transfer or sublicense your rights to use the App. Any notice or other communication to be given by you hereunder will be made in writing and sent to us at the following mailing address: 28 West 23rd Street, 4th Floor, New York, NY 10010. diff --git a/prebid-mobile/dr-prebid.md b/prebid-mobile/dr-prebid.md index 799f8dab86..4683098357 100644 --- a/prebid-mobile/dr-prebid.md +++ b/prebid-mobile/dr-prebid.md @@ -10,11 +10,14 @@ sidebarType: 3 # Dr. Prebid +{: .alert.alert-danger :} +This app has been deprecated and is no longer available on any major app store. + {:.no_toc} Dr. Prebid is a validation and troubleshooting app for publishers implementing Prebid Mobile. With this app you can validate your settings for your ad server setup, your Prebid Server configuration, and your end-to-end Prebid Mobile SDK implementation. -* TOC +- TOC {:toc } ## Get the App @@ -53,10 +56,11 @@ In this section, define the ad format and size of the ad server ad unit you’ll The type of ad you want to test. This will be the ad type that is associated with the line item you’re testing against in your ad server setup. Select from: -- *Banner* -- *Interstitial* -- *Native* -- *Video* + +- *Banner* +- *Interstitial* +- *Native* +- *Video* **Ad Size** @@ -70,9 +74,9 @@ These settings will enable you to test whether the Prebid Mobile line item in yo The primary ad server you’re using to serve your ads. -Select from: -- *DFP* -- *MoPub* +Select: + +- *DFP* **Bid Price** @@ -94,12 +98,12 @@ These settings will help verify that Prebid Mobile and Prebid Server are connect Select your Prebid Server host: -- *AppNexus* -- *Rubicon* -- *Custom* +- *AppNexus* +- *Rubicon* +- *Custom* **Custom Server Host** -Provide the url of the custom hosted prebid server +Provide the url of the custom hosted prebid server **Account ID** @@ -119,15 +123,15 @@ IDs for ad units and Prebid Server accounts and configurations are long strings To set up a QR code, follow these steps: -1. Go to any QR code generator. (There are many free options for QR code generation. Examples include [https://www.qr-code-generator.com/](https://www.qr-code-generator.com/) and [https://www.the-qrcode-generator.com/](https://www.the-qrcode-generator.com/).) +1. Go to any QR code generator. (There are many free options for QR code generation. Examples include [www.qr-code-generator.com/](https://www.qr-code-generator.com) and [www.the-qrcode-generator.com](https://www.the-qrcode-generator.com/).) -2. Copy the ID you want to use from your Ad Server or from Prebid Server, depending on which ID you’re working with. +2. Copy the ID you want to use from your Ad Server or from Prebid Server, depending on which ID you’re working with. -3. In the QR code generator, select the Text option, paste in the ID, and generate the code. +3. In the QR code generator, select the Text option, paste in the ID, and generate the code. -4. In Dr. Prebid, tap **Scan QR code** for the appropriate ID. This will open your QR code scanner (your camera). +4. In Dr. Prebid, tap **Scan QR code** for the appropriate ID. This will open your QR code scanner (your camera). -5. Scan the code. The ID will now be in the ID field in Dr. Prebid. +5. Scan the code. The ID will now be in the ID field in Dr. Prebid. {: .alert.alert-info :} **IMPORTANT:** Make sure you copy the full ID into the QR code generator. Also check to make sure you don’t copy in any extra trailing spaces. These will cause your validation tests to fail. @@ -142,7 +146,7 @@ After you’ve entered all the values on the **Setup** screen, tap **Run Tests** Three validation tests are performed: Ad Server Setup, Real-Time Demand, and End-to-End SDK Configuration. Each test will be displayed with either a green check mark (passed) or a red X (failed). -| Passed | | Failed | +| Passed | | Failed | |:-----------:| --- |:-----------:| | ![Dr. Prebid Validation Test Passed]({{site.baseurl}}/assets/images/prebid-mobile/dr-prebid-pass.png) | | ![Dr. Prebid Validation Test Failed]({{site.baseurl}}/assets/images/prebid-mobile/dr-prebid-fail.png) | @@ -158,22 +162,23 @@ This test determines whether your Prebid Mobile line items are configured correc The test generates Prebid-specific key-value pairs representing the bid price you specified in the **Bid Price** field of your setup. Based on the **Ad Format** you selected, these key-values are set on the banner ad views or interstitials, and a test ad is loaded to determine whether any matching Prebid line items will be selected. -- **Ad Server Request sent and Key-Value targeting sent** +- **Ad Server Request sent and Key-Value targeting sent** Verifies that the ad server request was sent. (Note: If Google Ad Manager was selected as the Ad Server on the Setup page and the IDs you entered on the Setup page are incorrect, the request will not be sent.) Tap this entry to see a list of key-value pairs that were sent with this request. - - Select **Prebid Key-Value Pairs** to view only the key-values sent that apply to prebid. - - Select **Ad Server Request** to view the full list of key-values sent in the ad request. -- **Prebid Mobile creative HTML served** + - Select **Prebid Key-Value Pairs** to view only the key-values sent that apply to prebid. + - Select **Ad Server Request** to view the full list of key-values sent in the ad request. +- **Prebid Mobile creative HTML served** Tap this entry to view: - - The HTML code for the Prebid Mobile creative. - - A rendering of the creative returned from the ad server (Received Creative) and a rendering of the Prebid.org test creative (Expected Creative). Tap the buttons to view each creative. In a successful test these two creatives will be the same. + - The HTML code for the Prebid Mobile creative. + - A rendering of the creative returned from the ad server (Received Creative) and a rendering of the Prebid.org test creative (Expected Creative). Tap the buttons to view each creative. In a successful test these two creatives will be the same. **Results** *Success*: If the test is successful, all steps will display green check marks. Tap into the **Prebid Mobile creative HTML served** screen to compare the ad server creative to the Prebid.org test creative. The **Received Creative** and the **Expected Creative** should be identical. *Failure*: If the test fails, either no **Received Creative** will appear, or the **Received Creative** will not match the **Expected Creative**. In either case, check the following: -- The key-value targeting sent to the ad server. Ensure that you have a Prebid Mobile line item targeting the `hb_pb` value with an active creative of the appropriate size and format. -- Line item contention. Ensure that no other line items are expected to contend with the Prebid Mobile line item during testing. + +- The key-value targeting sent to the ad server. Ensure that you have a Prebid Mobile line item targeting the `hb_pb` value with an active creative of the appropriate size and format. +- Line item contention. Ensure that no other line items are expected to contend with the Prebid Mobile line item during testing. ### Real-Time Demand Validation @@ -181,29 +186,30 @@ This test validates that the real-time requests generated using your Prebid Serv A summary of results will be displayed: -- **Bid requests sent** +- **Bid requests sent** The number of bid requests that were sent. Dr. Prebid will always attempt to send 100 requests. -- **Bid responses received** +- **Bid responses received** The number of responses received from demand partners. Tap this entry to view a summary of bid responses from each demand partner. From the summary page you'll be able to navigate to detailed request and response information. NOTE: If your configuration includes more than one demand partner, this number may exceed the number of bid requests sent. -- **Avg CPM** +- **Avg CPM** The average CPM (in USD) of all received bid responses. -- **Avg response time** +- **Avg response time** The average amount of time (in milliseconds) it took for demand partners to respond. **Bid Response Summary** -Tap **_n_ bid responses received** to see a breakdown of bid responses by demand partner. For each demand partner you'll see the following details: -- *# of Requests* +Tap ***n* bid responses received** to see a breakdown of bid responses by demand partner. For each demand partner you'll see the following details: + +- *# of Requests* The total number of bid requests sent. The test is configured to send 100 requests. -- *Valid Bid Rate* +- *Valid Bid Rate* The percentage of bid requests for which the demand partner returned a valid response. -- *Avg Bid CPM* +- *Avg Bid CPM* The average CPM (in USD) of all valid bid responses from the demand partner. -- *No-Bid Rate* +- *No-Bid Rate* The percentage of bid requests for which the demand partner did not return a bid response. -- *Timeout Rate* +- *Timeout Rate* The percentage of bid requests that timed out before a bid response could be sent. -- *Error Rate* +- *Error Rate* The percentage of bid requests that resulted in errors from the demand partner. On the Bid Response Summary screen, tap **Request & Response** for a demand partner to see the bid request sent to the demand partner and a response received (if any). @@ -217,8 +223,9 @@ There are three possible outcomes from this validation test: *Failure*: The auctions ran successfully, but no successful bid responses were returned. *Failure*: No auctions were run. If no auctions were run, verify the following in your setup: - - Check to make sure the Prebid Server Account ID and Prebid Server Configuration ID you entered on the Dr. Prebid Setup page are correct. Ensure they don’t contain leading or trailing spaces. - - Ensure that your Prebid Server Configuration is correct. See [Getting Started with Prebid Mobile]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html#configure-prebid-server) for more information. + +- Check to make sure the Prebid Server Account ID and Prebid Server Configuration ID you entered on the Dr. Prebid Setup page are correct. Ensure they don’t contain leading or trailing spaces. +- Ensure that your Prebid Server Configuration is correct. See [Getting Started with Prebid Mobile]({{site.github.url}}/prebid-mobile/prebid-mobile-getting-started.html#configure-prebid-server) for more information. ### End-to-End SDK Validation @@ -226,22 +233,22 @@ This test is a full end-to-end validation in which the Prebid Mobile SDK communi The summary screen displays the following information: -- **Ad unit registered** +- **Ad unit registered** This first step is successful if the Prebid Mobile API call was made to register the ad unit. -- **Request to Prebid Server sent** +- **Request to Prebid Server sent** This step is successful if a bid request was sent from Prebid Mobile to Prebid Server. -- **Prebid Server response received** +- **Prebid Server response received** This test passes if a bid response was received from Prebid Server. -- **Creative content cached** +- **Creative content cached** This test passes if the creative content from the bid received from Prebid Server was cached. -- **Ad server request sent and Key-value targeting sent** +- **Ad server request sent and Key-value targeting sent** Verifies whether the bid request was sent. (Note: If your ad server is Google Ad Manager, the request will not be sent if the IDs you entered on the Setup page are incorrect.) Tap this entry to see a list of key-value pairs that were sent with this request. - - Select **Prebid Key-Value Pairs** to view the specific key-value pairs that were generated by Prebid Mobile and sent to the ad server. - - Select **Ad Server Request** to view the full ad request sent to the ad server. -- **Prebid Mobile creative HTML served** + - Select **Prebid Key-Value Pairs** to view the specific key-value pairs that were generated by Prebid Mobile and sent to the ad server. + - Select **Ad Server Request** to view the full ad request sent to the ad server. +- **Prebid Mobile creative HTML served** Tap this entry to view: - - Prebid Mobile creative HTML. - - The rendering of the creative returned from the ad server. + - Prebid Mobile creative HTML. + - The rendering of the creative returned from the ad server. **Results** @@ -251,24 +258,26 @@ Possible outcomes from this test: *Failure*: There are many steps throughout this validation. If a problem is encountered at any step, the validation will be marked as failed. Some general things to check if this test fails include: -- Check all your settings on the Setup screen. In particular, make sure all the IDs you entered are correct and valid. -- Make sure your ad unit has been registered correctly. (See [Code Integration]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html#configure-prebid-server) for more information.) -- Verify that your Prebid Mobile line items are set up correctly on your ad server. -- Look through your bid request and bid response (if any). Check the key-value targeting. -- If a creative was returned, ensure that the HTML returned is the same as the Prebid Mobile creative code associated with your Prebid Mobile line item. (NOTE: The ad server should have replaced the macro placeholder for `hb_cache_id` with an alphanumeric GUID.) + +- Check all your settings on the Setup screen. In particular, make sure all the IDs you entered are correct and valid. +- Make sure your ad unit has been registered correctly. (See [Code Integration]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html#configure-prebid-server) for more information.) +- Verify that your Prebid Mobile line items are set up correctly on your ad server. +- Look through your bid request and bid response (if any). Check the key-value targeting. +- If a creative was returned, ensure that the HTML returned is the same as the Prebid Mobile creative code associated with your Prebid Mobile line item. (NOTE: The ad server should have replaced the macro placeholder for `hb_cache_id` with an alphanumeric GUID.) Here are some more specific things to look for and actions to take based on which step(s) of the validation failed. -- **Ad unit registered** + +- **Ad unit registered** Be sure you’ve implemented your ad unit code correctly. See [Ad Unit Setup for iOS]({{site.github.url}}/prebid-mobile/pbm-api/ios/code-integration-ios.html) or [Ad Unit Setup for Android]({{site.github.url}}/prebid-mobile/pbm-api/android/code-integration-android.html) for information. -- **Request to Prebid Server sent** +- **Request to Prebid Server sent** Make sure your account ID and configuration ID were entered correctly on the Setup screen. For more on integrating with Prebid Server see [Getting Started with Prebid Mobile]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html). -- **Prebid Server response received** +- **Prebid Server response received** Review the requests and responses from the Real-Time Demand Validation. -- **Creative content cached** +- **Creative content cached** This step is built into Dr. Prebid and should always pass. If it doesn’t, contact your account team. -- **Ad server request sent and Key-value targeting sent** +- **Ad server request sent and Key-value targeting sent** Tap on this step for more information. Review the Prebid-specific key-value targeting and verify that they match the values targeted by the Prebid Mobile line item in your ad server. -- **Prebid Mobile creative HTML served** +- **Prebid Mobile creative HTML served** Tap on this step to review the HTML and to see the creative that served (if any). Ensure that the HTML returned is the same as the Prebid Mobile creative code associated with your Prebid Mobile line item. NOTE: The ad server should have replaced the macro placeholder for `hb_cache_id` with an alphanumeric GUID. ## Further Reading diff --git a/prebid-mobile/index.md b/prebid-mobile/index.md index de1e7313f0..79afbfccbb 100644 --- a/prebid-mobile/index.md +++ b/prebid-mobile/index.md @@ -1,3 +1,3 @@ --- -redirect_to: "/prebid-mobile/prebid-mobile.html" +redirect_to: "prebid-mobile/prebid-mobile.html" --- diff --git a/prebid-mobile/legacy/android/code-integration-android.md b/prebid-mobile/legacy/android/code-integration-android.md deleted file mode 100644 index 8d2276392a..0000000000 --- a/prebid-mobile/legacy/android/code-integration-android.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -layout: page_v2 -title: Code Integration -description: Code Integration -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-android -sidebarType: 2 ---- - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - - -# Code Integration for Android - -{:.no_toc} - -Get started with Prebid Mobile by creating a [Prebid Server account]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html). - -### Use Maven? - -Easily include the Prebid Mobile SDK using Maven. Simply add this line to your gradle dependencies: - -``` -compile 'org.prebid:prebid-mobile-sdk:[0,1)' -``` - -### Build framework from source - -Build Prebid Mobile from source code. After cloning the repo, from the root directory run - -``` -./buildprebid.sh -``` - -to output the PrebidMobile framework for Android. - -## Ad Unit Setup for Android -{:.no_toc} - -Register Prebid Mobile ad units as early as possible in the application's lifecycle. - -When registering a Prebid Mobile ad unit, you must replace `"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. Prebid Mobile will use this identifier to determine the unique ad unit to which bid key-values will be associated. This identifier must be unique across all registered Prebid Mobile ad units, and does not need to map to any ad unit ID defined in your ad server. - -The steps for using Prebid Mobile are as follows: - -1. Create the ad units and add sizes for banner ad units. Be sure to replace `"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. - - NOTE: The [fluid ad size](https://developers.google.com/android/reference/com/google/android/gms/ads/AdSize.html#FLUID) (used in Google Ad Manager) is not supported. - -2. Add a server-side configuration for each ad unit to Prebid Server Adapter. -3. Set targeting parameters for the ad units. (Optional) -4. Set the primary adserver for the bid to either Google Ad Manager or MoPub. (Primary ad server is necessary to determine the caching mechanism.) -5. Set the Prebid Server host to AppNexus or Rubicon. -6. Register the ad units with the adapter to start the bid fetching process. - -### User-Replaced Macros - -In the code snippets below, any values that must be substituted by your developers are identified in capital letters. These values are defined below: - -{: .table .table-bordered .table-striped } -| Value | Description | -|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `PREBID-SERVER-ACCOUNT-ID` | Your unique account ID with your Prebid Server vendor. | -| `PREBID-MOBILE-SLOT-ID` | User-defined identifier that must be unique across all registered Prebid Mobile ad units. Note: this value should not map to any ad unit ID defined in your ad server, unless that ID is unique. | -| `PREBID-SERVER-CONFIGURATION-ID` | The ID of a Prebid Server demand partner configuration. Represents the set of demand that will be fetched for a given ad unit. | -| `AD-SERVER-OBJECT-INSTANCE` | The ad server object instance to which bids will be attached. Supported values are defined in a table below. | -| `AD-SERVER-AD-LOAD-METHOD` | The ad server API to load this ad type. | - -### Ad Unit Registration - -Create the ad units that represent the ad spaces in your app using following APIs: - -``` -ArrayList adUnits = new ArrayList(); - -/** - * Configure a Banner Ad Unit with size 320x50. - * - * Replace @"PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace @"PREBID-SERVER-CONFIGURATION-ID" with the ID of - * your Prebid Server demand partner configuration. - */ -BannerAdUnit adUnit1 = new BannerAdUnit("PREBID-MOBILE-SLOT-ID", "PREBID-SERVER-CONFIGURATION-ID"); -adUnit1.addSize(320, 50); - -/** - * Configure an Interstitial Ad Unit. - * - * Replace @"PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace @"PREBID-SERVER-CONFIGURATION-ID" with the ID of - * your Prebid Server demand partner configuration. - */ -InterstitialAdUnit adUnit2 = new InterstitialAdUnit("PREBID-MOBILE-SLOT-ID", "PREBID-SERVER-CONFIGURATION-ID"); - -// Add them to the list -adUnits.add(adUnit1); -adUnits.add(adUnit2); - -``` - -### Initialize the SDK - -Once configuration is done, use the following API to initialize Prebid Mobile and start fetching Prebid ads for your list of ad units. - -If you're using Google Ad Manager as your primary ad server, use the API like this: -``` -/** - * Register ad units for prebid. - * - * Replace "PREBID-SERVER-ACCOUNT-ID" with your Prebid Server account ID. - * - * If you are using a Prebid Server host other than AppNexus, be sure - * to replace 'Host.APPNEXUS'. - */ -try { - Prebid.init(getApplicationContext(), adUnits, "PREBID-SERVER-ACCOUNT-ID", Prebid.AdServer.DFP, Host.APPNEXUS); -} catch (PrebidException e) { - e.printStackTrace(); -} -``` -If you're using MoPub as your primary ad server, use the API like this: -``` -/** - * Register ad units for prebid. - * - * Replace "PREBID-SERVER-ACCOUNT-ID" with your Prebid Server account ID. - * - * If you are using a Prebid Server host other than AppNexus, be sure - * to replace 'Host.APPNEXUS'. - */ -try { - Prebid.init(getApplicationContext(), adUnits, "PREBID-SERVER-ACCOUNT-ID", Prebid.AdServer.MOPUB, Host.APPNEXUS); -} catch (PrebidException e) { - e.printStackTrace(); -} -``` -Note that host should be the prebid server host you're using. - -### Set Ad Server Targeting -{:.no_toc} - -The final step for implementing Prebid Mobile is to attach bid keywords on the ad object. You can either attach bids immediately or wait for ads before attaching bids. To attach bids immediately use the following API. - -``` -/** - * Replace "PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace AD-SERVER-OBJECT-INSTANCE with the ad view instance - * from your ad server (defined in the table below). - */ -Prebid.attachBids(AD-SERVER-OBJECT-INSTANCE, "PREBID-MOBILE-SLOT-ID", Context); -``` - -To wait for ads before attaching bids, implement the following listener. - -``` -@Override -public void onAttachComplete(Object adObj) { - // using Google Ad Manager implementation as an example - if (adView != null && adObj != null && adObj instanceof PublisherAdRequest) { - adView.loadAd((PublisherAdRequest) adObj); - Prebid.detachUsedBid(adObj); - } -} -``` - -Prebid Mobile will immediately tell your app whether it has a bid or not without waiting. If it does have a bid, the code below will attach the bids to the ad request by applying keyword targeting. Use the table below to see which ad objects are supported currently. - -{: .table .table-bordered .table-striped } -| Primary Ad Server | Ad Object Type | Ad Server Object Instance | Ad Server Ad Load Method | -|-------------------|----------------|----------------------------|----------------------------------------------------| -| Google Ad Manager | Banner | `PublisherAdRequest` | `public void loadAd(PublisherAdRequest adRequest)` | -| Google Ad Manager | Interstitial | `PublisherAdRequest` | `public void loadAd(PublisherAdRequest adRequest)` | -| MoPub | Banner | `MoPubView` | `public void loadAd()` | -| MoPub | Interstitial | `MoPubInterstitial` | `public void load()` | - -### Supporting Auto Refreshing Ad Units -Prebid Mobile Android does not update the bids automatically like iOS implementation. To enable prebid with auto refesh, the following code integration is required. - -#### Primary Ad Server is MoPub -For MoPub banner, in the banner ad listener implementation, add the following API usage. -``` -/** - * MoPub Banner Listener Implementation. - * - * Replace "PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - */ -@Override -public void onBannerLoaded(MoPubView banner) { - Prebid.attachBids(banner, "PREBID-MOBILE-SLOT-ID", Context); -} - -@Override -public void onBannerFailed(MoPubView banner, MoPubErrorCode errorCode) { - Prebid.attachBids(banner, "PREBID-MOBILE-SLOT-ID", Context); -} - ``` - -#### Primary Ad Server is Google Ad Manager -For Google Ad Manager banner, the `loadAd(AdRequest)` has to be called again with updated bids info. If not, same set of bids will be used repeatedly until `loadAd()` is called with a new `AdRequest`. We recommend doing client side auto refresh yourself using code like the following: - ``` - /** - * Replace "PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - */ -final Handler handler = new Handler(Looper.getMainLooper()); -Runnable refreshRunnable = new Runnable() { - @Override - public void run() { - Prebid.attachBids(request, "PREBID-MOBILE-SLOT-ID", Context); - adView.loadAd(request); - handler.postDelayed(this, 30000); // load ad with new bids every 30 seconds - } -}; -handler.post(refreshRunnable); - -// Assume some condition is triggered to stop the auto-refresh -boolean conditionToStopRefresh = true; -if(conditionToStopRefresh) { - // remove refresh runnable and destroy the banner - handler.removeCallbacks(refreshRunnable); - adView.destroy(); -} - ``` - -### ProGuard Support - -#### Primary Ad Server is Google Ad Manager -If ProGuard is enabled, the following lines must be added to your ProGuard file: -``` --keep class com.google.android.gms.ads.doubleclick.PublisherAdRequest { - public *; -} -``` - -To avoid PrebidServerAdapter class being obfuscated and prebid not working, add the following lines to your proguard file: -``` --keep class org.prebid.mobile.prebidserver.PrebidServerAdapter { - public *; -} - --keepnames class org.prebid.mobile.prebidserver.PrebidServerAdapter { - public *; -} -``` - - diff --git a/prebid-mobile/legacy/android/logging-troubleshooting-android.md b/prebid-mobile/legacy/android/logging-troubleshooting-android.md deleted file mode 100644 index 9ae77bd56b..0000000000 --- a/prebid-mobile/legacy/android/logging-troubleshooting-android.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -layout: page_v2 -title: Android Logging & Troubleshooting -description: Android Logging & Troubleshooting -sidebarType: 2 ---- - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - -# Android Logging & Troubleshooting -{:.no_toc} - -Troubleshoot your Prebid Mobile integration by following these steps to check your application logs. - -1. With your test device connected to the computer, run the following command in your terminal: -```adb shell setprop log.tag.PrebidMobile VERBOSE``` - -2. Navigate to the Android Monitor in Android Studio. - -3. In the logcat tab, set the Log Level to Verbose and search for "PrebidMobile". You should see a list of logs. - -## FAQs - -**Q:** I've defined a banner size as fluid in Google Ad Manager SDK (`AdSize(-3,-4)`), why am I receiving an empty response? - -**A:** Prebid Mobile does not support fluid size. - - diff --git a/prebid-mobile/legacy/android/targeting-params-android.md b/prebid-mobile/legacy/android/targeting-params-android.md deleted file mode 100644 index 01862d8399..0000000000 --- a/prebid-mobile/legacy/android/targeting-params-android.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -layout: page_v2 -title: Android Targeting Parameters -description: Add Android Targeting Parameters -sidebarType: 2 ---- - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - -# Android Targeting Parameters - -## User location - -By default, the Android Prebid Mobile SDK automatically sends location information. - -Disable (false) or enable (true) location data: - -``` -TargetingParams.setLocationEnabled(true); -``` - -Fetch location data and pass it to Prebid Mobile: - -``` -TargetingParams.setLocation(location); -``` - -Choose the precision of location data: - -``` -TargetingParams.setLocationDecimalDigits(6); -``` - -## Age and Gender - -Age and gender can be added to the targeting params directly. - -``` -TargetingParams.setYearOfBirth(1990); -TargetingParams.setGender(GENDER.FEMALE); -``` - - -## Custom Keywords - -Custom keywords are used to attach arbitrary key/value pairs to the ad call. Use key/value pairs to add users to segments, as shown here: - -``` -TargetingParams.setUserTargeting("foo", "bar"); -TargetingParams.setUserTargeting("foo", "bay"); -``` -This will result in the following request JSON body construct: - -``` -"user" : { - "keywords" : "foo=bar,foo=bay," -} -``` - -## GDPR Consent - -Prebid Mobile supports the [IAB GDPR recommendations](https://www.iab.com/topics/consumer-privacy/gdpr/). For a general overview of Prebid Mobile support for GDPR, see [Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice](/prebid-mobile/privacy-regulation.html) - -Enable (true) or disable (false) the ability to provide consent. -``` -TargetingParams.setSubjectToGDPR(context, true); -``` -Enable publishers to set the consent string. - -``` -TargetingParams.setGDPRConsentString(context, "consent_string"); -``` - -Prebid mobile also checks if the values are present in the [SharedPreferences](https://developer.android.com/training/data-storage/shared-preferences) keys specified by the IAB. If the values are also set in these objects they will be passed in the OpenRTB request object. - -## Other - -For more information about the TargetingParams, please check the source code in [Coding Integration for Android](/prebid-mobile/legacy/android/code-integration-android.html). diff --git a/prebid-mobile/legacy/ios/code-integration-ios.md b/prebid-mobile/legacy/ios/code-integration-ios.md deleted file mode 100644 index 398af36bc1..0000000000 --- a/prebid-mobile/legacy/ios/code-integration-ios.md +++ /dev/null @@ -1,196 +0,0 @@ ---- -layout: page_v2 -title: Code Integration -description: Code Integration -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-ios -sidebarType: 2 ---- - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. See our updated [code Integration document](/prebid-mobile/pbm-api/ios/code-integration-ios.html) for information on working with the current version of Prebid Mobile. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - - -# Code Integration for iOS - -Get started with Prebid Mobile by creating a [Prebid Server account]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html). - -### Use Cocoapods? - -Easily include the Prebid Mobile SDK for your primary ad server in your Podfile. - -``` -platform :ios, '11.0' - -target 'MyAmazingApp' do - pod 'PrebidMobile' -end -``` - -### Build framework from source - -Build Prebid Mobile from source code. After cloning the repo, from the root directory run - -``` -./scripts/buildPrebidMobile.sh -``` - -to output the PrebidMobile.framework. - - -## Ad Unit Setup for iOS -{:.no_toc} - -Register Prebid Mobile ad units as early as possible in the application's lifecycle. - -When registering a Prebid Mobile ad unit, you must replace `@"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. Prebid Mobile will use this identifier to determine the unique ad unit to which bid key-values will be associated. This identifier must be unique across all registered Prebid Mobile ad units, and does not need to map to any ad unit ID defined in your ad server. - -We recommend doing this in the `didFinishLaunchingWithOptions` method in `AppDelegate.m` using the following steps, as shown in the code sample below: - -1. Create the ad units and add sizes for banner ad units. Be sure to replace `@"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. - - NOTE: The [fluid ad size](https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/api/reference/Constants#/c:@kGADAdSizeFluid) (used in Google Ad Manager) is not supported. - -2. Add a server-side configuration for each ad unit to Prebid Server Adapter. -3. Set targeting parameters for the ad units. (Optional) -4. Set the primary adserver for the bid to either Google Ad Manager or MoPub. (Primary ad server is necessary to determine the caching mechanism.) -5. Set the Prebid Server host to AppNexus or Rubicon. -6. Register the ad units with the adapter to start the bid fetching process. - -### User-Replaced Macros - -In the code snippets below, any values that must be substituted by your developers are identified in capital letters. These values are defined below: - -{: .table .table-bordered .table-striped } -| Value | Description | -|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `PREBID-SERVER-ACCOUNT-ID` | Your unique account ID with your Prebid Server vendor. | -| `PREBID-MOBILE-SLOT-ID` | User-defined identifier that must be unique across all registered Prebid Mobile ad units. Note: this value should not map to any ad unit ID defined in your ad server, unless that ID is unique. | -| `PREBID-SERVER-CONFIGURATION-ID` | The ID of a Prebid Server demand partner configuration. Represents the set of demand that will be fetched for a given ad unit. | -| `AD-SERVER-AD-VIEW-INSTANCE` | The ad server ad view object instance to which bids will be attached. Supported values are defined in a table below. | -| `AD-SERVER-AD-LOAD-METHOD` | The ad server API to load this ad type. | - -### Ad Unit Registration - -Embed the ad unit registration in a try-catch block to catch all the exceptions (if any) thrown by the SDK. - -``` -#import "PrebidMobile/PBBannerAdUnit.h" -#import "PrebidMobile/PBServerAdapter.h" -#import "PrebidMobile/PBTargetingParams.h" -#import "PrebidMobile/PrebidMobile.h" - -// See http://prebid.org/prebid-mobile/logging-troubleshooting-ios.html for information on log level settings. - -[PBLogManager setPBLogLevel:PBLogLevelAll]; - -/** - * 1. Create the ad units and add sizes for banner ad units. - * - * Replace @"PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace @"PREBID-SERVER-CONFIGURATION-ID" with the ID of - * your Prebid Server demand partner configuration. - */ -PBBannerAdUnit *__nullable adUnit1 = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"PREBID-MOBILE-SLOT-ID" andConfigId:@"PREBID-SERVER-CONFIGURATION-ID"]; -[adUnit1 addSize:CGSizeMake(300, 250)]; - -/** - * 2. Set targeting parameters for the ad units (Optional). - */ -[[PBTargetingParams sharedInstance] setAge:25]; -[[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderFemale]; - -/** - * 3. Register the ad units with Prebid Mobile to start bid fetching process. - * - * Google Ad Manager Example - * - * Replace @"PREBID-SERVER-ACCOUNT-ID" with your Prebid Server account ID. - * - * If you are using a Prebid Server host other than AppNexus, be sure - * to replace 'PBServerHostAppNexus'. - */ -[PrebidMobile registerAdUnits:@[adUnit1, adUnit2] - withAccountId:@"PREBID-SERVER-ACCOUNT-ID" - withHost:PBServerHostAppNexus - andPrimaryAdServer:PBPrimaryAdServerDFP]; -``` - -If you are using MoPub as your ad server, modify step 3 above to use `PBPrimaryAdServerMoPub`, as shown below: -``` -/** - * 3. Register the ad units with Prebid Mobile to start bid fetching process. - * - * MoPub Example - * - * Replace @"PREBID-SERVER-ACCOUNT-ID" with your Prebid Server account ID. - * - * If you are using a Prebid Server host other than AppNexus, be sure - * to replace 'PBServerHostAppNexus'. - */ -[PrebidMobile registerAdUnits:@[adUnit1, adUnit2] - withAccountId:@"PREBID-SERVER-ACCOUNT-ID" - withHost:PBServerHostAppNexus - andPrimaryAdServer:PBPrimaryAdServerMoPub]; -``` -Note that host should be the prebid server host you're using. - -### Set Ad Server Targeting -{:.no_toc} - -Prebid Mobile continuously pre-caches creatives in the background, so that right before the ad unit makes an ad request from your network, your app can ask Prebid Mobile for a bid price and creative without waiting as shown in the code below. - - -``` -/** - * Set the prebid keywords on your adObject immediately. - * - * Replace @"PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace AD-SERVER-AD-VIEW-INSTANCE with the ad view instance - * from your ad server (defined in the table below). - */ -[PrebidMobile setBidKeywordsOnAdObject:AD-SERVER-AD-VIEW-INSTANCE withAdUnitId:@"PREBID-MOBILE-SLOT-ID"]; -``` - -Alternatively, if you want to set the bid keywords on your adObject shortly after registering ad units, you can wait for bids with a timeout using the API method below. - -``` -/** - * Set the prebid keywords on your adObject. - * Upon completion, call the ad server's ad load method. - * - * Replace @"PREBID-MOBILE-SLOT-ID" with the unique ad slot identifier - * you defined when you registered the ad unit with Prebid Mobile. - * - * Replace AD-SERVER-AD-VIEW-INSTANCE with the ad view instance - * from your ad server (defined in the table below). - * - * Replace AD-SERVER-AD-LOAD-METHOD with the ad server's method - * to load this ad type (defined in the table below). - */ -[PrebidMobile setBidKeywordsOnAdObject:AD-SERVER-AD-VIEW-INSTANCE withAdUnitId:@"PREBID-MOBILE-SLOT-ID" withTimeout:600 completionHandler:^{ - [AD-SERVER-AD-VIEW-INSTANCE AD-SERVER-AD-LOAD-METHOD]; -}]; -``` - -Use the table below to see which ad objects are supported currently. - -{: .table .table-bordered .table-striped } -| Primary Ad Server | Ad Object Type | Ad Server Ad View | Ad Server Ad Load Method | -|-------------------|----------------|------------------------------|---------------------------------------------| -| Google Ad Manager | Banner | `DFPBannerView` | `- (void)loadRequest:(GADRequest *)request` | -| Google Ad Manager | Interstitial | `DFPInterstitial` | `- (void)loadRequest:(GADRequest *)request` | -| MoPub | Banner | `MPAdView` | `- (void)loadAd` | -| MoPub | Interstitial | `MPInterstitialAdController` |` - (void)loadAd` | - - - - diff --git a/prebid-mobile/legacy/ios/logging-troubleshooting-ios.md b/prebid-mobile/legacy/ios/logging-troubleshooting-ios.md deleted file mode 100644 index f5f44cada9..0000000000 --- a/prebid-mobile/legacy/ios/logging-troubleshooting-ios.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -layout: page_v2 -title: iOS Logging & Troubleshooting -description: iOS Logging & Troubleshooting -sidebarType: 2 ---- - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - -# iOS Logging & Troubleshooting -{:.no_toc} - -To add Prebid Mobile logs for troubleshooting or to see successful bids simply import `PBLogging.h` and add the following code: - -```objc -[PBLogManager setPBLogLevel:PBLogLevelInfo]; -``` - -The following log level options are available: - -- PBLogLevelAll -- PBLogLevelOff (Disable all logging) -- PBLogLevelTrace -- PBLogLevelDebug -- PBLogLevelInfo -- PBLogLevelWarn (Default) -- PBLogLevelError - -Setting any log level other than `PBLogLevelAll` or `PBLogLevelOff` will enable all logging in the list at and below the level being set. For example, setting `PBLogLevelInfo` will enable logging for `PBLogLevelInfo`, `PBLogLevelWarn`, and `PBLogLevelWarn`. - -# FAQs - -**Q:** *I've defined a banner size as fluid in Google Ad Manager SDK (`AdSize(-3,-4)`), why am I receiving an empty response?* - -**A:** Prebid Mobile does not support fluid size. - - diff --git a/prebid-mobile/legacy/ios/targeting-params-ios.md b/prebid-mobile/legacy/ios/targeting-params-ios.md deleted file mode 100644 index 7ff81a3931..0000000000 --- a/prebid-mobile/legacy/ios/targeting-params-ios.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -layout: page_v2 -title: iOS Targeting Parameters -description: Add iOS Targeting Parameters -sidebarType: 2 ---- - - -{% capture warningNote %} -This document describes a pre-release version of the Prebid Mobile API that has been deprecated. -{% endcapture %} - -{% include alerts/alert_warning.html content=warningNote %} - -# iOS Targeting Parameters - -## User location - -By default, the iOS Prebid Mobile SDK does not automatically send location information. In order for Prebid Mobile to use location information for targeting, the app developer must explicitly pass the location information to Prebid Mobile. - -Note: Developers should ensure adequate consent is obtained before sharing location information. Developers can control whether location is collected and sent by Prebid Mobile. - -In this snippet, we implement the `CLLocationManagerDelegate` delegate. Create a location manager object as shown here: - -``` -@property (nonatomic, readwrite) CLLocationManager *locationManager; -``` - -Initialize the location manager: - -``` -- (void)setupPrebidLocationManager { - self.locationManager = [[CLLocationManager alloc] init]; - self.locationManager.delegate = self; - self.locationManager.distanceFilter = kCLDistanceFilterNone; - self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; - - // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. - - if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { - [self.locationManager requestWhenInUseAuthorization]; - } - [self.locationManager startUpdatingLocation]; -} -``` - -Implement the location delegate as: -``` -// Location Manager Delegate Methods -- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { - [[PBTargetingParams sharedInstance] setLocation:[locations lastObject]]; -} -``` - -## Age and Gender -{:.no_toc} - -Age and gender can be added to the targeting params directly. - -``` -[[PBTargetingParams sharedInstance] setAge:25]; -[[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderFemale]; -``` - - -## Pass Custom Keywords -{:.no_toc} - -Custom keywords are used to attach arbitrary key/value pairs to the ad call. Use key/value pairs to add users to segments, as shown here: - -``` -[[PBTargetingParams sharedInstance] setUserKeywords:@"foo" withValue:@"bar"]; -[[PBTargetingParams sharedInstance] setUserKeywords:@"foo" withValue:@"baz"]; -[[PBTargetingParams sharedInstance] setUserKeywords:@"foo" withValue:@"bay"]; -[[PBTargetingParams sharedInstance] setUserKeywords:@"foo" withValue:@"bee"]; -``` -If a value is set for an existing keyword, the value for the key is replaced with the new value. In the preceding example, the key `foo` will have a value of `bee`, the most recent value associated with that key. - -You can set a key to have an array of values with the following API: -``` -[[PBTargetingParams sharedInstance] setUserKeywords:@"boo" withValues:@[@"bar",@"baz",@"bay",@"bee"]]; -``` - -The preceding commands will result in the following request JSON body construct: - -``` -user = { -keywords = "foo=bar,foo=baz,foo=bay,foo=bee"; -}; -``` - -## GDPR Consent - -Prebid Mobile supports the [IAB GDPR recommendations](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Mobile%20In-App%20Consent%20APIs%20v1.0%20Final.md). For a general overview of Prebid Mobile support for GDPR, see [Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice](/prebid-mobile/privacy-regulation.html) - -Enable (true) or disable (false) the ability to provide consent. -``` -[[PBTargetingParams sharedInstance] setSubjectToGDPR:YES]; -``` -Enable publishers to set the consent string. - -``` -[[PBTargetingParams sharedInstance] setGdprConsentString:@"sample_consent_string"]; -``` - -Prebid mobile also checks if the values are present in the [NSUserDefaults](https://developer.apple.com/documentation/foundation/nsuserdefaults#1664798?language=objc) keys specified by the IAB. If the values are also set in these objects they will be passed in the OpenRTB request object. diff --git a/prebid-mobile/modules/modules-overview.md b/prebid-mobile/modules/modules-overview.md index 6db9db2a90..8d38467e84 100644 --- a/prebid-mobile/modules/modules-overview.md +++ b/prebid-mobile/modules/modules-overview.md @@ -17,10 +17,10 @@ This page will serve as the central location to link all modular packages, descr Some of the benefits to the modular architecture are the following: -- Allows the ability to customize the Prebid SDK to the developer needs -- Allows for the reduced size of Prebid SDK, adding only modules need -- Allows for the community to add custom and/or 3rd party code without adding code to the core of Prebid SDK -- Reduces the size of Prebid SDK +- Allows the ability to customize the Prebid SDK to the developer needs +- Allows for the reduced size of Prebid SDK, adding only modules need +- Allows for the community to add custom and/or 3rd party code without adding code to the core of Prebid SDK +- Reduces the size of Prebid SDK ## How It Works @@ -28,20 +28,15 @@ The following diagram describes the overall architecture of modularity prior and ![Modularity](/assets/images/prebid-mobile/modules/modularity.png) - -Prior to Prebid SDK 1.12 there were two targets(PrebidMobile and PrebidMobileCore) which use the same product name and module name(PrebidMobile). These two modules are the same, they include the same source files. Since no new modules have been created prior to 1.12, new modules can be added and built - 1. Set a unique product name and module name for each product: - * PrebidMobile instead of PrebidMobileCore. It will allows us to seamless migration because it doesn't cause breaking changes. All publishers which now use PrebidMobileCore or PrebidMobile don't need to replace module names in source files - * PrebidMobileFull instead of PrebidMobile. PrebidMobileFull will not include any source files it will be just a name of dependency which will be responsible to add all sub-dependencies + - PrebidMobile instead of PrebidMobileCore. It will allows us to seamless migration because it doesn't cause breaking changes. All publishers which now use PrebidMobileCore or PrebidMobile don't need to replace module names in source files + - PrebidMobileFull instead of PrebidMobile. PrebidMobileFull will not include any source files it will be just a name of dependency which will be responsible to add all sub-dependencies 1. Set dependencies between them 1. Edit final distribution binaries(FatFramework, CocoaPods, Carthage, SPM, cross-project dependency) Usage: -```bash +```swift import PrebidMobile import PrebidMobileRendering ``` - - diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-admob.md b/prebid-mobile/modules/rendering/android-sdk-integration-admob.md new file mode 100644 index 0000000000..6730e44c5e --- /dev/null +++ b/prebid-mobile/modules/rendering/android-sdk-integration-admob.md @@ -0,0 +1,427 @@ +--- + +layout: page_v2 +title: Prebid Mobile Rendering GAM Line Item Setup +description: Prebid Mobile Rendering Modules GAM line item setup +sidebarType: 2 + +--- + +# AdMob Integration + +{:.no_toc} + +The integration of Prebid Mobile with Google AdMob assumes that the publisher has an AdMob account and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app. + +See the [Google's integration documentation](https://developers.google.com/admob/android/quick-start) for the AdMob integration details. + +Prebid is integrated into the AdMob monetization via adapters. + +* TOC +{:toc} + +## AdMob Integration Overview + +![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-admob.png) + +**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid. + +**Step 3** GMA SDK makes an ad request. AdMob returns the mediation chain with respective ad sources. + +**Step 4** For each prebid's ad source, the GMA SDK sequentially instantiates an adapter. + +**Step 5** The adapter verifies the targeting keywords of the winning bid and the server properties of the given ad source. If they match the adapter will render the winning bid. Otherwise, it will immediately fail with a "no ad" error and the next ad source will instantiate the same adapter but for another set of server params. + +## Integrate Prebid Adapters + +To integrate Prebid Adapters for AdMob just add the following lines into your build.gradle files: + +Root build.gradle + +```gradle +allprojects { + repositories { + ... + mavenCentral() + ... + } +} +``` + +App module build.gradle: + +```gradle +implementation('org.prebid:prebid-mobile-sdk-admob-adapters:x.x.x') +``` + +## Banner API + +Integration example: + +```kotlin +// 1. Create AdView and AdRequest +bannerView = AdView(activity) +bannerView?.adSize = AdSize.BANNER +bannerView?.adUnitId = adUnitId +adWrapperView.addView(bannerView) + +val extras = Bundle() +val request = AdRequest + .Builder() + .addNetworkExtrasBundle(PrebidBannerAdapter::class.java, extras) + .build() + +// 2. Create AdMobBannerMediationUtils +val mediationUtils = AdMobBannerMediationUtils(extras, bannerView) + +// 3. Create MediationBannerAdUnit +adUnit = MediationBannerAdUnit( + wrapper.context, + configId, + org.prebid.mobile.rendering.bidding.data.AdSize(width, height), + mediationUtils +) +adUnit?.setRefreshInterval(autoRefreshTime / 1000) + +// 4. Make a bid request +adUnit?.fetchDemand { result -> + Log.d("Prebid", "Fetch demand result: $result") + + // 5. Request the ad + bannerView?.loadAd(request) +} +``` + +### Step 1: Create AdView and AdRequest + +{:.no_toc} + +This step is the same as for the original [AdMob integration](https://developers.google.com/admob/android/banner). You don't have to make any modifications here. + +### Step 2: Create AdMobMediationBannerUtils + +{:.no_toc} + +The `AdMobBannerMediationUtils` is a helper class, which performs certain utilty work for the `MediationBannerAdUnit`, like passing the targeting keywords to the adapters and checking the visibility of the ad view. + +### Step 3: Create MediationBannerAdUnit + +{:.no_toc} + +The `MediationBannerAdUnit` is part of the prebid mediation API. This class is responsible for making the bid request and providing the winning bid and targeting keywords to the mediating SDKs. + +### Step 4: Make a bid request + +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server and provides a result in a completion handler. + +### Step 5: Make an Ad Request + +{:.no_toc} + +Now you should just make a regular AdMob's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +## Interstitial API + +Integration example: + +```kotlin +// 1. Create AdRequest +val extras = Bundle() +val request = AdRequest + .Builder() + .addNetworkExtrasBundle(PrebidInterstitialAdapter::class.java, extras) + .build() + +// 2. Create AdMobInterstitialMediationUtils +val mediationUtils = AdMobInterstitialMediationUtils(extras) + +// 3. Create MediationInterstitialAdUnit +adUnit = MediationInterstitialAdUnit( + activity, + configId, + AdUnitFormat.BANNER, + mediationUtils +) + +// 4. Make a bid request +adUnit?.fetchDemand { result -> + Log.d("Prebid", "Fetch demand result: $result") + + // 5. Make an ad request + InterstitialAd.load(activity, adUnitId, request, object : InterstitialAdLoadCallback() { + override fun onAdLoaded(interstitial: InterstitialAd) { + interstitialAd = interstitial + + // 6. Display the ad + interstitialAd?.show(activity) + } + + override fun onAdFailedToLoad(error: LoadAdError) { + interstitialAd = null + } + }) +} +``` + +### Step 1: Create AdRequest + +{:.no_toc} + +This step is the same as for original [AdMob integration](https://developers.google.com/admob/android/interstitial). You don't have to make any modifications here. + +### Step 2: Create AdMobInterstitialMediationUtils + +{:.no_toc} + +The `AdMobInterstitialMediationUtils` is a helper class, which performs certain utilty work for the `MediationInterstitialAdUnit`, like passing the targeting keywords to adapters. + +### Step 3: Create MediationInterstitialAdUnit + +{:.no_toc} + +The `MediationInterstitialAdUnit` is part of the prebid mediation API. This class is responsible for making a bid request and providing the winning bid and targeting keywords to mediating SDKs. + +The **default** ad format for interstitial is **DISPLAY**. In order to make a `multiformat bid request`, set the respective values into the `adUnitFormats` parameter. + +```kotlin +adUnit = MediationInterstitialAdUnit( + activity, + configId, + EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO), + mediationUtils + ) +``` + +### Step 4: Make a bid request + +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server and provides a result in a completion handler. + +### Step 5: Make an ad request + +{:.no_toc} + +Now you should just make a regular AdMob's ad request. Evetything else will be handled by GMA SDK and prebid adapters. + +### Step 6: Display an ad + +{:.no_toc} + +Once you receive the ad it will be ready for display. You can show interstitial right in the listener or later according to the app logic. + +## Rewarded API + +Integration example: + +```kotlin +// 1. Create AsRequest +val extras = Bundle() +val request = AdRequest + .Builder() + .addNetworkExtrasBundle(PrebidRewardedAdapter::class.java, extras) + .build() + +// 2. Create AdMobRewardedMediationUtils +val mediationUtils = AdMobRewardedMediationUtils(extras) + +// 3. Create MediationRewardedVideoAdUnit +adUnit = MediationRewardedVideoAdUnit(activity, configId, mediationUtils) + +// 4. Make a bid request +adUnit?.fetchDemand { result -> + Log.d("Prebid", "Fetch demand result: $result") + + // 5. Make an ad request + RewardedAd.load(activity, adUnitId, request, object : RewardedAdLoadCallback() { + override fun onAdLoaded(ad: RewardedAd) { + Log.d(TAG, "Ad was loaded.") + rewardedAd = ad + + // 6. Display an ad + rewardedAd?.show(activity) { rewardItem -> + val rewardAmount = rewardItem.amount + val rewardType = rewardItem.type + Log.d(TAG, "User earned the reward ($rewardAmount, $rewardType)") + } + } + + override fun onAdFailedToLoad(adError: LoadAdError) { + Log.e(TAG, adError.message) + rewardedAd = null + } + }) +} +``` + +### Step 1: Create AdRequest + +{:.no_toc} + +This step is the same as for the original [AdMob integration](https://developers.google.com/admob/android/rewarded). You don't have to make any modifications here. + +### Step 2: Create AdMobRewardedMediationUtils + +{:.no_toc} + +The `AdMobRewardedMediationUtils` is a helper class, which performs certain utilty work for the `MediationInterstitialAdUnit`, like passing the targeting keywords to adapters. + +### Step 3: Create MediationRewardedVideoAdUnit + +{:.no_toc} + +The `MediationRewardedVideoAdUnit` is part of the prebid mediation API. This class is responsible for making bid request and managing the winning bid. + +### Step 4: Make a bid request + +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server and provides a result in a completion handler. + +### Step 5: Make an ad request + +{:.no_toc} + +Now you should just make a regular AdMob's ad request. Evetything else will be handled by GMA SDK and prebid adapters. + +### Step 6: Display an ad + +{:.no_toc} + +Once you receive the ad it will be ready for display. You can show interstitial right in the listener or later according to the app logic. + +## Native API + +Integration example: + +```kotlin +// 1. Create AdLoader and AdRequest +val nativeAdOptions = NativeAdOptions + .Builder() + .build() + +val adLoader = AdLoader + .Builder(wrapper.context, adUnitId) + .forNativeAd { ad: NativeAd -> + nativeAd = ad + createCustomView(wrapper, nativeAd!!) + } + .withAdListener(object : AdListener() { + override fun onAdFailedToLoad(adError: LoadAdError) { + Log.e(TAG, "Error: ${adError.message}") + } + }) + .withNativeAdOptions(nativeAdOptions) + .build() + +val extras = Bundle() +val adRequest = AdRequest + .Builder() + .addNetworkExtrasBundle(PrebidInterstitialAdapter::class.java, extras) + .build() + +// 2. Create Native AdUnit +val nativeAdUnit = NativeAdUnit(configId) + +// 3. Configure NativeAdUnit +configureNativeAdUnit(nativeAdUnit) + +// 4. Make a bid request +nativeAdUnit.fetchDemand(extras) { resultCode -> + Log.d(TAG, "Fetch demand result: $resultCode") + + // 5. Make an ad request + adLoader.loadAd(adRequest) +} +``` + +### Step 1: Create AdRequest + +{:.no_toc} + +Prepare the `AdLoader` and `AdRequest` objects before you make the bid request. They are needed for prebid mediation utils. Follow the [AdMob integration instructions](https://developers.google.com/admob/android/native/start) for this step. + +### Step 2: Create NativeAdUnit + +{:.no_toc} + +The `NativeAdUnit` is responsible for making bid requests. Once the bid responce is received you can load an ad from AdMob. + +### Step 3: Configure NativeAdUnit + +{:.no_toc} + +The bid request for native ad should have a description of expected assets. The full spec for the Native template can be found in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +Example of creating the assets array and configuring the `NativeAdUnit`: + +```kotlin +private fun configureNativeAdUnit(nativeAdUnit: NativeAdUnit) { + + // Configure Ad Unit + nativeAdUnit.setContextType(NativeAdUnit.CONTEXT_TYPE.SOCIAL_CENTRIC) + nativeAdUnit.setPlacementType(NativeAdUnit.PLACEMENTTYPE.CONTENT_FEED) + nativeAdUnit.setContextSubType(NativeAdUnit.CONTEXTSUBTYPE.GENERAL_SOCIAL) + + // Create the list of required assets + val title = NativeTitleAsset() + title.setLength(90) + title.isRequired = true + nativeAdUnit.addAsset(title) + + val icon = NativeImageAsset() + icon.imageType = NativeImageAsset.IMAGE_TYPE.ICON + icon.wMin = 20 + icon.hMin = 20 + icon.isRequired = true + nativeAdUnit.addAsset(icon) + + val image = NativeImageAsset() + image.imageType = NativeImageAsset.IMAGE_TYPE.MAIN + image.hMin = 200 + image.wMin = 200 + image.isRequired = true + nativeAdUnit.addAsset(image) + + val data = NativeDataAsset() + data.len = 90 + data.dataType = NativeDataAsset.DATA_TYPE.SPONSORED + data.isRequired = true + nativeAdUnit.addAsset(data) + + val body = NativeDataAsset() + body.isRequired = true + body.dataType = NativeDataAsset.DATA_TYPE.DESC + nativeAdUnit.addAsset(body) + + val cta = NativeDataAsset() + cta.isRequired = true + cta.dataType = NativeDataAsset.DATA_TYPE.CTATEXT + nativeAdUnit.addAsset(cta) + + // Create the list of required event trackers + val methods: ArrayList = ArrayList() + methods.add(NativeEventTracker.EVENT_TRACKING_METHOD.IMAGE) + methods.add(NativeEventTracker.EVENT_TRACKING_METHOD.JS) + try { + val tracker = NativeEventTracker(NativeEventTracker.EVENT_TYPE.IMPRESSION, methods) + nativeAdUnit.addEventTracker(tracker) + } catch (e: Exception) { + e.printStackTrace() + } +} +``` + +### Step 4: Make a bid request + +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server and provides a result in a completion handler. + +### Step 5: make an ad request + +{:.no_toc} + +Now load an native ad from AdMob according to the [AdMob instructions](https://developers.google.com/admob/android/native/start). Everything else will be handled by GMA SDK and prebid adapters. diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-gam-native.md b/prebid-mobile/modules/rendering/android-sdk-integration-gam-native.md index 11a4d091fd..2211345625 100644 --- a/prebid-mobile/modules/rendering/android-sdk-integration-gam-native.md +++ b/prebid-mobile/modules/rendering/android-sdk-integration-gam-native.md @@ -23,7 +23,7 @@ The general integration scenario requires these steps from publishers: 6. After receiving response from GAM - check if prebid has won and find native ad using `GamUtils` 7. Bind the winner data from the native ad response with the layout. -``` kotlin +```kotlin val builder = AdManagerAdRequest.Builder() val publisherAdRequest = builder.build() nativeAdUnit?.fetchDemand { result -> @@ -40,10 +40,9 @@ nativeAdUnit?.fetchDemand { result -> **NOTE:** `loadGam` method is creating GAM adLoader and executing `loadAd(publisherAdRequest)`. - Example of handling NativeAd response (the same applies to Custom): -``` kotlin +```kotlin private fun handleNativeAd(nativeAd: NativeAd) { if (GamUtils.didPrebidWin(nativeAd)) { GamUtils.findNativeAd(nativeAd) { @@ -56,13 +55,13 @@ private fun handleNativeAd(nativeAd: NativeAd) { } ``` -## Native Styles +## Native Styles [See Native Ads Guideline page](rendering-native-guidelines.html) for more details about SDK integration and supported ad types. Integration Example: -``` kotlin +```kotlin // 1. Create banner custom event handler for GAM ad server. val eventHandler = GamBannerEventHandler(requireContext(), GAM_AD_UNIT, GAM_AD_SIZE) @@ -82,7 +81,7 @@ viewContainer?.addView(bannerView) bannerView?.loadAd() ``` -#### Step 1: Create Event Handler +### Step 1: Create Event Handler GAM's event handlers are special containers that wrap GAM Ad Views and help to manage collaboration between GAM and Prebid views. @@ -92,21 +91,20 @@ To create the event handler you should provide a GAM Ad Unit Id and the list of **Note:** There is a helper function `convertGamAdSize` in GamBannerEventHandler to help you convert GAM AdSize into Prebid AdSize. - -#### Step 2: Create Ad View +### Step 2: Create Ad View **BannerView** - is a view that will display the particular ad. It should be added to the UI. To create it you should provide: -- **configId** - an ID of Stored Impression on the Prebid server -- **eventHandler** - the instance of the banner event handler +* **configId** - an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server +* **eventHandler** - the instance of the banner event handler Also, you should add the instance of `BannerView` to the UI. -#### Step 3: Create and provide NativeAdConfiguration +### Step 3: Create and provide NativeAdConfiguration NativeAdConfiguration creation example: -``` kotlin +```kotlin private fun createNativeAdConfiguration(): NativeAdConfiguration { val nativeAdConfiguration = NativeAdConfiguration() nativeAdConfiguration.contextType = NativeAdConfiguration.ContextType.SOCIAL_CENTRIC @@ -161,6 +159,6 @@ private fun createNativeAdConfiguration(): NativeAdConfiguration { See more NativeAdConfiguration options [here](rendering-native-ad-configuration.html). -#### Step 4: Load the Ad +### Step 4: Load the Ad -Call the `loadAd()` method to start an In-App Bidding flow. \ No newline at end of file +Call the `loadAd()` method to start an In-App Bidding flow. diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-gam.md b/prebid-mobile/modules/rendering/android-sdk-integration-gam.md index 3f9cffac56..2093dbbc11 100644 --- a/prebid-mobile/modules/rendering/android-sdk-integration-gam.md +++ b/prebid-mobile/modules/rendering/android-sdk-integration-gam.md @@ -8,63 +8,34 @@ sidebarType: 2 --- # Google Ad Manager Integration +{:.no_toc} -The integration of Prebid Rendering API with Google Ad Manager (GAM) assumes that publisher has an account on GAM and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app project. +The integration of Prebid Rendering API with Google Ad Manager (GAM) assumes that the publisher has an account on GAM and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app project. -If you do not have GAM SDK in the app yet, refer the the [Google Integration Documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/android/quick-start). - -Prebid Rendering API was tested with **GAM SDK 20.4.0**. +If you do not have the GAM SDK in the app yet, refer to the [Google Integration Documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/android/quick-start). +* TOC +{:toc} ## GAM Integration Overview ![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-GAM.png) -**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid. +**Steps 1-2** Prebid SDK makes a bid request. Prebid Server runs an auction and returns the winning bid. -**Step 3** Prebid Rendering Module via GAM Event Handler sets up the targeting keywords into the GAM's ad unit. +**Step 3** The Prebid Rendering Module, through the GAM Event Handler, sets up the targeting keywords into the GAM's ad unit. -**Step 4** GMA SDK makes an ad request. GAM returns the winned line item. +**Step 4** The GMA SDK makes an ad request. GAM returns the winning line item. -**Step 5** Basing on the ad response Prebid GAM Event Handler defines which line item has won on the GAM - the Prebid's one or another ad source on GAM. +**Step 5** Based on the ad response, Prebid GAM Event Handler defines which line item has won in GAM - Prebid's or another ad source. **Step 6** The winner is displayed in the app with the respective rendering engine. -Prebid Rendering API supports these ad formats: - -- Display Banner -- Video Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video - -[//]: # (- Native) -[//]: # (- Native Styles) - -They can be integrated using these API categories. - -- [**Banner API**](#banner-api) - for *Display Banner* and *Outstream Video* -- [**Interstitial API**](#interstitial-api) - for *Display* and *Video* Interstitials -- [**Rewarded API**](#rewarded-api) - for *Rewarded Video* - -[//]: # (- [**Native API**](android-sdk-integration-gam-native.html) - for *Native Ads*) +## Integrate Event Handlers -## Init Prebid Rendering Module - -To start running bid requests you have to provide an **Account Id** for your organization on Prebid server to the SDK: - -``` -PrebidRenderingSettings.setBidServerHost(HOST) -PrebidRenderingSettings.setAccountId(YOUR_ACCOUNT_ID) -``` - -The best place to do it is the `onCreate()` method of your Application class. - -> **NOTE:** The account ID is an identifier of the **Stored Request**. - -### Event Handlers +Prebid SDK provides rendering integration into GAM setup via [app events ](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner#app_events) mechanism. To integrate Prebid Event Handlers into your app, add the following line to your Podfile: GAM Event Handlers is a set of classes that wrap the GAM Ad Units and manage them respectively to the In-App Bidding flow. These classes are provided in the form of library that could be added to the app via Gradle: @@ -86,17 +57,16 @@ App module build.gradle: implementation('org.prebid:prebid-mobile-sdk-gam-event-handlers:x.x.x') ``` - ## Banner API To integrate the banner ad you need to implement three easy steps: -``` kotlin -// 1. Create banner custom event handler for GAM ad server. +```kotlin +// 1. Create a banner custom event handler for GAM ad server. val eventHandler = GamBannerEventHandler(requireContext(), GAM_AD_UNIT, GAM_AD_SIZE) -// 2. Create a bannerView instance and provide GAM event handler +// 2. Create a bannerView instance and provide the GAM event handler bannerView = BannerView(requireContext(), configId, eventHandler) // (Optional) set an event listener bannerView?.setBannerListener(this) @@ -104,11 +74,17 @@ bannerView?.setBannerListener(this) // Add bannerView to your viewContainer viewContainer?.addView(bannerView) -// 3. Execute ad loading +// 3. Execute the loadAd function. bannerView?.loadAd() ``` +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} + #### Step 1: Create Event Handler +{:.no_toc} GAM's event handlers are special containers that wrap GAM Ad Views and help to manage collaboration between GAM and Prebid views. @@ -117,10 +93,11 @@ GAM's event handlers are special containers that wrap GAM Ad Views and help to m To create the event handler you should provide a GAM Ad Unit Id and the list of available sizes for this ad unit. #### Step 2: Create Ad View +{:.no_toc} -**BannerView** - is a view that will display the particular ad. It should be added to the UI. To create it you should provide: +**BannerView** - is the view that will display a particular ad. It should be added to the UI. To create it you should provide: -- **configId** - an ID of Stored Impression on the Prebid server +- **configId** - an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server - **eventHandler** - the instance of the banner event handler Also, you should add the instance of `BannerView` to the UI. @@ -128,77 +105,77 @@ Also, you should add the instance of `BannerView` to the UI. And assign the listeners for processing ad events. #### Step 3: Load the Ad +{:.no_toc} -Simply call the `loadAd()` method to start [In-App Bidding](../android-in-app-bidding-getting-started.html) flow. The In-App Bidding SDK starts the bidding process right away. +Call the `loadAd()` method to make a bid request. ### Outstream Video +{:.no_toc} For **Outstream Video** you also need to specify video placement type of the expected ad: -``` kotlin +```kotlin bannerView.videoPlacementType = PlacementType.IN_BANNER // or any other available type ``` ### Migration from the original API +{:.no_toc} + +GAM setup: +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create new GAM ad unit. +3. Setup new [GAM Order](/adops/mobile-rendering-gam-line-item-setup.html) for rendering approach. +Integration: 1. Replace the `AdManagerAdView` with `BannerView` in the UI. 3. Implement the interface `BannerViewListener`. -4. Remove usage of `AdManagerAdView`, `AdManagerAdRequest`, and implementation of the `AdListener`. -5. Remove original `BannerAdUnit`. -5. Follow the instructions to integrate [Banner API](#banner-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. You can create a new order or just replace the code of creative in the original one and continue to use it for rendering integration. +4. Remove both `AdManagerAdView` and `AdManagerAdRequest` and implement an`AdListener`. +5. Remove the original `BannerAdUnit`. +6. Follow the instructions to integrate [Banner API](#banner-api). + ## Interstitial API -To integrate interstitial ad you need to implement four easy steps: +To integrate interstitial ad follow these steps: -``` kotlin -// 1. Create interstitial custom event handler for GAM ad server. +```kotlin +// 1. Create an interstitial custom event handler for GAM ad server. val eventHandler = GamInterstitialEventHandler(requireContext(), gamAdUnit) -// 2. Create interstitialAdUnit instance and provide GAM event handler +// 2. Create an interstitialAdUnit instance and provide GAM event handler interstitialAdUnit = InterstitialAdUnit(requireContext(), configId, minSizePercentage, eventHandler) // (Optional) set an event listener interstitialAdUnit?.setInterstitialAdUnitListener(this) -// 3. Execute ad load +// 3. Execute the loadAd function. interstitialAdUnit?.loadAd() //.... -// 4. After ad is loaded you can execute `show` to trigger ad display +// 4. After ad is loaded you can execute the `show` function to trigger ad display interstitialAdUnit?.show() ``` -The way of displaying **Video Interstitial Ad** is almost the same with two differences: - -- Need to customize the ad unit format -- No need to set up `minSizePercentage` +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} -``` kotlin -// 1. Create interstitial custom event handler for GAM ad server. -val eventHandler = GamInterstitialEventHandler(requireContext(), gamAdUnit) - -// 2. Create interstitialAdUnit instance and provide GAM event handler -interstitialAdUnit = InterstitialAdUnit(requireContext(), configId, AdUnitFormat.VIDEO, eventHandler) - -// (Optional) set an event listener -interstitialAdUnit?.setInterstitialAdUnitListener(this) - -// 3. Execute ad load -interstitialAdUnit?.loadAd() - -//.... - -// 4. After ad is loaded you can execute `show` to trigger ad display -interstitialAdUnit?.show() +The **default** ad format for an interstitial ad is **DISPLAY**. In order to make a `multiformat bid request`, set the respective values into the `adUnitFormats` parameter. ``` +interstitialAdUnit = InterstitialAdUnit( + requireContext(), + configId, + EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO), + eventHandler) +``` #### Step 1: Create Event Handler +{:.no_toc} GAM's event handlers are special containers that wrap the GAM Ad Views and help to manage collaboration between GAM and Prebid views. @@ -207,84 +184,97 @@ GAM's event handlers are special containers that wrap the GAM Ad Views and help To create an event handler you should provide a GAM Ad Unit. #### Step 2: Create Interstitial Ad Unit +{:.no_toc} -**InterstitialAdUnit** - is an object that will load and display the particular ad. To create it you should provide: +**InterstitialAdUnit** - is an object that will load and display a particular ad. To create it you should provide: -- **configId** - an ID of Stored Impression on the Prebid server -- **minSizePercentage** - specifies the minimum width and height percent an ad may occupy of a device’s real estate. +- **configId** - an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server +- **minSizePercentage** - specifies the minimum width and height percent an ad may occupy of a device’s screen. - **eventHandler** - the instance of the interstitial event handler Also, you can assign the listeners for processing ad events. -> **NOTE:** minSizePercentage - plays an important role in a bidding process for display ads. If provided space is not enough demand partners won't respond with the bids. - +> **NOTE:** minSizePercentage - plays an important role in a bidding process for display ads. If the provided space is too small demand partners won't respond with bids. #### Step 3: Load the Ad +{:.no_toc} -Simply call the `loadAd()` method to start [In-App Bidding](../android-in-app-bidding-getting-started.html) flow. The ad unit will load an ad and will wait for explicit instructions to display the Interstitial Ad. +Call the `loadAd()` method make a bid request. The ad unit will load an ad and will wait for explicit instructions to display the Interstitial Ad. #### Step 4: Show the Ad when it is ready +{:.no_toc} +The most convenient way to determine if the interstitial ad is ready for displaying is to listen to the listener method: -The most convenient way to determine if the interstitial ad is ready for displaying is to listen to the particular listener method: - -``` kotlin +```kotlin override fun onAdLoaded(interstitialAdUnit: InterstitialAdUnit) { //Ad is ready for display } ``` ### Migration from the original API +{:.no_toc} + +GAM setup: +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create a new GAM ad unit. +3. Setup a new [GAM Order](rendering-gam-line-item-setup.html) for rendering approach. +Integration: 1. Replace the `AdManagerInterstitialAd` with `InterstitialRenderingAdUnit`. -3. Implement the interface `InterstitialEventListener`. -4. Remove usage of `AdManagerInterstitialAd`, `AdManagerAdRequest`. -5. Remove original `InterstitialAdUnit`. -5. Follow the instructions to integrate [Interstitial API](#interstitial-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. **Pay Attention** that you can replace the code of creative in the original order **only for display** ads. For video interstitial you have to create a special order and remove the original one. +3. Implement the interface for `InterstitialEventListener`. +4. Remove both `AdManagerInterstitialAd` and `AdManagerAdRequest`. +5. Remove the original `InterstitialAdUnit`. +6. Follow the instructions to integrate [Interstitial API](#interstitial-api). ## Rewarded API -To display an Rewarded Ad need to implement four easy steps: +To display a Rewarded Ad follow these steps: -``` kotlin -// 1. Create rewarded custom event handler for GAM ad server. +```kotlin +// 1. Create a rewarded custom event handler for GAM ad server. val eventHandler = GamRewardedEventHandler(requireActivity(), gamAdUnitId) -// 2. Create rewardedAdUnit instance and provide GAM event handler +// 2. Create a rewardedAdUnit instance and provide the GAM event handler rewardedAdUnit = RewardedAdUnit(requireContext(), configId, eventHandler) -// (Optional) set an event listener +// You can also set an event listener, this step is optional. rewardedAdUnit?.setRewardedAdUnitListener(this) -// 3. Execute ad load +// 3. Execute the loadAd function. rewardedAdUnit?.loadAd() //... -// 4. After ad is loaded you can execute `show` to trigger ad display +// 4. After the ad is loaded you can execute the `show` function to display the ad. rewardedAdUnit?.show() ``` -The way of displaying the **Rewarded Ad** is totally the same as for the Interstitial Ad. You can customize a kind of ad: +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} +Displaying the **Rewarded Ad** is the same as displaying an Interstitial Ad. The type of ad can be customized to: -To be notified when user earns a reward - implement `RewardedAdUnitListener` interface: -``` kotlin +Be notified when user earns a reward - implement `RewardedAdUnitListener` interface: + +```kotlin fun onUserEarnedReward(rewardedAdUnit: RewardedAdUnit) ``` -The actual reward object is stored in the `RewardedAdUnit`: +When the actual reward object is stored in the `RewardedAdUnit`: -``` kotlin +```kotlin val reward = rewardedAdUnit.getUserReward() ``` #### Step 1: Create Event Handler +{:.no_toc} GAM's event handlers are special containers that wrap the GAM Ad Views and help to manage collaboration between GAM and Prebid views. @@ -292,37 +282,42 @@ GAM's event handlers are special containers that wrap the GAM Ad Views and help To create an event handler you should provide a GAM Ad Unit. - #### Step 2: Create Rewarded Ad Unit +{:.no_toc} **RewardedAdUnit** - is an object that will load and display the particular ad. To create it you should provide -- **configId** - an ID of Stored Impression on the Prebid server -- **eventHandler** - the instance of rewarded event handler - -Also, you can assign the listener for processing ad events. +- **configId** - is an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server +- **eventHandler** - is the instance of the rewarded event handler +You can also assign the listener for processing ad events. #### Step 3: Load the Ad +{:.no_toc} -Simply call the `loadAd()` method to start an In-App Bidding flow. The ad unit will load an ad and will wait for explicit instructions to display the Rewarded Ad. - +Call the `loadAd()` method to make a bid request. The ad unit will load an ad and will wait for explicit instructions to display the Rewarded Ad. -#### Step 4: Show the Ad when it is ready +#### Step 4: Display the Ad when it is ready +{:.no_toc} +The most convenient way to determine if the ad is ready for displaying is to listen for the listener method: -The most convenient way to determine if the ad is ready for displaying is to listen for particular listener method: - -``` kotlin +```kotlin override fun onAdLoaded(rewardedAdUnit: RewardedAdUnit) { //Ad is ready for display } ``` ### Migration from the original API +{:.no_toc} + +GAM setup: +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create a new GAM ad unit. +3. Setup a new [GAM Order](rendering-gam-line-item-setup.html) for rendering approach. +Integration: 1. Replace the `RewardedAd` with `RewardedAdUnit`. -3. Implement the interface `RewardedAdUnitListener`. -5. Remove original `RewardedVideoAdUnit`. -5. Follow the instructions to integrate [Rewarded API](#rewarded-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. **Pay Attention** that you have to create a new special order for rewarded video ad and remove the original one. +2. Implement the interface for `RewardedAdUnitListener`. +3. Remove the original `RewardedVideoAdUnit`. +4. Follow the instructions to integrate [Rewarded API](#rewarded-api). diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-max.md b/prebid-mobile/modules/rendering/android-sdk-integration-max.md new file mode 100644 index 0000000000..1da49c21df --- /dev/null +++ b/prebid-mobile/modules/rendering/android-sdk-integration-max.md @@ -0,0 +1,347 @@ +--- +layout: page_v2 +title: AppLovin MAX Integration +description: Integration of Prebid Rendering module whith AppLovin MAX +sidebarType: 2 +--- + +# AppLovin MAX Integration +{:.no_toc} + +The integration of Prebid Mobile with AppLovin MAX assumes that publisher has MAX account and has already integrated the AppLovin MAX SDK into the app. + +See the [AppLovin MAX Documentation](https://dash.applovin.com/documentation/mediation/android/getting-started/integration) for the MAX integration details. + +* TOC +{:toc} + +## MAX Integration Overview + +![Rendering with MAX](/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-max.png) + +**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid. + +**Step 3** MAX SDK makes an ad request. MAX returns the waterfall with respective placements. + +**Step 4** For each prebid's placement, the MAX SDK sequentially instantiates an adapter. + +**Step 5** The adapter verifies the targeting keywords of the winning bid and the custom properties of the given placement. If they match the adapter will render the winning bid. Otherwise, adpater will fail with "no ad" immediately and the next placement will instantiate the same adapter but for another custom properties. + + +## Integrate Prebid Adapters + +Prebid SDK is integrated into AppLovin MAX setup via custom adapters. To integrate Prebid Adapters into your app, add the following lines into your build.gradle files: + +Root build.gradle + +``` +allprojects { + repositories { + ... + mavenCentral() + ... + } +} +``` + +App module build.gradle: + +``` +implementation('org.prebid:prebid-mobile-sdk-max-adapters:x.x.x') +``` + +## Banner API + +Integration example: + +```kotlin +// 1. Create MaxAdView +adView = MaxAdView(adUnitId, requireContext()) +adView?.setListener(createListener()) +adWrapperView.addView(adView) + +// 2. Create MaxMediationBannerUtils +val mediationUtils = MaxMediationBannerUtils(adView) + +// 3. Create MediationBannerAdUnit +adUnit = MediationBannerAdUnit( + requireContext(), + configId, + AdSize(width, height), + mediationUtils +) + +// 4. Make a bid request +adUnit?.fetchDemand { + + // 5. Make an ad request to MAX + adView?.loadAd() +} +``` + +#### Step 1: Create MaxAdView +{:.no_toc} + +This step is totally the same as for original [MAX integration](https://dash.applovin.com/documentation/mediation/android/getting-started/banners#loading-and-showing-banners-programmatically). You don't have to make any modifications here. + + +#### Step 2: Create MaxMediationBannerUtils +{:.no_toc} + +The `MaxMediationBannerUtils` is a helper class, which performs certain utilty work for the `MediationBannerAdUnit`, like passing the targeting keywords to the adapters and checking the visibility of the ad view. + +#### Step 3: Create MediationBannerAdUnit +{:.no_toc} + +The `MediationBannerAdUnit` is a part of Prebid mediation API. This class is responsible for making bid request and providing the winning bid and targeting keywords to mediating SDKs. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to prebid server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Now you should make a regular MAX's ad request. Everything else will be handled by prebid adapters. + +## Interstitial API + +Integration example: + +```kotlin +// 1. Create MaxInterstitialAd +maxInterstitialAd = MaxInterstitialAd(adUnitId, activity) +maxInterstitialAd?.setListener(createListener()) + +// 2. Create MaxMediationInterstitialUtils +val mediationUtils = MaxMediationInterstitialUtils(maxInterstitialAd) + +// 3. Create MediationInterstitialAdUnit +adUnit = MediationInterstitialAdUnit( + activity, + configId, + EnumSet.of(AdUnitFormat.BANNER), + mediationUtils + ) + +// 4. Make a bid request +adUnit?.fetchDemand { + + // 5. Make an ad request to MAX + maxInterstitialAd?.loadAd() +} + +``` + +The **default** ad format for interstitial is **DISPLAY**. In order to make a `multiformat bid request`, set the respective values into the `adUnitFormats` parameter. + +``` +adUnit = MediationInterstitialAdUnit( + activity, + configId, + EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO), + mediationUtils + ) +``` + +#### Step 1: Create MaxInterstitialAd +{:.no_toc} + +This step is totally the same as for original [MAX integration](https://dash.applovin.com/documentation/mediation/android/getting-started/interstitials). You don't have to make any modifications here. + + +#### Step 2: Create MaxMediationInterstitialUtils +{:.no_toc} + +The `MaxMediationInterstitialUtils` is a helper class, which performs certain utilty work for the `MediationInterstitialAdUnit`, like passing the targeting keywords to the adapters and checking the visibility of the ad view. + +#### Step 3: Create MediationInterstitialAdUnit +{:.no_toc} + +The `MediationInterstitialAdUnit` is part of the prebid mediation API. This class is responsible for making a bid request and providing a winning bid to the mediating SDKs. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to prebid server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Now you should make a regular MAX's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +#### Steps 6: Display an ad +{:.no_toc} + +Once you receive the ad it will be ready for display. Folow the [MAX instructions](https://dash.applovin.com/documentation/mediation/android/getting-started/interstitials#showing-an-interstitial-ad) about how to do it. + +## Rewarded API + +Integration example: + +```swift +// 1. Get an instance of MaxRewardedAd +maxRewardedAd = MaxRewardedAd.getInstance(adUnitId, activity) +maxRewardedAd?.setListener(createListener()) + +// 2. Create MaxMediationRewardedUtils +val mediationUtils = MaxMediationRewardedUtils(maxRewardedAd) + +// 3. Create MediationRewardedVideoAdUnit +adUnit = MediationRewardedVideoAdUnit( + activity, + configId, + mediationUtils + ) + +// 4. Make a bid request +adUnit?.fetchDemand { + + // 5. Make an ad request to MAX + maxRewardedAd?.loadAd() +} +``` + +The way of displaying the rewarded ad is the same as for the Interstitial Ad. + +To be notified when user earns a reward follow the [MAX intructions](https://dash.applovin.com/documentation/mediation/android/getting-started/rewarded-ads#accessing-the-amount-and-currency-for-a-rewarded-ad). + +#### Step 1: Get an instance of MaxRewardedAd +{:.no_toc} + +This step is totally the same as for original [MAX integration](https://dash.applovin.com/documentation/mediation/android/getting-started/rewarded-ads). You don't have to make any modifications here. + +#### Step 2: Create MaxMediationRewardedUtils +{:.no_toc} + +The `MaxMediationRewardedUtils` is a helper class, which performs certain utilty work for the `MediationRewardedVideoAdUnit`, like passing the targeting keywords to the adapters. + +#### Step 3: Create MediationRewardedVideoAdUnit +{:.no_toc} + +The `MediationRewardeVideoAdUnit` is part of the prebid mediation API. This class is responsible for making a bid request and providing a winning bid and targeting keywords to the adapters. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Now you should make a regular MAX's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +#### Steps 6: Display an ad +{:.no_toc} + +Once the rewarded ad is received you can display it. Folow the [MAX instructions](https://dash.applovin.com/documentation/mediation/android/getting-started/rewarded-ads#showing-a-rewarded-ad) for the details. + +## Native Ads + +Integration example: + +``` +// 1. Create MaxNativeAdLoader +nativeAdLoader = MaxNativeAdLoader(adUnitId, requireActivity()) +nativeAdLoader.setNativeAdListener(createNativeAdListener(viewContainer)) +nativeAdLoader.setRevenueListener(createRevenueListener()) + +// 2. Create and configure MediationNativeAdUnit +nativeAdUnit = NativeAdUnit(configId) + +nativeAdUnit.setContextType(NativeAdUnit.CONTEXT_TYPE.SOCIAL_CENTRIC) +nativeAdUnit.setPlacementType(NativeAdUnit.PLACEMENTTYPE.CONTENT_FEED) +nativeAdUnit.setContextSubType(NativeAdUnit.CONTEXTSUBTYPE.GENERAL_SOCIAL) + +// 3. Set up assets for bid request +// See the code below + +// 4. Set up event tracker for bid request +// See the code below + +// 5. Make a bid request +nativeAdUnit.fetchDemand(nativeAdLoader) { +// 6. Make an ad request to MAX + self?.nativeAdLoader?.loadAd(into: self?.createNativeAdView()) +} +``` + +#### Step 1: Create MaxNativeAdLoader +{:.no_toc} + +Prepare the `MaxNativeAdLoader` object before you make a bid request. It will be needed for prebid mediation utils. + +#### Step 2: Create and configure NativeAdUnit +{:.no_toc} + +The `NativeAdUnit` class is responsible for making a bid request and providing a winning bid and targeting keywords. Fot the better targetting you should provide additional properties like `conteaxtType` and `placemantType`. + +#### Step 3: Set up assets for bid request +{:.no_toc} + +The bid request for native ads should have the description of expected assets. The full spec for the native template you can find in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +The example of creating the assets array: + +``` +val title = NativeTitleAsset() +title.setLength(90) +title.isRequired = true +nativeAdUnit.addAsset(title) + +val icon = NativeImageAsset(20, 20, 20, 20) +icon.imageType = NativeImageAsset.IMAGE_TYPE.ICON +icon.isRequired = true +nativeAdUnit.addAsset(icon) + +val image = NativeImageAsset(200, 200, 200, 200) +image.imageType = NativeImageAsset.IMAGE_TYPE.MAIN +image.isRequired = true +nativeAdUnit.addAsset(image) + +val data = NativeDataAsset() +data.len = 90 +data.dataType = NativeDataAsset.DATA_TYPE.SPONSORED +data.isRequired = true +nativeAdUnit.addAsset(data) + +val body = NativeDataAsset() +body.isRequired = true +body.dataType = NativeDataAsset.DATA_TYPE.DESC +nativeAdUnit.addAsset(body) + +val cta = NativeDataAsset() +cta.isRequired = true +cta.dataType = NativeDataAsset.DATA_TYPE.CTATEXT +nativeAdUnit.addAsset(cta) +``` + +#### Step 4: Set up event tracker for bid request +{:.no_toc} + +The bid request for mative ads may have a descrition of expected event trackers. The full spec for the Native template you can find in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +The example of creating the event trackers array: + +``` +val methods: ArrayList = ArrayList() +methods.add(NativeEventTracker.EVENT_TRACKING_METHOD.IMAGE) +methods.add(NativeEventTracker.EVENT_TRACKING_METHOD.JS) +try { + val tracker = NativeEventTracker(NativeEventTracker.EVENT_TYPE.IMPRESSION, methods) + nativeAdUnit.addEventTracker(tracker) +} catch (e: Exception) { + e.printStackTrace() +} +``` + +#### Step 5: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to prebid server and provides a result in a completion handler. + +#### Step 6: Load Native ad +{:.no_toc} + +Now just load a native ad from MAX according to the [MAX instructions](https://dash.applovin.com/documentation/mediation/android/getting-started/native-manual#load-the-native-ad). diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-mopub-native.md b/prebid-mobile/modules/rendering/android-sdk-integration-mopub-native.md deleted file mode 100644 index 4ee0ae230f..0000000000 --- a/prebid-mobile/modules/rendering/android-sdk-integration-mopub-native.md +++ /dev/null @@ -1,182 +0,0 @@ ---- - -layout: page_v2 -title: MoPub Integration -description: Integration the Rendering Module with MoPub on Android -sidebarType: 2 - ---- - -# MoPub: Native Ads Integration - -## Native Ads - -The integration of native ads into MoPub monetization is based on MoPub's Mediation feature (using `PrebidNativeAdapter`). -Here are the basic steps of integration: - -``` kotlin -fun initAd() { - // Initialize AdapterHelper and MoPubNative. - adapterHelper = AdapterHelper() - mopubNative = MoPubNative(requireContext(), adUnitId, nativeNetworkListener) - - // Create viewBinder. - val viewBinder = ViewBinder.Builder(R.layout.lyt_native_ad) - // ... - .build() - - // Register ad renderers. - mopubNative.registerAdRenderer(PrebidNativeAdRenderer(viewBinder)) - mopubNative.registerAdRenderer(MoPubStaticNativeAdRenderer(viewBinder)) - - // Initialize MoPubNativeAdUnit and provide necessary configuration. - mopubNativeAdUnit = MoPubNativeAdUnit(requireContext(), configId, getNativeAdConfig()) - - // Execute ad load. - loadAd() -} - -fun loadAd() { - // Initialize MoPub SDK and make ad request. - MoPub.initializeSdk(requireContext(), SdkConfiguration.Builder(adUnitId).build()) { - mopubNativeAdUnit.fetchDemand(keywordsContainer, mopubNative) { - val requestParameters = RequestParameters.Builder() - .keywords(convertMapToMoPubKeywords(keywordsContainer)) - .build() - mopubNative.makeRequest(requestParameters) - } - } -} -``` - -``` kotlin -// Add view when receiving a successful NativeAd response from MoPub. -object : MoPubNative.MoPubNativeNetworkListener { - override fun onNativeLoad(nativeAd: NativeAd?) { - val view = adapterHelper.getAdView(null, viewContainer, nativeAd) - viewContainer.removeAllViews() - // Add view to viewContainer - viewContainer.addView(view) - } -} -``` - -### Step 1: Create Ad View - -You have to create and place MoPub's Ad View into the app page. - - -### Step 2: Create Ad Unit - -Create the **MoPubBannerAdUnit** object with parameters: - -- **configId** - an ID of Stored Impression on the Prebid server -- **size** - the size of the ad unit which will be used in the bid request. - - -### Step 3: Create and provide NativeAdConfiguration - -NativeAdConfiguration creation example: - -``` kotlin -private fun createNativeAdConfiguration(): NativeAdConfiguration { - val nativeAdConfiguration = NativeAdConfiguration() - nativeAdConfiguration.contextType = NativeAdConfiguration.ContextType.SOCIAL_CENTRIC - nativeAdConfiguration.placementType = NativeAdConfiguration.PlacementType.CONTENT_FEED - nativeAdConfiguration.contextSubType = NativeAdConfiguration.ContextSubType.GENERAL_SOCIAL - - val methods = ArrayList() - methods.add(NativeEventTracker.EventTrackingMethod.IMAGE) - methods.add(NativeEventTracker.EventTrackingMethod.JS) - val eventTracker = NativeEventTracker(NativeEventTracker.EventType.IMPRESSION, methods) - nativeAdConfiguration.addTracker(eventTracker) - - val assetTitle = NativeAssetTitle() - assetTitle.len = 90 - assetTitle.isRequired = true - nativeAdConfiguration.addAsset(assetTitle) - - val assetIcon = NativeAssetImage() - assetIcon.type = NativeAssetImage.ImageType.ICON - assetIcon.wMin = 20 - assetIcon.hMin = 20 - assetIcon.isRequired = true - nativeAdConfiguration.addAsset(assetIcon) - - val assetImage = NativeAssetImage() - assetImage.hMin = 20 - assetImage.wMin = 200 - assetImage.isRequired = true - nativeAdConfiguration.addAsset(assetImage) - - val assetData = NativeAssetData() - assetData.len = 90 - assetData.type = NativeAssetData.DataType.SPONSORED - assetData.isRequired = true - nativeAdConfiguration.addAsset(assetData) - - val assetBody = NativeAssetData() - assetBody.isRequired = true - assetBody.type = NativeAssetData.DataType.DESC - nativeAdConfiguration.addAsset(assetBody) - - val assetCta = NativeAssetData() - assetCta.isRequired = true - assetCta.type = NativeAssetData.DataType.CTA_TEXT - nativeAdConfiguration.addAsset(assetCta) - - return nativeAdConfiguration -} -``` -See more NativeAdConfiguration options [here](../../info-modules/native/in-app-bidding-native-ad-configuration.html). - -### Step 4: Fetch Demand - -To run an auction on Prebid run the `fetchDemand()` method which performs several actions: - -- Makes a bid request to Prebid -- Sets up the targeting keywords to the MoPub's ad unit -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -### Step 5: Load the Ad - -When the bid request has completed, the responsibility of making the Ad Request is passed to the publisher. That is why you have to invoke `loadAd()` on the MoPub's Ad View explicitly in the completion handler of `fetchDemand()`. -## Native Styles - -[See MoPub Integration page](../integration-mopub/android-in-app-bidding-mopub-info.html) for more info about MoPub order setup and Adapter integration. - -To display an ad you need to implement these easy steps: - -``` kotlin -private fun initBanner() { - // 1. Create and initialize MoPubView instance - bannerView = MoPubView(requireContext()) - bannerView?.setAdUnitId(moPubAdUnit) - bannerView?.bannerAdListener = this - - // 2. initialize MoPubBannerAdUnit - if (bannerAdUnit == null) { - bannerAdUnit = MoPubBannerAdUnit(requireContext(), configId, AdSize(width, height)) - } - - // 3. Provide NativeAdConfiguration - val nativeAdConfiguration = createNativeAdConfiguration() - bannerAdUnit?.setNativeAdConfiguration(nativeAdConfiguration) - - // Add moPubView to your viewContainer - viewContainer?.addView(bannerView) - - val builder = SdkConfiguration.Builder(moPubAdUnit) - MoPub.initializeSdk(requireContext(), builder.build()) { - - // 4. Run an Header Bidding auction on Prebid and provide MoPubView as parameter. It is important to execute this method after MoPub SDK initialization. - bannerAdUnit?.fetchDemand(bannerView!!) { - // 5. execute MoPubView `loadAd` when receiving a valid demand result - bannerView?.loadAd() - } - } -} -``` - - diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-mopub.md b/prebid-mobile/modules/rendering/android-sdk-integration-mopub.md deleted file mode 100644 index 33a6daa3bf..0000000000 --- a/prebid-mobile/modules/rendering/android-sdk-integration-mopub.md +++ /dev/null @@ -1,330 +0,0 @@ ---- - -layout: page_v2 -title: MoPub Integration -description: Integration the Rendering Module with MoPub on Android -sidebarType: 2 - ---- - -# MoPub Integration - -The integration of Prebid Rendering API with MoPub assumes that publisher has an account on MoPub and has already integrated the MoPub SDK into the app project. - -If you do not have MoPub SDK in the app yet, refer the [MoPub's Documentation](https://github.com/mopub/mopub-android-sdk). - - -## MoPub Integration Overview - -The integration of header bidding into MoPub monetization is based on MoPub's Mediation feature. - -![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-MoPub.png) - -**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid. - -**Step 3** Prebid SDK via MoPub Adapters Framework sets up targeting keywords into the MoPub's ad unit. - -**Step 4** MoPub SDK makes an ad request. MoPub returns the mediation chain. - -**Step 5** If Prebid's creative wins in the waterfall then the MoPub SDK will instantiate respective Prebid Adapter which will render the winning bid. - -**Step 6** The winner is displayed in the App with the respective rendering engine. - -Prebid Rendering API provides ability to integrate header bidding for these ad kinds: - -- Display Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video - -[//]: # (- Native) -[//]: # (- Native Styles) - -They can be integrated using these API categories. - -- [**Banner API**](#banner-api) - for **Display Banner** -- [**Interstitial API**](#interstitial-api) - for **Display** and **Video** Interstitials -- [**Rewarded API**](#rewarded-api) - for **Rewarded Video** - -[//]: # (- [**Native API**](android-sdk-integration-mopub-native.html)) - - -## Init Prebid Rendering Module - -Set up a Prebid Server host amd provide an **Account Id** of your organization first. - -``` -PrebidRenderingSettings.setBidServerHost(HOST) -PrebidRenderingSettings.setAccountId(YOUR_ACCOUNT_ID) -``` - -The best place to do it is the `onCreate()` method of your Application class. - -The account ID is an identifier of the **Stored Request**. - -### Prebid Adapters - -To integrate Prebid Adapters just add the following lines in your build.gradle files: - -Root build.gradle - -``` -allprojects { - repositories { - ... - mavenCentral() - ... - } -} -``` - -App module build.gradle: - -``` -implementation('org.prebid:prebid-mobile-sdk-mopub-adapters:x.x.x') -``` - -For more details about Adapters read the [MoPub's Documentation](https://developers.mopub.com/networks/integrate/mopub-network-mediation-guidelines/). - - -## Banner API - -Integration example: - - -``` kotlin -private fun initBanner() { - // 1. Create and initialize MoPubView instance - bannerView = MoPubView(requireContext()) - bannerView?.setAdUnitId(moPubAdUnit) - bannerView?.bannerAdListener = this - - // Add moPubView to your viewContainer - viewContainer?.addView(bannerView) - - val builder = SdkConfiguration.Builder(moPubAdUnit) - MoPub.initializeSdk(requireContext(), builder.build()) { - fetchAdUnit(configId, AdSize(320, 50)) - } -} - -private fun fetchAdUnit(configId: String, size: AdSize) { - if (bannerAdUnit == null) { - // 2. initialize MoPubBannerAdUnit - bannerAdUnit = MediationBannerAdUnit(requireContext(), configId, size, MoPubMediationDelegate() ) - } - // 3. Run an Header Bidding auction on Prebid and provide MoPubView as parameter. It is important to execute this method after MoPub SDK initialization. - bannerAdUnit?.fetchDemand(bannerView!!) { - // 4. execute MoPubView `loadAd` when receiving a valid demand result - bannerView?.loadAd() - } -} -``` - -#### Step 1: Create Ad View - -Follow the [MoPub Instructions](https://developers.mopub.com/publishers/android/banner/) for Banner integration. - -#### Step 2: Create Ad Unit - -Create the `MediationBannerAdUnit` object with parameters: - -- `configId` - an ID of Stored Impression on the Prebid server -- `size` - the size of the ad unit which will be used in the bid request. -- `mediationDelegate` - the object from the MoPubAdapters framework responsible for managing MoPub’s ad objects. - -#### Step 3: Fetch Demand - -To run an auction on Prebid run the `fetchDemand()` method which performs several actions: - -- Makes a bid request to Prebid Server -- Sets up the targeting keywords to the MoPub's ad unit -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -#### Step 4: Load the Ad - -When the bid request is completed, the responsibility of making the Ad Request is passed to the publisher. Call the `loadAd()` method on the MoPub's Ad View explicitly in the completion handler of the `fetchDemand()`. - -#### Step 5: Rendering - -If the Prebid Line Item is processed in the waterfall the winning bid will be rendered by `PrebidBannerAdapter`. You shouldn't do anything for this. Just make sure that your order has been set up correctly and an adapter has been added to the project. - -### Migration from the original API - -1. Replace the `BannerAdUnit` with `MediationBannerlAdUnit`. -5. Follow the instructions to integrate [Banner API](#banner-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. - -## Interstitial API - -To display an ad you need to implement these easy steps: - -``` kotlin -private fun initInterstitial() { - // 1. Create and initialize MoPubInterstitial instance - moPubInterstitial = MoPubInterstitial(requireActivity(), adUnit) - moPubInterstitial?.interstitialAdListener = this - - // 2. Initialize MoPubInterstitialAdUnit - moPubInterstitialAdUnit = MediationInterstitialAdUnit(requireContext(), configId, minSizePercentage. MoPubMediationAdUnit()) - - val builder = SdkConfiguration.Builder(adUnit) - MoPub.initializeSdk(requireContext(), builder.build()) { - fetchInterstitial() - } -} - -private fun fetchInterstitial() { - // 3. Execute `fetchDemand` method and provide MoPubInterstitial as parameter. It is important to execute this method after MoPub SDK initialization. - moPubInterstitialAdUnit?.fetchDemand(moPubInterstitial!!) { - // 4. Execute MoPubInterstitial `load` when receiving a valid demand result - moPubInterstitial?.load() - } -} - - -//... -// After ad is loaded you can execute `show` to trigger ad display -moPubInterstitial?.show() -``` - -The way of displaying **Video Interstitial Ad** is almost the same with two differences: - -- Need customize the ad format -- No need to set up `minSizePercentage` - -``` kotlin -private fun initInterstitial() { - // 1. Create and initialize MoPubInterstitial instance - moPubInterstitial = MoPubInterstitial(requireActivity(), adUnit) - moPubInterstitial?.interstitialAdListener = this - - // 2. Initialize MoPubInterstitialAdUnit and provide VIDEO AdUnitFormat - moPubInterstitialAdUnit = MediationInterstitialAdUnit(requireContext(), configId, AdUnitFormat.VIDEO, MoPubMediationAdUnit()) - - val builder = SdkConfiguration.Builder(adUnit) - MoPub.initializeSdk(requireContext(), builder.build()) { - fetchInterstitial() - } -} - -private fun fetchInterstitial() { - // 3. Execute `fetchDemand` method and provide MoPubInterstitial as parameter. It is important to execute this method after MoPub SDK initialization. - moPubInterstitialAdUnit?.fetchDemand(moPubInterstitial!!) { - // 4. Execute MoPubInterstitial `load` when receiving a valid demand result - moPubInterstitial?.load() - } -} - -//... -// After ad is loaded you can execute `show` to trigger ad display -moPubInterstitial?.show() -``` - -#### Step 1: Integrate interstitial ad - -Follow the [MoPub Instructions](https://developers.mopub.com/publishers/android/interstitial/) and intgrate Interstital ad unit. - - -#### Step 2: Create prebid Ad Unit - -Create the `MediationInterstitialAdUnit` object with parameters: - -- `configId` - an ID of Stored Impression on the Prebid server -- `mediationDelegate` - the object from the MoPubAdapters framework responsible for managing MoPub’s ad objects. - -#### Step 3: Fetch Demand - -To run an auction on Prebid run the`fetchDemand()` method which performs several actions: - -- Makes a bid request to Prebid Server -- Sets up the targeting keywords to the MoPub's ad unit -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -#### Step 4: Load the Ad - -Call the `loadAd()` on the MoPub Interstitial Ad explicitly in the completion handler of the `fetchDemand()`. - -#### Step 5: Rendering - -If the Prebid bid wins on MoPub it will be rendered by `PrebidInterstitialAdapter`. You shouldn't do anything for this. Just make sure that your order has been set up correctly and an adapter has been added to the project. - - -However, due to the expiration, the ad could become invalid with time. So it is always useful to check it with `interstitial?.isReady` before display. - -### Migration from the original API - -1. Replace the `InterstitialAdUnit` with `MediationInterstitialAdUnit`. -5. Follow the instructions to integrate [Interstitial API](#interstitial-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. - -## Rewarded API - -Integration Example: - -``` kotlin -private fun initRewarded() { - // 1. Create MoPubRewardedVideoAdUnit instance - rewardedAdUnit = MediationRewardedAdUnit(requireContext(), adUnitId, configId) - - // 2. Initialize MoPub SDK and MoPubRewardedVideoManager. - val builder = SdkConfiguration.Builder(adUnitId) - MoPubRewardedVideoManager.init(requireActivity()) - MoPubRewardedVideoManager.updateActivity(requireActivity()) - MoPubRewardedVideos.setRewardedVideoListener(this) - MoPub.initializeSdk(requireContext(), builder.build()) { - fetchRewarded(adUnitId) - } -} - -private fun fetchRewarded(adUnitId: String) { - // 3. Execute `fetchDemand` method and keywords Map as parameter. It is important to execute this method after MoPub SDK initialization. - rewardedAdUnit?.fetchDemand(keywordsMap) { - val keywordsString = convertMapToMoPubKeywords(keywordsMap) - val params = MoPubRewardedVideoManager.RequestParameters(keywordsString) - - // 4. After creating RequestParameters from keywordsMap you can execute rewardedVideo loading - MoPubRewardedVideos.loadRewardedVideo(adUnitId, params, null) - } -} - -//... -// After ad is loaded you can execute `show` to trigger ad display -MoPubRewardedVideos.showRewardedVideo(adUnitId) -``` - -#### Step 1: Create an Rewarded Ad Unit - -Create the `MediationRewardedVideoAdUnit` object with parameters: - -- `configId` - an ID of Stored Impression on the Prebid server - -#### Step 2: Fetch Demand - -To run an auction on Prebid run the `fetchDemand()` method which does several things: - -- Makes a bid request to Prebid Server -- Sets up the targeting keywords -- Returns the result of bid request for future processing - -#### Step 3: Load the Ad - -Call the `loadAd()` of the MoPub's Ad View explicitly in the completion handler of the `fetchDemand()`. - - -#### Step 5: Rendering - -If the Prebid bid wins on MoPub it will be rendered by ``. You do not have to do anything for this. Just make sure that your order had been set up correctly and an adapter is added. - -If the Prebid Line Item is processed in the waterfall the winning bid will be rendered by `PrebidRewardedVideoAdapter `. You shouldn't do anything for this. Just make sure that your order has been set up correctly and an adapter has been added to the project. - -1. Replace the `RewardedVideoAdUnit` with `MediationRewardedAdUnit`. -5. Follow the instructions to integrate [Rewarded Video API](#rewarded-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. - - - - - diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-pb-native.md b/prebid-mobile/modules/rendering/android-sdk-integration-pb-native.md deleted file mode 100644 index cac3bb4205..0000000000 --- a/prebid-mobile/modules/rendering/android-sdk-integration-pb-native.md +++ /dev/null @@ -1,159 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Pure In-App Bidding Native Ads Integration -description: Integration of native ads for pure In-App Bidding scenario -sidebarType: 2 - ---- - -# Prebid Rendering: Native Ads Integration - -## Native Ads - -The general integration scenario requires these steps from publishers: - -1. Prepare the ad layout. -2. Create Native Ad Unit. -3. Configure the Native Ad unit using [NativeAdConfiguration](rendering-native-ad-configuration.html). - * Provide the list of **[Native Assets](rendering-native-guidelines.html#components)** representing the ad's structure. - * Tune other general properties of the ad. -4. Make a bid request. -5. Extract NativeAd using `NativeUtils.findNativeAd` -7. Bind the data from the native ad with the layout. - -``` kotlin -nativeAdUnit?.fetchDemand { - if (it.fetchDemandResult != FetchDemandResult.SUCCESS) { - return@fetchDemand - } - NativeUtils.findNativeAd(it) { nativeAd -> - if (nativeAd == null) { - return@findNativeAd - } - inflateViewContentWithPrebid(nativeAd) - } -} -``` - -## Native Styles - -[See Native Ads Guidelines page](rendering-native-guidelines.html) for more details about SDK integration and supported ad types. - -To display an ad using Native Styles you'll need to implement these easy steps: - -``` kotlin -// 1. Create an Ad View -bannerView = BannerView(requireContext(), configId, adSize) -bannerView?.setBannerListener(this) - -// 2. Provide NativeAdConfiguration -val nativeAdConfiguration = createNativeAdConfiguration() -bannerView?.setNativeAdConfiguration(nativeAdConfiguration) - -// Add view to viewContainer -viewContainer?.addView(bannerView) - -// 3. Load ad -bannerView?.loadAd() -``` - -#### Step 1: Create Ad View - -In the Pure In-App Bidding scenario you just need to initialize the Banner Ad View using correct properties: - -- **configId** - an ID of Stored Impression on the Prebid server. -- **size** - the size of the ad unit which will be used in the bid request. - -#### Step 2: Create and provide NativeAdConfiguration - -NativeAdConfiguration creation example: - -``` kotlin -private fun createNativeAdConfiguration(): NativeAdConfiguration { - val nativeAdConfiguration = NativeAdConfiguration() - nativeAdConfiguration.contextType = NativeAdConfiguration.ContextType.SOCIAL_CENTRIC - nativeAdConfiguration.placementType = NativeAdConfiguration.PlacementType.CONTENT_FEED - nativeAdConfiguration.contextSubType = NativeAdConfiguration.ContextSubType.GENERAL_SOCIAL - - val methods = ArrayList() - methods.add(NativeEventTracker.EventTrackingMethod.IMAGE) - methods.add(NativeEventTracker.EventTrackingMethod.JS) - val eventTracker = NativeEventTracker(NativeEventTracker.EventType.IMPRESSION, methods) - nativeAdConfiguration.addTracker(eventTracker) - - val assetTitle = NativeAssetTitle() - assetTitle.len = 90 - assetTitle.isRequired = true - nativeAdConfiguration.addAsset(assetTitle) - - val assetIcon = NativeAssetImage() - assetIcon.type = NativeAssetImage.ImageType.ICON - assetIcon.wMin = 20 - assetIcon.hMin = 20 - assetIcon.isRequired = true - nativeAdConfiguration.addAsset(assetIcon) - - val assetImage = NativeAssetImage() - assetImage.hMin = 20 - assetImage.wMin = 200 - assetImage.isRequired = true - nativeAdConfiguration.addAsset(assetImage) - - val assetData = NativeAssetData() - assetData.len = 90 - assetData.type = NativeAssetData.DataType.SPONSORED - assetData.isRequired = true - nativeAdConfiguration.addAsset(assetData) - - val assetBody = NativeAssetData() - assetBody.isRequired = true - assetBody.type = NativeAssetData.DataType.DESC - nativeAdConfiguration.addAsset(assetBody) - - val assetCta = NativeAssetData() - assetCta.isRequired = true - assetCta.type = NativeAssetData.DataType.CTA_TEXT - nativeAdConfiguration.addAsset(assetCta) - - nativeAdConfiguration.nativeStylesCreative = nativeStylesCreative - - return nativeAdConfiguration -} -``` - -Native Styles creative example: - -``` html - - - -``` - -See more NativeAdConfiguration options [here](rendering-native-ad-configuration.html). - -**IMPORTANT:** - -You should add HTML and CSS to define your native ad template with universal creative and provide it via NativeAdConfiguration. - -#### Step 3: Load the Ad - -Call `loadAd()` and SDK will: - -- make bid request to Prebid server -- render the winning bid on display \ No newline at end of file diff --git a/prebid-mobile/modules/rendering/android-sdk-integration-pb.md b/prebid-mobile/modules/rendering/android-sdk-integration-pb.md index a0178aa5a5..231aa81caa 100644 --- a/prebid-mobile/modules/rendering/android-sdk-integration-pb.md +++ b/prebid-mobile/modules/rendering/android-sdk-integration-pb.md @@ -1,50 +1,90 @@ --- layout: page_v2 -title: Prebid Mobile Rendering Pure In-App Bidding +title: Custom or No mediation description: Integration of Prebid SDK withou primaty Ad Server sidebarType: 2 --- -# Pure In-App Bidding Integration +# Custom Bidding Integration +{:.no_toc} -## Table of Contents +You can use Prebid SDK to monetize your app with a custom ad server or even without it. Use the `Transport API` to obtain the targeting keywords for following usage with the custom ad server. Use the `Rendering API` to display the winning bid without primary ad server and its SDK. -- [Overview of Rendering API](#mobile-api) -- [Banner](#banner-api) -- [Interstitial](#interstitial-api) -- [Rewarded](#rewarded-api) +* TOC +{:toc} -[//]: # (- [Native](android-sdk-integration-pb-native.html)) +## Transport API -## Overview of Rendering API +The default ad server for Prebid's Mobile SDK is GAM. The SDK can be expanded to include support for 3rd party ad servers through the fetchDemand function. This function returns the Prebid Server bidder key/values (targeting keys), which can then be passed to the ad server of choice. -The integration and usage of the Rendering API are similar to any other Ad SDK. It sends the bid requests to the Prebid Server and renders the winning bid. +In this mode, the publisher will be responsible for the following actions: -![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png) +* Call fetchDemand with extended targetingDict callback +* Retrieve targeting keys from the extended fetchDemand function +* Convert targeting keys into the format for your ad server +* Pass converted keys to your ad server +* Render ad with Prebid Universal Creative or custom renderer + +This approach is available for the following ad formats: + +* Display Banner via `BannerAdUnit` +* Video Banner and Instream Video via `VideoAdUnit` +* Display Interstitial via `InterstitialAdUnit` +* Video Interstitial via `VideoInterstitialAdUnit` +* Rewarded Video via `RewardedVideoAdUnit` +* Native Styles via `NativeRequest` + +The basic integration steps for these ad units you can find on the page for integration using [Original API](/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.html). The difference is that you should use the `fetchDemand` function with the following signature: + +```kotlin +public void fetchDemand(OnFetchDemandResult listener) { ... } -Prebid Rendering API provides ability to integrate these ad formats: +public interface OnFetchDemandResult { + void onComplete(@NonNull BidInfo bidInfo); +} +``` -- Display Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video -- Outstream Video +Examples: -[//]: # (- [Native](android-sdk-integration-pb-native.html)) +``` kotlin +adUnit?.fetchDemand { bidInfo -> + if(bidInfo.getResultCode() == ResultCode.SUCCESS) { + val keywords = bidInfo.targetingKeywords -Rendering API provides three kinds of API classes for these ad formats: + makeAdRequest(keywords) + } +} +``` -- **Banner API** - for **Display** and **Video** Banners -- **Interstitial API** - for **Display** and **Video** Interstitials -- **Rewarded API** - for **Rewarded Video** +The `BidInfo` provides the following properties: + +* `resultCode` - the object of type `ResultCode` describing the status of the bid request. +* `targetingKeywords` - the targeting keywords of the winning bid +* `exp` - the number of seconds that may elapse between the auction and the actual impression. In this case, it indicates the approximate TTL of the bid in the Prebid Cache. Note that the actual expiration time of the bid will be less than this number due to the network and operational overhead. The Prebid SDK doesn't make any adjustments to this value. +* `nativeAdCacheId` - the local cache ID of the winning bid. Applied only to the `native` ad format. +* `events` - the map of some publically available event URLs attached to the bid. These can be used to enable Prebid Server-based analytics when the Prebid Universal Creative (PUC) is not involved in the rendering process. If the PUC is used for rendering, it will take care of hitting these events. These are the available event URLs: + * **EVENT_WIN** - this bid was chosen by the ad server as the one to display. This is the main metric for banner and native. This returns the OpenRTB `seatbid.bid.ext.prebid.events.win` field. (requires SDK v2.1.6) + * **EVENT_IMP** - the ad creative for this bid was actually displayed. This is often the main metric for video ads. This returns the OpenRTB `seatbid.bid.ext.prebid.events.imp` field. (requires SDK v2.1.6) + +Code sample to extract the events: + +``` kotlin +val win = bidInfo.events.get(BidInfo.EVENT_WIN) +val imp = bidInfo.get(BidInfo.EVENT_IMP) +``` + +## Rendering API + +The integration and usage of the Rendering API is similar to any other Ad SDK. It sends the bid requests to the Prebid Server and renders the winning bid. + +![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png) ### Banner API Integration example: - ``` kotlin // 1. Create an Ad View bannerView = BannerView(requireContext(), configId, adSize) @@ -57,23 +97,31 @@ viewContainer?.addView(bannerView) bannerView?.loadAd() ``` +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} + #### Step 1: Create Ad View +{:.no_toc} Initialize the `BannerAdView` with properties: -- `configId` - an ID of Stored Impression on the Prebid server. -- `size` - the size of the ad unit which will be used in the bid request. +* `configId` - an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server +* `size` - the size of the ad unit which will be used in the bid request. #### Step 2: Load the Ad +{:.no_toc} Call `loadAd()` and SDK will: -- make bid request to Prebid -- render the winning bid on display +* make bid request to Prebid +* render the winning bid on display #### Outstream Video +{:.no_toc} -For **Banner Video** you also need to specify the `bannerView.videoPlacementType`: +For **Banner Video** you will also need to specify the `bannerView.videoPlacementType`: ``` kotlin bannerView.videoPlacementType = PlacementType.IN_BANNER // or any other available type @@ -96,45 +144,41 @@ interstitialAdUnit?.loadAd() interstitialAdUnit?.show() ``` -The way of displaying **Video Interstitial Ad** is almost the same with two differences: +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} -- Need customize the ad unit format. -- No need to set up `minSizePercentage`. +The **default** ad format for interstitial is **DISPLAY**. In order to make a `multiformat bid request`, set the respective values into the `adUnitFormats` parameter. ``` kotlin -// 1. Create an Interstitial Ad Unit -interstitialAdUnit = InterstitialAdUnit(requireContext(), configId, AdUnitFormat.VIDEO) -interstitialAdUnit?.setInterstitialAdUnitListener(this) - -// 2. Load Ad -interstitialAdUnit?.loadAd() - -// ..... - -// 3. Show the ad -interstitialAdUnit?.show() +interstitialAdUnit = InterstitialAdUnit( + requireContext(), + configId, + EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO)) ``` - #### Step 1: Create an Ad Unit +{:.no_toc} -Initialize the `InterstitialAdUnit ` with properties: +Initialize the `InterstitialAdUnit` with properties: -- `configId` - an ID of Stored Impression on the Prebid server -- `minSizePercentage` - specifies the minimum width and height percent an ad may occupy of a device’s real estate. +* `configId` - an ID of a [Stored Impression](/prebid-server/features/pbs-storedreqs.html) on the Prebid server +* `minSizePercentage` - specifies the minimum width and height percent an ad may occupy of a device’s real estate. -Also you can assign the listener for processing ad events. +You can also assign the listener to process ad events. -> **NOTE:** the `minSizePercentage` - plays an important role in a bidding process for display ads. If provided space is not enough demand partners won't respond with the bids. +> **NOTE:** the `minSizePercentage` - plays an important role in the bidding process for display ads. If the provided space is not enough demand partners won't respond with bids. #### Step 2: Load the Ad +{:.no_toc} -Simply call the `loadAd()` method which will make a request to Prebid server. - +Call the `loadAd()` to make a bid request. #### Step 3: Show the Ad when it is ready +{:.no_toc} -Wait until the ad will be loaded and present it to the user in any suitable time. +Wait until the ad is loaded and present it to the user in any suitable time. ``` kotlin override fun onAdLoaded(interstitialAdUnit: InterstitialAdUnit) { @@ -150,34 +194,40 @@ Integration example: // 1. Create an Ad Unit rewardedAdUnit = RewardedAdUnit(requireContext(), configId) rewardedAdUnit?.setRewardedAdUnitListener(this) - -// 2. Execute ad load + +// 2. Execute the loadAd function rewardedAdUnit?.loadAd() /// ....... -// After ad is loaded you can execute `show` to trigger ad display +// After the ad is loaded you can execute `show` to trigger ad display rewardedAdUnit?.show() ``` -#### Step 1: Create Rewarded Ad Unit +{% capture warning_note %} +Pay attention that the `loadAd()` should be called on the main thread. +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} + +#### Step 1: Create a Rewarded Ad Unit +{:.no_toc} Create the `RewardedAdUnit` object with parameters: -- `adUnitId` - an ID of Stored Impression on the Prebid server. +* `adUnitId` - an ID of Stored Impression on the Prebid server. #### Step 2: Load the Ad +{:.no_toc} -Simply call the `loadAd()` method which will make a request to Prebid server. - +Call the `loadAd()` to make a bid request. #### Step 3: Show the Ad when it is ready +{:.no_toc} - -Wait until the ad will be loaded and present it to the user in any suitable time. +Wait until the ad is loaded and present it to the user in any suitable time. ``` kotlin override fun onAdLoaded(rewardedAdUnit: RewardedAdUnit) { //Ad is ready for display } -``` \ No newline at end of file +``` diff --git a/prebid-mobile/modules/rendering/android-sdk-integration.md b/prebid-mobile/modules/rendering/android-sdk-integration.md deleted file mode 100644 index 6555bfbe12..0000000000 --- a/prebid-mobile/modules/rendering/android-sdk-integration.md +++ /dev/null @@ -1,81 +0,0 @@ ---- - -layout: page_v2 -title: Integrating the Android SDK -description: Prebid Android Rendering SDK Integration -sidebarType: 2 - ---- - -# Integrating the Android SDK with your project - -## Gradle Integration - - -To add the dependency, open your project and update the app module’s build.gradle to have the following repositories and dependencies (note that rendering module is in the beta stage): - -``` -allprojects { - repositories { - ... - google() - mavenCentral() - ... - } -} - -// ... - -dependencies { - ... - implementation('org.prebid:prebid-mobile-sdk:1.13.0-beta+') - ... -} -``` - -## Updating your Android manifest - - -Before you start, you need to integrate the SDK by updating your Android manifest. - -1. Open your AndroidManifest.xml and add the following permissions and activity declarations according to the bundle you are integrating. - -``` xml - - - - - -``` - - **Notes:** - - - `ACCESS_COARSE_LOCATION` or `ACCESS_FINE_LOCATION` will - automatically allow the device to send user location for - targeting, which can help increase revenue by increasing the - value of impressions to buyers. - - `WRITE_EXTERNAL_STORAGE` is optional and only required for MRAID - 2.0 storePicture ads. - -2. For *banner and interstitial ads only*, include the following custom activities (even though you won't instantiate them directly). This is not necessary for video interstitial ads. - - Custom Activities: - -``` xml - -``` - -**NOTE** ->Interstitial ads are implemented in a dialog. For proper interstitial workflow it is recommended to use a separate Activity with `configChanges` attribute specified to avoid any issues which may occur on orientation change. -> See above example with `configChanges` attribute. - -3. Add this tag to your `` to use Google Play Services: - - ``` xml - -``` diff --git a/prebid-mobile/modules/rendering/android-sdk-parameters.md b/prebid-mobile/modules/rendering/android-sdk-parameters.md deleted file mode 100644 index c32c11e1f6..0000000000 --- a/prebid-mobile/modules/rendering/android-sdk-parameters.md +++ /dev/null @@ -1,81 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Modules -description: Prebid Mobile Rendering Modules architecture -sidebarType: 2 - ---- - -# Parameters - -The tables below list the methods and properties that the Prebid Rendering API allows to customize. -The more actual info about the user, the app, and the device you provide the more chances to win an impression. - -Please strictly follow the recommendations in the below tables and provide all ❗ **Required** and **Highly Recommended** values. - - -1. [Targeting](#targeting) -2. [PrebidRenderingSettings](#prebidrenderingsettings) - -## Targeting - -{: .table .table-bordered .table-striped } - -| **Parameter** | **Method** | Description | Required?| -| -------------------------- | ------------------------- | ------------------------------------------------------------ | -------- | -| age | `setUserAge` | Age of the user in years. For example: `35` | ❗ Highly Recommended | -| buyerid | `setBuyerId` | Buyer-specific ID for the user as mapped by the exchange for the buyer. | Optional | -| crr | `setCarrier` | Mobile carrier - Defined by the Mobile Country Code (MCC) and Mobile Network Code (MNC), using the format: -. For example: `"310-410"` | Optional | -| customdata | `setUserCustomData` | Optional feature to pass bidder data that was set in the exchange’s cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include “escaped” quotation marks. | Optional | -| dma | `setDma` | A designated market are. For US locations, indicates the end-user's Designated Market Area. For example: dma=803. | Optional | -| ext | `setUserExt` | Placeholder for exchange-specific extensions to OpenRTB. | Optional | -| gen | `setUserGender` | The gender of the user (Male, Female, Other, Unknown). For example: `Gender.FEMALE` | ❗ Highly Recommended | -| inc | `setUserAnnualIncomeInUs` | Annual income of the user in US dollars. For example: `55000`| ❗ Highly Recommended | -| ip | `setDeviceIpAddress` | The IP address of the carrier gateway. If this is not present, Prebid Rendering retrieves it from the request header. For example: `"192.168.0.1"` | ❗ Highly Recommended | -| keywords | `setUserKeywords` | Comma separated list of keywords, interests, or intent. | Optional | -| lat, lon | `setUserLatLng` | Location of the user’s home base defined by a provided longitude and latitude. It's highly recommended to provide Geo data to improve the request.| Optional | -| publisher | `setPublisherName` | Publisher name (may be aliased at the publisher’s request).| Recommended if available | -| url/storeurl | `setAppStoreMarketUrl` | The URL for the mobile application in Google Play. That field is required in the request.
        **For example:**` https://play.google.com/store/apps/details?id=com.outfit7.talkingtom`. | ❗ Required | -| xid | `setUserId` | ID of the user within the app. For example: `"24601"` | ❗ Highly Recommended | - -## How to set user parameters - -You can use `Targeting` to pass ad call request parameters. - -``` java -// Set user parameters to enrich ad request data. -// Please see Targeting for the userKeys and the APIs available. -Targeting.setUserKeywords("socialNetworking"); -Targeting.setUserAge(18); -Targeting.setUserAnnualIncomeInUs(50000); - -// Set parameters. -// Targeting.setCustomParameters(Hashtable params) -// Targeting.setParameters(Hashtable params) -// clear parameters -// Targeting.clearParameters() -// Targeting.clearParameter(String key) -``` - -## Custom key-value parameters - -You can submit values through `Targeting` for the extended (`c.xxx`) ad-call -parameters. - -{: .table .table-bordered .table-striped } - -| **Parameter** | **Method** | **Description** | -| ----------------------- | ------------------- | ------------------------------------------------------------ | -| custom
        parameter | setCustomParameter | A custom user parameter auto-prepended with c..
        You should provide the plain name of the parameter, such as xxx, which will be changed to c.xxx when sent. | -| custom
        parameters | setCustomParameters | Custom user parameters, which consist of a dictionary of name-value parameter pairs, where each param name will be automatically prepended with c.. | - -## PrebidRenderingSettings - -{: .table .table-bordered .table-striped } - -| **Field** | **Description** | **Default** | -| ----------------------- | ------------------------------------------------------------ | ----------- | -| defaultAutoRefreshDelay | Controls the initial value of `autoRefreshDelay` for all newly created BannerAdViews in seconds. | 60 | -| logLevel | Controls the type of messages of the internal logger. Options are:
        - DEBUG - this is the noisiest level.
        - ERROR
        - WARN
        - NONE | NONE | -| sendMRAIDSupportParams | If `true`, the SDK sends "`af=3,5`", indicating support for MRAID. | true | diff --git a/prebid-mobile/modules/rendering/combined-ad-experience-controls.md b/prebid-mobile/modules/rendering/combined-ad-experience-controls.md new file mode 100644 index 0000000000..87da78a7f8 --- /dev/null +++ b/prebid-mobile/modules/rendering/combined-ad-experience-controls.md @@ -0,0 +1,317 @@ +--- + +layout: page_v2 +title: Ad Experience Controls +description: Customization of ad expirience +sidebarType: 2 + +--- + +# Ad Experience Controls +{:.no_toc} + +If you use Prebid SDK to render the winning bid you can customize behaviour using the following API. + +* TOC +{:toc} + +## Rendering Controls + +The following properties enable rendering customization of Video Interstitial Ads. + +### Max Video Duration + +This setting determines the longest video duration allowed, measured in seconds. When using the Prebid SDK, this value is sent in the `imp.video.maxduration` object of the bid request. If the `` in the VAST tag received is longer than this set maximum, the SDK won't load the video file, the ad won't load, and an error message will appear. + +{% capture android %} +{: .table .table-bordered .table-striped } + |**API Object** | `InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setMaxVideoDuration(seconds)`| + |**Server Property** | `maxvideoduration` | + |**Default Value** | `3600 seconds`| +{% endcapture %} +{% capture ios %} + {: .table .table-bordered .table-striped } + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.videoParameters.maxDuration`| + |**Server Property** | `maxvideoduration` | + |**Default Value** | `3600 seconds`| +{% endcapture %} + +{% include code/mobile-sdk.html id="max-video-duration" kotlin=android swift=ios %} + +### Application Muted + +This option lets you switch the sound on or off during playback. + +{% capture android %} + {: .table .table-bordered .table-striped } + |**API Object** | `InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setIsMuted(true)`| + |**Server Property** | `ismuted` | + |**Default Value** | `false`| +{% endcapture %} +{% capture ios %} + {: .table .table-bordered .table-striped } + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.isMuted`| + |**Server Property** | `ismuted` | + |**Default Value** | `false`| +{% endcapture %} + +{% include code/mobile-sdk.html id="application-muted" kotlin=android swift=ios %} + +### Close Button Area + +This setting determines the percentage of the device screen that the close button should cover. + +{% capture android %} + {: .table .table-bordered .table-striped } + |**API Object** | `InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setCloseButtonArea(factor)`| + |**Server Property** | `closebuttonarea` | + |**Allowed Values** | `0..1`| + |**Default Size** | `70dp`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Area - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-default.jpg){:width="250px"}|![Close Button Area - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-area-custom.jpg){:width="250px"}| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.closeButtonArea`| + |**Server Property** | `closebuttonarea` | + |**Allowed Values** | `0..1`| + |**Default Value** | `0.1`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Area - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png){:width="250px"}|![Close Button Area - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-020.png){:width="250px"}| +{% endcapture %} + +{% include code/mobile-sdk.html id="close-button-area" kotlin=android swift=ios %} + +### Close Button Position + +This setting controls where the close button appears on the screen. + +{% capture android %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setCloseButtonPosition(Position.TOP_LEFT)`| + |**Server Property** | `closebuttonposition` | + |**Allowed Values** | `Position.TOP_LEFT, Position.TOP_RIGHT`| + |**Default Value** | `Position.TOP_RIGHT`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Position - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-default.jpg){:width="250px"}|![Close Button Position - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-close-button-position-custom.jpg){:width="250px"}| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.closeButtonPosition`| + |**Server Property** | `closebuttonposition` *| + |**Allowed Values** | `topLeft, topRight`| + |**Default Value** | `topRight`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Position - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png){:width="250px"}|![Close Button Position - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-possition-top-left.png){:width="250px"}| +{% endcapture %} + +{% include code/mobile-sdk.html id="close-button-position" kotlin=android swift=ios %} + +### Skip Button Area + +This setting determines the percentage of the device screen that the skip button should cover. + +{% capture android %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setSkipButtonArea(factor)`| + |**Server Property** | `skipbuttonarea` | + |**Allowed Values** | `0..1`| + |**Default Value** | `70dp`| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.skipButtonArea`| + |**Server Property** | `skipbuttonarea` | + |**Allowed Values** | `0..1`| + |**Default Value** | `0.1`| +{% endcapture %} + +{% include code/mobile-sdk.html id="skip-button-area" kotlin=android swift=ios %} + +Customization Example + +{: .table .table-bordered .table-striped } + +|**Default**|**Custom**| +|![Close Button Position - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-default.jpg){:width="250px"}|![Close Button Position - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-area-custom.jpg){:width="250px"}| + +### Skip Button Position + +This control sets the position of the skip button. + +{% capture android %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setSkipButtonPosition(Position.TOP_LEFT)`| + |**Server Property** | `skipbuttonposition` | + |**Allowed Values** | `Position.TOP_LEFT, Position.TOP_RIGHT`| + |**Default Value** | `Position.TOP_RIGHT`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Position - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-default.jpg){:width="250px"}|![Close Button Position - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-skip-button-position-custom.jpg){:width="250px"}| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit. skipButtonPosition`| + |**Server Property** | `skipbuttonposition` | + |**Allowed Values** | `topLeft, topRight`| + |**Default Value** | `topLeft`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Position - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-left.png){:width="250px"}|![Close Button Position - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-skip-button-possition-top-right.png){:width="250px"}| +{% endcapture %} + +{% include code/mobile-sdk.html id="skip-button-position" kotlin=android swift=ios %} + +### Skip Delay + +This setting determines the number of seconds after the start of playback before the skip or close button should appear. + +{% capture android %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setSkipDelay(seconds)`| + |**Server Property** | `skipdelay` | + |**Default Value** | `10 seconds`| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.skipDelay`| + |**Server Property** | `skipdelay` | + |**Default Value** | `10 seconds`| +{% endcapture %} + +{% include code/mobile-sdk.html id="skip-delay" kotlin=android swift=ios %} + +### Sound Button + +This option switches on or off the visibility of the sound/mute button for users. + +{% capture android %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedVideoAdUnit` | + |**Ad Unit Property** | `adUnit.setIsSoundButtonVisible(true)`| + |**Server Property** | *not supported*| + |**Default Value** | `false`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Custom**| + |![Close Button Area - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/android-sound-button.jpg){:width="250px"}| +{% endcapture %} + +{% capture ios %} + {: .table .table-bordered .table-striped } + + |**API Object** |`InterstitialRenderingAdUnit`, `RewardedAdUnit`,
        `MediationInterstitialAdUnit`, `MediationRewardedAdUnit` | + |**Ad Unit Property** | `adUnit.isSoundButtonVisible`| + |**Server Property** | *not supported*| + |**Default Value** | `false`| + + Customization Example + + {: .table .table-bordered .table-striped } + + |**Default**|**Custom**| + |![Close Button Area - Default](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-close-button-area-010.png){:width="250px"}|![Close Button Area - Custom](/assets/images/prebid-mobile/modules/rendering/ad-experience/ios-mute-button-visible.png){:width="250px"}| +{% endcapture %} + +{% include code/mobile-sdk.html id="sound-button" kotlin=android swift=ios %} + +### Code Example + +Here is how you can implement all the API's to customize your ad. + +{% capture android %} + + ```kotlin + adUnit = MediationInterstitialAdUnit( + activity, + configId, + EnumSet.of(AdUnitFormat.BANNER), + mediationUtils + ) + + adUnit?.setMaxVideoDuration(30) + adUnit?.setCloseButtonArea(0.1) + adUnit?.setSkipDelay(5) + adUnit?.setSkipButtonArea(0.1) + adUnit?.setSkipButtonPosition(Position.TOP_RIGHT) + adUnit?.setCloseButtonPosition(Position.TOP_LEFT) + ``` + +{% endcapture %} + +{% capture ios %} + + ```swift + interstitialController = InterstitialRenderingAdUnit(configID: prebidConfigId, + minSizePercentage: CGSize(width: 30, height: 30)) + interstitialController?.delegate = self + interstitialController?.videoParameters.maxDuration = SingleContainerInt(integerLiteral: 30) + interstitialController?.closeButtonArea = 0.1 + interstitialController?.skipDelay = 5 + interstitialController?.skipButtonArea = 0.1 + interstitialController?.skipButtonPosition = .topRight + interstitialController?.closeButtonPosition = .topRight + ``` + +{% endcapture %} + +{% include code/mobile-sdk.html id="code-example" kotlin=android swift=ios %} diff --git a/prebid-mobile/modules/rendering/ios-sdk-Integration.md b/prebid-mobile/modules/rendering/ios-sdk-Integration.md deleted file mode 100644 index 2114faa855..0000000000 --- a/prebid-mobile/modules/rendering/ios-sdk-Integration.md +++ /dev/null @@ -1,68 +0,0 @@ ---- - -layout: page_v2 -title: Integrating the Android SDK -description: Prebid Android Rendering SDK Integration -sidebarType: 2 - ---- - -# Code Integration for iOS - - - -## CocoaPods integration (BETA) - -The rendering API is introduced as a beta release. In order to integrate it you have to set the beta version explisitly: - -``` -pod 'PrebidMobile', '1.13.0-beta2' -``` - -If you need to integrate Prebid with GAM or MoPub add these pods respectively - -``` -# + Google Ad Manager (optional) -pod 'PrebidMobileGAMEventHandlers', '1.13.0-beta2' - -# + MoPub (optional) -pod 'PrebidMobileMoPubAdapters', '1.13.0-beta2' -``` - - - -## Init Prebid Rendering - -The best place for initialization is the `application:didFinishLaunchingWithOptions` method. Import the SDK first: - -``` -import PrebidMobile -``` - -Then set the predefined or costom Prebid Server **host** and provide the **Prebid Account ID**. - -``` -PrebidRenderingConfig.shared.accountID = YOUR_ACCOUNT_ID -PrebidRenderingConfig.shared.prebidServerHost = HOST -``` - - - diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-admob.md b/prebid-mobile/modules/rendering/ios-sdk-integration-admob.md new file mode 100644 index 0000000000..b61fe4517b --- /dev/null +++ b/prebid-mobile/modules/rendering/ios-sdk-integration-admob.md @@ -0,0 +1,363 @@ +--- +layout: page_v2 +title: Google Ad Manager Integration +description: Integration of Prebid Rendering module whith Google Ad Manager +sidebarType: 2 +--- + +# AdMob Integration +{:.no_toc} + +The integration of Prebid Mobile with Google AdMob assumes that the publisher has an AdMob account and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app. + +See the [Google Integration Documentation](https://developers.google.com/admob/ios/quick-start) for the AdMob integration details. + +* TOC +{:toc} + +## AdMob Integration Overview + +![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-admob.png) + +**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid. + +**Step 3** GMA SDK makes an ad request. AdMob returns the mediation chain with respective ad sources. + +**Step 4** For each prebid's ad source, the GMA SDK sequentially instantiates an adapter. + +**Step 5** The adapter verifies the targeting keywords of the winning bid and the server properties of the given ad source. If they match the adapter will render the winning bid. Otherwise, it will immediately fail with an error of "no ad" and the next ad source will instantiate the same adapter but for another set of server params. + +## Adapters Integration + +Prebid SDK is integrated into AdMob setup thru custom adapters. To integrate Prebid Adapters into your app, add the following line to your Podfile: + +```pod +pod 'PrebidMobileAdMobAdapters' +``` + +## Adapters Initialization + +{: .alert.alert-warning :} +**Warning:** The `GADMobileAds.sharedInstance().start()` should be called in the adapters bundle, otherwise, GMA SDK won't load the ads with error: `adView:didFailToReceiveAdWithError: SDK tried to perform a networking task before being initialized.` + +To avoid the error add the following line to your app right after initialization of GMA SDK: + +```swift +AdMobUtils.initializeGAD() +``` + +## Banner API + +Integration example: + +```swift +// 1. Create GADRequest and GADBannerView +gadRequest = GADRequest() + +gadBanner = GADBannerView(adSize: size) +gadBanner.delegate = self +gadBanner.rootViewController = self + +gadBanner.adUnitID = adUnitId + +// 2. Create an AdMobMediationBannerUtils +mediationDelegate = AdMobMediationBannerUtils(gadRequest: gadRequest, + bannerView: gadBanner) + +// 3. Create the MediationBannerAdUnit +prebidAdMobMediaitonAdUnit = MediationBannerAdUnit(configID: configID, + size: CGSize(width: 320, height: 50), + mediationDelegate: mediationDelegate) + +// 4. Make a bid request +prebidAdMobMediaitonAdUnit.fetchDemand { [weak self] result in + +// 5. Make an ad request to AdMob + self?.gadBanner.load(self?.gadRequest) +} +``` + +### Step 1: Create GADRequest and GADBannerView +{:.no_toc} + +This step is the same as for the original [AdMob integration](https://developers.google.com/admob/ios/banner). You don't have to make any modifications here. + +### Step 2: Create AdMobMediationBannerUtils +{:.no_toc} + +The `AdMobMediationBannerUtils` is a helper class, which performs certain utilty work for the `MediationBannerAdUnit`, such as passing the targeting keywords to the adapters and checking the visibility of the ad view. + +### Step 3: Create MediationBannerAdUnit +{:.no_toc} + +The `MediationBannerAdUnit` is part of Prebid mediation API. This class is responsible for making a bid request and providing the winning bid and targeting keywords to mediating SDKs. + +### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to a Prebid server and returns a result in a completion handler. + +### Step 5: Make an Ad Request +{:.no_toc} + +Make a regular AdMob's ad request. Everything else will be handled by Prebid adapters. + +## Interstitial API + +Integration example: + +```swift +// 1. Create GADRequest +gadRequest = GADRequest() + +// 2. Create AdMobMediationInterstitialUtils +mediationDelegate = AdMobMediationInterstitialUtils(gadRequest: self.gadRequest) + +// 3. Create MediationInterstitialAdUnit +admobAdUnit = MediationInterstitialAdUnit(configId: configID, + mediationDelegate: mediationDelegate!) + +// 4. Make a bid request +admobAdUnit?.fetchDemand(completion: { [weak self]result in + +// 5. Make an ad request to AdMob +GADInterstitialAd.load(withAdUnitID: adUnitID, request: self?.gadRequest) { [weak self] ad, error in + guard let self = self else { return } + if let error = error { + PBMLog.error(error.localizedDescription) + return + } + + // 6. Present the interstitial ad + self.interstitial = ad + self.interstitial?.fullScreenContentDelegate = self + self.interstitial?.present(fromRootViewController: self) + } +}) +``` + +The **default** ad format for interstitial is **.banner**. In order to make a `multiformat bid request`, set the respective values into the `adFormats` property. + +```swift +// Make bid request for video ad +adUnit?.adFormats = [.video] + +// Make bid request for both video amd banner ads +adUnit?.adFormats = [.video, .banner] + +// Make bid request for banner ad (default behaviour) +adUnit?.adFormats = [.banner] + +``` + +### Step 1: Create GADRequest +{:.no_toc} + +This step is the same as for the original [AdMob integration](https://developers.google.com/admob/ios/interstitial#swift). You don't have to make any modifications here. + +### Step 2: Create AdMobMediationInterstitialUtils +{:.no_toc} + +The `AdMobMediationInterstitialUtils` is a helper class, which performs certain utilty work for the `MediationInterstitialAdUnit`, such as passing the targeting keywords to adapters and checking the visibility of the ad view. + +### Step 3: Create MediationInterstitialAdUnit +{:.no_toc} + +The `MediationInterstitialAdUnit` is part of the Prebid mediation API. This class is responsible for making a bid request and providing a winning bid to the mediating SDKs. + +### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to a Prebid server and provides a result in a completion handler. + +### Step 5: Make an Ad Request +{:.no_toc} + +Make a regular AdMob's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +### Steps 6: Display an ad +{:.no_toc} + +Once you receive the ad it will be ready for display. Follow the [AdMob instructions](https://developers.google.com/admob/ios/interstitial#swift) for displaying an ad. + +## Rewarded API + +Integration example: + +```swift +// 1. Create GADRequest +let request = GADRequest() + +// 2. Create AdMobMediationInterstitialUtils +let mediationDelegate = AdMobMediationRewardedUtils(gadRequest: request) + +// 3. Create MediationInterstitialAdUnit +admobRewardedAdUnit = MediationRewardedAdUnit(configId: "12f58bc2-b664-4672-8d19-638bcc96fd5c", mediationDelegate: mediationDelegate) + +// 4. Make a bid request +admobRewardedAdUnit.fetchDemand { [weak self] result in + guard let self = self else { return } + +// 5. Make an ad request to AdMob +GADRewardedAd.load(withAdUnitID: self.admobPrebidAdUnitId, request: request) { [weak self] ad, error in + guard let self = self else { return } + if let error = error { + PBMLog.error(error.localizedDescription) + return + } + + // 6. Present the interstitial ad + self.gadRewardedAd = ad + self.gadRewardedAd?.fullScreenContentDelegate = self + DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) { + self.gadRewardedAd?.present(fromRootViewController: self, userDidEarnRewardHandler: { + print("Reward user") + }) + } + } +} +``` + +The process of displaying the rewarded ad is the same as for displaying an Interstitial Ad. + +To be notified when a user earns a reward follow the [AdMob intructions](https://developers.google.com/admob/ios/rewarded#show_the_ad). + +### Step 1: Create GADRequest +{:.no_toc} + +This step is the same as for the original [AdMob integration](https://developers.google.com/admob/ios/rewarded). You don't have to make any modifications here. + +### Step 2: Create MediationRewardedAdUnit +{:.no_toc} + +The `AdMobMediationRewardedUtils` is a helper class, which performs certain utilty work for the `MediationRewardedAdUnit`, like passing the targeting keywords to the adapters. + +### Step 3: Create MediationInterstitialAdUnit +{:.no_toc} + +The `MediationRewardedAdUnit` is part of the Prebid mediation API. This class is responsible for making a bid request and providing a winning bid and targeting keywords to the adapters. + +### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the a Prebid server and provides a result in a completion handler. + +### Step 5: Make an Ad Request +{:.no_toc} + +Make a regular AdMob's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +### Steps 6: Display an ad +{:.no_toc} + +Once the rewarded ad is received you can display it. Follow the [AdMob instructions](https://developers.google.com/admob/ios/rewarded#swift) for displaying an ad. + +## Native Ads + +{: .alert.alert-warning :} +**Warning:** If you use Native Ads you **must** integrate AdMob Adapters via the source files instead of cocoapods integration or standalone framework. The integration using framework leads to [runtime errors](https://github.com/prebid/prebid-mobile-ios/issues/516) related to the type casting. + +In order to integrate AdMob adapters just add the adapters' source files to your app project. + +Integration example: + +```swift +// 1. Create GAD Request +gadRequest = GADRequest() + +// 2. Create AdMobMediationNativeUtils +mediationDelegate = AdMobMediationNativeUtils(gadRequest: gadRequest) + +// 3. Create and configure MediationNativeAdUnit +nativeAdUnit = MediationNativeAdUnit(configId: prebidConfigId, + mediationDelegate: mediationDelegate!) + +nativeAdUnit.setContextType(ContextType.Social) +nativeAdUnit.setPlacementType(PlacementType.FeedContent) +nativeAdUnit.setContextSubType(ContextSubType.Social) + +// 4. Set up assets for bid request +nativeAdUnit.addNativeAssets(nativeAssets) + +// 5. Set up event tracker for bid request +nativeAdUnit.addEventTracker(eventTrackers) + +// 6. Make a bid request +nativeAdUnit.fetchDemand { [weak self] result in +guard let self = self else { return } + +// 7. Load AdMob Native ad +self.adLoader = GADAdLoader(adUnitID: self.adMobAdUnitId!, + rootViewController: self.rootController, + adTypes: [ .native ], + options: nil) + +self.adLoader?.delegate = self + +self.adLoader?.load(self.gadRequest) +} +``` + +### Step 1: Create GAD Request +{:.no_toc} + +Prepare the `GADRequest` object before you make a bid request. It will be needed for the Prebid mediation utils. + +### Step 2: Create AdMobMediationNativeUtils +{:.no_toc} + +The `AdMobMediationNativeUtils` is a helper class, which performs certain utilty work for `MediationNativeAdUnit`, like passing the targeting keywords to adapters and checking the visibility of the ad view. + +### Step 3: Create and configure MediationNativeAdUnit +{:.no_toc} + +The `MediationNativeAdUnit` is part of the Prebid mediation API. This class is responsible for making a bid request and providing a winning bid and targeting keywords to the adapters. For better targetting you should provide additional properties like `conteaxtType` and `placemantType`. + +### Step 4: Set up assets for bid request +{:.no_toc} + +The bid request for native ads should have the description of any expected assets. The full spec for the native template can be found in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +Example of creating the assets array: + +```swift +let image = NativeAssetImage(minimumWidth: 200, minimumHeight: 50, required: true) +image.type = ImageAsset.Main + +let icon = NativeAssetImage(minimumWidth: 20, minimumHeight: 20, required: true) +icon.type = ImageAsset.Icon + +let title = NativeAssetTitle(length: 90, required: true) + +let body = NativeAssetData(type: DataAsset.description, required: true) + +let cta = NativeAssetData(type: DataAsset.ctatext, required: true) + +let sponsored = NativeAssetData(type: DataAsset.sponsored, required: true) + +return [icon, title, image, body, cta, sponsored] +``` + +### Step 5: Set up event tracker for bid request +{:.no_toc} + +The bid request for mative ads may have a description of expected event trackers. The full spec for the Native template can be found in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +The example of creating the event trackers array: + +```swift +let eventTrackers = [ + NativeEventTracker(event: EventType.Impression, + methods: [EventTracking.Image,EventTracking.js]) +] +``` + +### Step 6: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to Prebid server and provides a result in a completion handler. + +### Step 7: Load AdMob Native ad +{:.no_toc} + +Now just load a native ad from AdMob according to the [AdMob instructions](https://developers.google.com/admob/ios/native/start). diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-gam-native.md b/prebid-mobile/modules/rendering/ios-sdk-integration-gam-native.md index c8a8a53402..1b378f87d3 100644 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-gam-native.md +++ b/prebid-mobile/modules/rendering/ios-sdk-integration-gam-native.md @@ -22,7 +22,7 @@ The general integration scenario requires these steps from publishers: 6. After receiving response from GAM - check if prebid has won and find native ad using `GAMUtils` 7. Bind the winner data from the native ad response with the layout. -``` swift +```swift func loadAd() { guard let nativeAdConfig = nativeAdConfig else { return @@ -50,7 +50,7 @@ func loadAd() { Example of handling NativeAd response (the same applies to Custom Native Ads): -``` swift +```swift func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) { unifiedAdRequestSuccessful.isEnabled = true customTemplateAd = nil @@ -92,13 +92,13 @@ func adLoader(_ adLoader: GADAdLoader, didReceive nativeAd: GADNativeAd) { } ``` -## Native Styles +## Native Styles -The Native Styles ads are integrated with Baner API. +The Native Styles ads are integrated with Baner API. Integration Example: -``` swift +```swift // 1. Create an Event Handler let eventHandler = BannerEventHandler(adUnitID: GAM_AD_UNIT_ID, validGADAdSizes: [NSValueFromGADAdSize(adSize)]) @@ -115,7 +115,7 @@ banner.nativeAdConfig = NativeAdConfiguration(testConfigWithAssets: assets) banner.loadAd() ``` -#### Step 1: Create Event Handler +### Step 1: Create Event Handler To create the event handler you should provide a GAM Ad Unit Id and the list of available sizes for this ad unit. @@ -123,16 +123,16 @@ To create the event handler you should provide a GAM Ad Unit Id and the list of **BannerView** - is a view that will display the particular ad. It should be added to the UI. To create it you should provide: -- **configID** - an ID of Stored Impression on the Prebid server -- **eventHandler** - the instance of the banner event handler +* **configID** - an ID of Stored Impression on the Prebid server +* **eventHandler** - the instance of the banner event handler Also, you should add the instance of `BannerView` to the UI. -#### Step 3: Create and provide Native Assets +### Step 3: Create and provide Native Assets To make a proper bid request publishers should provide the needed assets to the NativeAdConfiguration class. Each asset describes the UI element of the ad according to the [OpenRTB standarts](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). -``` swift +```swift let assets = [ { let title = NativeAssetTitle(length: 90) @@ -175,6 +175,6 @@ let assets = [ See the full description of NativeAdConfiguration options [here](rendering-native-ad-configuration.md). -#### Step 4: Load the Ad +### Step 4: Load the Ad -Call the `loadAd()` method in order to make bid request and render the winning bid. \ No newline at end of file +Call the `loadAd()` method in order to make bid request and render the winning bid. diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-gam.md b/prebid-mobile/modules/rendering/ios-sdk-integration-gam.md index 156ac3dc14..c667c79871 100644 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-gam.md +++ b/prebid-mobile/modules/rendering/ios-sdk-integration-gam.md @@ -1,26 +1,21 @@ --- layout: page_v2 -title: Google Ad Manager Integration +title: GAM with Prebid Rendering description: Integration of Prebid Rendering module whith Google Ad Manager sidebarType: 2 --- -# Google Ad Manager Integration +# GAM with Prebid Rendering -The integration of Prebid Rendering API with Google Ad Manager (GAM) assumes that publisher has an account on GAM and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app project. +{:.no_toc} -If you do not have GMA SDK in the app yet, refer the the [Google Integration Documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/quick-start). +The integration of Prebid Rendering API with Google Ad Manager (GAM) assumes that the publisher has an account on GAM and has already integrated the Google Mobile Ads SDK (GMA SDK) into the app project. -{: .alert.alert-warning :} -**Warning:** GMA SDK is a closed library that sometimes works in an unexpected way. The `GADMobileAds.sharedInstance().start()` should be called in all bundles where it is used. Otherwise, GMA SDK won't load the ads with error: `adView:didFailToReceiveAdWithError: SDK tried to perform a networking task before being initialized.` - -To avoid the error add the following line to your app right after initialization of GMA SDK: +If you do not have GMA SDK in the app yet, refer to the [Google Integration Documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/quick-start). -``` -GAMUtils.shared.initializeGAM() -``` +- TOC +{:toc} - ## GAM Integration Overview ![Rendering with GAM as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-GAM.png) @@ -31,35 +26,34 @@ GAMUtils.shared.initializeGAM() **Step 4** GMA SDK makes an ad request. GAM returns the winner of the waterfall. -**Step 5** Basing on the ad response Prebid GAM Event Handler decides who has won on the GAM - the Prebid bid or another ad source on GAM. +**Step 5** Based on the ad response Prebid GAM Event Handler decides who has won on GAM - the Prebid bid or another ad source on GAM. -**Step 6** The winner is displayed in the App with the respective rendering engine. The winning bid will be renderd by Prebid SDK. An other ad will be rendered by GMA SDK. The GAM Event Handler manages this process. +**Step 6** The winner is displayed in the App with the respective rendering engine. The winning bid will be renderd by Prebid SDK. Other winners will be rendered by GMA SDK. The GAM Event Handler manages this process. -Prebid Rendering API supports these ad formats: +## Integrate Event Handlers -- Display Banner -- Video Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video +Prebid SDK provides rendering integration into GAM setup thru [app events](https://developers.google.com/ad-manager/mobile-ads-sdk/ios/banner#app_events) mechanism. To integrate Prebid Event Handlers into your app, add the following line to your Podfile: -[//]: # (- Native) -[//]: # (- Native Styles) +```pod +pod 'PrebidMobileAdMobAdapters' +``` -They can be integrated using these API categories: +## Event Handlers Initialization -- [**Banner API**](#banner-api) - for *Display* and *Video* Banner -- [**Interstitial API**](#interstitial-api) - for *Display* and *Video* Interstitials -- [**Rewarded API**](#rewarded-api) - for *Rewarded Video* +{: .alert.alert-warning :} +**Warning:** GMA SDK is a closed library that sometimes works in unexpected ways. The `GADMobileAds.sharedInstance().start()` should be called in all bundles where it is used. Otherwise, GMA SDK won't load the ads with an error of: `adView:didFailToReceiveAdWithError: SDK tried to perform a networking task before being initialized.` -[//]: # (- [**Native API**](android-sdk-integration-gam-native.html) - for *Native Ads*) +To avoid this error add the following line to your app right after initialization of GMA SDK: +```swift +GAMUtils.shared.initializeGAM() +``` ## Banner API Integration example: -``` swift +```swift // 1. Create an Event Handler let eventHandler = GAMBannerEventHandler(adUnitID: GAM_AD_UNIT_ID, validGADAdSizes: [NSValueFromGADAdSize(adSize)]) @@ -76,54 +70,70 @@ addBannerToUI(banner: banner) banner.loadAd() ``` -#### Step 1: Create Event Handler +### Step 1: Create Event Handler -To create the `GAMBannerEventHandler ` you should provide: +{:.no_toc} + +To create the `GAMBannerEventHandler` you should provide: - a **GAM Ad Unit Id** - the list of available **sizes** for this ad unit. +### Step 2: Create Ad View -#### Step 2: Create Ad View +{:.no_toc} -`BannerView` - is a view that will display the particular ad. It should be added to the UI. To create it you should provide: +`BannerView` - is a view that will display the particular ad. It should be added to the UI. To create a BannerView you should provide: - `configID` - an ID of Stored Impression on the Prebid server - `eventHandler` - the instance of the banner event handler -Also, you should add the instance of `BannerView` to the UI. +You should also add the instance of `BannerView` to the UI. + +### Step 3: Load the Ad -#### Step 3: Load the Ad +{:.no_toc} Call the method `loadAd()` which will: - make a bid request to Prebid Server. - render the winning bid on display. -### Banner Video +## Banner Video + +{:.no_toc} For **Banner Video** you also need to specify the ad format: -``` swift +```swift banner.adFormat = .video ``` -And all the rest code will be the same as for integration of Display Banner. +The rest of the code will be the same as for integration of Display Banner. ### Migration from the original API +{:.no_toc} + +GAM setup: + +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create new GAM ad unit. +3. Setup new [GAM Order](/adops/mobile-rendering-gam-line-item-setup.html) for rendering approach. + +Integration: + 1. Replace the `GAMBannerView` with `BannerView` in the UI. -3. Implement the protocol `BannerViewDelegate` in the View Controller. -4. Remove usage of `GAMBannerView`, `GAMRequest`, and implementation of the `GADBannerViewDelegate`. -5. Remove original `BannerAdUnit`. +2. Implement the protocol `BannerViewDelegate` in the ViewController. +3. Remove usage of `GAMBannerView`, `GAMRequest`, and implementation of the `GADBannerViewDelegate`. +4. Remove original `BannerAdUnit`. 5. Follow the instructions to integrate [Banner API](#banner-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. You can create a new order or just replace the code of creative in the original one and continue to use it for rendering integration. ## Interstitial API Integration example: -``` swift +```swift // 1. Create Event Handler let eventHandler = GAMInterstitialEventHandler(adUnitID: GAM_AD_UNIT_ID) @@ -146,39 +156,29 @@ if interstitial.isReady { ``` -The way of displaying **Video Interstitial Ad** is almost the same with two differences: - -- Need to customize the ad format -- No need to set up `minSizePercentage` +The **default** ad format for interstitial is **.banner**. In order to make a `multiformat bid request`, set the respective values in the `adFormats` property. -``` swift - // 1. Create Event Handler -let eventHandler = GAMInterstitialEventHandler(adUnitID: GAM_AD_UNIT_ID) - -// 2. Create Interstitial Ad Unit -interstitial = InterstitialRenderingAdUnit(configID: CONFIG_ID, - eventHandler: eventHandler) - -interstitial.adFormat = .video -interstitial.delegate = self - -// 3. Load an Ad -interstitial.loadAd() +```swift +// Make bid request for video ad +adUnit?.adFormats = [.video] -/// ....... +// Make bid request for both video amd disply ads +adUnit?.adFormats = [.video, .banner] -// 4. Show Ad -if interstitial.isReady { - interstitial.show(from: self) -} +// Make bid request for banner ad (default behaviour) +adUnit?.adFormats = [.banner] ``` -#### Step 1: Create Event Handler +### Step 1: Create Event Handler + +{:.no_toc} To create an event handler you should provide a **GAM Ad Unit**. -#### Step 2: Create Interstitial Ad Unit +### Step 2: Create Interstitial Ad Unit + +{:.no_toc} Initialize the `InterstitialRenderingAdUnit` with properties: @@ -186,19 +186,22 @@ Initialize the `InterstitialRenderingAdUnit` with properties: - `minSizePercentage` - specifies the minimum width and height percent an ad may occupy of a device’s real estate. - `eventHandler` - the instance of the interstitial event handler -> **NOTE:** the `minSizePercentage` - plays an important role in a bidding process for display ads. If provided space is not enough demand partners won't respond with the bids. +> **NOTE:** the `minSizePercentage` - plays an important role in the bidding process for display ads. If provided space is not enough demand partners won't respond with bids. +### Step 3: Load the Ad -#### Step 3: Load the Ad +{:.no_toc} Call the method `loadAd()` which will make a bid request to Prebid Server. -#### Step 4: Show the Ad when it is ready +### Step 4: Show the Ad when it is ready + +{:.no_toc} -Wait for the ad to and show it to the user in any suitable time. +Wait for the Prebid Server to return an ad and show it to the user in any suitable time. -``` swift +```swift // MARK: InterstitialRenderingAdUnitDelegate func interstitialDidReceiveAd(_ interstitial: InterstitialAdUnit) { @@ -208,18 +211,27 @@ func interstitialDidReceiveAd(_ interstitial: InterstitialAdUnit) { ### Migration from the original API +{:.no_toc} + +GAM setup: + +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create a new GAM ad unit. +3. Setup the new [GAM Order](rendering-gam-line-item-setup.html) for rendering approach. + +Integration: + 1. Replace the `GAMInterstitialAd` with `InterstitialRenderingAdUnit` in the View Controller. -3. Implement the protocol `InterstitialAdUnitDelegate` in the View Controller. -4. Remove usage of `GAMInterstitialAd`, `GAMRequest`. -5. Remove original `InterstitialAdUnit`. +2. Implement the protocol `InterstitialAdUnitDelegate` in the View Controller. +3. Remove usage of `GAMInterstitialAd`, `GAMRequest`. +4. Remove original `InterstitialAdUnit`. 5. Follow the instructions to integrate [Interstitial API](#interstitial-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. **Pay Attention** that you can replace the code of creative in the original order **only for display** ads. For video interstitial you have to create a special order and remove the original one. ## Rewarded API Integration example: -``` swift +```swift // 1. Create an Event Handler let eventHandler = GAMRewardedEventHandler(adUnitID: GAM_AD_UNIT_ID) @@ -241,43 +253,50 @@ if rewardedAd.isReady { ``` -The way of displaying the Rewarded Ad is totally the same as for the Interstitial Ad. +The proccess for displaying the Rewarded Ad is the same as for the Interstitial Ad. -To be notified when user earns a reward - implement the method of `RewardedAdUnitDelegate`: +To be notified when a user earns a reward - implement the method of `RewardedAdUnitDelegate`: -``` swift +```swift - (void)rewardedAdUserDidEarnReward:(RewardedAdUnit *)rewardedAd; ``` -The actual reward object is stored in the `RewardedAdUnit`: +The reward object is stored in the `RewardedAdUnit`: -``` +```swift if let reward = rewardedAd.reward as? GADAdReward { // ... } ``` -#### Step 1: Create Event Handler +### Step 1: Create Event Handler + +{:.no_toc} To create an event handler you should provide a **GAM Ad Unit ID**. -#### Step 2: Create Rewarded Ad Unit +### Step 2: Create Rewarded Ad Unit + +{:.no_toc} Create the `RewardedAdUnit` object with parameters: - `configID` - an ID of Stored Impression on the Prebid server - `eventHandler` - the instance of rewarded event handler -#### Step 3: Load the Ad +### Step 3: Load the Ad + +{:.no_toc} Call the `loadAd()` method which will make a bid request to Prebid server. -#### Step 4: Show the Ad when it is ready +### Step 4: Show the Ad when it is ready -Wait for the ad to load and show it to the user in any suitable time. +{:.no_toc} +Wait for the ad to load and display it to the user in any suitable time. -``` swift +```swift // MARK: RewardedAdUnitDelegate func rewardedAdDidReceiveAd(_ rewardedAd: RewardedAdUnit) { @@ -287,9 +306,18 @@ func rewardedAdDidReceiveAd(_ rewardedAd: RewardedAdUnit) { ### Migration from the original API +{:.no_toc} + +GAM setup: + +1. Leave the original order and ad units as is. They are not relevant for the rendering approach but they will serve ads for released applications. +2. Create a new GAM ad unit. +3. Setup the new [GAM Order](rendering-gam-line-item-setup.html) for rendering approach. + +Integration: + 1. Replace the `GADRewardedAd` with `RewardedAdUnit` in the View Controller. -3. Implement the protocol `RewardedAdUnitDelegate` in the View Controller. -4. Remove usage of `GAMRequest`. -5. Remove original `RewardedVideoAdUnit`. +2. Implement the protocol `RewardedAdUnitDelegate` in the View Controller. +3. Remove usage of `GAMRequest`. +4. Remove original `RewardedVideoAdUnit`. 5. Follow the instructions to integrate [Rewarded API](#rewarded-api). -6. Setup the [GAM Order](rendering-gam-line-item-setup.html) for rendering. **Pay Attention** that you have to create a new special order for rewarded video ad and remove the original one. diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-max.md b/prebid-mobile/modules/rendering/ios-sdk-integration-max.md new file mode 100644 index 0000000000..db1974d534 --- /dev/null +++ b/prebid-mobile/modules/rendering/ios-sdk-integration-max.md @@ -0,0 +1,320 @@ +--- +layout: page_v2 +title: AppLovin MAX Integration +description: Integration of Prebid Rendering module whith AppLovin MAX +sidebarType: 2 +--- + +# AppLovin MAX Integration +{:.no_toc} + +The integration of Prebid Mobile with AppLovin MAX assumes that publisher has a MAX account and has integrated the AppLovin MAX SDK into the app. + +See the [AppLovin MAX Documentation](https://dash.applovin.com/documentation/mediation/ios/getting-started/integration) for the MAX integration details. + +* TOC +{:toc} + +## MAX Integration Overview + +![Rendering with AppLovin MAX as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/prebid-in-app-bidding-overview-max.png) + +**Steps 1-2** Prebid SDK makes a bid request. Prebid Server runs an auction and returns the winning bid. + +**Step 3** MAX SDK makes an ad request. MAX returns the waterfall with respective placements. + +**Step 4** For each Prebid placement, the MAX SDK sequentially instantiates an adapter. + +**Step 5** The adapter verifies the targeting keywords of the winning bid and the custom properties of the given placement. If they match the adapter will render the winning bid. Otherwise, the adpater will immediately fail with a "no ad" error and the next placement will instantiate the same adapter but for another custom properties. + +## Integrate Prebid Adapters + +Prebid SDK is integrated into AppLovin MAX setup thru custom adapters. To integrate Prebid adapters into your app add the following line to your Podfile: + +``` +pod 'PrebidMobileMAXAdapters' +``` + +## Banner API + +Integration example: + +```swift +// 1. Create MAAdView +adBannerView = MAAdView(adUnitIdentifier: maxAdUnitId) +adBannerView?.delegate = self + +// 2. Create MAXMediationBannerUtils +mediationDelegate = MAXMediationBannerUtils(adView: adBannerView!) + +// 3. Create MediationBannerAdUnit +adUnit = MediationBannerAdUnit(configID: prebidConfigId, + size: adUnitSize, + mediationDelegate: mediationDelegate!) + +// 4. Make a bid request +adUnit?.fetchDemand { [weak self] result in + + // 5. Make an ad request to MAX + self?.adBannerView.loadAd() +} +``` + +#### Step 1: Create MAAdView +{:.no_toc} + +This step is the same as for the original [MAX integration](https://dash.applovin.com/documentation/mediation/ios/getting-started/banners#loading-a-banner). You don't have to make any modifications here. + + +#### Step 2: Create MAXMediationBannerUtils +{:.no_toc} + +The `MAXMediationBannerUtils ` is a helper class, which performs certain utilty work for the `MediationBannerAdUnit`, like passing the targeting keywords to the adapters and checking the visibility of the ad view. + +#### Step 3: Create MediationBannerAdUnit +{:.no_toc} + +The `MediationBannerAdUnit` is a part of the Prebid Mediation API. This class is responsible for making bid request and providing the winning bid and targeting keywords to mediating SDKs. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to Prebid Server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Make a regular MAX's ad request. Everything else will be handled by prebid adapters. + +## Interstitial API + +Integration example: + +```swift +// 1. Create MAInterstitialAd +interstitial = MAInterstitialAd(adUnitIdentifier: maxAdUnitId) +interstitial.delegate = self + +// 2. Create MAXMediationInterstitialUtils +mediationDelegate = MAXMediationInterstitialUtils(interstitialAd: interstitial!) + +// 3. Create MediationInterstitialAdUnit +adUnit = MediationInterstitialAdUnit(configId: prebidConfigId, + minSizePercentage: CGSize(width: 30, height: 30), + mediationDelegate: mediationDelegate!) + +// 4. Make a bid request +adUnit?.fetchDemand { [weak self] result in + guard let self = self else { return } + + guard result == .prebidDemandFetchSuccess else { + self.fetchDemandFailedButton.isEnabled = true + return + } + + // 5. Make an ad request to MAX + self.interstitial?.load() +}) +``` + +The **default** ad format for interstitial is **.banner**. In order to make a `multiformat bid request` set the respective values in the `adFormats` property. + +```swift +// Make bid request for video ad +adUnit?.adFormats = [.video] + +// Make bid request for both video amd banner ads +adUnit?.adFormats = [.video, .banner] + +// Make bid request for banner ad (default behaviour) +adUnit?.adFormats = [.banner] + +``` + +#### Step 1: Create MAInterstitialAd +{:.no_toc} + +This step is the same as for the original [MAX integration](https://dash.applovin.com/documentation/mediation/ios/getting-started/interstitials). You don't have to make any modifications here. + + +#### Step 2: Create MAXMediationInterstitialUtils +{:.no_toc} + +The `MAXMediationInterstitialUtils` is a helper class, which performs certain utilty work for the `MediationInterstitialAdUnit `, like passing the targeting keywords to the adapters and checking the visibility of the ad view. + +#### Step 3: Create MediationInterstitialAdUnit +{:.no_toc} + +The `MediationInterstitialAdUnit` is a part of the Prebid Mediation API. This class is responsible for making a bid request and providing a winning bid to the mediating SDKs. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to Prebid Server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Now you should make a regular MAX's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +#### Steps 6: Display an ad +{:.no_toc} + +Once you receive the ad it will be ready for display. Follow the [MAX instructions](https://dash.applovin.com/documentation/mediation/ios/getting-started/interstitials#showing-an-interstitial-ad) for displaying an ad. + +## Rewarded API + +Integration example: + +```swift +// 1. Get an instance of MARewardedAd +rewarded = MARewardedAd.shared(withAdUnitIdentifier: maxAdUnitId) +rewarded.delegate = self + +// 2. Create MAXMediationRewardedUtils +mediationDelegate = MAXMediationRewardedUtils(rewardedAd: rewarded!) + +// 3. Create MediationRewardedAdUnit +adUnit = MediationRewardedAdUnit(configId: prebidConfigId, mediationDelegate: mediationDelegate!) + +// 4. Make a bid request +adUnit?.fetchDemand { [weak self] result in + guard let self = self else { return } + +// 5. Make an ad request to MAX +self.rewarded?.load() +} +``` + +The process for displaying the rewarded ad is the same as for displaying the Interstitial Ad. + +To be notified when a user earns a reward follow the [MAX intructions](https://dash.applovin.com/documentation/mediation/ios/getting-started/rewarded-ads#loading-a-rewarded-ad). + +#### Step 1: Get an instance of MARewardedAd +{:.no_toc} + +This step is the same as for the original [MAX integration](https://dash.applovin.com/documentation/mediation/ios/getting-started/rewarded-ads). You don't have to make any modifications here. + + +#### Step 2: Create MAXMediationRewardedUtils +{:.no_toc} + +The `MAXMediationRewardedUtils` is a helper class, which performs certain utilty work for the `MediationRewardedAdUnit`, like passing the targeting keywords to the adapters. + +#### Step 3: Create MediationRewardedAdUnit +{:.no_toc} + +The `MediationRewardedAdUnit` is a part of the Prebid Mediation API. This class is responsible for making a bid request and providing a winning bid and targeting keywords to the adapters. + +#### Step 4: Make bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server and provides a result in a completion handler. + +#### Step 5: Make an Ad Reuest +{:.no_toc} + +Make a regular MAX's ad request. Everything else will be handled by GMA SDK and prebid adapters. + +#### Steps 6: Display an ad +{:.no_toc} + +Once the rewarded ad is received you can display it. Follow the [MAX instructions](https://dash.applovin.com/documentation/mediation/ios/getting-started/rewarded-ads#showing-a-rewarded-ad) for the details. + +## Native Ads + +Integration example: + +```swift +// 1. Create MANativeAdLoader +nativeAdLoader = MANativeAdLoader(adUnitIdentifier: maxAdUnitId) +nativeAdLoader?.nativeAdDelegate = self + +// 2. Create MAXMediationNativeUtils +mediationDelegate = MAXMediationNativeUtils(nativeAdLoader: nativeAdLoader!) + +// 3. Create and configure MediationNativeAdUnit +nativeAdUnit = MediationNativeAdUnit(configId: prebidConfigId, + mediationDelegate: mediationDelegate!) + +nativeAdUnit.setContextType(ContextType.Social) +nativeAdUnit.setPlacementType(PlacementType.FeedContent) +nativeAdUnit.setContextSubType(ContextSubType.Social) + +// 4. Set up assets for bid request +nativeAdUnit.addNativeAssets(nativeAssets) + +// 5. Set up event tracker for bid request +nativeAdUnit.addEventTracker(eventTrackers) + +// 6. Make a bid request +nativeAdUnit.fetchDemand { [weak self] result in + + // 7. Make an ad request to MAX + self?.nativeAdLoader?.loadAd(into: self?.createNativeAdView()) +} +``` + +#### Step 1: Create MANativeAdLoader +{:.no_toc} + +Prepare the `MANativeAdLoader` object before you make a bid request. It will be needed for prebid mediation utils. + +#### Step 2: Create MAXMediationNativeUtils +{:.no_toc} + +The `MAXMediationNativeUtils` is a helper class, which performs certain utilty work for `MediationNativeAdUnit`, like passing the targeting keywords to adapters and checking the visibility of the ad view. + +#### Step 3: Create and configure MediationNativeAdUnit +{:.no_toc} + +The `MediationNativeAdUnit` is a part of the Prebid Mediation API. This class is responsible for making a bid request and providing a winning bid and targeting keywords to the adapters. Fot the better targetting you should provide additional properties like `conteaxtType` and `placemantType`. + +#### Step 4: Set up assets for bid request +{:.no_toc} + +The bid request for native ads should have the description of expected assets. The full spec for the native template can be found in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +The example of creating the assets array: + +``` +let image = NativeAssetImage(minimumWidth: 200, minimumHeight: 50, required: true) +image.type = ImageAsset.Main + +let icon = NativeAssetImage(minimumWidth: 20, minimumHeight: 20, required: true) +icon.type = ImageAsset.Icon + +let title = NativeAssetTitle(length: 90, required: true) + +let body = NativeAssetData(type: DataAsset.description, required: true) + +let cta = NativeAssetData(type: DataAsset.ctatext, required: true) + +let sponsored = NativeAssetData(type: DataAsset.sponsored, required: true) + +return [icon, title, image, body, cta, sponsored] +``` + +#### Step 5: Set up event tracker for bid request +{:.no_toc} + +The bid request for mative ads may have a descrition of expected event trackers. The full spec for the Native template can be found in the [Native Ad Specification from IAB](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). + +The example of creating the event trackers array: + +``` +let eventTrackers = [ + NativeEventTracker(event: EventType.Impression, + methods: [EventTracking.Image,EventTracking.js]) +] +``` + +#### Step 6: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to Prebid Server and provides a result in a completion handler. + +#### Step 7: Load Native ad +{:.no_toc} + +Load a native ad from MAX according to the [MAX instructions](https://dash.applovin.com/documentation/mediation/ios/getting-started/native-manual#load-the-native-ad). diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-mopub-native.md b/prebid-mobile/modules/rendering/ios-sdk-integration-mopub-native.md deleted file mode 100644 index 88f8ca022c..0000000000 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-mopub-native.md +++ /dev/null @@ -1,184 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Modules -description: Prebid Mobile Rendering Modules architecture -sidebarType: 2 - ---- - -# MoPub: Native Ads Integration - -## Native Ads - -There are two ways to integrate Native ads with MoPub: - - - using custom native ad renderer from MoPub adapters - - bind the UI components with data from the winning bid manualy in the app - -### Antive Ad Renderer - -The integration with native ad renere is the same as wi any other adpater. See the [MoPub docs](https://developers.mopub.com/publishers/mediation/integrate-android/#set-up-ad-renderers-for-native-ads) for the details. - -### Manual binding - -Integration Example: - -```swift - -func loadAd() { - guard let nativeAdConfig = nativeAdConfig, let adRenderingViewClass = adRenderingViewClass else { - return - } - - adUnit = MoPubNativeAdUnit(configID: prebidConfigId, nativeAdConfiguration: nativeAdConfig) - - let targeting = MPNativeAdRequestTargeting() - - adUnit?.fetchDemand(with: targeting!) { [weak self] result in - guard let self = self else { - return - } - - let settings = MPStaticNativeAdRendererSettings(); - settings.renderingViewClass = adRenderingViewClass - let prebidConfig = PrebidMoPubNativeAdRenderer.rendererConfiguration(with: settings); - let mopubConfig = MPStaticNativeAdRenderer.rendererConfiguration(with: settings); - - PrebidMoPubAdaptersUtils.shared.prepareAdObject(targeting!) - - let adRequest = MPNativeAdRequest.init(adUnitIdentifier: self.moPubAdUnitId, rendererConfigurations: [prebidConfig, mopubConfig!]) - adRequest?.targeting = targeting - - adRequest?.start { [weak self] request, response , error in - guard let self = self else { - return - } - - guard error == nil else { - return - } - - guard let moPubNativeAd = response else { - return - } - - let nativeAdDetectionListener = NativeAdDetectionListener { [weak self] nativeAd in - guard let self = self else { - return - } - self.setupPrebidNativeAd(nativeAd) - } onPrimaryAdWin: { [weak self] in - guard let self = self else { - return - } - self.setupMoPubNativeAd(moPubNativeAd) - } onNativeAdInvalid: { [weak self] error in - self?.nativeAdInvalidButton.isEnabled = true - } - - PrebidMoPubAdaptersUtils.shared.find(nativeAd: moPubNativeAd, - nativeAdDetectionListener: nativeAdDetectionListener) - } - } -} - -``` - -## Native Styles - -The Native Styles ads are integrated with Baner API. - -Integration Example: - -``` swift -// 1. Create a MoPub AdView -banner = MPAdView(adUnitId: MOPUB_AD_UNIT_ID) -banner.delegate = self - -// 2. Create an Prebid Ad Unit -adUnit = MoPubBannerAdUnit(configID: CONFIG_ID, size: adSize) - -// 3. Provide NativeAdConfiguration -adUnit.nativeAdConfig = NativeAdConfiguration(testConfigWithAssets: assets) - -// 4. Run a Header Bidding auction on Prebid -adUnit.fetchDemand(with: banner!) { [weak self] result in - -// 5. Load an Ad -self?.banner.loadAd() -} -``` - -#### Step 1: Create Ad View - -You have to create and place MoPub's Ad View into the app page. - - -#### Step 2: Create Ad Unit - -Create the **MoPubBannerAdUnit** object with parameters: - -- **configID** - an ID of Stored Impression on the Prebid server -- **size** - the size of the ad unit which will be used in the bid request. - -#### Step 3: Create and provide Native Assets - -To make a proper bid request publishers should provide the needed assets to the NativeAdConfiguration class. Each asset describes the UI element of the ad according to the [OpenRTB standarts](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). - -``` swift -let assets = [ - { - let title = NativeAssetTitle(length: 90) - title.required = true - return title - }(), - { - let icon = NativeAssetImage() - icon.widthMin = 50 - icon.heightMin = 50 - icon.required = true - icon.imageType = NSNumber(value: PBMImageAssetType.icon.rawValue) - return icon - }(), - { - let image = NativeAssetImage() - image.widthMin = 150 - image.heightMin = 50 - image.required = true - image.imageType = NSNumber(value: PBMImageAssetType.main.rawValue) - return image - }(), - { - let desc = NativeAssetData(dataType: .desc) - desc.required = true - return desc - }(), - { - let cta = NativeAssetData(dataType: .ctaText) - cta.required = true - return cta - }(), - { - let sponsored = NativeAssetData(dataType: .sponsored) - sponsored.required = true - return sponsored - }(), -] -``` - -See the full description of NativeAdConfiguration options [here](rendering-native-ad-configuration.md). - -### Step 4: Fetch Demand - -To run an auction on Prebid run the `fetchDemand()` method which performs several actions: - -- Makes a bid request to Prebid -- Sets up the targeting keywords to the MoPub's ad unit -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -### Step 5: Load the Ad - -When the bid request has completed, the responsibility of making the Ad Request is passed to the publisher. That is why you have to invoke `loadAd()` on the MoPub's Ad View explicitly in the completion handler of `fetchDemand()`. - diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-mopub.md b/prebid-mobile/modules/rendering/ios-sdk-integration-mopub.md deleted file mode 100644 index c35499b22f..0000000000 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-mopub.md +++ /dev/null @@ -1,272 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Modules -description: Prebid Mobile Rendering Modules architecture -sidebarType: 2 - ---- - -# MoPub Integration - -The integration of Prebid Rendering API with MoPub assumes that publisher has an account on MoPub and has already integrated the MoPub SDK into the app. - -If you do not have MoPub SDK in the app yet, refer the [MoPub's Documentation](https://github.com/mopub/mopub-ios-sdk). - -{% capture warning_note %} -MoPub Adapters for the Prebid SDK are compatible with **MoPub 5.16** and above. The ads won't be shown with earlier versions of MoPub SDK. -{% endcapture %} -{% include /alerts/alert_important.html content=warning_note %} - -## MoPub Integration Overview - -The integration of Prebid Rendering API into MoPub monetization flow is based on MoPub's Mediation feature. - -![Rendering with MoPub as the Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-MoPub.png) - -**Steps 1-2** Prebid SDK makes a bid request. Prebid server runs an auction and returns the winning bid to the SDK. - -**Step 3** Prebid SDK via MoPubAdapters framework sets up targeting keywords into the MoPub's ad unit. - -**Step 4** MoPub SDK makes an ad request. MoPub adds the prebid's line item into the mediation chain. - -**Step 5** If Prebid's creative win the waterfall then the MoPub SDK will instantiate respective Prebid Adapter which will render the winning bid. For more details about Mediation and Adapters read the [MoPub's Documentation](https://developers.mopub.com/networks/integrate/mopub-network-mediation-guidelines/). - -**Step 6** The winner is displayed in the app with the respective rendering engine. - -Prebid **Mediation API** supports these ad kinds: - -- Display Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video - -[//]: # (- Native) -[//]: # (- Native Styles) - -They can be integrated using these API categories. - -- [**Banner API**](#banner-api) - for *Display Banner* -- [**Interstitial API**](#interstitial-api) - for *Display* and *Video* Interstitials -- [**Rewarded API**](#rewarded-api) - for *Rewarded Video* - -[//]: # (- [**Native API**](ios-sdk-integration-mopub-native.html) - for *Native* and *Native Styles* ads) - -## Banner API - -Integration example: - -``` swift -// 1. Create an AdView -banner = MPAdView(adUnitId: MOPUB_AD_UNIT_ID) -banner.delegate = self - -// 2. Create an In-App Bidding Ad Unit -adUnit = MediationBannerAdUnit( configID: CONFIG_ID, - size: adSize, - mediationDelegate: MoPubMediationDelegate()) - -// 3. Run an Header Bidding auction on Prebid -adUnit.fetchDemand(with: banner!) { [weak self] result in - - // 4. Load an Ad - self?.banner.loadAd() -} -``` - -#### Step 1: Create Ad View - -Follow the [MoPub Instructions](https://developers.mopub.com/publishers/ios/banner/) for Banner integration. - -#### Step 2: Create Ad Unit - -Create the `MediationBannerAdUnit` object with parameters: - -- `configID` - an ID of Stored Impression on the Prebid server -- `size` - the size of the ad unit which will be used in the bid request -- `mediationDelegate` - the object from the MoPubAdapters framework responsible for managing MoPub's ad objects. - -#### Step 3: Fetch Demand - -Call the method `fetchDemand()` which performs several actions: - -- Makes a bid request to Prebid Server -- Sets up the targeting keywords to the MoPub's ad unit using provided `mediationDelegate` -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -#### Step 4: Load the Ad - -When the bid request is completed, the responsibility of making the Ad Request is passed to the publisher. You have to invoke `loadAd()` on the MoPub's Ad View explicitly in the completion handler of the `fetchDemand()`. - -#### Step 5: Rendering - -If the Prebid bid wins on MoPub it will be rendered by `PrebidBannerAdapter`. You shouldn't do anything for this. Just make sure that your order has been set up correctly and Prebid MoPub adapter is added to the project. - -### Migration from the original API - -1. Replace the `BannerAdUnit` with `MediationBannerAdUnit`. -5. Follow the instructions to integrate [Banner API](#banner-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. - -## Interstitial API - -Integration example: - -``` swift -// 1. Create an MoPub's Interstitial Controller -interstitialController = MPInterstitialAdController.init(forAdUnitId: MOPUB_AD_UNIT_ID) -interstitialController.delegate = self - -// 2. Create an In-App Bidding Interstitial Ad Unit -interstitialAdUnit = MediationInterstitialAdUnit(configID: CONFIG_ID, - minSizePercentage: CGSize(width: 30, height: 30), - mediationDelegte: MoPubMediationDelegate() ) - -// 3. Run an Header Bidding auction on Prebid -interstitialAdUnit.fetchDemand(with: interstitialController!) { [weak self] result in - - // 4. Load an Ad - self?.interstitialController.loadAd() -} - -// ..... - -// 5. Show the ad -if interstitialController.ready { - interstitialController.show(from: self) -} -``` - -The way of displaying **Video Interstitial Ad** is almost the same with two differences: - -- Need customize the ad unit kind -- No need to set up `minSizePercentage` - -``` swift -// 1. Create an MoPub's Interstitial Controller -interstitialController = MPInterstitialAdController.init(forAdUnitId: MOPUB_AD_UNIT_ID) -interstitialController.delegate = self - -// 2. Create an In-App Bidding Interstitial Ad Unit -interstitialAdUnit = MediationInterstitialAdUnit(configID: CONFIG_ID, - minSizePercentage: CGSize(width: 30, height: 30), - mediationDelegate: MoPubMediationDelegate()) -interstitialAdUnit.adFormat = .video - -// 3. Run an Header Bidding auction on Prebid -interstitialAdUnit.fetchDemand(with: interstitialController!) { [weak self] result in - - // 4. Load an Ad - self?.interstitialController.loadAd() -} -// ..... - -// 5. Show the ad -if interstitialController.ready { - interstitialController?.show(from: self) -} -``` - -#### Step 1: Create Ad View - -Follow the [MoPub Instructions](https://developers.mopub.com/publishers/ios/interstitial/) and intgrate Interstital ad unit. - -#### Step 2: Create Ad Unit - -Create the `MediationInterstitialAdUnit` object with parameters: - -- `configID` - an ID of Stored Impression on the Prebid server -- `mediationDelegate` - the object from the MoPubAdapters framework responsible for managing MoPub's ad objects. - -#### Step 3: Fetch Demand - -Run the `fetchDemand()` method which performs several actions: - -- Makes a bid request to Prebid -- Sets up the targeting keywords to the MoPub's ad unit -- Passes the winning bid to the MoPub's ad unit -- Returns the result of bid request for future processing - -#### Step 4: Load the Ad - -When the bid request is completed, the responsibility of making the Ad Request is passed to the publisher. You have to invoke `loadAd()` on the MoPub's Ad View explicitly in the completion handler of the `fetchDemand()`. - -#### Step 5: Rendering - -If the Prebid bid wins on MoPub it will be rendered by `MoPubInterstitialAdapter`. You shouldn't do anything for this. Just make sure that your order has been set up correctly and an adapter is added to the project - -Pay attention that due to the expiration, the ad could become invalid with time. So it is always useful to check the availability with `interstitialController?.isReady` before displaying it. - -### Migration from the original API - -1. Replace the `InterstitialAdUnit` with `MediationInterstitialAdUnit`. -5. Follow the instructions to integrate [Interstitial API](#interstitial-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. - -## Rewarded API - -Integration example: - -``` swift -// 1. Create an In-App Bidding Interstitial Ad Unit -rewardedAdUnit = MediationRewardedAdUnit(configID: CONFIG_ID) - -// 2. Run an Header Bidding auction on Prebid -let bidInfoWrapper = MediationBidInfoWrapper() -rewardedAdUnit.fetchDemand(with: bidInfoWrapper) { [weak self] result in - guard let self = self else { - return - } - - // 3. Load an Ad - MPRewardedVideo.setDelegate(self, forAdUnitId: self.MOPUB_AD_UNIT_ID) - MPRewardedVideo.loadAd(withAdUnitID: self.MOPUB_AD_UNIT_ID, - keywords: bidInfoWrapper.keywords as String?, - userDataKeywords: nil, - customerId: "testCustomerId", - mediationSettings: [], - localExtras: bidInfoWrapper.localExtras) -} - -/// ....... - -// 4. Try to Display an Ad -if MPRewardedVideo.hasAdAvailable(forAdUnitID: MOPUB_AD_UNIT_ID) { - let rewards = MPRewardedVideo.availableRewards(forAdUnitID: MOPUB_AD_UNIT_ID) - guard let reward = rewards?.first as? MPRewardedVideoReward else { - return - } - - // 5. Present Ad - MPRewardedVideo.presentAd(forAdUnitID: MOPUB_AD_UNIT_ID, from: self, with: reward, customData: nil) -} -``` - -#### Step 1: Create an Rewarded Ad Unit - -Create the `MediationRewardedAdUnit` object with parameter: - -- `configID` - an ID of Stored Impression on the Prebid server - -#### Step 2: Fetch Demand - -Call the `fetchDemand()` method which does several things: - -- Makes a bid request to Prebid Server -- Sets up the targeting keywords to auxiliary class `MediationBidInfoWrapper` -- Returns the result of bid request for the future processing - -#### Step 3: Load the Ad - -When the bid request is completed, the responsibility of making the Ad Request is passed to the publisher. You have to invoke `loadAd()` on the MoPub's Ad View explicitly in the completion handler of the `fetchDemand()`. - -#### Step 5: Present the Rewarded Ad - -If the Prebid bid wins on MoPub it will be rendered by `MoPubRewardedVideoAdapter`. You shouldn't do anything for this. Just make sure that your order has been set up correctly and an adapter is added to the project - -### Migration from the original API - -1. Replace the `RewardedVideoAdUnit` with `MediationRewardedAdUnit`. -5. Follow the instructions to integrate [Rewarded Video API](#rewarded-api). -6. Setup the [MoPub Order](rendering-mopub-line-item-setup.html) for rendering. You should create a new order with **Network Line Items** instead of the original one. \ No newline at end of file diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-pb-native.md b/prebid-mobile/modules/rendering/ios-sdk-integration-pb-native.md deleted file mode 100644 index 1e21555af7..0000000000 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-pb-native.md +++ /dev/null @@ -1,174 +0,0 @@ ---- - -layout: page_v2 -title: Native Ads Integration -description: Integration of Prebid SDK without Primary Ad Server SDK -sidebarType: 2 - ---- - -# Native Ads Integration - -## Unified Native Ads - -The general integration scenario requires these steps from publishers: - -1. Prepare the ad layout. -2. Create Native Ad Unit. -3. Configure the Native Ad unit using [NativeAdConfiguration](rendering-native-ad-configuration.html). - * Provide the list of [Native Assets](rendering-native-guidelines.html#components) representing the ad's structure. - * Tune other general properties of the ad. -4. Make a bid request. -5. Extract NativeAd using `NativeUtils.findNativeAd` -7. Bind the data from the native ad with the layout. - - -``` swift -func loadAd() { - guard let nativeAdConfig = nativeAdConfig else { - return - } - adUnit = NativeAdUnit(configID: prebidConfigId, nativeAdConfiguration: nativeAdConfig) - - adUnit?.fetchDemand { [weak self] demandResponseInfo in - guard let self = self, - demandResponseInfo.fetchDemandResult == .ok else { - return - } - - demandResponseInfo.getNativeAd { [weak self] nativeAd in - guard let self = self, - let nativeAd = nativeAd else { - return - } - - self?.renderNativeAd(nativeAd) - - self.theNativeAd = nativeAd // Note: RETAIN! or the tracking will not occur! - nativeAd.trackingDelegate = self - nativeAd.uiDelegate = self - - if let _ = nativeAd.videoAd?.mediaData { - self.nativeAdViewBox?.mediaViewDelegate = self - self.setupMediaPlaybackTrackers(isVisible: true) - } - } - } -} -``` - -## Native Styles - -[See Native Ads Guidelines page](rendering-native-guidelines.html) for more details about SDK integration and supported ad types. - -To display an ad using Native Styles you'll need to implement these easy steps: - -``` swift -// 1. Create an Ad View -let banner = BannerView(configId: CONFIG_ID, - adSize: adSize) - -banner.delegate = self - -// 2. Set the Native Ad Configurations -let nativeAdConfig = NativeAdConfiguration(testConfigWithAssets: assets) -nativeAdConfig.nativeStylesCreative = nativeStylesCreative - -banner.nativeStylesCreative = nativeAdConfig - -// 3. Load an Ad -banner.loadAd() -``` - -#### Step 1: Create Ad View - -In the Pure In-App Bidding scenario you just need to initialize the Banner Ad View using correct properties: - -- **configID** - an ID of Stored Impression on the Apollo server. -- **size** - the size of the ad unit which will be used in the bid request. - - -{% capture warning_note %} -You should add HTML and CSS to define your native ad template with universal creative and provide it via the nativeStylesCreative property of NativeAdConfiguration. -{% endcapture %} -{% include /alerts/alert_important.html content=warning_note %} - -#### Step 2: Create and provide Native Assets - -To make a proper bid request publishers should provide the needed assets to the NativeAdConfiguration class. Each asset describes the UI element of the ad according to the [OpenRTB standarts](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf). - -``` swift -let assets = [ - { - let title = NativeAssetTitle(length: 90) - title.required = true - return title - }(), - { - let icon = NativeAssetImage() - icon.widthMin = 50 - icon.heightMin = 50 - icon.required = true - icon.imageType = NSNumber(value: ImageAssetType.icon.rawValue) - return icon - }(), - { - let image = NativeAssetImage() - image.widthMin = 150 - image.heightMin = 50 - image.required = true - image.imageType = NSNumber(value: ImageAssetType.main.rawValue) - return image - }(), - { - let desc = NativeAssetData(dataType: .desc) - desc.required = true - return desc - }(), - { - let cta = NativeAssetData(dataType: .ctaText) - cta.required = true - return cta - }(), - { - let sponsored = NativeAssetData(dataType: .sponsored) - sponsored.required = true - return sponsored - }(), -] -``` - -Native Styles creative example: - -``` html - - - -``` - - -See the full description of NativeAdConfiguration options [here](rendering-native-ad-configuration.html). - -#### Step 3: Load the Ad - -Call `loadAd()` and SDK will: - -- make a bid request to Prebid server -- render the winning bid on display - - diff --git a/prebid-mobile/modules/rendering/ios-sdk-integration-pb.md b/prebid-mobile/modules/rendering/ios-sdk-integration-pb.md index f5cf98148a..16ce40ef90 100644 --- a/prebid-mobile/modules/rendering/ios-sdk-integration-pb.md +++ b/prebid-mobile/modules/rendering/ios-sdk-integration-pb.md @@ -1,44 +1,83 @@ --- layout: page_v2 -title: Pure In-App Bidding Integrations +title: Custom or No mediation description: Integration of Prebid SDK without Primary Ad Server SDK sidebarType: 2 --- -# Pure In-App Bidding Integration +# Custom Bidding Integration +{:.no_toc} -## Table of Contents +You can use Prebid SDK to monetize your app with a custom ad server or even without it. Use the `Transport API` to obtain the targeting keywords for following usage with the custom ad server. Use the `Rendering API` to display the winning bid without primary ad server and its SDK. -- [Mobile API](#mobile-api) -- [Banner](#banner-api) -- [Interstitial](#interstitial-api) -- [Rewarded](#rewarded-api) +* TOC +{:toc} -## Mobile API +## Transport API -The Pure In-App Bidding integration is similar to the integration of regular Ad SDK with Prebid in the role of the Ad Server. +The default ad server for Prebid's Mobile SDK is GAM. The SDK can be expanded to include support for 3rd party ad servers through the fetchDemand function. This function returns additional bid information like Prebid Server bidder key/values (targeting keys), which can then be passed to the ad server of choice. -![In-App Bidding with Prebid](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png) +In this mode, the publisher will be responsible for the following actions: + +* Call the `fetchDemand` method with specific callback +* Retrieve targeting keys from the `BidInfo` callback parameter +* Convert targeting keys into the format for your ad server +* Pass converted keys to your ad server +* Render ad with Prebid Universal Creative or custom renderer + +This approach is available for the following ad formats: -Prebid supports rendering of these ad formats: +* Display Banner via `BannerAdUnit` +* Video Banner and Instream Video via `VideoAdUnit` +* Display Interstitial via `InterstitialAdUnit` +* Video Interstitial via `VideoInterstitialAdUnit` +* Rewarded Video via `RewardedVideoAdUnit` +* Native Styles via `NativeRequest` +* Multiformat ad unit via `PrebidAdUnit` -- Display Banner -- Display Interstitial -- Video Interstitial -- Rewarded Video -- Outstream Video +The basic integration steps for these ad units you can find at the page for integration using [Original API](/prebid-mobile/pbm-api/ios/ios-sdk-integration-gam-original-api.html). The diference is that you should use the `fetchDemand` function with following signature: + +``` swift +public func fetchDemand(adObject: AnyObject, request: PrebidRequest, + completion: @escaping (BidInfo) -> Void) +``` -[//]: # (- Native) +Examples: + +``` swift +adUnit.fetchDemand(adObject: gamRequest, request: prebidRequest) { [weak self] bidInfo in + guard let self = self else { return } + + //Publisher should provide support for converting keys into format of 3rd party ad server and loading ads + let keywords = convertDictToAdServerKeywords(dict: bidInfo.targetingKeywords) + AdServerLoadAds.loadAd(withAdUnitID: "46d2ebb3ccd340b38580b5d3581c6434", keywords: keywords) +} +``` -They can be integrated using these API categories: +The `BidInfo` provides the following properties: -- [**Banner API**](#banner-api) - for *Display* and *Video* Banners -- [**Interstitial API**](#interstitial-api) - for *Display* and *Video* Interstitials -- [**Rewarded API**](#rewarded-api) - for *Rewarded Video* +* `resultCode` - the object of type `ResultCode` describing the status of the bid request. +* `targetingKeywords` - the targeting keywords of the winning bid +* `exp` - the number of seconds that may elapse between the auction and the actual impression. In this case, it indicates the approximate TTL of the bid in the Prebid Cache. Note that the actual expiration time of the bid will be less than this number due to the network and operational overhead. The Prebid SDK doesn't make any adjustments to this value. +* `nativeAdCacheId` - the local cache ID of the winning bid. Applied only to the `native` ad format. +* `events` - the map of some publically available event URLs attached to the bid. These can be used to enable Prebid Server-based analytics when the Prebid Universal Creative (PUC) is not involved in the rendering process. If the PUC is used for rendering, it will take care of hitting these events. These are the available event URLs: + * **EVENT_WIN** - this bid was chosen by the ad server as the one to display. This is the main metric for banner and native. This returns the OpenRTB `seatbid.bid.ext.prebid.events.win` field. (requires SDK v2.1.6) + * **EVENT_IMP** - the ad creative for this bid was actually displayed. This is often the main metric for video ads. This returns the OpenRTB `seatbid.bid.ext.prebid.events.imp` field. (requires SDK v2.1.6) -[//]: # (- [**Native API**](ios-sdk-integration-pb-native.html) - for *Native Ads*) +Code sample to extract the events: + +``` swift +let win = bidInfo.events[BidInfo.EVENT_WIN] +let imp = bidInfo.events[BidInfo.EVENT_IMP] +``` + +## Rendering API + +The Rendering API integration and usage are similar to any other Ad SDK. In this case, Prebid SDK sends the bid requests to the Prebid Server and renders the winning bid. + +![In-App Bidding with Prebid](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png) ### Banner API @@ -49,29 +88,32 @@ Integration example: let banner = BannerView(frame: CGRect(origin: .zero, size: adSize), configID: CONFIG_ID, adSize: adSize) - + banner.delegate = self - + // 2. Load an Ad banner.loadAd() ``` #### Step 1: Create Ad View +{:.no_toc} Initialize the `BannerAdView` with properties: -- `frame` - the frame rectangle for the view -- `configID` - an ID of the Stored Impression on the Prebid Server -- `size` - the size of the ad unit which will be used in the bid request. +* `frame` - the frame rectangle for the view +* `configID` - an ID of the Stored Impression on the Prebid Server +* `size` - the size of the ad unit which will be used in the bid request. #### Step 2: Load the Ad +{:.no_toc} Call the method `loadAd()` which will: -- make a bid request to the Prebid Server. -- render the winning bid on display. +* make a bid request to the Prebid Server. +* render the winning bid on display. #### Outstream Video +{:.no_toc} For **Banner Video** you also need to specify the ad format: @@ -87,9 +129,9 @@ Integration example: // 1. Create an Interstitial Ad Unit interstitial = InterstitialRenderingAdUnit(configID: CONFIG_ID, minSizePercentage: CGSize(width: 30, height: 30)) - + interstitial.delegate = self - + // 2. Load an Ad interstitial.loadAd() @@ -102,53 +144,43 @@ if interstitial.isReady { ``` -The way of displaying **Video Interstitial** is almost the same with two differences: - -- Need to customize the ad format -- No need to set up `minSizePercentage` +The **default** ad format for interstitial is **.banner**. In order to make a `multiformat bid request`, set the respective values into the `adFormats` property. ``` swift +// Make bid request for video ad +adUnit?.adFormats = [.video] -// 1. Create an Interstitial Ad Unit -let interstitial = InterstitialRenderingAdUnit(configID: CONFIG_ID) - -interstitial.adFormat = .video -interstitial.delegate = self - -// 2. Load an Ad -interstitial.loadAd() +// Make bid request for both video and banner ads +adUnit?.adFormats = [.video, .banner] -// ..... - -// 3. Show An Ad -if interstitial.isReady { - interstitial.show(from: self) -} +// Make bid request for banner ad (default behaviour) +adUnit?.adFormats = [.banner] ``` #### Step 1: Create an Ad Unit - +{:.no_toc} Initialize the Interstitial Ad Unit with properties: - -- `configID` - an ID of Stored Impression on the Prebid Server -- `minSizePercentage` - specifies the minimum width and height percent an ad may occupy of a device’s real estate. -> **NOTE:** minSizePercentage - plays an important role in a bidding process for display ads. If provided space is not enough demand partners won't respond with the bids. +* `configID` - an ID of Stored Impression on the Prebid Server +* `minSizePercentage` - specifies the minimum width and height percent an ad may occupy of a device’s real estate. + +> **NOTE:** minSizePercentage - plays an important role in a bidding process for banner ads. If provided space is not enough demand partners won't respond with the bids. #### Step 2: Load the Ad +{:.no_toc} Call the method `loadAd()` which will make a bid request to Prebid server. - #### Step 3: Show the Ad when it is ready +{:.no_toc} Wait until the ad will be loaded and present it to the user in any suitable time. ``` swift // MARK: InterstitialRenderingAdUnitDelegate - + func interstitialDidReceiveAd(_ interstitial: InterstitialRenderingAdUnit) { // Now the ad is ready for display } @@ -162,7 +194,7 @@ Integration example: // 1. Create an Ad Unit rewardedAd = RewardedAdUnit(configID: CONFIG_ID) rewardedAd.delegate = self - + // 2. Load an Ad rewardedAd.loadAd() @@ -174,25 +206,27 @@ if rewardedAd.isReady { } ``` - #### Step 1: Create Rewarded Ad Unit +{:.no_toc} Create the `RewardedAdUnit` object with parameter: -- **configID** - an ID of Stored Impression on the Prebid Server +* `configID` - an ID of Stored Impression on the Prebid Server #### Step 2: Load the Ad +{:.no_toc} Call the `loadAd()` method which will make a bid request to Prebid server. #### Step 3: Show the Ad when it is ready +{:.no_toc} Wait until the ad will be loaded and present it to the user in any suitable time. ``` swift // MARK: RewardedAdUnitDelegate - + func rewardedAdDidReceiveAd(_ rewardedAd: RewardedAdUnit) { // Now the ad is ready for display -} -``` \ No newline at end of file +} +``` diff --git a/prebid-mobile/modules/rendering/ios-sdk-parameters.md b/prebid-mobile/modules/rendering/ios-sdk-parameters.md deleted file mode 100644 index a4c6f0e0fe..0000000000 --- a/prebid-mobile/modules/rendering/ios-sdk-parameters.md +++ /dev/null @@ -1,88 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Modules -description: Prebid Mobile Rendering Modules architecture -sidebarType: 2 - ---- - -# Request parameters - -The tables below list methods and properties that the Rendering Module allows to customize in order to enrich the bid requests with actual data. The more info is provided about the user, the app, and the device the more chances to win a bid. - -Please strictly follow the recommendations in the below tables and provide all ❗ **Required** and **Highly Recommended** values. - - -1. [PrebidRenderingTargeting Properties](#prebidrenderingtargeting-variables) -1. [PrebidRenderingTargeting Methods](#prebidrenderingtargeting-methods) -1. [PrebidRenderingConfig](#prebidrenderingconfig) - -## PrebidRenderingTargeting proeprties - -{: .table .table-bordered .table-striped } - -| **Variable** | **Description** | **Required?** | -| -------------------- | ---------------- | ------------------------------------------------------------ | ------------------------ | -| appStoreMarketURL | Stores URL for the mobile application. For example: `"https://itunes.apple.com/us/app/your-app/id123456789"` | ❗ Required | -|contentUrl | This is the deep-link URL for the app screen that is displaying the ad. This can be an iOS universal link. | ❗ Highly Recommended | -|publisherName| App's publisher's name. | ❗ Highly Recommended | -| userAge | User's age in years. For example: `35` | ❗ Highly Recommended | -| coppa | Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes | ❗ Highly Recommended | -| userAnnualIncomeInUS | User's annual income in US dollars. For example: `55000` | ❗ Highly Recommended | -| userGender | User's gender (Male, Female, Other, Unknown). For example: `GenderFemale` | ❗ Highly Recommended | -|userGenderDescription| String representation of the user's gender, where “M” = male, “F” = female, “O” = known to be other (i.e., omitted is unknown) | | -| userID | ID of the user within the app. For example: `"24601"` | ❗ Highly Recommended | -| buyerUID | Buyer-specific ID for the user as mapped by the exchange for the buyer. | ❗ Highly Recommended | -| userEthnicity | User's ethnicity (African American, Asian, Hispanic, White, Other). For example: `EthnicityAsian` | Recommended if available | -| userMaritalStatus | User's marital status (Single, Married, Divorced, Unknown). For example: `MaritalStatusDivorced` | Recommended if available | -| networkType | Network connection type of the user (offline, wifi, or cell).For example: `NetworkTypeWifi` | ❗ Required | -| IP | The IP address of the carrier gateway. If this is not present, Prebid retrieves it from the request header. For example: `"192.168.0.1"` | ❗ Highly Recommended | -| carrier | Mobile carrier - Defined by the Mobile Country Code (MCC) and Mobile Network Code (MNC), using the format: -. For example: `"310-410"` | Optional | -| DMA | For US locations, indicates the user's Designated Market Area. For example: `"803"` | Optional | -| keywords | Comma separated list of keywords, interests, or intent | Optional | -| userCustomData| Optional feature to pass bidder the data that was set in the exchange’s cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include “escaped” quotation marks. | Optional | -|userExt| Placeholder for exchange-specific extensions to OpenRTB. | Optional | - -The code sample: - -``` swift -let targeting = PrebidRenderingTargeting.shared -targeting.userGender = .male -targeting.userAge = 99 -targeting.userAnnualIncomeInUS = 9999 -targeting.setLatitude(123.0, longitude: 456.0) -``` - - -## PrebidRenderingTargeting methods - -{: .table .table-bordered .table-striped } - -| **Method** | **Description** | -| ---------------------------------------- | ------------------------------------------------------------ | -| addCustomParam:@"val1" withName:@"key1" | Adds the custom parameters. The name will be auto-prepended with `c.` to avoid collisions. Example: `addCustomParam:@"73" withName:@"temperature"` | -| setCustomParams:@["key1":@"val1"] | Adds a dictionary of name-value parameter pairs, where each parameter name will be prepended with `c.` to avoid name collisions. Example: `setCustomParams:@["key1":@"val1"]` | -| addParam:@"val1" withName:@"key1" | Adds a new `param` by name and sets its value. If an ad call parameter doesn't exist in this SDK, you can set it manually using this method.
        Example: `addParam:@"73" withName:@"temperature"` | -| setLatitude:latitude longitude:longitude | Sets the latitude and longitude of a geographic location.
        Latitude from -90.0 to +90.0, where negative is south.
        Longitude from -180.0 to +180.0, where negative is west. | -| resetUserAge; | Sets the User Age to 0 | -| resetUserAnnualIncomeInUS; | Sets the userAnnualIncomeInUS to 0 | - -## PrebidRenderingConfig - -{: .table .table-bordered .table-striped } - -| **Method** | **Description** | **Default** | -| -------------------------------------- | ------------------------------------------------------------ | ----------- | -| creativeFactoryTimeout | Controls how long in seconds each creative has to load before it is considered a failure. | 3 | -| creativeFactoryTimeoutPreRenderContent | Controls how long (in seconds) the video and display interstitial creative has to completely pre-render before it is considered a failure. | 30 | -| useInternalClickthroughBrowser | Controls whether to use in-app browser or the Safari app for displaying ad click-through content. | true | -| logLevel | Controls the verbosity of PrebidRenderingModule's internal logger. Options are (from most to least noisy):
        - .info
        - .warn
        - .error
        - .none | .info | -| debugLogFileEnabled | If `true`, the output of PrebidRenderingModule's internal logger is written to a text file. This can be helpful for debugging. | false | - -The code sample: - -``` swift -PrebidRenderingConfig.shared.creativeFactoryTimeout = 5.0 -``` - diff --git a/prebid-mobile/modules/rendering/modules-rendering.md b/prebid-mobile/modules/rendering/modules-rendering.md index 81fcd0a189..9d82a5efd6 100644 --- a/prebid-mobile/modules/rendering/modules-rendering.md +++ b/prebid-mobile/modules/rendering/modules-rendering.md @@ -7,68 +7,15 @@ sidebarType: 2 --- -# Prebid Mobile Rendering (Open Beta) +# Prebid Mobile Rendering - The Prebid Mobile has added a rendering module (currently in open beta) which provides an API for rendering display and video media types independently of the current core feature set and interfaces. The API enables Prebid Mobile to have full ownership of the Web view selected for rendering and will pass any associated ad markup to the controlled view. This new functionality enables publishers to have improved control of features such as Open Measurement, MRAID, SKAdNetwork. This same functionality is available for rendering video (VAST) creatives through an internal video player. +Prebid Mobile has added a rendering module (currently in open beta) which provides an API for rendering display and video media types independently of the current core feature set and interfaces. The API enables Prebid Mobile to have full ownership of the Web view selected for rendering and will pass any associated ad markup to the controlled view. This new functionality enables publishers to have improved control of features such as Open Measurement, MRAID, SKAdNetwork. This same functionality is available for rendering video (VAST) creatives through an internal video player. -{% capture warning_note %} -This open beta release will contain a temporary API structure and is subject to change when a general audience release is made available. -{% endcapture %} -{% include /alerts/alert_important.html content=warning_note %} +The **rendering API** is available on iOS and Android starting with the `1.13.0-beta1` version. -The rendering API is available on iOS and Android starting with the `1.13.0-beta1` version. +Starting with `1.14.0-beta1` Prebid mobile supports integration with **AdMob**. -## Benefits - -Prebid SDK rendering offers the following benefits: - -- **Monetization without an Ad Server**: Publishers who do not have a direct sales force or have no need for an ad server can still access Prebid's mobile demand stack. Publishers will be able to render ads directly without relying on any 3rd party SDKs. -- **Reduced ad delivery latency**: The rendering module enables Prebid SDK to render ads immediately when demand is returned from Prebid Server or when receiving the render signal from an ad server. The render process should vastly reduce ad delivery speeds. -- **Less infrastructure**: The Prebid SDK does not rely on Prebid Server's Cache server reducing the cost and utility of Prebid Server Cache. -- **Less discrepancy**: Having control of the rendering process provides the potential to reduce discrepancy by having ads instantly available (less http calls, less infrastructure, less setup). This control enables the publisher to follow open and transparent industry standards or even potentially custom requirements from buyers. -- **Framework support**: Full support of SKAdNetworks and similar frameworks -- **MRAID 3.0 support** -- **Flexible Ad Measurement**: Controlling the rendering and Open Measurement process allows publishers to potentially configure any measurement provider in a transparent and open source process. Prebid SDK will eventually be IAB Open Measurement certified. -- **Community driven**: Being a part of Prebid, there is the ability to add features not readily or easily available either through the Ad Server or other SDKs - -## Potential Features - -This set of features are not supported in the current release but are designated for future implementation. - -- **Multiformat Ad Unit**: The rendering module will enable Prebid SDK to display any bid format in the given inventory regardless of Primary Ad Server capabilities. -- **Support of Custom Ad Servers**: The rendering module will work with any ad server not just GAM and MoPub. -- **Rendering Delegation**: The module will potentially delegate rendering of the winning bid to the Demand Partner SDK if it is required for special creatives. - -## How It Works - -Prebid Mobile SDK supports two integration scenarios: - -* **Pure In-App Bidding** With in-app bidding, no Primay Ad Server is used. The module renders the winning bid immediately when it is available. -* **Using a Primary Ad Server** Prebid SDK detects when a Prebid line item wins on the ad server and renders the cached bid in the owned Web view or Video view. - -In both scenarios, Prebid SDK leverages Prebid Server for demand. Below are the processes for both In-App and Primary Ad Server modes: - -### Pure In-App Bidding - -![In-App Rendering](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png) - -1. The rendering module sends the bid request to the Prebid Server -1. Prebid Server runs the header bidding auction among preconfigured demand partners -1. Prebid Server responses with the winning bid -1. The rendering module renders the winning bid - -### Prebid Rendering Module with Primary Ad Server - -![Rendering with Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/In-App-Bidding-Integration.png) - -1. The rendering module sends the bid request to the Prebid server. -1. Prebid server runs the header bidding auction among preconfigured demand partners. -1. Prebid Server responds with the winning bid that contains targeting keywords. -1. The rendering module sets up the targeting keywords of the winning bid to the ad unit configuration of the primary ad server SDK. -1. The primary ad server SDK sends the ad request to the primary ad server. -1. The primary ad server SDK responds with an ad. -1. The winning ad meta information is passed to the rendering module. -1. Depending on the ad response, the rendering module renders the winning bid or allows the primary ad server SDK to show its own winning ad. +Starting with `2.0.0` Prebid mobile supports integration with **AppLovin MAX**. ## Supported Ad Formats @@ -76,46 +23,10 @@ In both scenarios, Prebid SDK leverages Prebid Server for demand. Below are the Prebid Mobile rendering supports the following ad formats: * Display Banner +* Video Banner * Display Interstitial * Video Interstitial * Rewarded Video -* Outstream Video (for GAM, pure in-app bidding) - -[//]: # (The support of native will be added later) -[//]: # (* Native Styles Ads) -[//]: # (* Native Ads) - -## Integration Scenarios - -### Android - -Follw these steps to integrate the Prebid Mobile rendering module: - -1. If integrating into an ad server, create line items specific for rendering (line items are unique for the rendering module and do not coincide with the standard Prebid SDK line items): - * [GAM](rendering-gam-line-item-setup.html) - * [MoPub](rendering-mopub-line-item-setup.html) -1. Build the Prebid SDK project [integrate](android-sdk-integration.html) with the Prebid Rendering Module -1. Integrate app with the Prebid SDK Rendering Module scenario - * Integrate with [Google Ad Manager (GAM)](android-sdk-integration-gam.html) as a Primary Ad Server - * Integrate with [MoPub](android-sdk-integration-mopub.html) as a Primary Ad Server - * [Pure In-App Bidding](android-sdk-integration-pb.html) integration without Primary Ad Server -1. Actualize the [integration and targeting](android-sdk-parameters.html) properties. - -### iOS - -To integrate Prebid SDK Rendering, developers are required to peform the following actions: -1. If integrating into an ad server, create line items specific for rendering (line items are uniqe for the Rendering Module and do not cooicide with the standard Prebid SDK line items): - * [GAM](rendering-gam-line-item-setup.html) - * [MoPub](rendering-mopub-line-item-setup.html) -1. Build the Prebid SDK project [integrate](ios-sdk-integration.html) with the the rendering module. -1. Integrate your app with the Prebid Mobile rendering module: - * Integrate with [Google Ad Manager (GAM)](ios-sdk-integration-gam.html) as a primary ad server. - * Integrate with [MoPub](ios-sdk-integration-mopub.html) as a primary ad server. - * [Pure In-App Bidding](ios-sdk-integration-pb.html) integration without a primary ad server. -1. Actualize the [integration and targeting](ios-sdk-parameters.html) properties. -## Additional refences -- [Deep Links Support](rendering-deeplinkplus.html) -- [Impression Tracking](rendering-impression-tracking.html) diff --git a/prebid-mobile/modules/rendering/rendering-deeplinkplus.md b/prebid-mobile/modules/rendering/rendering-deeplinkplus.md index 0a95c02cb3..4b5d8c943d 100644 --- a/prebid-mobile/modules/rendering/rendering-deeplinkplus.md +++ b/prebid-mobile/modules/rendering/rendering-deeplinkplus.md @@ -9,7 +9,7 @@ sidebarType: 2 # Deep Link+ -Prebid Rendering Module supports the premium standard for retargeting campaigns - [DeepLink+](https://developers.mopub.com/dsps/ad-formats/deep-linking/) +Prebid Rendering Module supports the premium standard for retargeting campaigns - DeepLink+. ## Advantages over traditional mobile deep-linking functionality diff --git a/prebid-mobile/modules/rendering/rendering-gam-line-item-setup.md b/prebid-mobile/modules/rendering/rendering-gam-line-item-setup.md deleted file mode 100644 index 8d076a3502..0000000000 --- a/prebid-mobile/modules/rendering/rendering-gam-line-item-setup.md +++ /dev/null @@ -1,206 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering GAM Line Item Setup -description: Prebid Mobile Rendering Modules GAM line item setup -sidebarType: 2 - ---- - -# Google Ad Manager Setup - -## Step 1: Create New Order - - Pipeline Screenshot - - -## Step 2: Create Line Item - -To integrate the Prebid demand you have to create a Line Items with a specific price and targeting keywords. - -> Even though a Line Item can be named in any way, we strongly recommend to use the price or targeting keyword in the name. It will help to navigate through hundreds of them. - -### Select Type - -Create a Line Item depending on the type of expected creative kind: - -* **Display** - for the Banner, HTML Interstitial -* **Video and Audio** - for the Video Interstitial, Rewarded Video, and Outstream Video ads. - -Pipeline Screenshot - -Set sizes respectively to expected creatives. - -### Select Price - -The Line Item price should be chosen according to the price granularity policy. - -Pipeline Screenshot - -### Set Targeting Keywords - -The **Custom targeting** property should contain a special keyword with the price of winning bid. The same as a Rate of the Line Item. - -Pipeline Screenshot - -## Step 3: Prepare Prebid Creative - -### Display Banner, Video Banner, Display Interstitial, Video Interstitial. - -The Prebid SDK integrates with GAM basing on [App Events](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner#app_events) feature, almost for all ad formats. That means that creative should contain a special tag that will be processed by Prebid's GAM Event Handlers. - -If GAM Event Handler receives the `PrebidAppEvent` event it will render the winning bid. Otherwise the control will be passed to the GAM Ad View and it will render the received creative. - -``` html - - -``` - -Pipeline Screenshot - -### Rewarded Video - -Prebid rendering for Rewarded video ads is based on the [OnAdMetadataChangedListener](https://developers.google.com/android/reference/com/google/android/gms/ads/rewarded/OnAdMetadataChangedListener). So you need to set up a special VAST tag in the creative. - -``` js -https://cdn.jsdelivr.net/npm/prebid-universal-creative/dist/prebid-mobile-rewarded-vast.xml -``` - -Pipeline Screenshot - -If GAM Event Handler receives the tag's info it will render the winning bid. Otherwise the control will be passed to the GAM Ad View and it will render the received creative. - - \ No newline at end of file diff --git a/prebid-mobile/modules/rendering/rendering-impression-tracking.md b/prebid-mobile/modules/rendering/rendering-impression-tracking.md index 868bf3c075..6d84a1b5e2 100644 --- a/prebid-mobile/modules/rendering/rendering-impression-tracking.md +++ b/prebid-mobile/modules/rendering/rendering-impression-tracking.md @@ -13,19 +13,16 @@ sidebarType: 2 The impression tracking depends on a certain integration approach. -In case of GAM or MoPub integration when the Ad Server ad wins - the impression will be tracked according to the policy of the certain Primary Ad Server SDK that will handle the rendering. +In case of GAM integration when the Ad Server ad wins - the impression will be tracked according to the policy of the certain Primary Ad Server SDK that will handle the rendering. If Prebid ad wins on the Primary Ad Server Auction, the impression tracking will depend on particular integration kind: * **GAM** impression will be tracked only for banner ads since it allows [manual impression counting](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner#manual_impression_counting). Rendering Module is not able to track impressions for GAM Interstitial or Rewarded ads. -* **MoPub** impression will be tracked as stated in the MoPub policies since the rendering part is performed according to the Mediation feature. * **Pure In-App Bidding** impression pixels for Open Measurement and VAST will be tracked according to the [In-App Bidding Impression](#in-app-bidding-impression) policies of the SDK. - ## In-App Bidding Impression -Prebid Rendering Module tracks the impression pixel as stated in a definition of **render impression** from [Mobile Application Advertising Measurement Guidelines](http://mediaratingcouncil.org/Mobile%20In-App%20Measurement%20Guidelines%20(MMTF%20Final%20v1.1).pdf): - +Prebid Rendering Module tracks the impression pixel as stated in a definition of **render impression** from [Mobile Application Advertising Measurement Guidelines](https://mediaratingcouncil.org/sites/default/files/Standards/Mobile%20In-App%20Measurement%20Guidelines%20%28MMTF%20Final%20v1.1%29.pdf): > **Ad Impression**: A measurement of responses from an ad delivery system to an ad request from the user's device, which is filtered for invalid traffic and is recorded at a point as late as possible in the process of delivery of the creative material to the user's device. The ad must be loaded and at minimum begin to render in order to count it as a valid ad impression. Measurement of begin to render should include logical components necessary to display the ad, but does not necessarily include logical elements that are not essential (such as other tracking elements). > @@ -40,8 +37,7 @@ This rule is applied to all tracking pixels display, video, Open Measurement. SDK broadcasts the `mraid.viewableChange()` event when the ad becomes rendered. It means that for proper impression tracking with MRAID the creative's code for tracking impression must depend on `mraid.isViewable()`. For example: - -``` javascript +```javascript if ( mraid.viewableChangeEventWasDetected() ) if( mraid.isViewable() == true) fireMyImpressionTrackers(); @@ -55,4 +51,4 @@ Otherwise the impression tracking would be inconsistent with Prebid Rendering SD For the ads that support the MRAID 3, the impression tracking code should be rather dependent on `exposureChange()` function. Since it provides much more information about the viewability of an Ad Container, the impression tracking could be much more accurate and correspond to the MRC and IAB guidelines. -However, the IAB strongly recommends not to use the MRAID facilities to track impressions. The best practice is to use the **Open Measurement** framework which is supported by SDK as well. \ No newline at end of file +However, the IAB strongly recommends not to use the MRAID facilities to track impressions. The best practice is to use the **Open Measurement** framework which is supported by SDK as well. diff --git a/prebid-mobile/modules/rendering/rendering-mopub-line-item-setup.md b/prebid-mobile/modules/rendering/rendering-mopub-line-item-setup.md deleted file mode 100644 index cc4f376fc8..0000000000 --- a/prebid-mobile/modules/rendering/rendering-mopub-line-item-setup.md +++ /dev/null @@ -1,105 +0,0 @@ ---- - -layout: page_v2 -title: Prebid Mobile Rendering Modules -description: Prebid Mobile Rendering Modules architecture -sidebarType: 2 - ---- - -# MoPub Setup - -## Order Setup - -### Step 1: Create New Order - - Pipeline Screenshot - -### Step 2: Create Line Item - -#### Line Item: Display, Video - -To integrate Prebid demand you have to create a Custom Ad Network Line Items with a specific Targeting keyword. - -- **Line Item Name**: hb_pb 0.10 -- **Type & Priority**: Network Line Item -- **Network**: Custom SDK network -- **Custom event class**: - - For Banner API: - - iOS: **PrebidBannerAdapter** - - Android: **com.mopub.mobileads.PrebidBannerAdapter** - - For Interstitial API: - - iOS: **PrebidInterstitialAdapter** - - Android: **com.mopub.mobileads.PrebidInterstitialAdapter** - - For Rewarded API: - - iOS: **PrebidRewardedVideoAdapter** - - Android: **com.mopub.mobileads.PrebidRewardedVideoAdapter** - - For Native API: - - iOS: **PrebidNativeAdapter** - - Android: **com.mopub.nativeads.PrebidNativeAdapter** -- **Custom event data**: {} - -Pipeline Screenshot - -> Even though a Line Item can be named in any way, we strongly recommend to use the price or targeting keyword in the name. It will help to navigate through hundreds of them. - - - -#### Ad Unit Targeting - -Pipeline Screenshot - -#### Audience Targeting - -The **Keyword targeting** property should contain a special keyword with the price of winning bid. - -Pipeline Screenshot - - diff --git a/prebid-mobile/modules/rendering/rendering-native-guidelines.md b/prebid-mobile/modules/rendering/rendering-native-guidelines.md index 4c589e694d..1e32e47032 100644 --- a/prebid-mobile/modules/rendering/rendering-native-guidelines.md +++ b/prebid-mobile/modules/rendering/rendering-native-guidelines.md @@ -34,7 +34,7 @@ The general integration scenario requires these steps from publishers: * Provide the list of [Native Assets](#components) representing the ad's structure. * Tune other general properties of the ad. 4. Make a bid request. -5. Find the winning native ad using `GAMUtils.shared.findNativeAd` or `MoPubUtils.findNativeAd`. +5. Find the winning native ad using `GAMUtils.shared.findNativeAd`. 6. Bind the data from the native ad response with the layout. ### Native Styles @@ -51,7 +51,7 @@ The Prebid Rendering Module supports the original prebid's approach for renderin The ad will be rendered in the web view. The rendering engine will be the prebid's universal creative. It will load the winning bid from the prebid cache and substitute assets into the ad markup. For the more detailed info visit the Prebid's instructions about [How Native Ads Work](https://docs.prebid.org/dev-docs/show-native-ads.html#how-native-ads-work). -In order to prepare the valid layout folow the instructions in the Prebid docs for [Mobile in general](https://docs.prebid.org/prebid-mobile/adops-native-setup.html) and for [Google Ad Manager](https://docs.prebid.org/adops/setting-up-prebid-native-in-dfp.html). +In order to prepare the valid layout follow the instructions in the Prebid docs for [Google Ad Manager](/adops/gam-native.html). In the case of integration of Native Styles ads without Primary Ad Server publishers should provide the Ad Layout to the SDK. And the winning bid will be rendered right after receiving it from Prebid. @@ -61,14 +61,13 @@ In the case of integration of Native Styles ads without Primary Ad Server publis 2. Prebid Rendering Module sends the bid request. 3. Prebid server runs the header bidding auction among preconfigured demand partners. 3. The received creative will be rendered in the Web View of Prebid Rendering Module. - + ## Components The Prebid Rendering Module supports all Native Ad components proclaimed by the OpenRTB specification: **title**, **image**, **video**, **data**. We strongly recommend to follow the industry best practices and requirements, especially in the case of integration with Primary Ad Server: -* [OpenRTB Specification](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) -* [The Native Advertizing Playbook](https://www.iab.com/wp-content/uploads/2015/06/IAB-Native-Advertising-Playbook2.pdf) -* [Google Guidelines](https://support.google.com/admanager/answer/6075370) -* [MoPub Guidelines](https://developers.mopub.com/publishers/best-practices/native-ads/) +- [OpenRTB Specification](https://www.iab.com/wp-content/uploads/2018/03/OpenRTB-Native-Ads-Specification-Final-1.2.pdf) +- [The Native Advertizing Playbook](https://www.iab.com/wp-content/uploads/2015/06/IAB-Native-Advertising-Playbook2.pdf) +- [Google Guidelines](https://support.google.com/admanager/answer/6075370) diff --git a/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.md b/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.md new file mode 100755 index 0000000000..0c345afff6 --- /dev/null +++ b/prebid-mobile/pbm-api/android/android-sdk-integration-gam-original-api.md @@ -0,0 +1,1639 @@ +--- +layout: page_v2 +title: Prebid Mobile - GAM with Original API +description: Overview of Prebid Mobile API for Android +top_nav_section: prebid-mobile +nav_section: prebid-mobile +sidebarType: 2 +--- + +# Prebid Mobile with GAM (Original API) +{:.no_toc} + +Prebid Mobile is an open-source library that provides an end-to-end header bidding solution for mobile app publishers. + +* TOC +{:toc} + +## Overview + +This is the original Prebid mobile integration approach when SDK plays the transport role, and the winning bid is rendered by the Primary Ad Server SDK using PUC. You can find details of how it works and other integration approaches on the [overview page](/prebid-mobile/prebid-mobile.html#with-ad-server-original-api). + +![In-App Bidding with Prebid](/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original-gam.png) + +## Banner API + +Starting with Prebid Mobile `2.1.0` you can use `BannerAdUnit` to bid over the banner and/or video demand. The default ad format is `BANNER`. To customize the bidding format, specify the ad formats in the `BannerAdUnit` constructor. + +### HTML Banner + +Integration example: + +```kotlin +private fun createAd() { + + // 1. Create BannerAdUnit + adUnit = BannerAdUnit(CONFIG_ID, WIDTH, HEIGHT) + adUnit?.setAutoRefreshInterval(refreshTimeSeconds) + + // 2. Configure banner parameters + val parameters = BannerParameters() + parameters.api = listOf(Signals.Api.MRAID_3, Signals.Api.OMID_1) + adUnit.bannerParameters = parameters + + // 3. Create AdManagerAdView + val adView = AdManagerAdView(this) + adView.adUnitId = AD_UNIT_ID + adView.setAdSizes(AdSize(WIDTH, HEIGHT)) + adView.adListener = createGAMListener(adView) + + // Add GMA SDK banner view to the app UI + adWrapperView.addView(adView) + + // 4. Make a bid request to Prebid Server + val request = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(request) { + + // 5. Load GAM Ad + adView.loadAd(request) + } +} +``` + +GAM ad view listener: + +```kotlin +private fun createGAMListener(adView: AdManagerAdView): AdListener { + return object : AdListener() { + override fun onAdLoaded() { + super.onAdLoaded() + + // 6. Resize ad view if needed + AdViewUtils.findPrebidCreativeSize(adView, object : AdViewUtils.PbFindSizeListener { + override fun success(width: Int, height: Int) { + adView.setAdSizes(AdSize(width, height)) + } + + override fun failure(error: PbFindSizeError) {} + }) + } + } +} +``` + +#### Step 1: Create a BannerAdUnit +{:.no_toc} + +Initialize the `BannerAdUnit` with properties: + +* `configId` - an ID of the Stored Impression on the Prebid Server +* `width` - the width of the ad unit which will be used in the bid request. +* `height` - the height of the ad unit which will be used in the bid request. + +#### Step 2: Configure banner parameters +{:.no_toc} + +Using the `BannerParameters()` you can customize the bid request for BannerAdUnit. + +{: .alert.alert-warning :} +Starting from PrebidMobile `2.1.0` the `BannerBaseAdUnit.Parameters` class is deprecated. Use `BannerParameters` instead. + +The `api` property is dedicated to adding values for API Frameworks to a bid response according to the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) spec. The supported values for GMA SDK integration are: + +* `3` or `Signals.Api.MRAID_1` : MRAID-1 support signal +* `5` or `Signals.Api.MRAID_2` : MRAID-2 support signal +* `6` or `Signals.Api.MRAID_3` : MRAID-3 support signal +* `7` or `Signals.Api.OMID_1` : signals OMSDK support + +#### Step 3: Create an AdManagerAdView +{:.no_toc} + +Follow the [GMA SDK documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner) to integrate a banner ad unit. + +#### Step 4: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +#### Step 5: Load an Ad +{:.no_toc} + +You should now request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain the targeting keywords, and Prebid's ad won't ever be displayed. + +#### Step 6: Adjust the ad view size +{:.no_toc} + +Once an app receives a signal that an ad is loaded, you should use the method `AdViewUtils.findPrebidCreativeSize` to verify whether it's Prebid's ad and resize the ad slot respectively to the creative's properties. + +### Video Banner (Outstream Video) + +Integration example: + +```kotlin +private fun createAd() { + // 1. Create VideoAdUnit + adUnit = BannerAdUnit(CONFIG_ID, WIDTH, HEIGHT, EnumSet.of(AdUnitFormat.VIDEO)) + + // 2. Configure video ad unit + adUnit?.videoParameters = configureVideoParameters() + + // 3. Create AdManagerAdView + val gamView = AdManagerAdView(this) + gamView.adUnitId = AD_UNIT_ID + gamView.setAdSizes(AdSize(WIDTH, HEIGHT)) + gamView.adListener = createListener(gamView) + + adWrapperView.addView(gamView) + + // 4. Make an ad request + val request = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(request) { + gamView.loadAd(request) + } +} +``` + +{: .alert.alert-warning :} +Starting from PrebidMobile `2.1.0` the `VideoAdUnit` class is deprecated. Use `BannerAdUnit` class with video ad format instead. + +Configure Video parameters: + +```kotlin +private fun configureVideoParameters(): VideoParameters { + return VideoParameters(listOf("video/x-flv", "video/mp4")).apply { + api = listOf( + Signals.Api.VPAID_1, + Signals.Api.VPAID_2 + ) + + maxBitrate = 1500 + minBitrate = 300 + maxDuration = 30 + minDuration = 5 + playbackMethod = listOf(Signals.PlaybackMethod.AutoPlaySoundOn) + protocols = listOf( + Signals.Protocols.VAST_2_0 + ) + } +} +``` + +Setup ad listener: + +```kotlin +private fun createListener(gamView: AdManagerAdView): AdListener { + return object : AdListener() { + override fun onAdLoaded() { + AdViewUtils.findPrebidCreativeSize(gamView, object : PbFindSizeListener { + override fun success(width: Int, height: Int) { + gamView.setAdSizes(AdSize(width, height)) + } + + override fun failure(error: PbFindSizeError) {} + }) + } + } +} +``` + +#### Step 1: Create a BannerAdUnit with the video ad type +{:.no_toc} + +Initialize the `BannerAdUnit` with the following properties: + +* `configId` - an ID of the Stored Impression on the Prebid Server +* `adSize` - the size of the ad unit which will be used in the bid request. +* `adUnitFormats` - `AdUnitFormat.VIDEO` for a video ad + +#### Step 2: Configure video parameters +{:.no_toc} + +Using the `VideoParameters` you can customize the bid request for a `BannerAdUnit`. + +{: .alert.alert-warning :} +Starting from PrebidMobile `2.1.0` the `VideoBaseAdUnit.Parameters` class is deprecated. Use `VideoParameters` instead. + +#### placement +{:.no_toc} + +[OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Placement Type for the auction can be expressed as an integer array or can use an enum for easier readability. Option 1 (in-stream) is intentionally left out due to lack of in-stream support in Prebid SDK. + +In the context of a VideoInterstitialAdUnit, rewarded video ads are typically labeled as interstitial. As such, Prebid SDK will default to value 5 if no placement value is supplied. + +* `2` or `InBanner` : In-Banner placement exists within a web banner that leverages the banner space to deliver a video experience as opposed to another static or rich media format. The format relies on the existence of display ad inventory on the page for its delivery. +* `3` or `InArticle` : In-Article placement loads and plays dynamically between paragraphs of editorial content; existing as a standalone branded message. +* `4` or `InFeed` : In-Feed placement is found in content, social, or product feeds. +* `5` or `Slider`, `Floating` or `Interstitial` : Open RTB supports one of three values for option 5 as either Slider, Floating or Interstitial. If an enum value is supplied in placement, bidders will receive value 5 for placement type and assume to be interstitial with the instl flag set to 1. + +#### api +{:.no_toc} + +The `api` property is dedicated to adding values for API Frameworks to a bid response according to the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) spec. The supported values for GMA SDK integration are: + +* `1` or `Signals.Api.VPAID_1` : VPAID 1.0 +* `2` or `Signals.Api.VPAID_2` : VPAID 2.0 +* `3` or `Signals.Api.MRAID_1` : MRAID-1 support signal +* `5` or `Signals.Api.MRAID_2` : MRAID-2 support signal +* `6` or `Signals.Api.MRAID_3` : MRAID-3 support signal +* `7` or `Signals.Api.OMID_1` : signals OMSDK support + +#### maxBitrate +{:.no_toc} + +Integer representing the OpenRTB 2.5 maximum bit rate in Kbps. + +#### minBitrate +{:.no_toc} + +Integer representing the OpenRTB 2.5 minimum bit rate in Kbps. + +#### maxDuration +{:.no_toc} + +Integer representing the OpenRTB 2.5 maximum video ad duration in seconds. + +#### minDuration +{:.no_toc} + +Integer representing the OpenRTB 2.5 minimum video ad duration in seconds. + +#### mimes +{:.no_toc} + +Array of strings representing the supported OpenRTB 2.5 content MIME types (e.g., “video/x-ms-wmv”, “video/mp4”). + +#### playbackMethod +{:.no_toc} + +Array of OpenRTB 2.5 playback methods. If none are specified, any method may be used. Only one method is typically used in practice. It is strongly advised to use only the first element of the array. + +* `1` or `Signals.PlaybackMethod.AutoPlaySoundOn` : Initiates on Page Load with Sound On +* `2` or `Signals.PlaybackMethod.AutoPlaySoundOff` : Initiates on Page Load with Sound Off by Default +* `3` or `Signals.PlaybackMethod.ClickToPlay` : Initiates on Click with Sound On +* `4` or `Signals.PlaybackMethod.MouseOver` : Initiates on Mouse-Over with Sound On +* `5` or `Signals.PlaybackMethod.EnterSoundOn` : Initiates on Entering Viewport with Sound On +* `6` or `Signals.PlaybackMethod.EnterSoundOff`: Initiates on Entering Viewport with Sound Off by Default + +#### protocols +{:.no_toc} + +Array or enum of OpenRTB 2.5 supported Protocols. Values can be one of: + +* `1` or `Signals.Protocols.VAST_1_0` : VAST 1.0 +* `2` or `Signals.Protocols.VAST_2_0` : VAST 2.0 +* `3` or `Signals.Protocols.VAST_3_0` : VAST 3.0 +* `4` or `Signals.Protocols.VAST_1_0_Wrapper` : VAST 1.0 Wrapper +* `5` or `Signals.Protocols.VAST_2_0_Wrapper` : VAST 2.0 Wrapper +* `6` or `Signals.Protocols.VAST_3_0_Wrapper` : VAST 3.0 Wrapper +* `7` or `Signals.Protocols.VAST_4_0` : VAST 4.0 +* `8` or `Signals.Protocols.VAST_4_0_Wrapper` : VAST 4.0 Wrapper + +#### Step 3: Create an AdManagerAdView +{:.no_toc} + +Just follow the [GMA SDK documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner) to integrate a banner ad unit. + +#### Step 4: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +#### Step 5: Load an Ad +{:.no_toc} + +You should now request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain targeting keywords, and Prebid's ad won't ever be displayed. + +### Multiformat Banner (HTML + Video) + +Integration example: + +```kotlin +// 1. Create BannerAdUnit +adUnit = BannerAdUnit(configId, WIDTH, HEIGHT, EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO)) +adUnit?.setAutoRefreshInterval(refreshTimeSeconds) + +// 2. Configure banner and video parameters +val parameters = BannerParameters() +parameters.api = listOf(Signals.Api.MRAID_3, Signals.Api.OMID_1) +adUnit?.bannerParameters = parameters + +adUnit?.videoParameters = VideoParameters(listOf("video/mp4")) + +// 3. Create AdManagerAdView +val adView = AdManagerAdView(this) +adView.adUnitId = AD_UNIT_ID +adView.setAdSizes(AdSize(WIDTH, HEIGHT)) +adView.adListener = createGAMListener(adView) + +// Add GMA SDK banner view to the app UI +adWrapperView.addView(adView) + +// 4. Make a bid request to Prebid Server +val request = AdManagerAdRequest.Builder().build() +adUnit?.fetchDemand(request) { + + // 5. Load GAM Ad + adView.loadAd(request) +} +``` + +#### Step 1: Create a BannerAdUnit +{:.no_toc} + +Initialize the `BannerAdUnit` with properties: + +* `configId` - an ID of the Stored Impression on the Prebid Server +* `width` - the width of the ad unit which will be used in the bid request. +* `height` - the height of the ad unit which will be used in the bid request. +* `adUnitFormats` - ad unit formats for the current ad unit. + +#### Step 2-5 +{:.no_toc} + +Steps 2-5 are the same as for Display Banner. Setting up banner and video parameters can be found in Display Banner and Video Banner respectively. + +## Interstitial API + +Starting with Prebid Mobile `2.1.0` you can use `InterstitialAdUnit` to bid over the banner and/or video demand. The default ad format is `BANNER`. To customize the bidding format, specify the ad formats in the `InterstitialAdUnit` constructor. + +### HTML Interstitial + +Integration example: + +```kotlin +private fun createAd() { + // 1. Create InterstitialAdUnit + adUnit = InterstitialAdUnit(CONFIG_ID, 80, 60) + + // 2. Make a bid request to Prebid Server + val request = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(request) { + + // 3. Load a GAM interstitial ad + AdManagerInterstitialAd.load( + this, + AD_UNIT_ID, + request, + createListner()) + } +} +``` + +You also need to implement `AdManagerInterstitialAdLoadCallback` in order to track the ad rediness: + +```kotlin +private fun createListner(): AdManagerInterstitialAdLoadCallback { + return object : AdManagerInterstitialAdLoadCallback() { + + override fun onAdLoaded(adManagerInterstitialAd: AdManagerInterstitialAd) { + super.onAdLoaded(adManagerInterstitialAd) + + // 4. Present the interstitial ad + adManagerInterstitialAd.show(this@GamOriginalApiDisplayInterstitialActivity) + } + + override fun onAdFailedToLoad(loadAdError: LoadAdError) { + super.onAdFailedToLoad(loadAdError) + Log.e("GAM", "Ad failed to load: $loadAdError") + } + } +} +``` + +#### Step 1: Create an InterstitialAdUnit +{:.no_toc} + +Initialize the Interstitial Ad Unit with properties: + +* `configId` - an ID of Stored Impression on the Prebid Server +* `minWidthPerc`: Optional parameter to specify the minimum width percent an ad may occupy of a device's screen. Support in SDK version 1.2+ +* `minHeightPrec`: Optional parameter to specify the minimum height percent an ad may occupy of a device's screen. Support in SDK version 1.2+ + +> **NOTE:** As of version 1.2+, Prebid SDK has extended the functionality of Interstitial ad monetization by using a smart ad size selection process to monetize sizes smaller than full screen ads. App developers can specify a minimum width and minimum height percentage an ad can occupy of a devices screen, with Prebid Server (PBS) deriving a limited set of ad sizes (max 10) as eligible for the auction. +> +> PBS will take the AdUnit's size (width and height) as the max size for the interstitial as size, generating a list of ad sizes, selecting the first 10 sizes that fall within the imp's max size and minimum percentage size. All the interstitial parameters will still be passed to the bidders, allowing them to use their own size matching algorithms if they prefer. +> +> Prebid Server will send the eligible size list to each bidder to solicit a bid. For a full description of the Prebid Server logic, please refer to the [Prebid Server PR 797](https://github.com/prebid/prebid-server/pull/797/files). + +#### Step 2: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the prebid server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +#### Step 3: Load a GAM interstitial ad +{:.no_toc} + +You should now request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain targeting keywords, and Prebid's ad won't ever be displayed. + +#### Step 4: Present the interstitial ad +{:.no_toc} + +Follow the [GMA SDK guide](https://developers.google.com/ad-manager/mobile-ads-sdk/android/interstitial#display_the_ad) to display an interstitial ad right after receiving it or later in a natural pauses in the flow of an app. + +### Video Interstitial + +Integration Example: + +```kotlin +private fun createAd() { + + // 1. Create InterstitialAdUnit + adUnit = InterstitialAdUnit(CONFIG_ID, EnumSet.of(AdUnitFormat.VIDEO)) + + // 2. Configure video ad unit + adUnit?.videoParameters = configureVideoParameters() + + // 3. Make a bid request to Prebid Server + val request = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(request) { + + // 4. Load a GAM ad + AdManagerInterstitialAd.load( + this@GamOriginalApiVideoInterstitialActivity, + AD_UNIT_ID, + request, + createAdListener() + ) + } +} +``` + +{: .alert.alert-warning :} +Starting from PrebidMobile `2.1.0` the `VideoInterstitialAdUnit` class is deprecated. Use `InterstitialAdUnit` class with video ad format instead. + +Configuration function: + +```kotlin +private fun configureVideoParameters(): VideoParameters { + return VideoParameters(listOf("video/x-flv", "video/mp4")).apply { + placement = Signals.Placement.Interstitial + + api = listOf( + Signals.Api.VPAID_1, + Signals.Api.VPAID_2 + ) + + maxBitrate = 1500 + minBitrate = 300 + maxDuration = 30 + minDuration = 5 + playbackMethod = listOf(Signals.PlaybackMethod.AutoPlaySoundOn) + protocols = listOf( + Signals.Protocols.VAST_2_0 + ) + } +} +``` + +GAM Ad Listener: + +```kotlin +private fun createAdListener(): AdManagerInterstitialAdLoadCallback { + return object : AdManagerInterstitialAdLoadCallback() { + override fun onAdLoaded(interstitialAd: AdManagerInterstitialAd) { + super.onAdLoaded(interstitialAd) + + // 5. Display an interstitial ad + interstitialAd.show(this@GamOriginalApiVideoInterstitialActivity) + } + + override fun onAdFailedToLoad(loadAdError: LoadAdError) { + super.onAdFailedToLoad(loadAdError) + Log.e("GAM", "Ad failed to load: $loadAdError") + } + } +} +``` + +#### Step 1: Create an Ad Unit +{:.no_toc} + +Initialize the `InterstitialAdUnit` with the following properties: + +* `configId` - an ID of Stored Impression on the Prebid Server +* `adUnitFormats` - AdUnitFormat.VIDEO for a video ad + +#### Step 2: Configure video parameters +{:.no_toc} + +Provide configuration properties for the video ad using the [VideoParameters](#step-2-configure-video-parameters) object. + +#### Step 3: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +#### Step 4: Load a GAM interstitial ad +{:.no_toc} + +Now you should request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain targeting keywords, and Prebid's ad won't ever be displayed. + +#### Step 5: Present the interstitial ad +{:.no_toc} + +Follow the [GMA SDK guide](https://developers.google.com/ad-manager/mobile-ads-sdk/android/interstitial#display_the_ad) to display an interstitial ad right after receiving it or later in a natural pauses in the flow of an app. + +### Multiformat Interstitial (HTML + Video) + +Integration example: + +```kotlin +// 1. Create InterstitialAdUnit +adUnit = InterstitialAdUnit(configId, EnumSet.of(AdUnitFormat.BANNER, AdUnitFormat.VIDEO)) +adUnit?.setMinSizePercentage(80, 60) +adUnit?.videoParameters = VideoParameters(listOf("video/mp4")) + +// 2. Make a bid request to Prebid Server +val request = AdManagerAdRequest.Builder().build() +adUnit?.fetchDemand(request) { + + // 3. Load a GAM interstitial ad + AdManagerInterstitialAd.load( + this, + AD_UNIT_ID, + request, + createListener() + ) +} +``` + +#### Step 1: Create an Ad Unit +{:.no_toc} + +Initialize the `InterstitialAdUnit` with the following properties: + +* `configId` - an ID of Stored Impression on the Prebid Server +* `adUnitFormats` - ad unit formats for the current ad unit. + +#### Steps 2-3 +{:.no_toc} + +Steps 2-3 are the same as for Display Banner. Setting up banner and video parameters can be found in Display Interstitial and Video Interstitial respectively. + +## Rewarded Video API + +Integration example: + +```kotlin +private fun createAd() { + // 1. Create RewardedVideoAdUnit + adUnit = RewardedVideoAdUnit(CONFIG_ID) + + // 2. Configure Video parameters + adUnit?.videoParameters = configureVideoParameters() + + // 3. Make a bid request to Prebid Server + val request = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(request) { + + // 4. Load a GAM Rewarded Ad + RewardedAd.load( + this, + AD_UNIT_ID, + request, + createListener() + ) + } +} +``` + +Configure video ad unit: + +```kotlin +private fun configureVideoParameters(): VideoParameters { + return VideoParameters(listOf("video/mp4")).apply { + protocols = listOf(Signals.Protocols.VAST_2_0) + playbackMethod = listOf(Signals.PlaybackMethod.AutoPlaySoundOff) + } +} +``` + +Implement Rewarded ad listener: + +```kotlin +private fun createListener(): RewardedAdLoadCallback { + return object : RewardedAdLoadCallback() { + override fun onAdLoaded(rewardedAd: RewardedAd) { + + // 5. Display rewarded ad + rewardedAd.show( + this@GamOriginalApiVideoRewardedActivity + ) { } + } + + override fun onAdFailedToLoad(loadAdError: LoadAdError) { + Log.e("GAM", "Ad failed to load: $loadAdError") + } + } +} +``` + +### Step 1: Create an Ad Unit +{:.no_toc} + +Initialize the Rewarded Video Ad Unit with the following properties: + +* `configId` - an ID of Stored Impression on the Prebid Server + +### Step 2: Configure video parameters +{:.no_toc} + +Provide configuration properties for the video ad using the [VideoParameters](#step-2-configure-video-parameters) object. + +### Step 3: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +### Step 4: Load a GAM Rewarded Ad +{:.no_toc} + +Now you should request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain targeting keywords, and Prebid's ad won't ever be displayed. + +### Step 5: Present the Rewarded Ad +{:.no_toc} + +Follow the [GMA SDK guide](https://developers.google.com/ad-manager/mobile-ads-sdk/android/rewarded#show_the_ad) to display a rewarded ad right after receiving it or later in a natural pauses in the flow of an app. + +## Instream Video API + +Integration example: + +```kotlin +private fun createAd() { + // 1. Create VideoAdUnit + adUnit = InStreamVideoAdUnit(CONFIG_ID, WIDTH, HEIGHT) + + // 2. Configure video parameters + adUnit?.videoParameters = configureVideoParameters() + + // 3. Init player view + playerView = PlayerView(this) + val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 600) + adWrapperView.addView(playerView, params) + + // 4. Make a bid request to Prebid Server + adUnit?.fetchDemand { _: ResultCode?, keysMap: Map? -> + + // 5. Prepare the creative URI + val sizes = HashSet() + sizes.add(AdSize(WIDTH, HEIGHT)) + val prebidURL = Util.generateInstreamUriForGam( + AD_UNIT_ID, + sizes, + keysMap + ) + + adsUri = Uri.parse(prebidURL) + + // 6. Init player + initializePlayer() + } +} +``` + +{: .alert.alert-warning :} +Starting from PrebidMobile `2.1.0` the `VideoAdUnit` class is deprecated. Use `InStreamVideoAdUnit` instead. + +Configure the video ad: + +```kotlin +private fun configureVideoParameters(): VideoParameters { + return VideoParameters(listOf("video/x-flv", "video/mp4")).apply { + placement = Signals.Placement.InStream + + api = listOf( + Signals.Api.VPAID_1, + Signals.Api.VPAID_2 + ) + + maxBitrate = 1500 + minBitrate = 300 + maxDuration = 30 + minDuration = 5 + playbackMethod = listOf(Signals.PlaybackMethod.AutoPlaySoundOn) + protocols = listOf( + Signals.Protocols.VAST_2_0 + ) + } +} +``` + +Init and run IMA player: + +```kotlin +private fun initializePlayer() { + + adsLoader = ImaAdsLoader.Builder(this).build() + + val playerBuilder = SimpleExoPlayer.Builder(this) + player = playerBuilder.build() + playerView!!.player = player + adsLoader!!.setPlayer(player) + + val uri = Uri.parse("https://storage.googleapis.com/gvabox/media/samples/stock.mp4") + + val mediaItem = MediaItem.fromUri(uri) + val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(this, getString(R.string.app_name)) + val mediaSourceFactory = ProgressiveMediaSource.Factory(dataSourceFactory) + val mediaSource: MediaSource = mediaSourceFactory.createMediaSource(mediaItem) + val dataSpec = DataSpec(adsUri!!) + val adsMediaSource = AdsMediaSource( + mediaSource, dataSpec, "ad", mediaSourceFactory, + adsLoader!!, playerView!! + ) + player?.setMediaSource(adsMediaSource) + player?.playWhenReady = true + player?.prepare() +} +``` + +### Step 1: Create an Ad Unit +{:.no_toc} + +Initialize the VideoAdUnit with the following properties: + +* `configId` - an ID of Stored Impression on the Prebid Server +* `width` - Width of the video ad unit. +* `height` - Height of the video ad unit + +### Step 2: Configure the video parameters +{:.no_toc} + +Provide configuration properties for the video ad using the [VideoParameters](#step-2-configure-video-parameters) object. + +### Step 3: Prepare the Player +{:.no_toc} + +Create the instance of `PlayerView` and display it in the app UI. + +### Step 4: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. Use the methods which return the targeting map in the result closure. + +### Step 5: Generate GAM Instream URI +{:.no_toc} + +Using Prebid util method, generate Google IMA URI for downloading the cached creative from the winning bid. + +### Step 6: Cretae and init IMA player +{:.no_toc} + +Follow the Google Guide for [integrating IMA with ExoPlayer](https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/exoplayer-extension) to run a video and show instream ad from the winning bid. + +## Native API + +### Native Banner + +Integration example: + +```kotlin +private fun createAd() { + // 1. Create Ad unit + nativeAdUnit = NativeAdUnit(CONFIG_ID) + nativeAdUnit?.setContextType(NativeAdUnit.CONTEXT_TYPE.SOCIAL_CENTRIC) + nativeAdUnit?.setPlacementType(NativeAdUnit.PLACEMENTTYPE.CONTENT_FEED) + nativeAdUnit?.setContextSubType(NativeAdUnit.CONTEXTSUBTYPE.GENERAL_SOCIAL) + + // 2. Configure Native Assets and Trackers + addNativeAssets(nativeAdUnit) + + // 3. Create GAM Ad View + val gamView = AdManagerAdView(this) + gamView.adUnitId = AD_UNIT_ID + gamView.setAdSizes(AdSize.FLUID) + adWrapperView.addView(gamView) + + // 4. Make a bid request to Prebid Server + val request = AdManagerAdRequest.Builder().build() + nativeAdUnit?.fetchDemand(request) { + + // 5. Load a GAM Ad + gamView.loadAd(request) + } +} +``` + +Add native assets: + +```kotlin +private fun addNativeAssets(adUnit: NativeAdUnit?) { + // ADD ASSETS + + val title = NativeTitleAsset() + title.setLength(90) + title.isRequired = true + adUnit?.addAsset(title) + + val icon = NativeImageAsset(20, 20, 20, 20) + icon.imageType = NativeImageAsset.IMAGE_TYPE.ICON + icon.isRequired = true + adUnit?.addAsset(icon) + + val image = NativeImageAsset(200, 200, 200, 200) + image.imageType = NativeImageAsset.IMAGE_TYPE.MAIN + image.isRequired = true + adUnit?.addAsset(image) + + val data = NativeDataAsset() + data.len = 90 + data.dataType = NativeDataAsset.DATA_TYPE.SPONSORED + data.isRequired = true + adUnit?.addAsset(data) + + val body = NativeDataAsset() + body.isRequired = true + body.dataType = NativeDataAsset.DATA_TYPE.DESC + adUnit?.addAsset(body) + + val cta = NativeDataAsset() + cta.isRequired = true + cta.dataType = NativeDataAsset.DATA_TYPE.CTATEXT + adUnit?.addAsset(cta) + + // ADD EVENT TRACKERS + + val methods = ArrayList() + methods.add(NativeEventTracker.EVENT_TRACKING_METHOD.IMAGE) + + try { + val tracker = NativeEventTracker(NativeEventTracker.EVENT_TYPE.IMPRESSION, methods) + adUnit?.addEventTracker(tracker) + } catch (e: Exception) { + e.printStackTrace() + } +} +``` + +#### Step 1: Create a NativeAdUnit +{:.no_toc} + +Initialize the `NativeAdUnit` with properties: + +* `configId` - an ID of the Stored Impression on the Prebid Server + +#### Step 2: Add Native Assets and Event Trackers +{:.no_toc} + +In order to make a bid request for the native ads you should provide a description of native assets that should be present in the native bid response. Prebid SDK supports the following set of assets to request. + +* `NativeImageAsset` +* `NativeDataAsset` +* `NativeTitleAsset` + +#### Step 3: Create an AdManagerAdView +{:.no_toc} + +Follow the [GMA SDK documentation](https://developers.google.com/ad-manager/mobile-ads-sdk/android/banner) to integrate a banner ad unit. + +#### Step 3: Make a bid request +{:.no_toc} + +The `fetchDemand` method makes a bid request to the Prebid Server. You should provide an `AdManagerAdRequest` object to this method so Prebid SDK sets the targeting keywords of the winning bid for future ad requests. + +#### Step 4: Load an Ad +{:.no_toc} + +Now you should request the ad from GAM. If the `AdManagerAdRequest` contains targeting keywords, the respective Prebid line item will be returned from GAM, and GMA SDK will render its creative. + +Be sure that you make the ad request with the same `AdManagerAdRequest` object that you passed to the `fetchDemand` method. Otherwise, the ad request won't contain targeting keywords, and Prebid's ad won't ever be displayed. + +### In-App Native + +Visit the [AdOps guide](/adops/gam-native.html#create-mobile-in-app-creative) for instructions on setting up the In-App creatives on GAM. + +At a high level, the in-app workflow is happening the following way: + +1. The publisher prepares the ad layout and provides the native ad configuration to the SDK's ad unit. +2. Prebid SDK fetches native demand. However, instead of caching the native assets on the server, the assets are cached locally in the SDK. +3. Ad request are made to Google Ad Manager. +4. Upon receiving results from Google Ad Manager, the SDK determines if any of the received items are from Prebid Server. +5. If there are Prebid ads, the cached assets are then rendered. + +{% capture importantNote %} +The cached assets might expire. If this occurs the publisher will receive a notification and they will have to fetch the assets again. +{% endcapture %} + +#### Integration Example +{:.no_toc} + +```kotlin +private fun createAd() { + // 1. Create NativeAdUnit + adUnit = NativeAdUnit(CONFIG_ID); + adUnit?.setContextType(NativeAdUnit.CONTEXT_TYPE.SOCIAL_CENTRIC) + adUnit?.setPlacementType(NativeAdUnit.PLACEMENTTYPE.CONTENT_FEED) + adUnit?.setContextSubType(NativeAdUnit.CONTEXTSUBTYPE.GENERAL_SOCIAL) + + // 2. Add native assets and trackers + addNativeAssets(adUnit) + + // 3. Make a bid request to Prebid Server + val adRequest = AdManagerAdRequest.Builder().build() + adUnit?.fetchDemand(adRequest) { + + // 4. Load a GAM Native Ad + adLoader = createAdLoader(adWrapperView) + adLoader?.loadAd(adRequest) + } +} +``` + +Add native assets: + +```kotlin +private fun addNativeAssets(adUnit: NativeAdUnit?) { + // ADD NATIVE ASSETS + + val title = NativeTitleAsset() + title.setLength(90) + title.isRequired = true + adUnit?.addAsset(title) + + val icon = NativeImageAsset(20, 20, 20, 20) + icon.imageType = NativeImageAsset.IMAGE_TYPE.ICON + icon.isRequired = true + adUnit?.addAsset(icon) + + val image = NativeImageAsset(200, 200, 200, 200) + image.imageType = NativeImageAsset.IMAGE_TYPE.MAIN + image.isRequired = true + adUnit?.addAsset(image) + + val data = NativeDataAsset() + data.len = 90 + data.dataType = NativeDataAsset.DATA_TYPE.SPONSORED + data.isRequired = true + adUnit?.addAsset(data) + + val body = NativeDataAsset() + body.isRequired = true + body.dataType = NativeDataAsset.DATA_TYPE.DESC + adUnit?.addAsset(body) + + val cta = NativeDataAsset() + cta.isRequired = true + cta.dataType = NativeDataAsset.DATA_TYPE.CTATEXT + adUnit?.addAsset(cta) + + // ADD NATIVE EVENT TRACKERS + val methods = ArrayList() + methods.add(EVENT_TRACKING_METHOD.IMAGE) + methods.add(EVENT_TRACKING_METHOD.JS) + try { + val tracker = NativeEventTracker(NativeEventTracker.EVENT_TYPE.IMPRESSION, methods) + adUnit?.addEventTracker(tracker) + } catch (e: Exception) { + e.printStackTrace() + } +} +``` + +Prepare Native Ad Loader + +```kotlin +private fun createAdLoader(wrapper: ViewGroup): AdLoader? { + val onGamAdLoaded = OnAdManagerAdViewLoadedListener { adManagerAdView: AdManagerAdView -> + Log.d(TAG, "Gam loaded") + adView = adManagerAdView + wrapper.addView(adManagerAdView) + } + + val onUnifiedAdLoaded = OnNativeAdLoadedListener { unifiedNativeAd: NativeAd? -> + Log.d(TAG, "Unified native loaded") + this.unifiedNativeAd = unifiedNativeAd + } + + val onCustomAdLoaded = OnCustomFormatAdLoadedListener { nativeCustomTemplateAd: NativeCustomFormatAd? -> + Log.d(TAG, "Custom ad loaded") + + // 5. Find Prebid Native Ad + AdViewUtils.findNative(nativeCustomTemplateAd!!, object : PrebidNativeAdListener { + override fun onPrebidNativeLoaded(ad: PrebidNativeAd) { + + // 6. Render native ad + inflatePrebidNativeAd(ad, wrapper) + } + + override fun onPrebidNativeNotFound() { + Log.e(TAG, "onPrebidNativeNotFound") + } + + override fun onPrebidNativeNotValid() { + Log.e(TAG, "onPrebidNativeNotValid") + } + }) + } + + return AdLoader.Builder(wrapper.context, AD_UNIT_ID) + .forAdManagerAdView(onGamAdLoaded, AdSize.BANNER) + .forNativeAd(onUnifiedAdLoaded) + .forCustomFormatAd( + CUSTOM_FORMAT_ID, onCustomAdLoaded + ) { customAd: NativeCustomFormatAd?, s: String? -> } + .withAdListener(object : AdListener() { + override fun onAdFailedToLoad(loadAdError: LoadAdError) { + super.onAdFailedToLoad(loadAdError) + Log.e(TAG, "DFP onAdFailedToLoad") + } + }) + .build() +} +``` + +Render a native ad: + +```kotlin +private fun inflatePrebidNativeAd(ad: PrebidNativeAd, wrapper: ViewGroup) { + val nativeContainer = View.inflate(wrapper.context, R.layout.layout_native, null) + + val icon = nativeContainer.findViewById(R.id.imgIcon) + ImageUtils.download(ad.iconUrl, icon) + + val title = nativeContainer.findViewById(R.id.tvTitle) + title.text = ad.title + + val image = nativeContainer.findViewById(R.id.imgImage) + ImageUtils.download(ad.imageUrl, image) + + val description = nativeContainer.findViewById(R.id.tvDesc) + description.text = ad.description + + val cta = nativeContainer.findViewById
        - -### setAutoRefreshMillis -If set on a given Prebid Mobile ad unit, the `fetchDemand` function will be called every `periodMillis` until `stopAutoRefresh` is called. Each call to `fetchDemand` will invoke the `onComplete` function. This refresh only pertains to Prebid Mobile and not to any ad server refresh processes. It is suggested that the adServes refresh be turned off. - -### startAutoRefresh - -Starts the auto-refresh behavior for a given Prebid Mobile ad unit. - -### stopAutoRefresh -Halts the auto-refresh behavior for a given Prebid Mobile ad unit. If no auto-refresh behavior has been set, `stopAutoRefresh` will be ignored. - -### addContextKeyword -Ad Unit context keywords object is a free form list of comma separated keywords about the app as defined in app.keyword in OpenRTB 2.5. The `addContextKeyword` function adds a single keyword to the ad unit. - -``` -func addContextKeyword(_ newElement: String) -``` - -### addContextKeywords -Ad Unit context keywords object is a free form list of comma separated keywords about the app as defined in app.keyword in OpenRTB 2.5. The `addContextKeywords` function adds a multiple keyword to the ad unit. - -``` -func addContextKeywords(_ newElements: Set) -``` - -### removeContextKeyword - -``` -func removeContextKeyword(_ element: String) -``` - -### clearContextKeywords - -``` -func clearContextKeywords() -``` - - - - -### Data Object - -The Data object is free form data (also known as First Party Data)supplied by the publisher to provide additional targeting of the user or inventory context, used primarily for striking PMP (Private MarketPlace) deals with Advertisers. Data supplied in the data parameters are typically not sent to DSPs whereas information sent in non-data objects (i.e. `setYearOfBirth`, `setGender`, etc.) will be. Access to FPD can be limited to a supplied set of Prebid bidders via an access control list. - -Data is broken up into two different data types: -* User - * Global in scope only -* Inventory (context) - * Global scope - * Ad Unit grain - - The below first party inventory context will apply to the specic ad unit the data object is applied to. For global user or inventory context level first party data, refer to [first party data section of the Targeting](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html#first-party-data) page. - -#### addContextData -``` -func addContextData(key: String, value: String) -``` - -**Parameters** -`key`: string containing the key for the specific data object -`value`: String containing the value for the supplied key - - -#### updateContextData -``` -func updateContextData(key: String, value: Set) -``` - -**Parameters** -`key`: string containing the key for the specific data object -`value`: String containing the value for the supplied key - - -#### removeContextData -``` -func removeContextData(forKey: String) -``` - -**Parameters** -`key`: string containing the key for the specific data object -`value`: String containing the value for the supplied key - - -#### clearContextData -``` -func clearContextData() -``` - - - -## Examples - -**fetchDemand** - -**Swift** - - -
        -
        
        -
        - func loadDFPBanner(bannerUnit : AdUnit){
        -
        -     let bannerUnit = BannerAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45", size: CGSize(width: 300, height: 250))
        -     bannerUnit.ortb2Imp.ext.data.pbadslot = "/1111111/homepage/med-rect-2"`
        -
        -    let dfpBanner = DFPBannerView(adSize: kGADAdSizeMediumRectangle)
        -    dfpBanner.adUnitID = "/19968336/PriceCheck_300x250"
        -    dfpBanner.rootViewController = self
        -
        -    bannerView.addSubview(dfpBanner)
        -    request.testDevices = [ kGADSimulatorID ]
        -
        -    // Do any additional setup after loading the view, typically from a nib.
        -    bannerUnit.fetchDemand(adObject: self.request) { (ResultCode) in
        -        print("Google Ad Manager banner bids fetch successfull")
        -        dfpBanner.load(self.request)
        -    }
        -}
        -
        - -**Objective-C** - -``` --(void) loadDFPBanner { - - self.bannerUnit = [[BannerAdUnit alloc] initWithConfigId:@"6ace8c7d-88c0-4623-8117-75bc3f0a2e45" size:CGSizeMake(300, 250)]; - [self.bannerUnit setAutoRefreshMillisWithTime:35000]; - self.dfpView = [[DFPBannerView alloc] initWithAdSize:kGADAdSizeMediumRectangle]; - self.dfpView.rootViewController = self; - self.dfpView.adUnitID = @"/19968336/PrebidMobileValidator_Banner_All_Sizes"; - self.dfpView.delegate = self; - [self.bannerView addSubview:self.dfpView]; - self.dfpView.backgroundColor = [UIColor redColor]; - self.request = [[DFPRequest alloc] init]; - self.request.testDevices = @[kDFPSimulatorID]; - - [self.bannerUnit fetchDemandWithAdObject:self.request completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - dispatch_async(dispatch_get_main_queue(), ^{ - [self.dfpView loadRequest:self.request]; - }); - }]; -} -``` ---- -**addKeyword** - -``` -bannerUnit.addKeyword(key:"Sample", value:"Value to add") -``` - -**removeUserKeyword** - -``` -bannerUnit.removeUserKeyword(forKey:"sample") -``` - -**clearUserKeywords** - -``` -bannerUnit.clearUserKeywords() -``` - -**setAutoRefreshMillis** - -``` -bannerUnit.setAutoRefreshMillis(time:Double) -``` -**stopAutoRefresh** - -``` -bannerUnit.stopAutoRefresh() -``` - -**addContextKeyword** -``` -bannerAdUnit.addContextKeyword("adunitContextKeywordValue1") -bannerAdUnit.addContextKeyword("adunitContextKeywordValue2") -bannerAdUnit.addContextKeyword("adunitContextKeywordValue3") -``` - -**addContextData** -``` -bannerAdUnit.addContextData(key: "adunitContextDataKey1", value: "adunitContextDataValue1") -``` - - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Intersitial Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-api-ios.md b/prebid-mobile/pbm-api/ios/pbm-api-ios.md deleted file mode 100755 index 48b7abce0c..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-api-ios.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -layout: page_v2 -title: Prebid Mobile API - iOS -description: Prebid Mobile API - iOS -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Prebid Mobile API - iOS - -Use the Prebid Mobile API 1.0 for iOS to implement header bidding in your mobile apps. The elements in the API will allow you to participate in a header bidding auction and communicate with your ad server to display a creative. The API supports banner and interstitial creatives. - -## Key Features - -- The Publisher knows if the keywords are attached to the `adUnit`. -- Implements and supports its own auto refresh, no longer supporting `adServer` refresh. -- Clear [result codes](/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) that details the response of the Prebid demand fetch request. - -## Objects - -The Prebid Mobile API supports the following objects: - -- [Global Settings]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Interstitial Ad Unit](/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) - -## Result Codes - -For a list of possible result codes, see [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html). - -## Global Targeting - -For general targeting information, see [Global Targeting]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) Parameters. diff --git a/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.md b/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.md deleted file mode 100755 index 04f0c91559..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -layout: page_v2 -title: Prebid Mobile API Result Codes -description: Prebid Mobile API Result Codes -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Prebid Mobile API Result Codes - -When you use the Prebid Mobile API to retrieve bids, you'll receive a ResultCode indicating whether the request was successful. This page provides a descriptions of each code, and where go to find more information. - -## Success - -- **Return Code:** SUCCESS -- **Description:** Prebid Mobile received at least one valid bid from Prebid Server and successfully associated Prebid key-values with the appropriate ad server request. - -## Prebid Server Error - -- **Return Code**: PREBID_SERVER_ERROR -- **Description**: * General result code for an unknown error returned from Prebid Server. The actual Prebid Server error message will be exposed to the developer. - -## Invalid account ID - -- **Return Code**: INVALID_ACCOUNT_ID -- **Description**: Prebid Server did not recognize the account ID. Make sure you included an account ID and that the account ID you've set on the PrebidMobileObject is correct. -- **More Information**: [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) - -## Invalid configuration ID - -- **Return Code**: INVALID_CONFIG_ID -- **Description**: Prebid Server did not recognize the configuration ID that was passed in on your banner or interstitial ad unit object. Be sure you've passed in a non-empty configuration ID and that the ID is correct. -- **More Information**: - - [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) - - [InterstitialAdUnit](/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) - -## Invalid size - -- **Return Code**: INVALID_SIZE -- **Description**: Attempted to add an invalid size to a banner ad unit. This error usually occurs if you've attempted to add multiple sizes on a request to Mopub; Mopub allows only a single size. -- **More Information**: [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) - -## Network error - -- **Return Code**: NETWORK_ERROR -- **Description**: A network error occurred during the request to Prebid Server. - -## Timeout - -**Return Code**: TIME_OUT -**Description**: The ad request to Prebid Server exceeded the timeout period. - -## No bids - -- **Return Code**: NO_BIDS -- **Description**: Prebid Server responded without returning any valid bids. - -## Empty host URL - -- **Return Code**: INVALID_HOST_URL -- **Description**: Attempted to define a custom Prebid Server host without providing a host URL. -- **More Information**: [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Intersitial Ad Unit](/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.md deleted file mode 100755 index de4b40e466..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -layout: page_v2 -title: BannerAdUnit AdUnit -description: BannerAdUnit AdUnit -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# BannerAdUnit: AdUnit -{: .notoc} - -The BannerAdUnit is a subclass of the [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) class. Use the BannerAdUnit object to create and configure a banner ad unit in your app. - -- TOC - {:toc} - -## Object - -### BannerAdUnit - -Create a new Banner Ad Unit associated with a Prebid Server configuration ID and a banner size. - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - -**Parameters** - -`configId (String)`: Prebid Server configuration ID. - -`size (CGSize)`: Width and height of the banner. - - -#### Parameters - - -Parameters is a sub class of BannerAdUnit. Create a new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes. - -`api: [int]`: OpenRTB placement - -**Parameters** - -Array of integers or a predefined constant representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Frameworks. While OpenRTB allows additional API Frameworks, they were intentionally left out as constants since they do not make sense in a banner context. If there is a desire to pass API Frameworks that are not represented as a constants within Parameters, they can be passed an integer, where Prebid SDK will pass Prebid Server whatever is present: - -* `3` or `Signals.Api.MRAID_1` : MRAID-1 support signal -* `5` or `Signals.Api.MRAID_2` : MRAID-2 support signal -* `6` or `Signals.Api.MRAID_3` : MRAID-3 support signal -* `7` or `Signals.Api.OMID_1` : signals OMSDK support - - -## Methods - -### addAdditionalSize - -* Add an additional banner size to the Prebid Mobile ad unit. Banner ad units must be associated with one or more sizes. - -**Parameters** - -`sizes (CGSize)`: The width and height of the banner ad. - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for addtional parameters and methods. - ---- - -## Examples - -**Create a BannerAdUnit** -``` -let bannerUnit = BannerAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45", size: CGSize(width: 300, height: 250)) -``` -**Add additional ad sizes** - -``` -bannerUnit.addAdditionalSize(sizes: [CGSize(width: 320, height: 50), CGSize(width: 300, height: 250)]) -``` -Once a BannerAdUnit is created use Google Mobile Ads or MoPub to retrieve and display creatives. - -** Define any appropriate API Frameworks ** - -Swift -```swift -let parameters = BannerAdUnit.Parameters() -parameters.api = [Signals.Api.MRAID_2] //parameters.api = [Signals.Api(5)] -adUnit.setParameters(parameters); -``` - -Objective C -``` -PBBannerAdUnitParameters* parameters = [[PBBannerAdUnitParameters alloc] init]; -parameters.api = @[PBApi.MRAID_2]; -//parameters.api = @[[[PBApi alloc] initWithIntegerLiteral:5]]; -bannerAdUnit.parameters = parameters; -``` - -**Google Mobile Ads** - -Import the GoogleMobileAds from the [google-mobile-sdk](https://developers.google.com/admob/ios/download) into the UIViewController displaying the BannerAdUnit - -**Swift** -``` -func loadDFPBanner(bannerUnit : AdUnit){ - print("Google Mobile Ads SDK version: \(DFPRequest.sdkVersion())") - dfpBanner = DFPBannerView(adSize: kGADAdSizeMediumRectangle) - dfpBanner.adUnitID = "/19968336/PrebidMobileValidator_Banner_All_Sizes" - dfpBanner.rootViewController = self - dfpBanner.delegate = self - dfpBanner.backgroundColor = .red - appBannerView.addSubview(dfpBanner) - request.testDevices = [ kGADSimulatorID,"cc7ca766f86b43ab6cdc92bed424069b"] - - bannerUnit.fetchDemand(adObject:self.request) { (ResultCode) in - print("Prebid demand fetch for Google Ad Manager \(ResultCode.name())") - self.dfpBanner!.load(self.request) - } - } -``` -**Objective-C** - -``` --(void) loadDFPBanner { - - self.bannerUnit = [[BannerAdUnit alloc] initWithConfigId:@"6ace8c7d-88c0-4623-8117-75bc3f0a2e45" size:CGSizeMake(300, 250)]; - [self.bannerUnit setAutoRefreshMillisWithTime:35000]; - self.dfpView = [[DFPBannerView alloc] initWithAdSize:kGADAdSizeMediumRectangle]; - self.dfpView.rootViewController = self; - self.dfpView.adUnitID = @"/19968336/PrebidMobileValidator_Banner_All_Sizes"; - self.dfpView.delegate = self; - [self.bannerView addSubview:self.dfpView]; - self.dfpView.backgroundColor = [UIColor redColor]; - self.request = [[DFPRequest alloc] init]; - self.request.testDevices = @[kDFPSimulatorID]; - - [self.bannerUnit fetchDemandWithAdObject:self.request completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - dispatch_async(dispatch_get_main_queue(), ^{ - [self.dfpView loadRequest:self.request]; - }); - }]; -} -``` - - -**MoPub** - -Import MoPub from the [mopub-ios-sdk](https://github.com/mopub/mopub-ios-sdk) into the UIViewController displaying the BannerAdUnit - -**Swift** -``` -func loadMoPubBanner(bannerUnit: AdUnit){ - - let sdkConfig = MPMoPubConfiguration(adUnitIdForAppInitialization: "a935eac11acd416f92640411234fbba6") - sdkConfig.globalMediationSettings = [] - - MoPub.sharedInstance().initializeSdk(with: sdkConfig) { - - } - - mopubBanner = MPAdView(adUnitId: "a935eac11acd416f92640411234fbba6", size: CGSize(width: 300, height: 250)) - mopubBanner!.delegate = self - - appBannerView.addSubview(mopubBanner!) - - // Do any additional setup after loading the view, typically from a nib. - bannerUnit.fetchDemand(adObject: mopubBanner!){ (ResultCode) in - print("Prebid demand fetch for mopub \(ResultCode)") - - self.mopubBanner!.loadAd() - } - - } -``` - -**Objective-C** - -``` --(void) loadMoPubBanner { - - MPMoPubConfiguration *configuration = [[MPMoPubConfiguration alloc] initWithAdUnitIdForAppInitialization:@"a935eac11acd416f92640411234fbba6"]; - - [[MoPub sharedInstance] initializeSdkWithConfiguration:configuration completion:^{ - - }]; - self.mopubAdView = [[MPAdView alloc] initWithAdUnitId:@"a935eac11acd416f92640411234fbba6" size:CGSizeMake(300, 250)]; - self.mopubAdView.delegate = self; - - [self.bannerView addSubview:self.mopubAdView]; - - self.bannerUnit = [[BannerAdUnit alloc] initWithConfigId:@"6ace8c7d-88c0-4623-8117-75bc3f0a2e45" size:CGSizeMake(300, 250)]; - // Do any additional setup after loading the view, typically from a nib. - [self.bannerUnit fetchDemandWithAdObject:self.mopubAdView completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - [self.mopubAdView loadAd]; - }]; -} -``` - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Intersitial Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.md deleted file mode 100755 index 428d549eec..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -layout: page_v2 -title: InterstitialAdUnit - iOS -description: InterstitialAdUnit - iOS -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- -# InterstitialAdUnit (Banner) - -The InterstitialAdUnit is a subclass of the [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) class. Use the InterstitialAdUnit object to create and configure a interstitial ad unit in your app. - -## Object - -### InterstitialAdUnit - -Create a new Interstitial Ad Unit associated with a Prebid Server configuration ID. - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - -As of version 1.2+, Prebid SDK has extended the functionality of Interstitial ad monetization by using a smart ad size selection process to monetize sizes smaller than full screen ads. App developers can speicify a minimun width and minimum height percentage an ad can occupy of a devices real state, with Prebid Server (PBS) deriving a limited set of ad sizes (max 10) as eligible for the auction. - -PBS will take the AdUnit's size (width and height) as the max size for the interstitial as size, generating a list of ad sizes, selecting the first 10 sizes that fall within the imp's max size and minimum percentage size. All the interstitial parameters will still be passed to the bidders, allowing them to use their own size matching algorithms if they prefer. - -Prebid Server will send the eligible size list to each bidder to solicit a bid. For a full description of the Prebid Server logic, please refer to the [Prebid Server PR 797](https://github.com/prebid/prebid-server/pull/797/files). - -``` -BannerInterstitialAdUnit(configId: String, minWidthPerc: Int, minHeightPerc: Int) -``` - -**Parameters** - -`configId`: Prebid Server configuration ID. - -`minWidthPerc`: Optional parameter to specify the minimum width percent an ad may occuy of a device's real estate. Support in SDK version 1.2+ - -`minHeightPrec`: Optional parameter to specify the minimum height percent an ad may occuy of a device's real estate. Support in SDK version 1.2+ - -#### Parameters - - -Parameters is a sub class of BannerAdUnit. Create a new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes. - -`api: [int]`: OpenRTB placement - -**Parameters** - -Array of integers or a predefined constant representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Frameworks. While OpenRTB allows additional API Frameworks, they were intentionally left out as constants since they do not make sense in a banner context. If there is a desire to pass API Frameworks that are not represented as a constants within Parameters, they can be passed an integer, where Prebid SDK will pass Prebid Server whatever is present: - -* `3` or `Signals.Api.MRAID_1` : MRAID-1 support signal -* `5` or `Signals.Api.MRAID_2` : MRAID-2 support signal -* `6` or `Signals.Api.MRAID_3` : MRAID-3 support signal -* `7` or `Signals.Api.OMID_1` : signals OMSDK support - - - -## Examples - -**Create an InterstitialAdUnit** - -``` -let adUnit = InterstitialAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45") -``` - -With optional minWidthPerc and minHeightPerc parameters. -``` -let adUnit = InterstitialAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45", minWidthPerc: 50, minHeightPerc: 70) -``` - - -** Define any appropriate API Frameworks ** - -Swift -```swift -let parameters = BannerAdUnit.Parameters() -parameters.api = [Signals.Api.MRAID_2] //parameters.api = [Signals.Api(5)] -adUnit.setParameters(parameters); -``` - -Objective C -``` -PBBannerAdUnitParameters* parameters = [[PBBannerAdUnitParameters alloc] init]; -parameters.api = @[PBApi.MRAID_2]; -//parameters.api = @[[[PBApi alloc] initWithIntegerLiteral:5]]; -bannerAdUnit.parameters = parameters; -``` - -**Google Mobile Ads** - -**Swift** -``` -func loadDFPInterstitial(adUnit : AdUnit){ - print("Google Mobile Ads SDK version: \(DFPRequest.sdkVersion())") - - let interstitialUnit = InterstitialAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45", minWidthPerc: 50, minHeightPerc: 70) - dfpInterstitial = DFPInterstitial(adUnitID: "/19968336/PrebidMobileValidator_Interstitial") - dfpInterstitial.delegate = self - request.testDevices = [ kGADSimulatorID] - interstitialUnit.fetchDemand(adObject:self.request) { (ResultCode) in - - print("Prebid demand fetch for DFP \(ResultCode)") - self.dfpInterstitial!.load(self.request) - } - } -``` - -**Objective-C** - -``` --(void) loadDFPInterstitial { - - self.interstitialUnit = [[InterstitialAdUnit alloc] initWithConfigId:@"625c6125-f19e-4d5b-95c5-55501526b2a4" minWidthPerc:50 minHeightPerc:70]; - self.dfpInterstitial = [[DFPInterstitial alloc] initWithAdUnitID:@"/19968336/PrebidMobileValidator_Interstitial"]; - self.dfpInterstitial.delegate = self; - self.request = [[DFPRequest alloc] init]; - self.request.testDevices = @[kDFPSimulatorID]; - [self.interstitialUnit fetchDemandWithAdObject:self.request completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - [self.dfpInterstitial loadRequest:self.request]; - }]; -} -``` ---- -**MoPub** - -**Swift** - - -``` - func loadMoPubInterstitial(adUnit: AdUnit){ - - let interstitialUnit = InterstitialAdUnit(configId: "625c6125-f19e-4d5b-95c5-55501526b2a4") - - let sdkConfig = MPMoPubConfiguration(adUnitIdForAppInitialization: "2829868d308643edbec0795977f17437") - sdkConfig.globalMediationSettings = [] - - MoPub.sharedInstance().initializeSdk(with: sdkConfig) { - - } - - self.mopubInterstitial = MPInterstitialAdController(forAdUnitId: "2829868d308643edbec0795977f17437") - self.mopubInterstitial.delegate = self - - // Do any additional setup after loading the view, typically from a nib. - interstitialUnit.fetchDemand(adObject: mopubInterstitial!){ (ResultCode) in - print("Prebid demand fetch for mopub \(ResultCode)") - - self.mopubInterstitial.loadAd() - } - - } -``` - -**Objective-C** - -``` --(void) loadMoPubInterstitial { - - self.interstitialUnit = [[InterstitialAdUnit alloc] initWithConfigId:@"625c6125-f19e-4d5b-95c5-55501526b2a4"]; - MPMoPubConfiguration *configuration = [[MPMoPubConfiguration alloc] initWithAdUnitIdForAppInitialization:@"2829868d308643edbec0795977f17437"]; - [[MoPub sharedInstance] initializeSdkWithConfiguration:configuration completion:nil]; - self.mopubInterstitial = [MPInterstitialAdController interstitialAdControllerForAdUnitId:@"2829868d308643edbec0795977f17437"]; - self.mopubInterstitial.delegate = self; - [self.interstitialUnit fetchDemandWithAdObject:self.mopubInterstitial completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - [self.mopubInterstitial loadAd]; - }]; - - -} -``` -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-code-integration-ios.md b/prebid-mobile/pbm-api/ios/pbm-code-integration-ios.md deleted file mode 100644 index 6de803a46e..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-code-integration-ios.md +++ /dev/null @@ -1,260 +0,0 @@ ---- -layout: page_v2 -title: Code Integration -description: Code Integration -pid: 1 -top_nav_section: prebid-mobile -nav_section: prebid-mobile-ios -sidebarType: 2 ---- - - - - -# Code Integration for iOS - -Get started with Prebid Mobile by creating a [Prebid Server account]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html). - -### Use Cocoapods? - -Easily include the Prebid Mobile SDK for your primary ad server in your Podfile. - -``` -platform :ios, '8.0' - -target 'MyAmazingApp' do - pod 'PrebidMobile' -end -``` - -### Build framework from source - -Build Prebid Mobile from source code. After cloning the repo, from the root directory run - -``` -./scripts/buildPrebidMobile.sh -``` - -to output the PrebidMobile.framework. - - - - -## Ad Unit Setup for iOS -{:.no_toc} - -Register Prebid Mobile ad units as early as possible in the application's lifecycle. - -When registering a Prebid Mobile ad unit, you must replace `@"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. Prebid Mobile will use this identifier to determine the unique ad unit to which bid key-values will be associated. This identifier must be unique across all registered Prebid Mobile ad units, and does not need to map to any ad unit ID defined in your ad server. - -We recommend doing this in the `didFinishLaunchingWithOptions` method in `AppDelegate` using the following steps, as shown in the code sample below: - -1. Create the ad units and add sizes for banner ad units. Be sure to replace `@"PREBID-MOBILE-SLOT-ID"` with a unique user-defined identifier. - - NOTE: The [fluid ad size](https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/api/reference/Constants#/c:@kGADAdSizeFluid) (used in Google Ad Manager) is not supported. - -2. Add a server-side configuration for each ad unit to Prebid Server Adapter. -3. Set targeting parameters for the ad units. (Optional) -4. Set the primary adserver for the bid to either Google Ad Manager or MoPub. (Primary ad server is necessary to determine the caching mechanism.) -5. Set the Prebid Server host to AppNexus or Rubicon. -6. Register the ad units with the adapter to start the bid fetching process. - -### User-Replaced Macros - -In the code snippets below, any values that must be substituted by your developers are identified in capital letters. These values are defined below: - -{: .table .table-bordered .table-striped } -| Value | Description | -|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `PREBID-SERVER-ACCOUNT-ID` | Your unique account ID with your Prebid Server vendor. | -| `PREBID-SERVER-CONFIGURATION-ID` | The ID of a Prebid Server demand partner configuration. Represents the set of demand that will be fetched for a given ad unit. | - - -### Ad Unit Registration - -Embed the ad unit registration in a try-catch block to catch all the exceptions (if any) thrown by the SDK. - -#### Objective-C - -ViewController.h -``` -@interface ViewController : UIViewController - -@property (nonatomic, strong) NSString *adServer; -@property (nonatomic, strong) NSString *adUnit; - -@end -``` -ViewController.m -``` -@import PrebidMobile; -@import GoogleMobileAds; - -@interface ViewController () - - @property (weak, nonatomic) IBOutlet UIView *bannerView; - @property (nonatomic, strong) DFPBannerView *dfpView; - @property (nonatomic, strong) DFPInterstitial *dfpInterstitial; - @property (nonatomic, strong) DFPRequest *request; - @property (nonatomic, strong) MPAdView *mopubAdView; - @property (nonatomic, strong) MPInterstitialAdController *mopubInterstitial; - @property (nonatomic, strong) BannerAdUnit *bannerUnit; - @property (nonatomic, strong) InterstitialAdUnit *interstitialUnit; - -@end -... - -Prebid.shared.prebidServerAccountId = @"PREBID-SERVER-ACCOUNT-ID"; -Prebid.shared.prebidServerHost = PrebidHostAppnexus -Prebid.shared.shareGeoLocation = true; -``` -Create the ad units and add sizes for banner ad units. Replace `PREBID-SERVER-CONFIGURATION-ID` with the ID of your Prebid Server demand partner configuration. - - ``` -self.bannerUnit = [[BannerAdUnit alloc] initWithConfigId:@"PREBID-SERVER-CONFIGURATION-ID" size:CGSizeMake(300, 250)]; -``` -Set targeting parameters for the ad units (Optional). - - ``` -[[Targeting sharedInstance] setAge:25]; -[[Targeting sharedInstance] setGender:PBTargetingParamsGenderFemale]; -``` - - Register the ad units with Prebid Mobile to start bid fetching process. - - If you are using a Prebid Server host other than AppNexus, be sure to replace `PBServerHostAppNexus`. - - **Google Ad Manager Example** - -``` - self.dfpView = [[DFPBannerView alloc] initWithAdSize:kGADAdSizeMediumRectangle]; - self.dfpView.rootViewController = self; -self.dfpView.adUnitID = @"/19968336/PrebidMobileValidator_Banner_All_Sizes"; -self.dfpView.delegate = self; -[self.bannerView addSubview:self.dfpView]; - self.dfpView.backgroundColor = [UIColor redColor]; -self.request = [[DFPRequest alloc] init]; -self.request.testDevices = @[kDFPSimulatorID]; - -[self.bannerUnit fetchDemandWithAdObject:self.request completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - dispatch_async(dispatch_get_main_queue(), ^{ - [self.dfpView loadRequest:self.request]; - }); -}]; -``` -**MoPub Example** - -``` -MPMoPubConfiguration *configuration = [[MPMoPubConfiguration alloc] initWithAdUnitIdForAppInitialization:@"a935eac11acd416f92640411234fbba6"]; - - [[MoPub sharedInstance] initializeSdkWithConfiguration:configuration completion:^{ - }]; -self.mopubAdView = [[MPAdView alloc] initWithAdUnitId:@"a935eac11acd416f92640411234fbba6" size:CGSizeMake(300, 250)]; -self.mopubAdView.delegate = self; - - [self.bannerView addSubview:self.mopubAdView]; - - self.bannerUnit = [[BannerAdUnit alloc] initWithConfigId:@"6ace8c7d-88c0-4623-8117-75bc3f0a2e45" size:CGSizeMake(300, 250)]; - // Do any additional setup after loading the view, typically from a nib. - [self.bannerUnit fetchDemandWithAdObject:self.mopubAdView completion:^(enum ResultCode result) { - NSLog(@"Prebid demand result %ld", (long)result); - [self.mopubAdView loadAd]; - }]; -``` - - - -#### Swift -``` -import PrebidMobile -import GoogleMobileAds -import MoPub - -... - -@IBOutlet var appBannerView: UIView! -@IBOutlet var adServerLabel: UILabel! - -var adServerName:String = "" -let request = DFPRequest() -var dfpBanner: DFPBannerView! -var mopubBanner: MPAdView? -``` -Create the ad units and add sizes for banner ad units. Replace `PREBID-SERVER-CONFIGURATION-ID` with the ID of your Prebid Server demand partner configuration. Replace `PREBID-SERVER-ACCOUNT-ID` with your unique account ID with your Prebid Server vendor. - -``` -Prebid.shared.prebidServerAccountId = "`PREBID-SERVER-ACCOUNT-ID" -Prebid.shared.shareGeoLocation = true - -let bannerUnit = BannerAdUnit(configId: "PREBID-SERVER-CONFIGURATION-ID", size: CGSize(width: 300, height: 250)) - bannerUnit.setAutoRefreshMillis(time: 35000) -``` -**Google Ad Manager Example** - -``` -dfpBanner = DFPBannerView(adSize: kGADAdSizeMediumRectangle) -dfpBanner.adUnitID = "/19968336/PrebidMobileValidator_Banner_All_Sizes" -dfpBanner.rootViewController = self -dfpBanner.delegate = self -dfpBanner.backgroundColor = .red -appBannerView.addSubview(dfpBanner) -request.testDevices = [ kGADSimulatorID,"cc7ca766f86b43ab6cdc92bed424069b"] - -bannerUnit.fetchDemand(adObject:self.request) { (ResultCode) in - print("Prebid demand fetch for Google Ad Manager \(ResultCode.name())") - self.dfpBanner!.load(self.request) - } -``` -**MoPub Example** -``` -let sdkConfig = MPMoPubConfiguration(adUnitIdForAppInitialization: "a935eac11acd416f92640411234fbba6") - sdkConfig.globalMediationSettings = [] - - MoPub.sharedInstance().initializeSdk(with: sdkConfig) { - - } - -mopubBanner = MPAdView(adUnitId: "a935eac11acd416f92640411234fbba6", size: CGSize(width: 300, height: 250)) -mopubBanner!.delegate = self - -appBannerView.addSubview(mopubBanner!) - -// Do any additional setup after loading the view, typically from a nib. -bannerUnit.fetchDemand(adObject: mopubBanner!){ (ResultCode) in - print("Prebid demand fetch for mopub \(ResultCode)") - self.mopubBanner!.loadAd() -} -``` -Note that host should be the prebid server host you're using. - -### Set Ad Server Targeting -{:.no_toc} - -Prebid Mobile continuously pre-caches creatives in the background, so that right before the ad unit makes an ad request from your network, your app can ask Prebid Mobile for a bid price and creative without waiting as shown in the code below. - -**Objective-C** - ``` - [self.bannerAdUnit addUserKeyword:(NSString*)key:(NSString*)value]; -``` - -**Swift** -``` -self.bannerAdUnit.addUserKeyword(key: string, value: string) -``` - - -Use the table below to see which ad objects are supported currently. - -{: .table .table-bordered .table-striped } -| Primary Ad Server | Ad Object Type | Ad Server Ad View | Ad Server Ad Load Method | -|-------------------|----------------|------------------------------|---------------------------------------------| -| Google Ad Manager | Banner | `DFPBannerView` | `- (void)loadRequest:(GADRequest *)request` | -| Google Ad Manager | Interstitial | `DFPInterstitial` | `- (void)loadRequest:(GADRequest *)request` | -| MoPub | Banner | `MPAdView` | `- (void)loadAd` | -| MoPub | Interstitial | `MPInterstitialAdController` |` - (void)loadAd` | --> - -## Further Reading - -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-native-inapp-ios.md b/prebid-mobile/pbm-api/ios/pbm-native-inapp-ios.md deleted file mode 100644 index 95d2d2c45d..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-native-inapp-ios.md +++ /dev/null @@ -1,365 +0,0 @@ ---- -layout: page_v2 -title: Native In App Rendering - iOS -description: Native In App Rendering for iOS -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Native In App Rendering -{: .notoc} - -This document describes the Prebid Mobile (PBM) Native In App Rendering capability. Though PBM has the ability to render native ad components through its Banner Ad object, PBM's Native In App Rendering solution enables publishers to render the native assets in native code. - -## Overview - -At a high level the in app rendering process works like this: - -1. The publisher configures a native ad unit. -2. PBM fetches native demand. However, instead of caching the native assets on the server, the assets are cached locally in the SDK. -3. Bid request are made to Google Ad Manager/MoPub. -4. Upon receiving results from Google Ad Manager/MoPub, PBM determines if any of the received items are from Prebid Server. -5. If there are Prebid ads, the cached assets are then rendered. - -{% capture importantNote %} -The cached assets might expire. If this occurs the publisher will receive a notification and they will have to fetch the assets again. -{% endcapture %} - -{% include alerts/alert_important.html content=importantNote %} - -## Ad Ops Setup - -These instructions will enable you to create a creative template in either Google Ad Manager or MoPub that can then be applied to native ads in your app. - -### Google Ad Manager - -1. Sign in to Google Ad Manager. -2. Create an ad unit with fluid ad size. -3. Click `Delivery` and then `Native` -4. Click `Create native ad`. -5. Click `Android & iOS app code`. -6. Name your new format. -7. Choose `ADD VARIABLE` and add the following variable names and placeholders. - - {: .table .table-bordered .table-striped } - | Variable Name | Place Holder | - |---------------------+----------------------------------| - | isPrebid | [%isPrebid%] | - | hb_cache_id_local | [%hb_cache_id_local%] | - - Make sure to indicate that the variables are required. - -8. Return to the home screen, click `Delivery > Creatives`, and create a creative with `Native Format`, choosing the template you created. In the user-defined variables you just created, set the following values: - - {: .table .table-bordered .table-striped } - | Variable Name | Value | - |---------------------+----------------------------------| - | isPrebid | 1 | - | hb_cache_id_local | %%PATTERN:hb_cache_id_local%% | - -9. Now create Prebid line items with price priority and a display ad type that are targeting `hb_pb key-values`. Associate the creative you added in steps 4 thru 8 (making sure to choose your native format as expected creatives on the line item) to the ad unit you created in the second step. - -### MoPub - -1. Sign in to MoPub. -2. Select the order for the Prebid line items. -3. Create a line item that targets an `hb_pb key-value`. -4. Save your line item. -5. Create the creative. When prompted, input a name and choose the format `Native`. -6. Instead of `Easy Form` choose `Manual JSON`. -7. In the JSON input field insert the following content: -
        -
        -{
        -"mainimage": "https://dummyimage.com/600x400/000/fff",
        -"isPrebid": true,
        -"hb_cache_id_local": "%%KEYWORD:hb_cache_id_local%%"
        -}
        -
        -
        - -8. Click `Save`. - -{% capture importantNote %} -The mainimage is a dummy field that MoPub requires for caching. If the dummy image is not added, the ad will not work. You can insert any dummy pixel. -{% endcapture %} - -{% include alerts/alert_important.html content=importantNote %} - -## Code Integration - -### Interface - -#### NativeAdDelegate - -The `NativeAdDelegate` protocol provides three methods to handle the display and check the validity of the returned native ad. - -##### Methods - - **nativeAdLoaded** - - Use this method to pass a `NativeAd` to inflate. - -*Parameters* - - {: .table .table-bordered .table-striped } - | Name | Scope | Type | Description | - |-----------------+----------+----------+-----------------------| - | NativeAd | Required | ad | A NativeAd | - - **nativeAdNotFound** - - Use this method when a `NativeAd` is not found in the server returned response. The ad should be displayed as a regular AdUnit type. - - **nativeAdNotValid** - - Use this method when a Prebid native ad was returned, but a `NativeAd` object was not able to be created from the cached assets. Display different content. - -### Classes - -#### NativeAd - -An object representing the `NativeAd` to be displayed. - -#### Using Asset Ids with In-App Native Ad Units - -Setting this option to `true`, in your instance of Prebid Mobile, enables you to add an id for each asset in the assets array. The default setting is `false` - -**Swift** -``` -Prebid.shared.shouldAssignNativeAssetID = true -``` - -**Objective C** -``` -[Prebid shared].shouldAssignNativeAssetID = YES; -``` -##### Methods - - *registerViews* - - Takes a `View` that will handle the display of the native asset image and a `listener` object. - - *Parameters* - - {: .table .table-bordered .table-striped } - | Name | Scope | Type | Description | - |-----------------+----------+----------+--------------------------------------------------| - | view | Required | View | The view to display the native asset image in. | - | | | | | - - **unregister** - - Unregisters the `View` stored for displaying the native asset's image. - -##### Getters - - Use these getters to return various components of the native ad. - - {: .table .table-bordered .table-striped } - | Name | Returns | Description | - |-----------------+-------------+-----------------------------------------------| - | getTitle | String | Returns the title of the native ad. | - | getDescription | String | Returns the description of the native ad. | - | getIconUrl | String | Returns the path for the icon of the native ad. | - | getImageUrl | String | Returns the path for the image of the native ad.| - | getCallToAction | String | Returns the type of action of the native ad | - | getClickUrl | String | Returns the click url of the native ad | - -#### Util - -This object provides methods for searching for a `PrebidNativeAd` in the response and displaying the image from the image url in the response. - -##### Methods - -**findNative** - -This method searches for the variable `isPrebid` in the native response. If the variable is located and its value is `true` the `PrebidNativeAd` instance is created and passed back to `PrebidNativeAdListener`. - -*Parameters* - - {: .table .table-bordered .table-striped } - | Name | Scope | Type | Description | - |------------------------+----------+-----------+----------------------------------| - | adObject | Required | AnyObject | The ad object to search for. | | | - -### Examples - -#### Consume NativeAd - -How to consume native in iOS: -
        -
        -func createPrebidNativeView(){
        -    let adNib = UINib(nibName: "PrebidNativeAdView", bundle: Bundle(for: type(of: self)))
        -    let array = adNib.instantiate(withOwner: self, options: nil)
        -    if let prebidNativeAdView = array.first as? PrebidNativeAdView{
        -        self.prebidNativeAdView = prebidNativeAdView
        -        prebidNativeAdView.frame = CGRect(x: 0, y: 0, width: self.adContainerView.frame.size.width, height: 150 + self.screenWidth * 400 / 600)
        -        self.view.addSubview(prebidNativeAdView)
        -    }
        -}
        -
        -func loadNativeAssets(){
        -
        -    let image = NativeAssetImage(minimumWidth: 200, minimumHeight: 200, required: true)
        -    image.type = ImageAsset.Main
        -
        -    let icon = NativeAssetImage(minimumWidth: 20, minimumHeight: 20, required: true)
        -    icon.type = ImageAsset.Icon
        -
        -    let title = NativeAssetTitle(length: 90, required: true)
        -
        -    let body = NativeAssetData(type: DataAsset.description, required: true)
        -
        -    let cta = NativeAssetData(type: DataAsset.ctatext, required: true)
        -
        -    let sponsored = NativeAssetData(type: DataAsset.sponsored, required: true)
        -
        -    nativeUnit = NativeRequest(configId: "25e17008-5081-4676-94d5-923ced4359d3", assets: [icon,title,image,body,cta,sponsored])
        -
        -    nativeUnit.context = ContextType.Social
        -    nativeUnit.placementType = PlacementType.FeedContent
        -    nativeUnit.contextSubType = ContextSubType.Social
        -
        -    let event1 = EventType.Impression
        -    eventTrackers = NativeEventTracker(event: event1, methods: [EventTracking.Image,EventTracking.js])
        -    nativeUnit.eventtrackers = [eventTrackers]
        -}
        -
        -
        - -#### Google Ad Manager Integration -
        -
        -var adLoader: GADAdLoader?
        -var nativeUnit: NativeRequest!
        -var nativeAd:NativeAd?
        -var nativeUnit: NativeRequest!
        -var eventTrackers: NativeEventTracker!      
        -func loadPrebidNativeForDFP(){
        -    createPrebidNativeView()
        -    loadNativeAssets()    
        -    let dfpRequest:DFPRequest = DFPRequest()
        -    nativeUnit.fetchDemand(adObject: dfpRequest) { [weak self] (resultCode: ResultCode) in
        -              adLoader = GADAdLoader(adUnitID: "/19968336/Abhas_test_native_native_adunit",
        -                           rootViewController: self,
        -                           adTypes: [ GADAdLoaderAdType.dfpBanner, GADAdLoaderAdType.nativeCustomTemplate],
        -                           options: [ ])
        -              adLoader?.delegate  = self
        -              adLoader?.load(dfpRequest)
        -    }
        -}
        -
        -//MARK: : DFP Native Delegate
        -func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) {
        -    print("Prebid GADAdLoader failed \(error)")
        -}
        -
        -func nativeCustomTemplateIDs(for adLoader: GADAdLoader) -> [String] {
        -    return ["11963183"]
        -}
        -
        -func adLoader(_ adLoader: GADAdLoader,
        -              didReceive nativeCustomTemplateAd: GADNativeCustomTemplateAd){
        -    print("Prebid GADAdLoader received customTemplageAd")
        -    Utils.shared.delegate = self
        -    Utils.shared.findNative(adObject: nativeCustomTemplateAd)
        -}
        -
        -func adLoader(_ adLoader: GADAdLoader, didReceive bannerView: DFPBannerView) {
        -    prebidNativeAdView?.addSubview(bannerView)
        -}
        -
        -func validBannerSizes(for adLoader: GADAdLoader) -> [NSValue] {
        -    return [NSValueFromGADAdSize(kGADAdSizeBanner)]
        -}
        -
        -
        - -#### MoPub Integration - -
        -
        -var mpNative:MPNativeAdRequest?
        -var mpAd: MPNativeAd?
        -var nativeUnit: NativeRequest!
        -var nativeAd:NativeAd?
        -var nativeUnit: NativeRequest!
        -var eventTrackers: NativeEventTracker!
        -func loadPrebidNativeForMoPub(){
        -    removePreviousAds()
        -    createPrebidNativeView()
        -    loadNativeAssets()
        -
        -    let settings: MPStaticNativeAdRendererSettings = MPStaticNativeAdRendererSettings.init()
        -    let config:MPNativeAdRendererConfiguration = MPStaticNativeAdRenderer.rendererConfiguration(with: settings)
        -    self.mpNative = MPNativeAdRequest.init(adUnitIdentifier: "2674981035164b2db5ef4b4546bf3d49", rendererConfigurations: [config])
        -
        -    let targeting:MPNativeAdRequestTargeting = MPNativeAdRequestTargeting.init()
        -    self.mpNative?.targeting = targeting
        -
        -    nativeUnit.fetchDemand(adObject: mpNative!) { [weak self] (resultCode: ResultCode) in
        -        print("Prebid demand fetch for AdManager \(resultCode.name())")
        -        if let mpNative = mpNative{
        -            mpNative.start(completionHandler: { (request, response, error)->Void in
        -                if error == nil {
        -                    self.mpAd = response!
        -                    Utils.shared.delegate = self
        -                    Utils.shared.findNative(adObject: response!)
        -                }
        -            })
        -       }
        -    }
        -}
        -
        -
        - -#### Native Ad Delegate Integration -
        -
        -//MARK: : NativeAdDelegate Delegate
        -func nativeAdLoaded(ad:NativeAd) {
        -    print("nativeAdLoaded")
        -    nativeAd = ad
        -    nativeAd?.delegate = self
        -    if  let prebidNativeAdView = prebidNativeAdView {
        -        nativeAd?.registerView(view: prebidNativeAdView, clickableViews: [prebidNativeAdView.callToActionButton])
        -    }
        -
        -    prebidNativeAdView?.titleLabel.text = nativeAd?.title
        -    prebidNativeAdView?.bodyLabel.text = nativeAd?.text
        -    if let iconString = nativeAd?.iconUrl, let iconUrl = URL(string: iconString) {
        -        DispatchQueue.global().async {
        -            let data = try? Data(contentsOf: iconUrl)
        -            DispatchQueue.main.async {
        -                if data != nil {
        -                    self.prebidNativeAdView?.iconImageView.image = UIImage(data:data!)
        -                }
        -            }
        -        }
        -    }
        -    if let imageString = nativeAd?.imageUrl,let imageUrl = URL(string: imageString) {
        -        DispatchQueue.global().async {
        -            let data = try? Data(contentsOf: imageUrl)
        -            DispatchQueue.main.async {
        -                if data != nil {
        -                 self.prebidNativeAdView?.mainImageView.image = UIImage(data:data!)
        -                }
        -            }
        -        }
        -    }
        -    prebidNativeAdView?.callToActionButton.setTitle(nativeAd?.callToAction, for: .normal)
        -    prebidNativeAdView?.sponsoredLabel.text = nativeAd?.sponsoredBy
        -}
        -
        -func nativeAdNotFound() {
        -    print("nativeAdNotFound")
        -
        -}
        -func nativeAdNotValid() {
        -    print("nativeAdNotValid")
        -}
        -
        -
        diff --git a/prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.md index 4b56d569cd..1bbed01cb0 100644 --- a/prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.md +++ b/prebid-mobile/pbm-api/ios/pbm-nativeadunit-ios.md @@ -19,11 +19,11 @@ The NativeAdUnit is a subclass of the AdUnit class. Use the NativeAdUnit object ### NativeAdUnit Create a new `NativeAdUnit` associated with a Prebid Server configuration ID. -See [AdUnit](/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. + **Parameters** -`configId (String)`: Prebid Server configuration ID. +`configId (String)`: Prebid Server configuration ID. Note: this is a Prebid Server [impression-level stored request ID](/prebid-server/features/pbs-storedreqs.html). ## Examples @@ -106,13 +106,3 @@ nativeUnit.fetchDemand(adObject: self.request) { [weak self] (resultCode: Result } ``` -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Banner Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Intersitial Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md b/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md index 6fbb28f752..8319f7f67b 100644 --- a/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md +++ b/prebid-mobile/pbm-api/ios/pbm-targeting-ios.md @@ -8,494 +8,279 @@ sidebarType: 2 --- -# Global Targeting Parameters +# Request parameters {:.no_toc} -Prebid Mobile supports the following global targeting parameters. These targeting parameters are set only once and apply to all Prebid Mobile ad units. They do not change for a given user session. +The tables below list the methods and properties that the Prebid Rendering API uses for customization. +The more data about the user, app, and device that can be provided the more chances to win an impression. + +It is advised that you strictly follow the recommendations in the tables below. Any field marked with an ❗is required and recommended. * TOC {:toc} -## Global User Targeting +## GPDR API -### Gender +Prebid Mobile supports the [IAB GDPR recommendations](https://www.iab.com/topics/consumer-privacy/gdpr/). For a general overview of Prebid Mobile support for GDPR, see [Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice](/prebid-mobile/prebid-mobile-privacy-regulation.html) -``` -public var gender:Gender -``` +Prebid SDK doesn't modify values for IAB-defined keys in the `UserDefaults`. Instead, SDK will keep the provided value in the in-memory property. -gender is an enum with the following values: +The values provided via targeting API will be included in the bid request according to the `TCF v2` framework. -``` +{% capture warning_note %} -public enum Gender: String { - case unknown - case male - case female -} -``` +Since the SDK API has priority over CMP values, using the API blocks the CMP signals. Use a single way to provide the TCF signals. -You can retrieve and set the gender for targeting: +If you need to use an API way, ensure that all the following properties are set in the app code. -``` -let gender = Targeting.shared.gender +If you need to use a CMP way, ensure that you don't set any of the following API properties. -//do something with gender -``` +{% endcapture %} +{% include /alerts/alert_warning.html content=warning_note %} -``` -Targeting.shared.gender = .unknown; -``` - -### Year of Birth +### Subject To GPDR -``` -public var yearofbirth:Int? +```swift +public var subjectToGDPR:Bool? ``` -You can retrieve and set the year of birth for targeting: - -``` -if let yob = Targeting.shared.yearofbirth { - //do something with yob -}; +You can retrieve and set the subjectToGDPR for targeting: -guard let yob = Targeting.shared.yearofbirth else { - print("There was an error retrieving year of birth) +```swift +guard let subjectToGDPR = Targeting.shared.subjectToGDPR else { + print("There was an error retrieving subjectToGDPR) return } - -//do something with yob ``` +```swift +Targeting.shared.subjectToGDPR = false ``` -Targeting.shared.yearofbirth = 1990; -``` - -### User Keywords - -User keywords are a list of keywords, intrests or intent as defined by user.keywords in OpenRTB 2.5. Any keywords passed in the UserKeywords object may be passsed to DSPs. - -#### Add User Keyword - -``` -func addUserKeyword(_ newElement: String) -``` - -#### Add User Keywords + +### GDPR Consent String -``` -func addUserKeywords(_ newElements: Set) +```swift +public var gdprConsentString? ``` -#### Remove User Keywords +You can retrieve and set the subjectToGDPR for targeting: +```swift +guard let gdprConsentString = Targeting.shared.gdprConsentString else { + print("There was an error retrieving gdprConsentString") + return +} ``` -func removeUserKeyword(_ element: String) -``` - -#### Clear User Keywords -``` -func clearUserKeywords() +```swift +Targeting.shared.gdprConsentString = "A String" ``` -Examples: +### Purpose Consent ```swift -Targeting.shared.addUserKeyword("globalUserKeywordValue1") -Targeting.shared.addUserKeyword("globalUserKeywordValue2") -Targeting.shared.addUserKeyword("globalUserKeywordValue3") -``` - -```objective_c -[Targeting.shared addUserKeyword:@"globalUserKeywordValue1"]; -[Targeting.shared addUserKeyword:@"globalUserKeywordValue2"]; -[Targeting.shared addUserKeyword:@"globalUserKeywordValue3"]; +public var purposeConsents: String? ``` -## Global Application Targeting - - -### Domain - -Retrieve and set the domain of your app with the following commands: +You can retrieve and set the purposeConsents for targeting: +```swift +Targeting.shared.purposeConsents = "100000000000000000000000" ``` -Targeting.shared.domain -``` -``` -Targeting.shared.domain = domain -``` -### Store URL - -Retrieve and set the domain of your store URL with the following command: -``` -Targeting.shared.storeURL -``` +## Targeting properties -``` -Targeting.shared.storeURL = "itunes store URL string" -``` +{: .table .table-bordered .table-striped } -### iTunesID +| **Variable** | **Description** | **Required?** | +| -------------------- | ---------------- | ------------------------------------------------------------ | ------------------------ | +| `storeURL` | Stores URL for the mobile application. For example: `"https://itunes.apple.com/us/app/your-app/id123456789"` | ❗ Required | +|`contentUrl` | This is the deep-link URL for the app screen that is displaying the ad. This can be an iOS universal link. | ❗ Highly Recommended | +|`publisherName`| App's publisher's name. | ❗ Highly Recommended | +| `yearOfBirth` | For example: `1987` | ❗ Highly Recommended | +| `coppa` or `subjectToCOPPA` | Flag indicating if this request is subject to the COPPA regulations established by the USA FTC, where 0 = no, 1 = yes | ❗ Highly Recommended | +| `userGender` | User's gender (Male, Female, Other, Unknown). For example: `.female` | ❗ Highly Recommended | +|`userGenderDescription`| String representation of the user's gender, where “M” = male, “F” = female, “O” = known to be other (i.e., omitted is unknown) | | +| `userID` | ID of the user within the app. For example: `"24601"` | ❗ Highly Recommended | +| `buyerUID` | Buyer-specific ID for the user as mapped by the exchange for the buyer. | ❗ Highly Recommended | +| `keywords` | Comma separated list of keywords, interests, or intent | Optional | +| `userCustomData`| Optional feature to pass bidder the data that was set in the exchange’s cookie. The string must be in base85 cookie safe characters and be in any format. Proper JSON encoding must be used to include “escaped” quotation marks. | Optional | +|`userExt`| Placeholder for exchange-specific extensions to OpenRTB. | Optional | +|`domain`|Retrieve and set the domain of your app|Optional| +|`itunesID`|Retrieve and set the domain of your iTunes ID with the below command. This field will be transmitted to buyers as the bundle ID as recommended in OpenRTB 2.5. Failure to supply this value can have a negative monetary impact.|Optional| -Retrieve and set the domain of your iTunes ID with the below command. This field will be transmitted to buyers as the bundle ID as recommended in OpenRTB 2.5. Failure to supply this value can have a negative monetary impact. +The code sample: -``` -Targeting.shared.itunesID +```swift +let targeting = Targeting.shared + +targeting.userGender = .male +targeting.yearOfBirth = 1987 +targeting.userID = "X345Y678Z890" ``` -``` -Targeting.shared.itunesID = itunesID -``` +## Open Measurement SDK (OMSDK) API -### Open Measurement SDK (OMSDK) +> **NOTE**: these properties are relevant only for the original Prebid integration into GAM monetization. In this case the creative is rendered by GMA SDK and publishers should provide OMID description in the bid re qest. If you use Prebid SDK as a rendering engine you shouldn't use these properties. Prebid SDK sends them automaticaly according to the current OMID setup. -OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is eligible for OMSDK support. Prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code. +OMSDK is designed to facilitate 3rd party viewability and verification measurement for ads served in mobile app enviroments. Prebid SDK will provide the signaling component to Bid Adapters, by way of Prebid Server, indicating the impression is eligible for OMSDK support. Original API of prebid SDK does not currently integrate with OMSDK itself, instead it will rely on a publisher ad server to render viewability and verification measurement code. There three components to signaling support for OMSDK: + * Partner Name * Partner Version * API code -**Partner Name** +### Partner Name +{:.no_toc} This will be the [IAB OMSDK compliant partner name](https://complianceomsdkapi.iabtechlab.com/compliance/latest) responsible for integrating with the OMSDK spec. See below for configuration and examples -#### omidPartnerName -Open Measurement partner name. - -``` -Targeting.shared.omidPartnerName -``` - -Examples: - -Swift ```swift Targeting.shared.omidPartnerName = "Google" ``` -Objective C -```objective_c -Targeting.shared.omidPartnerName = @"Google"; -``` - - -**Partner Version** +### Partner Version +{:.no_toc} The OMSDK version number the partner integrated with. See below for configuration and examples. - -#### omidPartnerVersion -Partner's OMSDK version number implementation -``` -Targeting.shared.omidPartnerVersion -``` - -Examples: - -Swift ```swift Targeting.shared.omidPartnerVersion = "1.0" ``` -Objective C -```objective_c -Targeting.shared.omidPartnerVersion = @"1.0"; -``` - -**API Code** - -Per OpenRTB 2.5, support for OMSDK is signaled using the imp.[media type].api field represented in Prebid SDK withing each ad format type under the parameters object. Refer to the documentation of the respective ad unit class. - -Example: -``` -let bannerUnit = BannerAdUnit(configId: "6ace8c7d-88c0-4623-8117-75bc3f0a2e45", size: CGSize(width: 300, height: 250)) -let parameters = BannerAdUnit.Parameters() -parameters.api = [Signals.Api(7)] -adUnit.setParameters(parameters); -``` - -Note that the OMID value for imp.banner/video/native.api field should be 7, as defined by the IAB in the [OMSDK v1.2 document](https://s3-us-west-2.amazonaws.com/omsdk-files/docs/Open+Measurement+SDK+Onboarding_version_1.2.pdf). - +## Targeting methods -## Inventory (Context) Keywords +{: .table .table-bordered .table-striped } -Context Keywords are a list of keywords about the app as referenced in OpenRTB 2.5 as app.keywords. Any keyword passed in the context keyword field may be passed to the buyer for targeting. +### Inventory (Context) Keywords -### Add Context Keyword +Context Keywords are a list of keywords about the app as referenced in OpenRTB 2.5 as app.keywords. Any keyword passed in the context keyword field may be passed to the buyer for targeting. Prebid provides following functions to manage context keywords: -``` +```swift func addContextKeyword(_ newElement: String) -``` - -### Add Context Keywords -``` func addContextKeywords(_ newElements: Set) -``` -### Remove Context Keywords - -``` func removeContextKeyword(_ element: String) -``` -### Clear Context Keywords - -``` func clearContextKeywords() ``` -Examples: +Example: -Swift ```swift Targeting.shared.addContextKeyword("globalContextKeywordValue1") Targeting.shared.addContextKeyword("globalContextKeywordValue2") Targeting.shared.addContextKeyword("globalContextKeywordValue3") ``` -Objective C -```objective_c -[Targeting.shared addContextKeyword:@"globalContextKeywordValue1"]; -[Targeting.shared addContextKeyword:@"globalContextKeywordValue2"]; -[Targeting.shared addContextKeyword:@"globalContextKeywordValue3"]; -``` - -## First Party Data - -First Party Data (FPD) is free form data supplied by the publisher to provide additional targeting of the user or inventory context, used primarily for striking PMP (Private MarketPlace) deals with Advertisers. Data supplied in the data parameters are typically not sent to DSPs whereas information sent in non-data objects (i.e. setYearOfBirth, setGender, etc.) will be. Access to FPD can be limited to a supplied set of Prebid bidders via an access control list. - -Data is broken up into two different data types: - -* User - * Global in scope only -* Inventory (context) - * Global scope - * Ad Unit grain - - The below first party user and inventory context will apply to all ad units. For ad unit level first party data, refer to [First Party Data section in the Ad Unit](pbm-adunit-ios#first-party-data) page. - ### First Party User Data -#### Add User Data +Prebid provides following functions to manage First Party User Data: -``` +```swift func addUserData(key: String, value: String) -``` - -#### Update User Data -``` func updateUserData(key: String, value: Set) -``` -#### Remove User Data - -``` func removeUserData(forKey: String) -``` - -#### Clear User Data -``` func clearUserData() ``` -Examples: +Example: -Swift ```swift Targeting.shared.addUserData(key: "globalUserDataKey1", value: "globalUserDataValue1") ``` -Object C -```objective_c -[Targeting.shared addUserDataWithKey:@"globalUserDataKey1" value:@"globalUserDataValue1"]; -``` - ### First Party Inventory (Context) Data -#### Add Context Data +Prebid provides following functions to manage First Party Inventory Data: -``` +```swift func addContextData(key: String, value: String) -``` - -#### Update Context Data -``` func updateContextData(key: String, value: Set) -``` - -#### Remove Context Data -``` func removeContextData(forKey: String) -``` -#### Clear Context Data - -``` func clearContextData() ``` -Examples: +Example: -Swift ```swift Targeting.shared.addContextData(key: "globalContextDataKey1", value: "globalContextDataValue1") ``` -Objective C -```objective_c -[Targeting.shared addContextDataWithKey:@"globalContextDataKey1" value:@"globalContextDataValue1"]; -``` - -#### Ad Unit Context Data -For ad unit context data, please refer to the [ad unit](pbm-adunit-ios.html) section. - ### Access Control -The First Party Data Access Control List provides a method to restrict access to first party data to a supplied list of bidders. -#### addBidderToAccessControlList +The First Party Data Access Control List provides a methods to restrict access to first party data to a supplied list of bidders. -``` +```swift func addBidderToAccessControlList(_ bidderName: String) -``` - -#### removeBidderFromAccessControlList -``` func removeBidderFromAccessControlList(_ bidderName: String) -``` -#### clearAccessControlList - -``` func clearAccessControlList() ``` -Examples: +Example: -Swift ```swift Targeting.shared.addBidderToAccessControlList(Prebid.bidderNameRubiconProject) ``` -Objective C -```objective_c -[Targeting.shared addBidderToAccessControlList: Prebid.bidderNameRubiconProject]; -``` - - - -## GPDR - -Prebid Mobile supports the [IAB GDPR recommendations](https://www.iab.com/topics/consumer-privacy/gdpr/). For a general overview of Prebid Mobile support for GDPR, see [Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice](/prebid-mobile/privacy-regulation.html) - -### Subject To GPDR - -``` -public var subjectToGDPR:Bool? -``` - -You can retrieve and set the subjectToGDPR for targeting: - -``` -if let subjectToGDPR = Targeting.shared.subjectToGDPR { - //do something with subjectToGDPR -}; - -guard let subjectToGDPR = Targeting.shared.subjectToGDPR else { - print("There was an error retrieving subjectToGDPR) - return -} - -//do something with subjectToGDPR - -``` - -``` -Targeting.shared.subjectToGDPR = false -``` - -### GDPR Consent String +### Custom Params -``` -public var gdprConsentString? -``` +The methods that add or change the custom parameters. The name will be auto-prepended with `c.` to avoid collisions. -You can retrieve and set the subjectToGDPR for targeting: +```swift +public func addCustomParam(_ value: String, withName: String?) +public func setCustomParams(_ params: [String : String]?) ``` -if let gdprConsentString = Targeting.shared.gdprConsentString { - //do something with gdprConsentString -}; -guard let gdprConsentString = Targeting.shared.gdprConsentString else { - print("There was an error retrieving gdprConsentString) - return -} - -//do something with gdprConsentString +### Parameter -``` +Adds a new param by name and sets its value. -``` -Targeting.shared.gdprConsentString = "A String" +```swift +public func addParam(_ value: String, withName: String?) ``` -### Purpose Consent - -``` -public var purposeConsents: String? -``` +### Latitude Longitude -You can retrieve and set the purposeConsents for targeting: +Store location in the user's section +```swift +public func setLatitude(_ latitude: Double, longitude: Double) ``` -//given - -Targeting.shared.purposeConsents = "100000000000000000000000" - -defer { - - Targeting.shared.purposeConsents = nil -} +### ORTBConfig -//when +(requires SDK v2.2.1) -let deviceAccessConsent = Targeting.shared.getDeviceAccessConsent() -``` -### Subject to COPPA +Provides a way for app publishers to customize most ORTB fields in the partial bid request that Prebid Mobile sends to the Prebid Server. The customization comes in the form of the setOrtbConfig() method that takes a JSON String as input. The JSON string must follow the [ORTB guidelines](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/develop/2.6.md#321---object-bidrequest-) as it will be merged with the current JSON of the bid request. If you choose to input extra data using the setOrtbConfig() method, please extensively test your requests sent to Prebid Server. -Prebid supports passing of the Child Online Privacy Prection (COPPA) signal to Prebid Server (PBS) for all COPPA traffic. When PBS receives the COPPA flag we strip out all personal data from the requeset. For a general overview of COPPA, see the [FTC's guidlines](https://www.ftc.gov/enforcement/rules/rulemaking-regulatory-reform-proceedings/childrens-online-privacy-protection-rule). +There are certain protected fields such as regs, device, geo, ext.gdpr, ext.us_privacy, and ext.consent which cannot be changed. ```swift -var subjectToCOPPA: Bool -``` - -Example: - -SWIFT -``` -Targeting.shared.subjectToCOPPA = true +//global invocation +adUnitConfig.setOrtbConfig("{"ext":{"prebid":{"debug":1,"trace":"verbose"}}}") ``` -Objective C -``` -Targeting.shared.subjectToCOPPA = true; +```swift +//ad unit / impression-level +adUnit.setOrtbConfig("{"ext":{"gpid":"abc123"}}") ``` -## User Identity +## User Identity API Prebid SDK supports two interfaces to pass / maintain User IDs and ID vendor details: + * Real-time in Prebid SDK's API field externalUserIdArray * Store User Id(s) in local storage @@ -505,37 +290,23 @@ Any identity vendor's details in local storage will be sent over to Prebid Serve Prebid SDK supports passing an array of UserID(s) at auction time in the field externalUserIdArray, that is globably scopped. It is sufficient enough to set the externalUserIdArray object once per user session, as these values would be used in all consecutive ad auctions in the same session. - ```swift public var externalUserIdArray = [ExternalUserId]() ``` - **Exmaples** -SWIFT ```swift // User Id from External Third Party Sources var externalUserIdArray = [ExternalUserId]() + externalUserIdArray.append(ExternalUserId(source: "adserver.org", identifier: "111111111111", ext: ["rtiPartner" : "TDID"])) externalUserIdArray.append(ExternalUserId(source: "netid.de", identifier: "999888777")) externalUserIdArray.append(ExternalUserId(source: "criteo.com", identifier: "_fl7bV96WjZsbiUyQnJlQ3g4ckh5a1N")) externalUserIdArray.append(ExternalUserId(source: "liveramp.com", identifier: "AjfowMv4ZHZQJFM8TpiUnYEyA81Vdgg")) externalUserIdArray.append(ExternalUserId(source: "sharedid.org", identifier: "111111111111", atype: 1, ext: ["third" : "01ERJWE5FS4RAZKG6SKQ3ZYSKV"])) -Prebid.shared.externalUserIdArray = externalUserIdArray -``` - -Objective-C -```objective_c -// User Id from External Third Party Sources -NSMutableArray *externalUserIdArray = [[NSMutableArray alloc] init]; -[externalUserIdArray addObject:[[ExternalUserId alloc]initWithSource:@"adserver.org" identifier:@"111111111111" atype:nil ext:@{@"rtiPartner" : @"TDID"}]]; -[externalUserIdArray addObject:[[ExternalUserId alloc]initWithSource:@"netid.de" identifier:@"999888777" atype: nil ext:nil]]; -[externalUserIdArray addObject:[[ExternalUserId alloc]initWithSource:@"criteo.com" identifier:@" _fl7bV96WjZsbiUyQnJlQ3g4ckh5a1N" atype:nil ext:nil]]; -[externalUserIdArray addObject:[[ExternalUserId alloc]initWithSource:@"liveramp.com" identifier:@" AjfowMv4ZHZQJFM8TpiUnYEyA81Vdgg" atype:nil ext:nil]]; -[externalUserIdArray addObject:[[ExternalUserId alloc]initWithSource:@"sharedid.org" identifier:@"111111111111" atype:[NSNumber numberWithInt:1] ext:@{@"third" : @"01ERJWE5FS4RAZKG6SKQ3ZYSKV"}]]; -Prebid.shared.externalUserIdArray = externalUserIdArray; +Prebid.shared.externalUserIdArray = externalUserIdArray ``` ### Local Storage @@ -543,77 +314,17 @@ Prebid.shared.externalUserIdArray = externalUserIdArray; Prebid SDK provides a local storage interface to set, retrieve or update an array of user IDs with associated identity vendor details. Prebid SDK will retrieve and pass User IDs and ID vendor details to PBS if values are present in local storage. The main difference between the Prebid API interface and the local storage interface is the persistence of storage of data. Local Storage data will persist across user sessions whereas the Prebid API interface (externalUserIdArray) persists only for the user session. If a vendor's details are passed both in local storage and the Prebid API at the same time, the Prebid API data (externalUserIdArray) will prevail. Prebid SDK Provides five functions to handle User ID details: -* storeExternalUserId -* fetchStoredExternalUserIds -* fetchStoredExternalUserId -* removeStoredExternalUserId -* removeStoredExternalUserIds - ```swift -/** -* This method allows to save External User Id in the User Defaults -*/ -public func storeExternalUserId(_ externalUserId: ExternalUserId) { - if let index = externalUserIds.firstIndex(where: { - $0.source == externalUserId.source - }) - - { - externalUserIds[index] = externalUserId - } - - else{ - externalUserIds.append(externalUserId) - } - - StorageUtils.setExternalUserIds(value: externalUserIds) -} -/** -* This method allows to get All External User Ids from User Defaults -*/ -public func fetchStoredExternalUserIds()->[ExternalUserId]? { - return StorageUtils.getExternalUserIds() -} -/** -* This method allows to get External User Id from User Defaults by passing respective 'source' string as -param */ -public func fetchStoredExternalUserId(_ source : String)->ExternalUserId? { - guard let array = StorageUtils.getExternalUserIds(), let externalUserId = array.first(where: { - $0.source - == source - }) - - else{ - return nil - } - - return externalUserId -} -/** -* This method allows to remove specific External User Id from User Defaults by passing respective 'source' -string as param -*/ -public func removeStoredExternalUserId(_ source : String) { - if let index = externalUserIds.firstIndex(where: { - $0.source == source - }) - - { - externalUserIds.remove(at: index) - StorageUtils.setExternalUserIds(value: externalUserIds) - } +public func storeExternalUserId(_ externalUserId: ExternalUserId) -} -/** -* This method allows to remove all the External User Ids from User Defaults -*/ -public func removeStoredExternalUserIds() { - if var arrayExternalUserIds = StorageUtils.getExternalUserIds(){ - arrayExternalUserIds.removeAll() StorageUtils.setExternalUserIds(value: arrayExternalUserIds) - } +public func fetchStoredExternalUserIds() -> [ExternalUserId]? -} +public func fetchStoredExternalUserId(_ source : String) -> ExternalUserId? + +public func removeStoredExternalUserId(_ source : String) + +public func removeStoredExternalUserIds() ``` **Examples** @@ -634,9 +345,3 @@ Targeting.shared.removeStoredExternalUserId("sharedid.org") //Remove All External UserID Targeting.shared.removeStoredExternalUserIds() ``` - - -## Further Reading - -- [Prebid Mobile API - iOS](/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-util-ios.md b/prebid-mobile/pbm-api/ios/pbm-util-ios.md index ba6b65c8a9..5b4a64776b 100755 --- a/prebid-mobile/pbm-api/ios/pbm-util-ios.md +++ b/prebid-mobile/pbm-api/ios/pbm-util-ios.md @@ -16,76 +16,27 @@ This page will store any utilities that can used in conjuntion with the Prebid S {:toc} ## Find Prebid Creative Size -Prebid created `findPrebidCreativeSize` to address a bug in the Google Ad Manager ad server (described [here](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!category-topic/google-admob-ads-sdk/ios/648jzAP2EQY)) where under certain situations ads fail to render. It is recommended all Google Ad Manager integrations resize all ads served based on the winning Prebid creative size `findPrebidCreativeSize`. -Functionally speaking the Prebid SDK resizes ad slots based on the [adViewDidReceiveAd event](https://developers.google.com/admob/ios/banner) (when an ad is recieved) to determine the winning Prehbid ad size to determine how to resize the ad slot. +Prebid SDK provides a function `findPrebidCreativeSize` to address a bug in the Google Ad Manager ad server (described [here](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!category-topic/google-admob-ads-sdk/ios/648jzAP2EQY)) where under certain situations ads fail to render. -### Util +It is recommended all Google Ad Manager integrations resize all ads served based on the winning Prebid creative size `findPrebidCreativeSize`. Functionally speaking the Prebid SDK resizes ad slots based on the [adViewDidReceiveAd event](https://developers.google.com/admob/ios/banner) (when an ad is received) to determine the winning Prehbid ad size to determine how to resize the ad slot. -Supported in Prebid SDK version 1.1. +Usage example: ```swift -func findPrebidCreativeSize(_ adView: UIView, completion: @escaping (CGSize?) -> Void) -``` +func bannerViewDidReceiveAd(_ bannerView: GADBannerView) { -Exmple: -```swift -func adViewDidReceiveAd(_ bannerView: GADBannerView) { - print("adViewDidReceiveAd") + // Determine the kind of winning line item + AdViewUtils.findPrebidCreativeSize(bannerView, success: { size in + guard let bannerView = bannerView as? GAMBannerView else { return } - Utils.shared.findPrebidCreativeSize(bannerView) { (size) in - if let bannerView = bannerView as? DFPBannerView, let size = size { - bannerView.resize(GADAdSizeFromCGSize(size)) - } - } + // In the case of Prebid's line item - resize te ad view + bannerView.resize(GADAdSizeFromCGSize(size)) + }, failure: { (error) in + PrebidDemoLogger.shared.error("Error occuring during searching for Prebid creative size: \(error)") + }) } ``` -### AdViewUtils - -Improved `findPrebidCreativeSize` solution supported in Prebid SDK version 1.2+. - - -```swift -func findPrebidCreativeSize(_ adView: UIView, success: @escaping (CGSize) -> Void, failure: @escaping (Error) -> Void) -``` - -Examples: - -Swift -```swift -func adViewDidReceiveAd(_ bannerView: GADBannerView) { - - AdViewUtils.findPrebidCreativeSize(bannerView, - success: { (size) in - guard let bannerView = bannerView as? DFPBannerView else { - return - } - - bannerView.resize(GADAdSizeFromCGSize(size)) - }, - failure: { (error) in - print("error: \(error)"); - - }) -} -``` - -Objective C -```objective_c --(void) adViewDidReceiveAd:(GADBannerView *)bannerView { - NSLog(@"Ad received"); - [AdViewUtils findPrebidCreativeSize:bannerView - success:^(CGSize size) { - if ([bannerView isKindOfClass:[DFPBannerView class]]) { - DFPBannerView *dfpBannerView = (DFPBannerView *)bannerView; - - [dfpBannerView resize:GADAdSizeFromCGSize(size)]; - } - } failure:^(NSError * _Nonnull error) { - NSLog(@"error: %@", error); - }]; -} -``` diff --git a/prebid-mobile/pbm-api/ios/pbm-video-instream-ios.md b/prebid-mobile/pbm-api/ios/pbm-video-instream-ios.md deleted file mode 100644 index c2591172de..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-video-instream-ios.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -layout: page_v2 -title: VideoAdUnit AdUnit:Instream -description: VideoAdUnit AdUnit:Instream -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# VideoAdUnit AdUnit:Instream -{: .notoc} - -This page describes how to implement a `VideoAdUnit` for the display of instream videos. - -The VideoAdUnit is a subclass of the [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) class. Use the VideoAdUnit object to create and configure a video instream ad unit in your app. - -Video instream is only supported with Google Ad Manager. -{: .alert .alert-info} - -- TOC - {:toc} - -## VideoAdUnit - - Create a new Video Instream Ad Unit associated with a Prebid Server configuration ID and a video size. - - See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - - `VideoAdUnit(configId: String, size: CGSize(width: Int, height: Int))` - - **Parameters** - - `configId(String)`: Prebid Server configuration ID. - - `size(CGSize)`: Width and height of the video ad unit. - -### CGSize - - Size of video ad unit. - - **Parameters** - - `width`: Width of video ad unit in DIPs. - - `height`: Height of video ad unit in DIPs. - -### Parameters - - `placement`: [int] or [enum]: OpenRTB placement - - `api`: [int] or [enum]: OpenRTB api frameworks - - `maxBitrate`: int: OpenRTB maxBirate - - `minBitrate`: int: OpenRTB minBitrate - - `maxDuration`:int: OpenRTB maxDuration - - `minDuration`: int: OpenRTB minDuration - - `mimes`: [string]: OpenRTB mime types - - `playbackMethod`: [int]: OpenRTB playbackMethod - - `protocols`: [int] or [enum]: OpenRTB Protocols - -#### api - Array of integers or enum representing the supported OpenRTB 2.5 Frameworks: - - 1 or Signals.Api.VPAID_1 : VPAID 1.0 - - 2 or Signals.Api.VPAID_2 : VPAID 2.0 - - 3 or Signals.Api.MRAID_1 : MRAID-1 - - 4 or Signals.Api.ORMMA : ORMMA - - 5 or Signals.Api.MARAID_2 : MRAID-2 - - 6 or Signals.Api.MARAID_3 : MRAID-3 - -#### maxBitrate - Integer representing the OpenRTB 2.5 maximum bit rate in Kbps. - -#### minBitrate - Integer representing the OpenRTB 2.5 minimum bit rate in Kbps. - -#### maxDuration - Integer representing the OpenRTB 2.5 maximum video ad duration in seconds. - -#### minDuration - Integer representing the OpenRTB 2.5 minimum video ad duration in seconds. - -#### mimes - Array of strings representing the supported OpenRTB 2.5 content MIME types (e.g., “video/x-ms-wmv”, “video/mp4”). - -#### playbackMethod - Array of OpenRTB 2.5 playback methods. If none are specified, any method may be used. Only one method is typically used in practice. It is strongly advised to use only the first element of the array. - - 1 or Signals.PlaybackMethod.AutoPlaySoundOn : Initiates on Page Load with Sound On - - 2 or Signals.PlaybackMethod.AutoPlaySoundOff : Initiates on Page Load with Sound Off by Default - - 3 or Signals.PlaybackMethod.ClickToPlay : Initiates on Click with Sound On - - 4 or Signals.PlaybackMethod.MouseOver : Initiates on Mouse-Over with Sound On - - 5 or Signals.PlaybackMethod.EnterSoundOn : Initiates on Entering Viewport with Sound On - - 6 or Signals.PlaybackMethod.EnterSoundOff: Initiates on Entering Viewport with Sound Off by Default - -#### protocols - Array or enum of OpenRTB 2.5 supported Protocols. Values can be one of: - - 1 or Signals.Protocols.VAST_1_0 : VAST 1.0 - - 2 or Signals.Protocols.VAST_2_0 : VAST 2.0 - - 3 or Signals.Protocols.VAST_3_0 : VAST 3.0 - - 4 or Signals.Protocols.VAST_1_0_Wrapper : VAST 1.0 Wrapper - - 5 or Signals.Protocols.VAST_2_0_Wrapper : VAST 2.0 Wrapper - - 6 or Signals.Protocols.VAST_3_0_Wrapper : VAST 3.0 Wrapper - - 7 or Signals.Protocols.VAST_4_0 : VAST 4.0 - - 8 or Signals.Protocols.VAST_4_0_Wrapper : VAST 4.0 Wrapper - -See our documentation on [AdUnit](/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for more details. - -### Helper to Construct Google IMA adServer URL - -This utility method takes the adUnit Id of the publisher along with the adSlot sizes & Prebid custom keywords to construct the IMA adServer URL that the publisher can use to make the request. - -```public func constructAdTagURLForIMAWithPrebidKeys (adUnitID:String, adSlotSizes:[IMAAdSlotSize], customKeywords: [String:String]) throws -> String``` - -### Example - -
        -
        -
        -var adUnit: VideoAdUnit!
        -
        -var adsLoader: IMAAdsLoader!
        -var adsManager: IMAAdsManager!
        -
        -
        -//setup PB Video
        -let adUnit = VideoAdUnit(configId: "1001-1")
        -
        -//video parameters
        -parameters.mimes = ["video/mp4"]
        -parameters.protocols = [2,3,7]    // or alternative enum values [Protocols.VAST_2_0, Protocols.VAST_3_0]
        -parameters.playbackMethod = [1]   // or alternative enum value [PlaybackMethod.AutoPlaySoundOn]
        -parameters.api = [1,2]            // or alternative enum values [Api.VPAID_1, Api.VPAID_2]
        -parameters.maxBitrate = 1500
        -parameters.minBitrate = 300
        -parameters.maxDuration = 30
        -parameters.minDuration = 5
        -
        -adUnit.parameters = parameters
        -
        -//setup IMA Video
        -adsLoader = IMAAdsLoader(settings: nil)
        -adsLoader.delegate = self
        -adUnit.fetchDemand { (ResultCode, prebidKeys: [String : String]?) in
        -    print("prebid keys")
        -    if(ResultCode == .prebidDemandFetchSuccess){
        -        do {
        -                     let adServerTag:String = try IMAUtils.shared.constructAdTagURLForIMAWithPrebidKeys(adUnitID: "your_ad_unit",  
        -                    adSlotSizes: [.Size640x480,.Size400x300], customKeywords: prebidKeys!)
        -                    let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.appInstreamView)
        -                    // Create an ad request with our ad tag, display container, and optional user context.
        -                    let request = IMAAdsRequest(adTagUrl: adServerTag, adDisplayContainer: adDisplayContainer, contentPlayhead: nil, userContext: nil)
        -                    self.adsLoader.requestAds(with: request)
        -                }catch {
        -                    print (error)
        -                }
        -    } else {
        -                print ("Error constructing IMA Tag")
        -            }
        -    }
        -}
        -
        -
        -//adsLoader delegate
        -    func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) {
        -        // Grab the instance of the IMAAdsManager and set ourselves as the delegate.
        -        adsManager = adsLoadedData.adsManager
        -        adsManager.delegate = self
        -
        -
        -        // Create ads rendering settings and tell the SDK to use the in-app browser.
        -        let adsRenderingSettings = IMAAdsRenderingSettings()
        -        adsRenderingSettings.webOpenerPresentingController = self
        -
        -
        -        // Initialize the ads manager.
        -        adsManager.initialize(with: adsRenderingSettings)
        -    }
        -
        -    func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) {
        -        print("Error loading ads: \(adErrorData.adError.message ?? "nil")")
        -    }
        -
        -    //adsManager delegate
        -    func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) {
        -        if event.type == IMAAdEventType.LOADED {
        -          // When the SDK notifies us that ads have been loaded, play them.
        -          adsManager.start()
        -        }
        -    }
        -
        -    func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
        -        print("AdsManager error: \(error.message ?? "nil")")
        -    }
        -
        -
        -
        -
        diff --git a/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md deleted file mode 100755 index 2befade496..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-video-rewarded-adunit-ios.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -layout: page_v2 -title: VideoRewardedAdUnit - iOS -description: VideoRewardedAdUnit - iOS -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- -# RewardedVideoAdUnit - -Create a new Video Rewarded Ad Unit associated with a Prebid Server configuration ID and a video size. - - - -`RewardedVideoAdUnit(configId: String)` - - -**Parameters** - -`configId(String)`: Prebid Server configuration ID. - - - -# Parameters - -Parameters is a sub class of RewardedVideoAdUnit.Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes. - - -**Parameters** - -`placement: [int] or [enum]`: OpenRTB placement - -`api: [int] or [enum]`: OpenRTB api frameworks - -`maxBitrate: int`: OpenRTB maxBirate - -`minBitrate: int`: OpenRTB minBitrate - -`maxDuration:int`: OpenRTB maxDuration - -`minDuration: int`: OpenRTB minDuration - -`mimes: [string]`: OpenRTB mime types - -`playbackMethod: [int]`: OpenRTB playbackMethod - -`protocols: [int] or [enum]`: OpenRTB Protocols - - -### placement - -[OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Placement Type for the auction can be expressed as an integer array or can use an enum for easier readability. Option 1 (in-stream) is intentionally left out due to lack of in-stream support in Prebid SDK. - -In the context of a RewardedVideoAdUnit, rewarded video ads are typically labled as interstitial. As such, Prebid SDK will default to value 5 if no placement value is supplied. - -* `2` or `InBanner` : In-Banner placement exists within a web banner that leverages the banner space to deliver a video experience as opposed to another static or rich media format. The format relies on the existence of display ad inventory on the page for its delivery. -* `3` or `InArticle` : In-Article placement loads and plays dynamically between paragraphs of editorial content; existing as a standalone branded message. -* `4` or `InFeed` : In-Feed placement is found in content, social, or product feeds. -* `5` or `Slider`, `Floating` or `Interstitial` : Open RTB supports one of three values for option 5 as eitehr Slider, Floating or Interstitial. If an enum value is supplied in placement, bidders will recieve value 5 for placement type and assume to be interstitial with the instl flag set to 1. - - -### api - -Array of integers or enum representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Frameworks: - -* `1` or `Signals.Api.VPAID_1` : VPAID 1.0 -* `2` or `Signals.Api.VPAID_2` : VPAID 2.0 -* `3` or `Signals.Api.MRAID_1` : MRAID-1 -* `4` or `Signals.Api.ORMMA` : ORMMA -* `5` or `Signals.Api.MARAID_2` : MRAID-2 -* `6` or `Signals.Api.MARAID_3` : MRAID-3 - - -### maxBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum bit rate in Kbps. - - -### minBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum bit rate in Kbps. - - -### maxDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum video ad duration in seconds. - - -### minDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum video ad duration in seconds. - - -### mimes - -Array of string representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) content MIME types (e.g., “video/x-ms-wmv”, “video/mp4”). - - -### playbackMethod - -Array of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) playback methods. If none are specified, any method may be used. Only one method is typically used in practice. It is strongly advised to use only the first element of the array. - -* `1` or `Signals.PlaybackMethod.AutoPlaySoundOn` : Initiates on Page Load with Sound On -* `2` or `Signals.PlaybackMethod.AutoPlaySoundOff` : Initiates on Page Load with Sound Off by Default -* `3` or `Signals.PlaybackMethod.ClickToPlay` : Initiates on Click with Sound On -* `4` or `Signals.PlaybackMethod.MouseOver` : Initiates on Mouse-Over with Sound On -* `5` or `Signals.PlaybackMethod.EnterSoundOn` : Initiates on Entering Viewport with Sound On -* `6` or `Signals.PlaybackMethod.EnterSoundOff`: Initiates on Entering Viewport with Sound Off by Default - - -### protocols - -Array or enum of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) supported Protocols. Values can be one of: - -* `1` or `Signals.Protocols.VAST_1_0` : VAST 1.0 -* `2` or `Signals.Protocols.VAST_2_0` : VAST 2.0 -* `3` or `Signals.Protocols.VAST_3_0` : VAST 3.0 -* `4` or `Signals.Protocols.VAST_1_0_Wrapper` : VAST 1.0 Wrapper -* `5` or `Signals.Protocols.VAST_2_0_Wrapper` : VAST 2.0 Wrapper -* `6` or `Signals.Protocols.VAST_3_0_Wrapper` : VAST 3.0 Wrapper -* `7` or `Signals.Protocols.VAST_4_0` : VAST 4.0 -* `8` or `Signals.Protocols.VAST_4_0_Wrapper` : VAST 4.0 Wrapper - - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - ---- - -## Example - - -**Google Mobile Ads** -Import the GoogleMobileAds from [google-mobile-sdk](https://developers.google.com/admob/ios/download). - -**Swift** -```swift -//setup PB RewardedVideo -let adUnit = RewardedVideoAdUnit(configId: "1001-1") - -//video parameters -parameters.mimes = ["video/mp4"] -parameters.protocols = [2,3,7] // or alternative enum values [Protocols.VAST_2_0, Protocols.VAST_3_0] -parameters.playbackMethod = [1] // or alternative enum value [PlaybackMethod.AutoPlaySoundOn] -parameters.api = [1,2] // or alternative enum values [Api.VPAID_1, Api.VPAID_2] -parameters.maxBitrate = 1500 -parameters.minBitrate = 300 -parameters.maxDuration = 30 -parameters.minDuration = 5 - -adUnit.parameters = parameters - -//setup AM RewardedVideo -let amRewardedAd = GADRewardedAd(adUnitID: "adUnitId") -//load AM RewardedVideo -let amRequest = GADRequest() -let adUnit.fetchDemand(adObject: amRequest) { (resultCode: ResultCode) in - amRewardedAd.load(amRequest) { error in - if let error = error { - print("loadAMRewardedVideo failed:\(error)") - } else { - if amRewardedAd?.isReady == true { - amRewardedAd?.present(fromRootViewController: self, delegate:self) - } - } - } - } - -``` - -**Mopub** -Import the Mopub SDK from [Mopub](https://developers.mopub.com/publishers/ios/integrate/). - -**Swift** -```swift -//setup PB RewardedVideo -let adUnit = RewardedVideoAdUnit(configId: "1001-1") -//setup MP RewardedVideo -MPRewardedVideo.setDelegate(self, forAdUnitId: "adUnitId") -//load MP RewardedVideo -let targetingDict = NSMutableDictionary() -adUnit.fetchDemand(adObject: targetingDict) { (resultCode: ResultCode) in - print("Prebid demand fetch for mopub \(resultCode.name())") - if let targetingDict = targetingDict as? Dictionary { - let keywords = Utils.shared.convertDictToMoPubKeywords(dict: targetingDict) - MPRewardedVideo.loadAd(withAdUnitID: "adUnitId", keywords: keywords, userDataKeywords: nil, location: nil, mediationSettings: nil) - } -} - - -``` - - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Banner Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md deleted file mode 100755 index 7d54ba038a..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-videointerstitialadunit-ios.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -layout: page_v2 -title: VideoInterstitialAdUnit - iOS -description: VideoInterstitialAdUnit - iOS -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- -# VideoInterstitialAdUnit - -Create a new Video Outstream Ad Unit associated with a Prebid Server configuration ID and a video size. - -Video Insterstital is only supported with Google Ad Manager. -{: .alert .alert-info} - -`VideoInterstitialAdUnit(configId: String)` - -**Parameters** - -`configId(String)`: Prebid Server configuration ID. - - -# Parameters - -Parameters is a sub class of VideoInterstitialAdUnit.Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes. - - -**Parameters** - -`placement: [int] or [enum]`: OpenRTB placement - -`api: [int] or [enum]`: OpenRTB api frameworks - -`maxBitrate: int`: OpenRTB maxBirate - -`minBitrate: int`: OpenRTB minBitrate - -`maxDuration:int`: OpenRTB maxDuration - -`minDuration: int`: OpenRTB minDuration - -`mimes: [string]`: OpenRTB mime types - -`playbackMethod: [int]`: OpenRTB playbackMethod - -`protocols: [int] or [enum]`: OpenRTB Protocols - - -### placement - -[OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Placement Type for the auction can be expressed as an integer array or can use an enum for easier readability. Option 1 (in-stream) is intentionally left out due to lack of in-stream support in Prebid SDK. - -In the context of a VideoInterstitialAdUnit, rewarded video ads are typically labled as interstitial. As such, Prebid SDK will default to value 5 if no placement value is supplied. - -* `2` or `InBanner` : In-Banner placement exists within a web banner that leverages the banner space to deliver a video experience as opposed to another static or rich media format. The format relies on the existence of display ad inventory on the page for its delivery. -* `3` or `InArticle` : In-Article placement loads and plays dynamically between paragraphs of editorial content; existing as a standalone branded message. -* `4` or `InFeed` : In-Feed placement is found in content, social, or product feeds. -* `5` or `Slider`, `Floating` or `Interstitial` : Open RTB supports one of three values for option 5 as eitehr Slider, Floating or Interstitial. If an enum value is supplied in placement, bidders will recieve value 5 for placement type and assume to be interstitial with the instl flag set to 1. - - -### api - -Array of integers or enum representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Frameworks: - -* `1` or `Signals.Api.VPAID_1` : VPAID 1.0 -* `2` or `Signals.Api.VPAID_2` : VPAID 2.0 -* `3` or `Signals.Api.MRAID_1` : MRAID-1 -* `4` or `Signals.Api.ORMMA` : ORMMA -* `5` or `Signals.Api.MARAID_2` : MRAID-2 -* `6` or `Signals.Api.MARAID_3` : MRAID-3 - - -### maxBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum bit rate in Kbps. - - -### minBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum bit rate in Kbps. - - -### maxDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum video ad duration in seconds. - - -### minDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum video ad duration in seconds. - - -### mimes - -Array of string representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) content MIME types (e.g., “video/x-ms-wmv”, “video/mp4”). - - -### playbackMethod - -Array of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) playback methods. If none are specified, any method may be used. Only one method is typically used in practice. It is strongly advised to use only the first element of the array. - -* `1` or `Signals.PlaybackMethod.AutoPlaySoundOn` : Initiates on Page Load with Sound On -* `2` or `Signals.PlaybackMethod.AutoPlaySoundOff` : Initiates on Page Load with Sound Off by Default -* `3` or `Signals.PlaybackMethod.ClickToPlay` : Initiates on Click with Sound On -* `4` or `Signals.PlaybackMethod.MouseOver` : Initiates on Mouse-Over with Sound On -* `5` or `Signals.PlaybackMethod.EnterSoundOn` : Initiates on Entering Viewport with Sound On -* `6` or `Signals.PlaybackMethod.EnterSoundOff`: Initiates on Entering Viewport with Sound Off by Default - - -### protocols - -Array or enum of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) supported Protocols. Values can be one of: - -* `1` or `Signals.Protocols.VAST_1_0` : VAST 1.0 -* `2` or `Signals.Protocols.VAST_2_0` : VAST 2.0 -* `3` or `Signals.Protocols.VAST_3_0` : VAST 3.0 -* `4` or `Signals.Protocols.VAST_1_0_Wrapper` : VAST 1.0 Wrapper -* `5` or `Signals.Protocols.VAST_2_0_Wrapper` : VAST 2.0 Wrapper -* `6` or `Signals.Protocols.VAST_3_0_Wrapper` : VAST 3.0 Wrapper -* `7` or `Signals.Protocols.VAST_4_0` : VAST 4.0 -* `8` or `Signals.Protocols.VAST_4_0_Wrapper` : VAST 4.0 Wrapper - - - - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - ---- - -## Example - - -**Google Mobile Ads** -Import the GoogleMobileAds from [google-mobile-sdk](https://developers.google.com/admob/ios/download) into the UIViewController displaying the VideoInterstitialAdUnit. - -**Swift** -``` - var adUnit: AdUnit! - var amInterstitial: DFPInterstitial! - - func setupAndLoadAMInterstitialVAST() { - - setupPBInterstitialVAST() - setupAMInterstitialVAST() - - loadInterstitial() - } - - func setupPBInterstitialVAST() { - Prebid.shared.prebidServerHost = .Rubicon - Prebid.shared.prebidServerAccountId = "accountId" - adUnit = VideoInterstitialAdUnit(configId: "configId") - - - //video parameters - parameters.mimes = ["video/mp4"] - parameters.protocols = [2,3,7] // or alternative enum values [Protocols.VAST_2_0, Protocols.VAST_3_0] - parameters.playbackMethod = [1] // or alternative enum value [PlaybackMethod.AutoPlaySoundOn] - parameters.api = [1,2] // or alternative enum values [Api.VPAID_1, Api.VPAID_2] - parameters.maxBitrate = 1500 - parameters.minBitrate = 300 - parameters.maxDuration = 30 - parameters.minDuration = 5 - - adUnit.parameters = parameters - - self.adUnit = adUnit - - } - - func setupAMInterstitialVAST() { - amInterstitial = DFPInterstitial(adUnitID: "/5300653/test_adunit_vast_pavliuchyk") - } - - func loadInterstitial() { - - adUnit.fetchDemand(adObject: self.request) { (resultCode: ResultCode) in - print("Prebid demand fetch for DFP \(resultCode.name())") - } - } -``` - - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Banner Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md b/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md deleted file mode 100755 index 93c063b712..0000000000 --- a/prebid-mobile/pbm-api/ios/pbm-videooutstreamadunit-ios.md +++ /dev/null @@ -1,241 +0,0 @@ ---- -layout: page_v2 -title: VideoAdUnit AdUnit:Outstream -description: VideoAdUnit AdUnit:Outstream -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Outstream VideoAdUnit: AdUnit -{: .notoc} - -This page describes how to implement a `VideoAdUnit` for the display of outstream videos. - -The VideoAdUnit is a subclass of the [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) class. Use the VideoAdUnit object to create and configure a video outstream ad unit in your app. - -Video Outstream is only supported with Google Ad Manager. -{: .alert .alert-info} - -- TOC - {:toc} - -## VideoAdUnit - -Create a new Video Outstream Ad Unit associated with a Prebid Server configuration ID and a video size. - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - -`VideoAdUnit(configId: String, size: CGSize(width: Int, height: Int), type:Enum)` - -**Parameters** - -`configId(String)`: Prebid Server configuration ID. - -`size(CGSize)`: Width and height of the video ad unit. - -`type:Enum`: OpenRTB Placement Type. This field is being deprecated in favor of parameters.type - -### CGSize - -Size of video ad unit. - -**Parameters** - -`width`: Width of video ad unit in DIPs. - -`height`: Height of video ad unit in DIPs. - - -### type - -{% capture deprecate %} -VideoAdUnit type will be deprecated in future releases. Use parameters.placement below for future usage of type. -{% endcapture %} -{% include /alerts/alert_important.html content=deprecate %} - -OpenRTB Placement Type represented as an enumeration of values: - -* inBanner is transformed into OpenRTB value 2 to bid adapters -* inArticle is transformed into OpenRTB value 3 to bid adapters -* inFeed is transformed into OpenRTB value 4 to bid adapters - - -### Parameters - -Parameters is a sub class of videoAdUnit. Create new Parameters class to define the parameters of the video ad unit. Parameters contain the OpenRTB video attributes. - - -**Parameters** - -`placement: [int] or [enum]`: OpenRTB placement - -`api: [int] or [enum]`: OpenRTB api frameworks - -`maxBitrate: int`: OpenRTB maxBirate - -`minBitrate: int`: OpenRTB minBitrate - -`maxDuration:int`: OpenRTB maxDuration - -`minDuration: int`: OpenRTB minDuration - -`mimes: [string]`: OpenRTB mime types - -`playbackMethod: [int]`: OpenRTB playbackMethod - -`protocols: [int] or [enum]`: OpenRTB Protocols - - -#### placement - -[OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Placement Type for the auction can be expressed as an integer array or can use an enum for easier readability. Option 1 (in-stream) is intentionally left out due to lack of in-stream support in Prebid SDK. - -* `2` or `InBanner` : In-Banner placement exists within a web banner that leverages the banner space to deliver a video experience as opposed to another static or rich media format. The format relies on the existence of display ad inventory on the page for its delivery. -* `3` or `InArticle` : In-Article placement loads and plays dynamically between paragraphs of editorial content; existing as a standalone branded message. -* `4` or `InFeed` : In-Feed placement is found in content, social, or product feeds. -* `5` or `Slider` or `Floating` : While OpenRTB uses "5" to also designate interstitial as a placement type, interstitial is not used in the standard outsream format. For Interstital, use the videointerstital or RewardedVideoAdUnit ad unit - - -#### api - -Array of integers or enum representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) Frameworks: - -* `1` or `Signals.Api.VPAID_1` : VPAID 1.0 -* `2` or `Signals.Api.VPAID_2` : VPAID 2.0 -* `3` or `Signals.Api.MRAID_1` : MRAID-1 -* `4` or `Signals.Api.ORMMA` : ORMMA -* `5` or `Signals.Api.MARAID_2` : MRAID-2 -* `6` or `Signals.Api.MARAID_3` : MRAID-3 - - -#### maxBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum bit rate in Kbps. - - -#### minBitrate - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum bit rate in Kbps. - - -#### maxDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) maximum video ad duration in seconds. - - -#### minDuration - -Integer representing the [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) minimum video ad duration in seconds. - - -#### mimes - -Array of string representing the supported [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) content MIME types (e.g., “video/x-ms-wmv”, “video/mp4”). - - -#### playbackMethod - -Array of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) playback methods. If none are specified, any method may be used. Only one method is typically used in practice. It is strongly advised to use only the first element of the array. - -* `1` or `Signals.PlaybackMethod.AutoPlaySoundOn` : Initiates on Page Load with Sound On -* `2` or `Signals.PlaybackMethod.AutoPlaySoundOff` : Initiates on Page Load with Sound Off by Default -* `3` or `Signals.PlaybackMethod.ClickToPlay` : Initiates on Click with Sound On -* `4` or `Signals.PlaybackMethod.MouseOver` : Initiates on Mouse-Over with Sound On -* `5` or `Signals.PlaybackMethod.EnterSoundOn` : Initiates on Entering Viewport with Sound On -* `6` or `Signals.PlaybackMethod.EnterSoundOff`: Initiates on Entering Viewport with Sound Off by Default - - -#### protocols - -Array or enum of [OpenRTB 2.5](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) supported Protocols. Values can be one of: - -* `1` or `Signals.Protocols.VAST_1_0` : VAST 1.0 -* `2` or `Signals.Protocols.VAST_2_0` : VAST 2.0 -* `3` or `Signals.Protocols.VAST_3_0` : VAST 3.0 -* `4` or `Signals.Protocols.VAST_1_0_Wrapper` : VAST 1.0 Wrapper -* `5` or `Signals.Protocols.VAST_2_0_Wrapper` : VAST 2.0 Wrapper -* `6` or `Signals.Protocols.VAST_3_0_Wrapper` : VAST 3.0 Wrapper -* `7` or `Signals.Protocols.VAST_4_0` : VAST 4.0 -* `8` or `Signals.Protocols.VAST_4_0_Wrapper` : VAST 4.0 Wrapper - - - - -See [AdUnit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) for additional parameters and methods. - ---- - -## Example - - - -**Google Mobile Ads** - -Import the GoogleMobileAds from [google-mobile-sdk](https://developers.google.com/admob/ios/download) into the UIViewController displaying the VideoAdUnit. - -**Swift** -```swift - var amBanner: DFPBannerView! - var adUnit: AdUnit! - - func setupAndLoadAMBannerVAST() { - - setupPBBannerVAST() - - setupAMBannerVAST() - - loadBanner() - } - - func setupPBBannerVAST() { - - Prebid.shared.prebidServerHost = .Rubicon - Prebid.shared.prebidServerAccountId = "accountId" - - adUnit = VideoAdUnit(configId: "configId", size: CGSize(width: 300, height: 250)) - - let parameters = VideoBaseAdUnit.Parameters() - parameters.mimes = ["video/mp4"] - parameters.protocols = [2,3,7] // or alternative enum values [Protocols.VAST_2_0, Protocols.VAST_3_0] - parameters.playbackMethod = [1] // or alternative enum value [PlaybackMethod.AutoPlaySoundOn] - parameters.api = [1,2] // or alternative enum values [Api.VPAID_1, Api.VPAID_2] - parameters.maxBitrate = 1500 - parameters.minBitrate = 300 - parameters.maxDuration = 30 - parameters.minDuration = 5 - parameters.placement = 2 // or alternative enum value Signals.Placement.InBanner - - adUnit.parameters = parameters - } - - func setupAMBannerVAST() { - setupAMBanner(id: "/networkID/adUnit") - } - - func setupAMBanner(id: String) { - amBanner = DFPBannerView(adSize: kGADAdSizeMediumRectangle) - amBanner.adUnitID = id - } - - func loadBanner() { - - adUnit.fetchDemand(adObject: self.request) { [weak self] (resultCode: ResultCode) in - print("Prebid demand fetch for DFP \(resultCode.name())") - } - } - -``` - - - - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-adunit-ios.html) -- [Intersitial Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - Android]({{site.baseurl}}/prebid-mobile/pbm-api/android/pbm-api-android.html) diff --git a/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.md b/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.md deleted file mode 100644 index a00812968f..0000000000 --- a/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -layout: page_v2 -title: Prebid Mobile Object -description: Prebid Mobile Object -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Prebid: NSObject -{: .notoc} - -The Prebid class is a singleton that enables the user to apply global settings. - -- TOC - {:toc} - ---- - -## Object - -### Prebid - -**Properties** - -`prebidServerAccountId`: String containing the Prebid Server account ID. - -``` -var prebidServerAccountId: String { get set } -``` - -`prebidServerHost`: String containing configuration your Prebid Server host with which Prebid SDK will communicate. Choose from the system-defined Prebid Server hosts or define your own custom Prebid Server host. - -``` -var prebidServerHost: PrebidHost { get set } -func setCustomPrebidServer(url: String) throws -``` - -`shareGeoLocation`: Optional Bool, if this flag is True AND the app collects the user’s geographical location data, Prebid Mobile will send the user’s geographical location data to Prebid Server. If this flag is False OR the app does not collect the user’s geographical location data, Prebid Mobile will not populate any user geographical location information in the call to Prebid Server. The default setting is false. - -``` -var shareGeoLocation: Bool { get set } -``` - -`logLevel`: Optional level of loging to output in the console. Options are one of following sorted by verbosity of the log: - -``` -public enum LogLevel: String { -* debug = "[💬]" // debug -* verbose = "[🔬]" // verbose -* info = "[ℹ️]" // info -* warn = "[⚠️]" // warning -* error = "[‼️]" // error -* severe = "[🔥]" // severe -} -``` - -Default value is `debug`. All logging will be disabled in the release build. For furthe information, refer to [PR#217](https://github.com/prebid/prebid-mobile-ios/pull/217) - -``` -var logLevel: LogLevel { get set } -``` -`timeoutMillis`: The Prebid timeout (accessible to Prebid SDK 1.2+), set in milliseconds, will return control to the ad server SDK to fetch an ad once the expiration period is achieved. Because Prebid SDK solicits bids from Prebid Server in one payload, setting Prebid timeout too low can stymie all demand resulting in a potential negative revenue impact. - -```swift -var timeoutMillis: Int -``` - -`storedAuctionResponse`: Set as type string, stored auction responses signal Prebid Server to respond with a static response matching the storedAuctionResponse found in the Prebid Server Database, useful for debugging and integration testing. No bid requests will be sent to any bidders when a matching storedAuctionResponse is found. For more information on how stored auction responses work, refer to the written [description on github issue 133](https://github.com/prebid/prebid-mobile-android/issues/133). - -```swift -var storedAuctionResponse: String -``` - -`addStoredBidResponse`: Function containing two properties: - -* `bidder`: Bidder name as defined by Prebid Server bid adapter of type string. -* `responseId`: Configuration ID used in the Prebid Server Database to store static bid responses. - -Stored Bid Responses are similar to Stored Auction Responses in that they signal to Prebid Server to respond with a static pre-defined response, except Stored Bid Responses is done at the bidder level, with bid requests sent out for any bidders not specified in the bidder parameter. For more information on how stored auction responses work, refer to the written [description on github issue 133](https://github.com/prebid/prebid-mobile-android/issues/133). - -```swift -func addStoredBidResponse(bidder: String, responseId: String) -``` - -`clearStoredBidResponses`: Clears any stored bid responses. - -```swift -func clearStoredBidResponses() -``` - -`pbsDebug`: adds the debug flag ("test":1) on the outbound http call to Prebid Server. The test:1 flag will signal to Prebid Server to emit the full resolved request (resolving any Stored Request IDs) as well as the full Bid Request and Bid Response to and from each bidder. -```swift -pbsDebug = BOOL -``` - - -## Examples - -*SWIFT* -```swift -//Host -Prebid.shared.prebidServerHost = .Rubicon -//or set a custom host -Prebid.shared.prebidServerHost = PrebidHost.Custom -do { - try Prebid.shared.setCustomPrebidServer(url: "https://prebid-server.customhost.com") -} catch { - print(error) -} - -//Account Id -Prebid.shared.prebidServerAccountId = "1234" - -//Geolocation -Prebid.shared.shareGeoLocation = true - -//Log level data -Prebid.shared.logLevel = .verbose - -//set Prebid timeout in milliseconds -Prebid.shared.timeoutMillis = 3000 - -//Enable Prebid Server debug respones -Prebid.shared.pbsDebug = true - -//Stored responses can be one of storedAuction response or storedBidResponse -Prebid.shared.storedAuctionResponse = "111122223333" - -//or -Prebid.shared.addStoredBidResponse(bidder: "appnexus", responseId: "221144") -Prebid.shared.addStoredBidResponse(bidder: "rubicon", responseId: "221155") -``` - -*Objective C* -```objective_c -//Host -Prebid.shared.prebidServerHost = PrebidHostRubicon; - -//or set a custom host -Prebid.shared.prebidServerHost = PrebidHostCustom; - -NSError *error = nil; -bool ok = [Prebid.shared setCustomPrebidServerWithUrl:@"https://prebid-server.customhost.com" error: &error]; - -if (!ok) { - NSLog(@"An error happend: %@", error); -} - -//Account Id -Prebid.shared.prebidServerAccountId = @"1001"; - -//Geolocation -Prebid.shared.shareGeoLocation = YES; -Prebid.shared.timeoutMillis = 3000; - -//Stored responses can be one of storedAuction response or storedBidResponse -Prebid.shared.storedAuctionResponse = @"111122223333"; - -//Enable Prebid Server debug respones -Prebid.shared.pbsDebug = true; - -//or -[Prebid.shared addStoredBidResponseWithBidder:@"appnexus" responseId:@"221144"]; -[Prebid.shared addStoredBidResponseWithBidder:@"rubicon" responseId:@"221155"]; -``` - - - -## Related Topics - -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Banner Ad Unit](/prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html) -- [Intersitial Ad Unit]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-bannerinterstitialadunit-ios.html) -- [Result Codes]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html) -- [Targeting Parameters]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Prebid Mobile Object]({{site.baseurl}}/prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html) -- [Prebid Mobile API - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-api-ios.html) -- [Prebid Utilities - iOS]({{site.baseurl}}/prebid-mobile/pbm-api/ios/pbm-util-ios.html) diff --git a/prebid-mobile/prebid-mobile-download.md b/prebid-mobile/prebid-mobile-download.md index 135865ebdc..51efd0591b 100644 --- a/prebid-mobile/prebid-mobile-download.md +++ b/prebid-mobile/prebid-mobile-download.md @@ -1,11 +1,24 @@ --- - layout: page_v2 -title: Prebid Mobile | Prebid -description: Prebid Mobile Download -sidebarType: 0 - +title: Prebid Mobile +description: What is Prebid.js +sidebarType: 2 --- +# Downloading Prebid Mobile SDK + +For both Android and iOS, there are a couple of options for integrating the Prebid SDK. + +## Android + +- Option 1: Maven [org.prebid:prebid-mobile-sdk](https://mvnrepository.com/artifact/org.prebid/prebid-mobile-sdk) +- Option 2: clone and build [prebid/prebid-mobile-android](https://github.com/prebid/prebid-mobile-android) + +Follow the full instructions for [integrating the Android SDK](/prebid-mobile/pbm-api/android/code-integration-android.html). + +## iOS + +- Option 1: Cocoapod [PrebidMobile](https://cocoapods.org/pods/PrebidMobile) +- Option 2: clone and build [prebid/prebid-mobile-ios](https://github.com/prebid/prebid-mobile-ios) -## Prebid Mobile Download Page \ No newline at end of file +Follow the full instructions for [integrating the iOS SDK](/prebid-mobile/pbm-api/ios/code-integration-ios.html). diff --git a/prebid-mobile/prebid-mobile-for-contributors.md b/prebid-mobile/prebid-mobile-for-contributors.md new file mode 100644 index 0000000000..d80e01efbb --- /dev/null +++ b/prebid-mobile/prebid-mobile-for-contributors.md @@ -0,0 +1,26 @@ +--- +layout: page_v2 +title: Add an Ad Server Adapter +description: Add an Ad Server Adapter +pid: 0 +top_nav_section: prebid-mobile +nav_section: prebid-mobile-contributors +sidebarType: 2 +--- + + +# For Contributors + +{:.no_toc} + +We are looking for contributors to determine and implement features needed to improve the monetization of publishers' applications. + +Contributors should visit GitHub to learn how to contribute to Prebid Mobile. + +## For iOS + +[The iOS source code is hosted under the Prebid organization on GitHub](https://github.com/prebid/prebid-mobile-ios) + +### For Android + +[The Android source code is hosted under the Prebid organization on GitHub](https://github.com/prebid/prebid-mobile-android) diff --git a/prebid-mobile/prebid-mobile-getting-started.md b/prebid-mobile/prebid-mobile-getting-started.md new file mode 100644 index 0000000000..85f0e453f7 --- /dev/null +++ b/prebid-mobile/prebid-mobile-getting-started.md @@ -0,0 +1,115 @@ +--- +layout: page_v2 +title: Getting Started with Prebid Mobile +description: Getting Started with Prebid Mobile +sidebarType: 2 +--- + + +# Getting Started with Prebid Mobile + +{:.no_toc} + +This page gives an overview of steps you need to take, either as an ad ops user or as a developer, to start using Prebid Mobile. + +{% capture alertNote %} +If this is your first time working with header bidding, we recommend that you read [What is Prebid?](/overview/intro.html) before diving into Prebid Mobile. +{% endcapture %} + +{% include alerts/alert_note.html content=alertNote %} + +- TOC +{:toc} + +## Set Up Prebid Server + +Before you begin using Prebid Mobile in your apps, you need to prepare your end-to-end system. The first step is to set up your Prebid Server host. Prebid Mobile works in conjunction with Prebid Server to request and receive bids. Here are the options: + +- Register with a [Prebid.org member that hosts Prebid Server](https://prebid.org/product-suite/managed-services/). While you're waiting for your account, you can continue with the steps below. +- Set up your own Prebid Server host + +### Implement Your Own Prebid Server Host + +Prebid Server is an open source project. This allows you to host your own implementation of Prebid Server, though it's not as easy as downloading Prebid.js, because it needs to be hosted. The source code is available for [Prebid Server Go](https://github.com/prebid/prebid-server) and [Prebid Server Java](https://github.com/prebid/prebid-server-java). + +See the [Prebid Server documentation](/prebid-server/overview/prebid-server-overview.html) for more information on [setting up your own server host](/prebid-server/hosting/pbs-hosting.html). + +### A note on Accounts + +Several pages and examples in the mobile documentation refer to entering your "Prebid Server Account ID". + +In actuality, an `account ID` is just the name of the “top-level” stored request as described on the [Prebid Server Stored Request page](/prebid-server/features/pbs-storedreqs.html). + +By convention, most Prebid Server host companies define the top level stored request ID as the account ID they assign to the publisher. +This is a convenient convention since publishers generally set the same timeout and price granularity across all apps. +But it may not be the case for your Prebid Server host company, so please check with them. +If you’re hosting your own Prebid Server, this value can be whatever value you wish, not necessarily an account ID. + +## Configure Prebid Server + +After you've registered with your chosen Prebid Server host, you need to create at least one Prebid Server bidder configuration in a [stored request](/prebid-server/features/pbs-storedreqs.html). Each stored request configuration contains a list of bidders and their parameters. The configuration will be in the form of a JSON structure, similar to this: + +```json +[ + { + "bidder": "appnexus", + "params": { + "placementId": 13144370 + } + } +] +``` + +The preceding is an example "impression-level stored request" using AppNexus as the bidder. The parameters you need to set differ for each bidder. See [Bidder Parameters](/prebid-server/developers/add-new-bidder-go.html) for a full list of parameters for available Prebid Server bidders. + +Each block of JSON like this is called a "stored request" and gets an ID called a "stored request ID". This ID is then programmed into an adslot using the iOS or Android SDKs. Doing it this way allows the publisher to change bidders and parameters without +having to change the app. + +### Testing with stored configurations + +If you want to verify the SDK integration with test placements, you can add some [Stored Responses](https://docs.prebid.org/troubleshooting/pbs-troubleshooting.html#stored-responses) to your Prebid Server: + +1. Work with your Prebid Server provider to install the [Mobile Test Stored Requests](https://github.com/prebid/prebid-mobile-ios/tree/master/Example/PrebidDemo/stored-configs/stored-impressions) and [Mobile Test Stored Responses](https://github.com/prebid/prebid-mobile-ios/tree/master/Example/PrebidDemo/stored-configs/stored-responses). (Note: stored "impressions" are a special case of stored "requests" - your Prebid Server provider will know what to do.) + 1. Confirm that the bid prices in the stored responses reflects what you want to test. If you're using an ad server, you'll need line items set up that reflect the test bid CPMs and your price granularity setup. + 2. The Prebid Server **stored request IDs** could be the same as the filename in the repo, or could be different. If the IDs are different, your Prebid Server provider will let you know what IDs are available for testing. +2. Code the test mobile app setting the CONFIG_ID to the stored request ID of the relevant test, e.g. 'prebid-demo-banner-320-50'. +3. At runtime, here's what happens within Prebid Server: + 1. The stored request will pull in the stored response + 2. There will not be an actual auction + 3. The creative in the stored response will be sent to the SDK as the bid + +## Ad Ops - Setting Up the Ad Server + +Ad ops users configure the primary ad server with Prebid Mobile line items targeted to key/values. + +- [Set Up Line Items for Google Ad Manager](/adops/step-by-step.html) + +## Developers - Using the SDK + +To begin using Prebid Mobile follow the instructions for the respective platforms and integration approach: + +- [iOS Code Integration]({{site.github.url}}/prebid-mobile/pbm-api/ios/code-integration-ios.html) +- [Android Code Integration]({{site.github.url}}/prebid-mobile/pbm-api/android/code-integration-android.html) + +## Additional Information + +The following resources are available for further information on working with Prebid Mobile: + +### Ad Ops + +- [Price Granularity](/adops/price-granularity.html) Additional details to help you ensure your line items are set up to target bid prices at an appropriate level of granularity. + +### Mobile Developers + +#### Targeting Parameters + +Learn about the parameters available in the Prebid SDK + +- [iOS Targeting Parameters](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) Learn about the parameters available in the iOS Prebid Mobile SDK. +- [Android Targeting Parameters](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html) Learn about the parameters available in the Android Prebid Mobile SDK. + +#### GDPR + +Prebid Mobile provides APIs for app publishers in support of the [IAB Europe Transparency & Consent Framework](https://www.iab.com/topics/consumer-privacy/gdpr/). + +For general information on these APIs see [Prebid Mobile Guide to Privacy Regulation]({{site.baseurl}}/prebid-mobile/prebid-mobile-privacy-regulation.html). diff --git a/prebid-mobile/prebid-mobile-pbs.md b/prebid-mobile/prebid-mobile-pbs.md deleted file mode 100644 index 64cf7dd104..0000000000 --- a/prebid-mobile/prebid-mobile-pbs.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -layout: page_v2 -title: Getting Started with Prebid Mobile -description: Getting Started with Prebid Mobile -sidebarType: 2 ---- - - - -# Getting Started with Prebid Mobile -{:.no_toc} - -This page gives an overview of steps you need to take, either as an ad ops user or as a developer, to start using Prebid Mobile. - -{% capture alertNote %} -If this is your first time working with header bidding, we recommend that you read [What is Prebid?](/overview/intro.html) before diving into Prebid Mobile. -{% endcapture %} - -{% include alerts/alert_note.html content=alertNote %} - - -* TOC -{:toc} - -## Set Up Prebid Server - -Before you begin using Prebid Mobile in your apps, you need to prepare your end-to-end system. The first step is to set up your Prebid Server host. Prebid Mobile works in conjunction with Prebid Server to request and receive bids. Here are the options: - -- Register with a [Prebid.org member that hosts Prebid Server](https://prebid.org/product-suite/managed-services/). While you're waiting for your account, you can continue with the steps below. -- Set up your own Prebid Server host - -### Implement Your Own Prebid Server Host - -Prebid Server is an open source project. This allows you to host your own implementation of Prebid Server, though it's not as easy as downloading Prebid.js, because it needs to be hosted. The source code is available under the [Prebid organization on GitHub](https://github.com/prebid/prebid-server). There's also a [Java version of Prebid Server](https://github.com/prebid/prebid-server-java). - -See the [Prebid Server docs on GitHub](https://github.com/prebid/prebid-server/tree/master/docs/developers) for more information on setting up your own server host. - -## Configure Prebid Server - -After you've registered with your chosen Prebid Server host, you need to create at least one Prebid Server bidder configuration. Each configuration contains a list of bidders and their parameters. The configuration will be in the form of a JSON structure, similar to this: - -``` -[ - { - "bidder": "appnexus", - "params": { - "placementId": 13144370 - } - } -] -``` - -The preceding is an example structure using AppNexus as the bidder. The parameters you need to set differ for each bidder. See [Bidder Parameters]({{site.github.url}}/prebid-server/developers/add-new-bidder-go.html) for a full list of parameters for available Prebid Server bidders. - -## Developers - Using the SDK - -To begin using Prebid Mobile, download the Prebid Mobile SDK: -- [SDK for iOS](https://github.com/prebid/prebid-mobile-ios) -- [SDK for Android](https://github.com/prebid/prebid-mobile-android) - -After you have the SDK installed, register ad units with the Prebid Mobile framework. -- [iOS Code Integration]({{site.github.url}}/prebid-mobile/pbm-api/ios/code-integration-ios.html) -- [Android Code Integration]({{site.github.url}}/prebid-mobile/pbm-api/android/code-integration-android.html) - -## Ad Ops - Setting Up the Ad Server - -Ad ops users configure the primary ad server with Prebid Mobile line items targeted to key/values. -- [Set Up Line Items for Google Ad Manager]({{site.github.url}}/prebid-mobile/adops-line-item-setup-dfp.html) -- [Set Up Line Items for MoPub]({{site.github.url}}/prebid-mobile/adops-line-item-setup-mopub.html) - -## Additional Information - -The following resources are available for further information on working with Prebid Mobile: - -### Ad Ops - -- [Price Granularity](/prebid-mobile/adops-price-granularity.html) - Additional details to help you ensure your line items are set up to target bid prices at an appropriate level of granularity. - -### Mobile Developers - -**iOS** - -- [Targeting Parameters](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) - Learn about the parameters available in the iOS Prebid Mobile SDK. - - -**Android** - -- [Targeting Parameters](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html) - Learn about the parameters available in the Android Prebid Mobile SDK. - -### GDPR - -Prebid Mobile provides APIs for app publishers in support of the [IAB Europe Transparency & Consent Framework](https://www.iab.com/topics/consumer-privacy/gdpr/). - -For general information on these APIs see [Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice]({{site.baseurl}}/prebid-mobile/privacy-regulation.html). - -For specific implementation details, see the "GDPR Consent" section here: -- [iOS - Targeting Parameters](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Android - Targeting Parameters](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html) diff --git a/prebid-mobile/prebid-mobile-privacy-regulation.md b/prebid-mobile/prebid-mobile-privacy-regulation.md new file mode 100644 index 0000000000..025f1b4dc5 --- /dev/null +++ b/prebid-mobile/prebid-mobile-privacy-regulation.md @@ -0,0 +1,125 @@ +--- +layout: page_v2 +title: Prebid Mobile Guide to Privacy Regulation +description: Privacy Regulation Overview +pid: 2 +top_nav_section: prebid-mobile +nav_section: prebid-mobile +sidebarType: 2 +--- + +# Prebid Mobile Guide to Privacy Regulation +{:.no_toc} + +{% include legal-warning.html %} + +- TOC +{:toc} + +## Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice (GDPR) + +{% capture gdprNote %} + +In order for publishers to meet their transparency, notice and choice/consent requirements under the GDPR and the existing ePrivacy Directive, Prebid Mobile supports the [IAB Europe Transparency & Consent Framework](https://www.iab.com/topics/consumer-privacy/gdpr/) (the "Framework"). + +This is a reference for mobile app publishers using Prebid Mobile to surface notice, transparency and choice to end users located in the EEA and signal approved vendors and, where necessary, pass consent information to demand sources and their vendors. + +{% endcapture %} + +{% include alerts/alert_note.html content=gdprNote %} + +### Framework APIs + +Prebid Mobile provides API for app publishers to use with the Framework. This API allow you to: + +- Define whether the user is located in the European Economic Area (the "EEA") and if European privacy regulations should apply +- Set the [IAB Europe](https://www.iabeurope.eu/) (IAB) consent string + +This information will be persisted by Prebid Mobile and will be added to each ad call to the demand partners. + +Publishers/Consent Management Platforms (CMPs) are free to store these values in an `UserDefaults`/`SharedPreferences` interface (as defined by [IAB Tech Lab - CMP API v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md)) instead of passing them via the new APIs, and Prebid SDK will read the values as a fallback. The consent API's will check for TCF2.0 params -`IABTCF_gdprApplies` and `IABTCF_TCString`. + +Publishers are responsible for providing notice, transparency and choice and collecting consent from their users in accordance with [the Framework policies](https://www.iab.com/topics/consumer-privacy/gdpr/), either using their own CMP or working with a vendor. + +- [Register your own CMP](https://register.consensu.org/CMP) +- [List of registered CMPs](https://iabeurope.eu/cmp-list/) + +All vendor SDKs (including mediation SDKs) are responsible for looking up approved vendor and consent information on their own. + +- [iOS - Targeting Parameters](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) +- [Android - Targeting Parameters](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html) + +### Sending Device Information + +To ensure proper monetization and relevant targeting, the SDK should be enabled to send the device information. Setting the consentRequired and purposeConsents flag correctly will help ensure proper device information is sent. The table below provides information on: + +- Determining whether the device details will be passed or not. +- Describing the actions taken for the different purposeConsents values in combination with consentRequired values. + +{: .table .table-bordered .table-striped } +| | deviceAccessConsent= true | deviceAccessConsent= false | deviceAccessConsent= undefined | +|---------------------|------------------------------|--------------------------------|---------------------------------------| +|consentRequired=false
        (gdprApplies = false)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will read and pass IDFA/AAID info to server.| +|consentRequired=true
        (gdprApplies = true)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will **not** read and pass IDFA/AAID info to server.| +|consentRequired=undefined
        (gdprApplies = undefined)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will read and pass IDFA/AAID info to server.| + +{% capture codeNote %} + Publishers set the value of `gdprApplies` in `Targeting.shared.subjectToGDPR` and `purposeConsent` in `Targeting.shared.purposeConsents`. + + {% endcapture %} + +{% include /alerts/alert_important.html content=codeNote %} + +### Code Samples + +#### iOS + +```swift +Targeting.shared.subjectToGDPR = false; + +Targeting.shared.gdprConsentString = "BOMyQRvOMyQRvABABBAAABAAAAAAEA"; + +Targeting.shared.purposeConsents = "100000000000000000000000"; + +let deviceAccessConsent = Targeting.shared.getDeviceAccessConsent(); +``` + +#### Android + +```swift +TargetingParams.setSubjectToGDPR(context, true); + +TargetingParams.setGDPRConsentString("BOMyQRvOMyQRvABABBAAABAAAAAAEA"); + +TargetingParams.setPurposeConsents("101010001"); +``` + +## California Consumer Privacy Act (CCPA) + +{% capture ccpaNote %} + +In order for publishers to meet their notice and opt out obligations under the CCPA, +Prebid Mobile supports the IAB US Privacy signal as defined in the in-app section of the [IAB US Privacy signal for CCPA](https://iabtechlab.com/standards/ccpa/). + +This is a reference for mobile app publishers using Prebid Mobile to surface notice, transparency and choice to end users located in California, United States, passing notice and opt out signals where necessary, to demand sources and their vendors. + +{% endcapture %} +{% include alerts/alert_note.html content=ccpaNote %} + +### Notice and Opt out signal + +Prebid mobile supports the [IAB US Privacy signal](https://iabtechlab.com/standards/ccpa/) implementation for CCPA. Publishers will be required perform the following actions: + +- Collect notice and opt out signals from eligible CCPA users +- Translate notice and opt-out signals into [IAB US Privacy String format](https://iabtechlab.com/standards/ccpa/) +- Store IAB US Privacy signal in `UserDefaults` for iOS or `SharedPreferences` for Android for persistent storage allowing access for vendors per IAB recommendations + +The job of the Prebid SDK will: + +- Read from `UserDefaults` (iOS) or `SharedPreferences` (Android) for US Privacy signal + - Prebid SDK will look for the key `IABUSPrivacy_String`, all other key names or spellings will be ignored + - If the `IABUSPrivacy_String` key is present with a non-empty string value, the Prebid SDK will relay the privacy string to Prebid Server in the `regs.ext.us_privacy` extention +- Not perform or make any attempt to validate or ensure correctness of the US Privacy string +- Not strip any user data or signaling of the request regardless of Notice and Opt out signal + +It is worth noting Prebid Server will be a passthrough as well and will not validate format or correctness of US Privacy signal nor strip any user data from the request either, even if the presence of an opt out. diff --git a/prebid-mobile/prebid-mobile-video.md b/prebid-mobile/prebid-mobile-video.md new file mode 100644 index 0000000000..4de22086d1 --- /dev/null +++ b/prebid-mobile/prebid-mobile-video.md @@ -0,0 +1,53 @@ +--- +layout: page_v2 +title: Video Intro to Prebid Mobile +description: A video overview of Prebid Mobile SDK +sidebarType: 0 +--- + +# A Video Overview of Prebid Mobile + +A high-level overview of Prebid Mobile, Prebid’s header bidding product for iOS and Android applications. + +{% include vimeo-iframe.html id="822158733" title="1.4_Intro-to-Prebid-Mobile_v3" %} + +Further Content: + +- [Intro to Prebid](/overview/intro.html) +- [Prebid Managed Services](https://prebid.org/product-suite/managed-services/) +- [All videos](/overview/all-videos.html) + +Related Videos: + +- [Introduction to Header Bidding](/overview/intro-to-header-bidding-video.html) +- [Introduction to Prebid Server](/prebid-server/overview/prebid-server-overview-video.html) + +## Transcript + +Prebid is a non-profit organization, a JavaScript library, and a suite of products that extend the capabilities of the publisher ad stack. + +Prebid is a member-based organization made up of companies in the digital publishing and advertising technology industries. These companies work together through Prebid.org to build free, open source software that monetizes digital media through advertising. + +### Why Prebid? + +Prebid addresses the need for reliable shared technology in programmatic advertising. Serving a single ad is a complex and tightly choreographed routine that requires the cooperation of many entities. This process takes just a few seconds and occurs several billion times per day, accounting for billions of dollars per year in advertising spend. + +With such high stakes, the digital media industry needs standards that are accessible, transparent, and fair. Prebid establishes the foundation for sellers, buyers, and vendors to work together effectively to create high quality digital media supply chains and maximize the value of publishers’ content. + +### A Brief History of Prebid + +The birth of Prebid can be traced back to Prebid.js, an open-source JavaScript library that provided a simple and reliable way to implement header bidding on websites. Header bidding is technology that connects websites to programmatic advertising marketplaces. In the early days of header bidding, these integrations were complicated and opaque. This made it difficult for publishers to maximize the value of their content and difficult for advertisers to buy advertising space efficiently and transparently. + +Prebid.js addressed these problems by creating a standardized, transparent platform for header bidding. Following the rapid adoption of Prebid.js, Prebid.org was formed to oversee the development of Prebid technology and create new products. + +### Prebid’s Products + +Today, Prebid has three product areas: Prebid.js, Prebid Mobile, and Prebid Server. Prebid.js is a client-side header bidding wrapper for websites, while Prebid Mobile enables header bidding in iOS and Android applications. Prebid Server makes it possible to run header bidding auctions in the cloud for monetizing websites, apps, long form video streams, digital out-of-home, and other forms of media. + +### Prebid.org + +Prebid Org has a Board of Directors representing its publisher, buyer, and technology provider members. The Board steers Prebid, upholding its principles and setting its goals. Within Prebid.org, there are also several Project Management Committees, each of which drives the development of a specific Product area. The Committees are made up of people who work for Prebid’s member companies. Prebid also has a small full-time staff that does software development, community development, and administration. The Prebid community also includes companies who offer proprietary products and services that extend Prebid’s capabilities and provide enterprise support. + +### Learn More + +To learn more about Prebid, visit prebid.org. To get started using Prebid, visit docs.prebid.org. To learn about becoming a Prebid Member, visit prebid.org/membership. To contribute to the software, visit Prebid's Github repository at github.com/prebid. diff --git a/prebid-mobile/prebid-mobile.md b/prebid-mobile/prebid-mobile.md index 7346125dd4..42ca24320d 100644 --- a/prebid-mobile/prebid-mobile.md +++ b/prebid-mobile/prebid-mobile.md @@ -8,57 +8,189 @@ sidebarType: 2 --- # Prebid Mobile Overview +{:.no_toc} -Prebid Mobile is an open-source library that provides an end-to-end header bidding solution for mobile app publishers. Use this library with your ad server's Mobile SDK to communicate with Prebid Server to request and receive bids over RTB. These bids can then compete directly with bids from your primary ad server. +Prebid Mobile is an open-source library that provides an end-to-end header bidding solution for mobile app publishers. Prebid Mobile libraries are available for iOS and Android. -## Benefits and Features +{: .alert.alert-info :} +The Prebid Mobile team is pleased to announce that we're getting ready +to start building the next major version. Please see the +[plan for Prebid Mobile 3.0](/prebid-mobile/docs/Prebid_Mobile_3_0_0.pdf) +and provide feedback to . + +- TOC +{:toc} -Some of the benefits to using the Prebid Mobile header bidding solution include: +## Video Overview of Prebid Mobile -- Provides a single integration point with Prebid Server, enabling direct access to more mobile buyers. -- Allows for server-side configuration management; no need for developers to update the app to make configuration changes. -- Provides a transparent, open source header bidding solution. -- Flattens mediation layers, reducing ad ops burden for managing mediation partners. -- Reduces latency compared to mediation. -- Designed to integrate with any deployment of the open-source Prebid Server code. (Vendor must be registered in Prebid Mobile as a Prebid Server host.) +A high-level overview of Prebid Mobile, Prebid’s header bidding product for iOS and Android applications. -## Requirements +{% include vimeo-iframe.html id="822158733" title="1.4_Intro-to-Prebid-Mobile_v3" %} -- Prebid Server Configuration +Further Content: - You must have a Prebid Server account in order to use Prebid Mobile. Prebid Server is a server-based host that communicates bid requests and responses between Prebid Mobile and demand partners. +- [Transcript of this video](/prebid-mobile/prebid-mobile-video.html) +- [Prebid Managed Services](https://prebid.org/product-suite/managed-services/) + +## Benefits and Features - To set up your Prebid Server account for Prebid Mobile, refer to [Getting Started with Prebid Mobile]({{site.github.url}}/prebid-mobile/prebid-mobile-pbs.html). +Prebid SDK rendering offers the following benefits: -- Primary Ad Server Setup +- **Transparent, open source header bidding solution**. The single integration point with Prebid Server, enabling direct access to more mobile buyers. +- **Monetization without an Ad Server**: Publishers who do not have a direct sales force or have no need for an ad server can still access Prebid's mobile demand stack. Publishers will be able to render ads directly without relying on any 3rd party SDKs. +- **Reduced ad delivery latency**: The rendering module enables Prebid SDK to render ads immediately when demand is returned from Prebid Server or when receiving the render signal from an ad server. The render process should vastly reduce ad delivery speeds. +- **Less infrastructure**: The rendering API does not rely on Prebid Server's Cache server, reducing the cost and utility of Prebid Server Cache. +- **Less discrepancy**: Having control of the rendering process provides the potential to reduce discrepancy by having ads instantly available (less http calls, less infrastructure, less setup). This control enables the publisher to follow open and transparent industry standards or even potentially custom requirements from buyers. +- **Framework support**: Full support of SKAdNetworks and similar frameworks +- **MRAID 3.0 support** +- **Flexible Ad Measurement**: Controlling the rendering and Open Measurement process allows publishers to potentially configure any measurement provider in a transparent and open source process. Prebid SDK will eventually be IAB Open Measurement certified. +- **Ad Server Support**: can be integrated in any potential monetization stack. +- **Community driven**: Being a part of Prebid, there is the ability to add features not readily or easily available either through the Ad Server or other SDKs - Prebid Mobile enables you to retrieve bids simultaneously from multiple demand partners outside of a single ad server. This header bidding process does not determine a final winning bid. Ad ops users need to set up line items associated with each ad unit on a primary ad server. Prebid Mobile will send bids (via the primary ad server SDK) to the primary ad server. This ad server will include the bids from the header bidding process in determining a winning bid. (See "How It Works" below.) +### Potential Features -- Prebid Mobile SDK +This set of features are not supported in the current release but are designated for future implementation. - Mobile app developers implement header bidding through the Prebid Mobile SDK integration. SDKs are available for [iOS](https://github.com/prebid/prebid-mobile-ios) and [Android](https://github.com/prebid/prebid-mobile-android). +- **Multiformat Ad Unit**: The rendering engine will enable Prebid SDK to display any bid format in the given inventory regardless of Primary Ad Server capabilities. +- **Support of Custom Ad Servers**: With rendering engine, the Prebid SDK can work with any Ad Server. Right now it supports GAM, AdMob, and MAX. ## How It Works -The following diagram shows how the Prebid Mobile header bidding solution works. +Prebid SDK supports following integration scenarios: + +- **Custom or No mediation** when no Primay Ad Server is used. The SDK renders the winning bid immediately when it is available. +- **Using a Primary Ad Server**. There are three aproaches are avaliable for integration with primary ad server + - **Original API**. In this case the SDK plays a transport role of the bid from PBS to Primary ad Server where it takes place in the internal auction and the winning bid is rendered later with Prebid Universal Creative as part of Primary Ad Server Creaitve + - **Rendering API** Prebid SDK detects when a Prebid line item wins on the ad server and renders the cached bid in the owned Web view or Video view. + - **Mediation API** Prebid Adapter detects when a Prebid line item corresponds to the winning bid and renders the cached bid in the owned Web view or Video view. + +In all scenarios, Prebid SDK leverages Prebid Server for demand. + +The following chart shows which API is used for which Ad Server + +{: .table .table-bordered .table-striped } + +|Ad Server|Original API|Rendering API|Mediation API| +|------------|------------|-------------|-------------| +|No Ad Server| | ✅ | | +|GAM | ✅ | ✅ | | +|AdMob | | | ✅ | +|MAX | | | ✅ | + +The following sections describe each integration method. + +### No Ad Server + +![In-App Rendering](/assets/images/prebid-mobile/modules/rendering/Prebid-In-App-Bidding-Overview-Pure-Prebid.png){: .pb-lg-img :} + +1. The Prebid SDK sends the bid request to the Prebid Server +1. Prebid Server runs the header bidding auction among preconfigured demand partners +1. Prebid Server responds with the winning bid +1. The rendering module renders the winning bid + +### With Ad Server: Original API + +Supported Ad Servers: GAM. + +![How Prebid Mobile Works - Diagram]({{site.baseurl}}/assets/images/prebid-mobile/prebid-in-app-bidding-overview-prebid-original.png) +{: .pb-lg-img :} + +1. Prebid Mobile sends a request to Prebid Server. This request consists of the Prebid Server account ID and config ID for each tag included in the request. +1. Prebid Server constructs an OpenRTB bid request and passes it to the demand partners. Each demand partner returns a bid response to Prebid Server. The bid response includes the bid price and the creative content. +1. Prebid Server sends the bid responses to Prebid Mobile. +1. Prebid Mobile sets key/value targeting for each ad slot through the primary ad server mobile SDK. +1. The primary ad server SDK sends the ad request enriched with targeting keywords of the wiining bid. +1. The primary ad server responds with an ad. If the line item associated with the Prebid Mobile bid wins, the primary ad server returns the Prebid Universal Creative (PUC) to the ad server's SDK. +1. The primary ad server SDK starts the rendering recived ad markup. +1. The PUC fetches creative content of the winning bid from the Previd Cache and renders it. + +### With Ad Server: Rendering API + +Supported Ad Servers: GAM. + +![Rendering with Primary Ad Server](/assets/images/prebid-mobile/modules/rendering/In-App-Bidding-Integration.png) +{: .pb-lg-img :} + +1. The rendering module sends the bid request to the Prebid server. +1. Prebid server runs the header bidding auction among preconfigured demand partners. +1. Prebid Server responds with the winning bid that contains targeting keywords. +1. The rendering module sets up the targeting keywords of the winning bid into the ad unit of the primary ad server SDK. +1. The primary ad server SDK sends the ad request to the primary ad server. +1. The primary ad server responds with an ad or mediation chain. +1. The winning ad meta information is passed to the rendering module. +1. Depending on the ad response, the rendering module renders the winning bid or allows the primary ad server SDK to show its own winning ad. + +### With Ad Server: Mediation API + +Supported Ad Servers: AdMob, MAX. + +![How Prebid Mobile Works - Diagram]({{site.baseurl}}/assets/images/prebid-mobile/prebid-in-app-bidding-overview-mediation.png) +{: .pb-lg-img :} + +1. The Prebid SDK sends the bid request to the Prebid server. +1. Prebid server runs the header bidding auction among preconfigured demand partners. +1. Prebid Server responds with the winning bid that contains targeting keywords. +1. [OPTIONAL] The Prebid SDK sets up the targeting keywords of the winning bid into the ad unit of the primary ad server SDK. +1. The primary ad server SDK sends the ad request to the primary ad server. +1. The primary ad server responds with a mediation chain. +1. The Primary Ad Server SDK runs the Waterfall. +1. If the mediation item contains the name Prebid Adatper it instantiates the respoctive class. +1. [OPTIONAL] adaters checks the wheather the Line Item's targeting keywors match the bid targeting keywords +1. Adapter renders a wiining bid cached in the SDK. + +Note: passing the targeting keywords to the ad server depends on the server's ability to target line items. If the server doesn't provide such a feature, Prebid SDK doesn't enrich an ad request with targeting info. But activation of a line item with the proper price still works. The implementation details of such selection you can find in the respective integration guide. + +## Integration Reference + +### Prebid Server + +You must have a Prebid Server account in order to use Prebid Mobile. Prebid Server is a server-based host that communicates bid requests and responses between Prebid Mobile and demand partners. + +To set up your Prebid Server account for Prebid Mobile, refer to [Getting Started with Prebid Mobile]({{site.github.url}}/prebid-mobile/prebid-mobile-getting-started.html). + +### Android -![How Prebid Mobile Works - Diagram]({{site.baseurl}}/assets/images/prebid-mobile/pbm-overview-flow.png){: .pb-lg-img :} +Follow these steps to integrate the Prebid SDK: -1. Prebid Mobile sends a request to Prebid Server. This request consists of the Prebid Server account ID and config ID for each tag included in the request. +1. If integrating into an ad server, create line items specific for rendering (line items for rendering API are unique and do not coincide with the standard Prebid SDK line items): + - [GAM Original API](../adops/step-by-step.html) + - [GAM Rendering API](../adops/mobile-rendering-gam-line-item-setup.html) + - [AdMob](../adops/mobile-rendering-admob-line-item-setup.html) + - [MAX](../adops/mobile-rendering-max-line-item-setup.html) +1. [Integrate Prebid SDK](pbm-api/android/code-integration-android.html) into your project. +1. Add prebid's ad units to your app respectively to the monetization scenario: + - [GAM Original API](pbm-api/android/android-sdk-integration-gam-original-api.html) + - [Custom in-app bidding](modules/rendering/android-sdk-integration-pb.html) integration without primary ad server. + - [GAM Rendering API](modules/rendering/android-sdk-integration-gam.html) as a primary ad server + - [AdMob](modules/rendering/android-sdk-integration-admob) as a primary ad server. + - [AppLovin MAX](modules/rendering/android-sdk-integration-max.html) as a primary ad server. -2. Prebid Server constructs an OpenRTB bid request and passes it to the demand partners. +1. Actualize the [integration and targeting](pbm-api/android/pbm-targeting-params-android.html) properties. -3. Each demand partner returns a bid response to Prebid Server. The bid response includes the bid price and the creative content. +### iOS -4. Prebid Server sends the bid responses to Prebid Mobile. +Follow these steps to integrate the rendering API: -5. Prebid Mobile sets key/value targeting for each ad slot through the primary ad server mobile SDK. This targeting will activate one or more of Prebid line items that were previously configured in the primary ad server. +1. If integrating into an ad server, create line items specific for rendering (line items are uniqe for the Rendering Module and do not cooicide with the standard Prebid SDK line items): + - [GAM Original API](../adops/step-by-step.html) + - [GAM](../adops/mobile-rendering-gam-line-item-setup.html) + - [AdMob](../adops/mobile-rendering-admob-line-item-setup.html) + - [MAX](../adops/mobile-rendering-max-line-item-setup.html) +1. [Integrate Prebid SDK](pbm-api/ios/code-integration-ios.html). +1. Add prebid's ad units to your app respectively to the monetization scenario: + - [GAM Original API](pbm-api/ios/code-integration-ios.html) + - [Custom in-app bidding](modules/rendering/ios-sdk-integration-pb.html) integration without a primary ad server. + - [GAM Rendering API](modules/rendering/ios-sdk-integration-gam.html) as a primary ad server. + - [AdMob](modules/rendering/ios-sdk-integration-gam.html) as a primary ad server. + - [AppLovin MAX](modules/rendering/ios-sdk-integration-max.html) as a primary ad server. +1. Actualize the [integration and targeting](pbm-api/ios/pbm-targeting-params-ios.html) properties. -6. If the line item associated with the Prebid Mobile bid wins, the primary ad server returns the Prebid Mobile creative JavaScript to the ad server's SDK. +## Additional References -7. The Prebid Mobile creative JavaScript will fetch and render the corresponding creative content from the winning Prebid Server demand partner. +- [Deep Links Support](modules/rendering/rendering-deeplinkplus.html) +- [Impression Tracking](modules/rendering/rendering-impression-tracking.html) ## Mobile Analytics diff --git a/prebid-mobile/privacy-regulation.md b/prebid-mobile/privacy-regulation.md deleted file mode 100644 index cf672cf34a..0000000000 --- a/prebid-mobile/privacy-regulation.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -layout: page_v2 -title: Prebid Mobile Guide to Privacy Regulation -description: Privacy Regulation Overview -pid: 2 -top_nav_section: prebid-mobile -nav_section: prebid-mobile -sidebarType: 2 ---- - -# Prebid Mobile Guide to Privacy Regulation - -{:.no_toc} - -{% capture legalNotice %} - This resource should not be construed as legal advice and Prebid.org makes no guarantees about compliance with any law or regulation. Please note that because every company and its collection, use, and storage of personal data is different, you should seek independent legal advice relating to obligations under European and /or US regulations, including the GDPR, the ePrivacy Directive and CCPA. Only a lawyer can provide you with legal advice specifically tailored to your situation. Nothing in this guide is intended to provide you with, or should be used as a substitute for, legal advice tailored to your business. - {% endcapture %} - -{% include /alerts/alert_important.html content=legalNotice %} - -* TOC -{:toc} - -## Prebid Mobile Guide to European Ad Inventory and Providing Notice, Transparency and Choice (GDPR) - -{% capture gdprNote %} - - In order for publishers to meet their transparency, notice and choice/consent requirements under the GDPR and the existing ePrivacy Directive, Prebid Mobile supports the [IAB Europe Transparency & Consent Framework](https://www.iab.com/topics/consumer-privacy/gdpr/) (the "Framework"). - - This is a reference for mobile app publishers using Prebid Mobile to surface notice, transparency and choice to end users located in the EEA and signal approved vendors and, where necessary, pass consent information to demand sources and their vendors. - - -{% endcapture %} - -{% include alerts/alert_note.html content=gdprNote %} - -### Framework APIs - -Prebid Mobile provides three APIs for app publishers to use with the Framework. These APIs allow you to: - -- Define whether the user is located in the European Economic Area (the "EEA") and if European privacy regulations should apply -- Set the [IAB Europe](https://www.iabeurope.eu/) (IAB) consent string - -This information will be persisted by Prebid Mobile and will be added to each ad call to the demand partners. Publishers/Consent Management Platforms (CMPs) are free to store these values in an `NSUserDefaults/SharedPreferences` interface (as defined by [Mobile In-App CMP API v1.0: Transparency & Consent Framework](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/Mobile%20In-App%20Consent%20APIs%20v1.0%20Final.md)) instead of passing them via the new APIs, and Prebid Mobile will read the values as a fallback. The consent API's will check for TCF2.0 params (`IABTCF_gdprApplies` and `IABTCF_TCString`). If the parameters are not available they will fall back to TCF1.1 parameters (`IABConsent_SubjectToGDPR` and `IABConsent_ConsentString`) - -Publishers are responsible for providing notice, transparency and choice and collecting consent from their users in accordance with [the Framework policies](https://www.iab.com/topics/consumer-privacy/gdpr/), either using their own CMP or working with a vendor. - -- [Register your own CMP](https://register.consensu.org/CMP) -- [List of registered CMPs](https://iabeurope.eu/cmp-list/) - -All vendor SDKs (including mediation SDKs) are responsible for looking up approved vendor and consent information on their own. - -- [iOS - Targeting Parameters](/prebid-mobile/pbm-api/ios/pbm-targeting-ios.html) -- [Android - Targeting Parameters](/prebid-mobile/pbm-api/android/pbm-targeting-params-android.html) - -## Sending Device Information - -To ensure proper monetization and relevant targeting, the SDK should be enabled to send the device information. Setting the consentRequired and purposeConsents flag correctly will help ensure proper device information is sent. The table below provides information on: - -- Determining whether the device details will be passed or not. -- Describing the actions taken for the different purposeConsents values in combination with consentRequired values. - -{: .table .table-bordered .table-striped } -| | deviceAccessConsent= true | deviceAccessConsent= false | deviceAccessConsent= undefined | -|---------------------|------------------------------|--------------------------------|---------------------------------------| -|consentRequired=false
        (gdprApplies = false)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will read and pass IDFA/AAID info to server.| -|consentRequired=true
        (gdprApplies = true)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will **not** read and pass IDFA/AAID info to server.| -|consentRequired=undefined
        (gdprApplies = undefined)|The SDK will read and pass IDFA/AAID info to server. |The SDK will **not** read and pass IDFA/AAID info to server. | The SDK will read and pass IDFA/AAID info to server.| - -{% capture codeNote %} - Publishers set the value of `gdprApplies` in `Targeting.shared.subjectToGDPR` and `purposeConsent` in `Targeting.shared.purposeConsents`. - - {% endcapture %} - -{% include /alerts/alert_important.html content=codeNote %} - -## Code Samples - -### iOS - -
        -
        -
        -  /** * Set the consentRequired value in the SDK
        -  *
        -  * @param true if subject to GDPR regulations, false otherwise
        -  */
        -  Targeting.shared.subjectToGDPR = false;
        -
        -  /**
        -  * Set the consent string in the SDK
        -  *
        -  * @param A valid Base64 encode consent string as per https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework
        -  */
        -  Targeting.shared.gdprConsentString = "BOMyQRvOMyQRvABABBAAABAAAAAAEA";
        -
        -  /**
        -  * Set the purpose consents in the SDK
        -  *
        -  * @param A valid Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the consent status for purpose ID n+1; false and true respectively. eg. '1' at index 0 is consent true for purpose ID 1
        -  */
        -  Targeting.shared.purposeConsents = "100000000000000000000000";
        -
        -
        -  /**
        -  * Get the device consent extracted from the purpose1 consent provided
        -  *
        -  */
        -  let deviceAccessConsent = Targeting.shared.getDeviceAccessConsent();
        -
        -
        -
        - -### Android - -
        -
        -
        -    /** * Set the consentRequired value in the SDK
        -    *
        -    * @param true if subject to GDPR regulations, false otherwise
        -    */
        -    TargetingParams.setSubjectToGDPR(context, true);
        -
        -
        -    /**
        -    * Set the consent string in the SDK
        -    *
        -    * @param A valid Base64 encode consent string as per
        -    * https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework
        -    */
        -    TargetingParams.setGDPRConsentString("BOMyQRvOMyQRvABABBAAABAAAAAAEA");
        -
        -    /**
        -    * Set the purpose consents in the SDK
        -    *
        -    * @param A valid Binary String: The '0' or '1' at position n – where n's indexing begins at 0 – indicates the consent status for purpose ID n+1; false and true respectively. eg. '1' at index 0 is consent true for purpose ID 1
        -    */
        -    TargetingParams.setPurposeConsents("101010001");
        -
        -
        -
        - -## California Consumer Privacy Act (CCPA) - -{% capture ccpaNote %} - -In order for publishers to meet their notice and opt out obligations under the CCPA, -Prebid Mobile supports the IAB US Privacy signal as defined in the in-app section of the [IAB US Privacy signal for CCPA](https://iabtechlab.com/standards/ccpa/). - - This is a reference for mobile app publishers using Prebid Mobile to surface notice, transparency and choice to end users located in California, United States, passing notice and opt out signals where necessary, to demand sources and their vendors. - -{% endcapture %} -{% include alerts/alert_note.html content=ccpaNote %} - - -### Notice and Opt out signal - -Prebid mobile supports the [IAB US Privacy signal](https://iabtechlab.com/standards/ccpa/) implementation for CCPA. Publishers will be required perform the following actions: -- Collect notice and opt out signals from eligible CCPA users -- Translate notice and opt-out signals into [IAB US Privacy String format](https://iabtechlab.com/standards/ccpa/) -- Store IAB US Privacy signal in NSUserDefaults for iOS or SharedPreferences for Android for persistent storage allowing access for vendors per IAB recommendations - -The job of the Prebid SDK will: -- Read from NSUserDefaults (iOS) or SharedPreferences(Android) for US Privacy signal - - Prebid SDK will look for the key "IABUSPrivacy_String", all other key names or spellings will be ignored - - If the "IABUSPrivacy_String" key is present with a non-empty string value, the Prebid SDK will relay the privacy string to Prebid Server in the regs.ext.us_privacy extention -- Not perform or make any attempt to validate or ensure correctness of the US Privacy string -- Not strip any user data or signaling of the request regardless of Notice and Opt out signal - -It is worth noting Prebid Server will be a passthrough as well and will not validate format or correctness of US Privacy signal nor strip any user data from the request either, even if the presence of an opt out. - - - - diff --git a/prebid-server/developers/add-a-module-go.md b/prebid-server/developers/add-a-module-go.md new file mode 100644 index 0000000000..293b478d42 --- /dev/null +++ b/prebid-server/developers/add-a-module-go.md @@ -0,0 +1,314 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Developers | Adding a Go Module + +--- + +# Prebid Server - Adding a Go Module +{: .no_toc} + +- TOC +{:toc } + +## Overview + +This document details how to make a module for PBS-Go. + +You will want to be familiar with the following background information: + +- the [module overview](/prebid-server/developers/add-a-module.html) +- the [PBS-Go Modularity Tech Spec](https://docs.google.com/document/d/1CmamniQpwcI3p0_rHe2F17zV4sEhzpOdrqU7zuZVZ_I/edit?usp=sharing) + +### Contributing + +Check out the [PBS-Go contribution guide](https://github.com/prebid/prebid-server/blob/master/docs/developers/contributing.md) before introducing any code changes. + +## Module Directory Layout + +The Prebid Server repository contains a package `modules` located in the root project directory. It includes all available PBS modules. So, in order to add a new module, fork the repository and create a folder with the desired name inside the `modules` folder with the following structure: + +```text ++- prebid-server/ + +- modules/ <- package with modules that implement various hooks + +- builder.go <- contains a list of all available modules + +- {YOUR_VENDOR_NAME}/ <- top-level package used to group modules from the same vendor + +- {YOUR_MODULE_NAME}/ <- package with source code of your module + +- module.go <- file with module initialization function +``` + +Module directory names (`{YOUR_VENDOR_NAME}/YOUR_MODULE_NAME/}`) must consist of valid identifiers. +A valid identifier is defined as a sequence of one or more letters, including an underscore character (`_`), and digits. +All other symbols such as `-`, `.`, etc. are not permitted. + +### Your module's build file + +Here's a partial example of your module-specific `module.go` file: + +```go +package your_module_name + +import ( + "context" + "encoding/json" + + "github.com/prebid/prebid-server/hooks/hookstage" + "github.com/prebid/prebid-server/modules/moduledeps" +) + +func Builder(config json.RawMessage, deps moduledeps.ModuleDeps) (interface{}, error) { + return Module{}, nil +} + +// Module must implement at least 1 hook interface. +type Module struct{} + +func (m Module) HandleBidderRequestHook( + ctx context.Context, + invocationCtx hookstage.ModuleInvocationContext, + payload hookstage.BidderRequestPayload, +) (hookstage.HookResult[hookstage.BidderRequestPayload], error) { + result := hookstage.HookResult[hookstage.BidderRequestPayload]{} + + // hook handling logic + + return result, nil +} +``` + +In the example above, our module only implements the `bidder-request` hook interface. + +The module's `Builder` function receives 2 arguments: + +1. `config json.RawMessage` - represents a global config of your module, see [Configuration](#configuration). +2. `deps moduledeps.ModuleDeps` - contains dependencies that your module might require. + +and returns 2 values: + +1. `interface{}` - must implement at least 1 hook interface, see [hooks](#hook-interfaces). PBS uses type assertion to find out which hook interfaces implemented by module. +2. `error` - any error occurred during module initialization. + +### Expose your module to PBS + +All available modules are exposed through the `modules/builder.go` file. This file is auto-generated, so you shouldn’t edit it manually. + +To register a new module, you just need to run one of the following commands from the PBS root directory: + +- `make build-modules` +- or `go generate modules/modules.go` + +This command scans the `modules/` directory for files matching the pattern `modules/*/*/module.go` and adds all matching packages to the `modules/builder.go` file. + +## Module Code + +The quick start is to take a look in two places: + +- the [prebid ortb2blocking module](https://github.com/prebid/prebid-server/tree/master/modules/prebid/ortb2blocking) +- the [hook source code and tests](https://github.com/prebid/prebid-server/tree/master/hooks) + +### Adding module documentation +It is required to add a "README.md" file to the root of your module folder. It's recommended to specify the description of what the implemented module does, links to external documentation and include maintainer contact info (email, slack, etc). + +The documentation must also live on the docs.prebid.org site. Please add a markdown file to + +### Hook Interfaces + +The Prebid server processing workflow is divided into several 'stages' where module authors can inject a specific function signature called a 'hook'. + +The Prebid Server host company will define which modules to run in which order by setting up a configuration defining which hooks run serially and which can run in parallel. + +The supported stages are described in the [general module overview](/prebid-server/developers/add-a-module.html#2-understand-the-endpoints-and-stages) and in PBS-Core source code at the "github.com/prebid/prebid-server/hooks" package. + +These are the available hooks that can be implemented in a module: + +- github.com/prebid/prebid-server/hooks/hookstage.Entrypoint +- github.com/prebid/prebid-server/hooks/hookstage.RawAuctionRequest +- github.com/prebid/prebid-server/hooks/hookstage.ProcessedAuctionRequest +- github.com/prebid/prebid-server/hooks/hookstage.BidderRequest +- github.com/prebid/prebid-server/hooks/hookstage.RawBidderResponse +- github.com/prebid/prebid-server/hooks/hookstage.AllProcessedBidResponses +- github.com/prebid/prebid-server/hooks/hookstage.AuctionResponse + +In a module it is not necessary to implement all mentioned interfaces but at least one is required by your functionality. + +### Examples + +1. To **update** the request in the `BidderRequest`, your implementation would return a hook result with a change set: + + ```go + import ( + "context" + + "github.com/prebid/prebid-server/hooks/hookstage" + ) + + type Module struct{} + + func (m Module) HandleBidderRequestHook( + ctx context.Context, + invocationCtx hookstage.ModuleInvocationContext, + payload hookstage.BidderRequestPayload, + ) (hookstage.HookResult[hookstage.BidderRequestPayload], error) { + changeSet := hookstage.ChangeSet[hookstage.BidderRequestPayload]{} + changeSet.BidderRequest().BAdv().Update([]string{"a.com"}) + + return hookstage.HookResult[hookstage.BidderRequestPayload]{ChangeSet: changeSet}, nil + } + ``` + + Please note, the `hookstage.ChangeSet` has a restricted set of methods, but methods can be easily extended when more use cases come up. + + For more complex payload updates, you can choose another method: + + ```go + func (m Module) HandleBidderRequestHook( + ctx context.Context, + invocationCtx hookstage.ModuleInvocationContext, + payload hookstage.BidderRequestPayload, + ) (hookstage.HookResult[hookstage.BidderRequestPayload], error) { + battrByImp := map[string][]adcom1.CreativeAttribute{"imp_ID1": []adcom1.CreativeAttribute{adcom1.AttrAudioAuto}} + changeSet := hookstage.ChangeSet[hookstage.BidderRequestPayload]{} + changeSet.AddMutation(func(payload hookstage.BidderRequestPayload) (hookstage.BidderRequestPayload, error) { + for i, imp := range payload.BidRequest.Imp { + if battr, ok := battrByImp[imp.ID]; ok { + imp.Banner.BAttr = battr + payload.BidRequest.Imp[i] = imp + } + } + return payload, nil + }, hookstage.MutationUpdate, "bidrequest", "imp", "banner", "battr") + + return hookstage.HookResult[hookstage.BidderRequestPayload]{ChangeSet: changeSet}, nil + } + ``` + +2. To **reject** the bidder in the `BidderRequest`, your hook implementation would return a hook result with a reject flag and an NBR code: + + ```go + func (m Module) HandleBidderRequestHook( + ctx context.Context, + invocationCtx hookstage.ModuleInvocationContext, + payload hookstage.BidderRequestPayload, + ) (hookstage.HookResult[hookstage.BidderRequestPayload], error) { + return hookstage.HookResult[hookstage.BidderRequestPayload]{Reject: true, NbrCode: 7}, nil + } + ``` + + Refer [here](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/OpenRTB%20v3.0%20FINAL.md#list--no-bid-reason-codes-) for a list of available No Bid Response Codes. + +3. To supply [analytics tags](/prebid-server/developers/module-atags.html) in the `BidderRequest`, your hook implementation would return a hook result with analytics tags: + + ```go + import ( + "context" + + "github.com/prebid/prebid-server/hooks/hookstage" + "github.com/prebid/prebid-server/hooks/hookanalytics" + ) + + func (m Module) HandleBidderRequestHook( + ctx context.Context, + invocationCtx hookstage.ModuleInvocationContext, + payload hookstage.BidderRequestPayload, + ) (hookstage.HookResult[hookstage.BidderRequestPayload], error) { + return hookstage.HookResult[hookstage.BidderRequestPayload]{ + AnalyticsTags: hookanalytics.Analytics{ + Activities: []hookanalytics.Activity{ + { + Name: "enforce_blocking", + Status: hookanalytics.ActivityStatusSuccess, + Results: []hookanalytics.Result{ + { + Status: hookanalytics.ResultStatusBlock, + Values: map[string]interface{}{ + "attributes": []string{"bcat"}, + "bcat": []string{"IAB-1"}, + }, + AppliedTo: hookanalytics.AppliedTo{Bidder: "appnexus", ImpIds: []string{"imp_ID1"}}, + }, + { + Status: hookanalytics.ResultStatusAllow, + AppliedTo: hookanalytics.AppliedTo{Bidder: "appnexus", ImpIds: []string{"imp_ID2"}}, + }, + }, + }, + }, + }, + }, nil + } + ``` + +More test implementations for each hook can be found in unit-tests at [github.com/prebid/prebid-server/tree/master/modules/prebid/ortb2blocking](https://github.com/prebid/prebid-server/tree/master/modules/prebid/ortb2blocking) folder. + +### Configuration + +It's possible to define default module configuration which can be read by the module at PBS startup. An example configuration for hooks might look like this: + +```json +{ + "hooks": { + "enabled": true, + "modules": { + "vendor1": { + "module1": { + "enabled": true + } + } + }, + "host_execution_plan": { + "endpoints": { + "/openrtb2/auction": { + "stages": { + "bidder_request": { + "groups": [ + { + "timeout": 10, + "hook_sequence": [ + { + "module_code": "vendor1.module1", + "hook_impl_code": "code123" + } + ] + } + ] + } + } + } + } + } + } +} +``` + +### Testing + +Unit tests are required. Each implemented hook must be at least 90% covered by unit tests. + +### How to build and install a module + +Read about the module building in the [building section](https://docs.google.com/document/d/1CmamniQpwcI3p0_rHe2F17zV4sEhzpOdrqU7zuZVZ_I/edit#heading=h.o8dv0neoq4xm) of the technical specification. + +## Analytics Adapters and Modules + +Each module can inject analytics tags into the request as described in the analytics tags section. + +Analytics adapters receive these tags through the Auction/AMP analytic object. + +To get analytics tags you need to go into: + +```text +AuctionObject/AmpObject + -> HookExecutionOutcome (iterate through stages) + -> Groups (iterate through groups) + -> InvocationResults (go through hooks invocation results and find interested one) + -> AnalyticsTags +``` + +The `AnalyticsTags` object has activities with collection of `github.com/prebid/prebid-server/hooks/hookanalytics.Result` objects inside. Each `Result` has the `Values` field which holds arbitrary values set by a module. + +It depends on the particular module implementation how to parse their analytics tags, since the internal structure is custom and depends on the module. Therefore, analytics modules that want to report on specific behavior need to be coded to know about that module. See the prebid ortb2blocking module for an example of what analytics tags may be available. + +## Further Reading + +- [PBS Module Overview](/prebid-server/developers/add-a-module.html) +- [PBS Module Analytics Tags Conventions](/prebid-server/developers/module-atags.html) diff --git a/prebid-server/developers/add-a-module-java.md b/prebid-server/developers/add-a-module-java.md index a021a96ca4..c9f474e84c 100644 --- a/prebid-server/developers/add-a-module-java.md +++ b/prebid-server/developers/add-a-module-java.md @@ -8,7 +8,7 @@ title: Prebid Server | Developers | Adding a Java Module # Prebid Server - Adding a Java Module {: .no_toc} -* TOC +- TOC {:toc } ## Overview @@ -17,18 +17,18 @@ This document details how to make a module for PBS-Java. You will want to be familiar with the following background information: -- the [module overview](/prebid-server/developers/add-a-module.html) +- the [module overview](/prebid-server/developers/add-a-module.html) - the [PBS-Java Modularity Tech Spec](https://docs.google.com/document/d/1VP_pi7L5Iy3ikHMbtC2_rD5RZTVSc3OkTWKvtRS5x5Y/edit#heading=h.oklyk2bogkx4) ### Coding standards -The module’s code style should correspond to the [PBS-Java project code style](https://github.com/prebid/prebid-server-java/blob/master/docs/code-style.md). +The module’s code style should correspond to the [PBS-Java project code style](https://github.com/prebid/prebid-server-java/blob/master/docs/developers/code-style.md). ## Module Directory Layout The Prebid Server repository contains a maven submodule called `all-modules` located in the `extra/modules` folder. It includes all available PBS modules. So, in order to add a new module, fork the repository and create a folder with the desired name inside the modules folder with the following structure: -``` +```text +- prebid-server-java/ +- extra/ +- modules/ @@ -37,13 +37,13 @@ The Prebid Server repository contains a maven submodule called `all-modules` loc +- pom.xml <- POM of all included modules ``` -A benefit of open sourcing your module in this way is that it can use the parent `all-modules` as a maven dependency. It simplifies management of the PBS-Core and other commonly used dependencies and you will be confident that it works well with the current version of Prebid Server. +A benefit of open sourcing your module in this way is that it can use the parent `all-modules` as a maven dependency. It simplifies management of the PBS-Core and other commonly used dependencies and you will be confident that it works well with the current version of Prebid Server. ### Your module's build file Here's a partial example of your module-specific `pom.xml` file: -``` +```text @@ -60,6 +60,7 @@ Here's a partial example of your module-specific `pom.xml` file: ``` where: + - PREBID_SERVER_VERSION is the current version of Prebid Server. The release team will update this value for all modules with each release, but you need to set it to the version of PBS that you're developing with. - YOUR_MODULE_ARTIFACT_ID is the name of your module JAR file without version and extension. e.g. ortb2-blocking - YOUR_MODULE_TEXTUAL_NAME is unique within the space of all other modules. e.g. instead of naming a module "blocking", a better name would be "ortb2blocking". @@ -68,7 +69,7 @@ where: Add your module within `extra/modules/pom.xml` in the "modules" section: -``` +```text ... YOUR_MODULE_ARTIFACT_ID @@ -79,7 +80,7 @@ Add your module within `extra/modules/pom.xml` in the "modules" section: The structure of your module source code inside the modules directory must have a standard maven-compatible structure: -``` +```text +- src/ +- main/ +- java/ <- source code @@ -95,17 +96,19 @@ The structure of your module source code inside the modules directory must have ## Module Code The quick start is to take a look in two places: + - the [ortb2-blocking module](https://github.com/prebid/prebid-server-java/tree/master/extra/modules/ortb2-blocking) - the [module test cases](https://github.com/prebid/prebid-server-java/tree/master/src/test/java/org/prebid/server/it/hooks) ### Adding module documentation + It is required to add a "README.md" file to the root of your module folder. Recommended this file contains the description of what the implemented module does, links to external documentation and includes maintainer contact info (email, slack, etc). -The documentation must also live on the docs.prebid.org site. Please add a markdown file to https://github.com/prebid/prebid.github.io/tree/master/prebid-server/pbs-modules +The documentation must also live on the docs.prebid.org site. Please add a markdown file to ### Hook Interfaces -The Prebid server processing workflow is divided into serveal 'stages' where module authors can code agaist a specific function signature called a 'hook'. +The Prebid server processing workflow is divided into several 'stages' where module authors can code agaist a specific function signature called a 'hook'. The Prebid Server host company will define which modules to run in which order by setting up a configuration defining which hooks run, and which can run in parallel. @@ -118,63 +121,67 @@ These are the available hooks that can be implemented in a module: - org.prebid.server.hooks.v1.auction.ProcessedAuctionRequestHook - org.prebid.server.hooks.v1.bidder.BidderRequestHook - org.prebid.server.hooks.v1.bidder.RawBidderResponseHook -- org.prebid.server.hooks.v1.bidder.ProcessedBidderResponseHook +- org.prebid.server.hooks.v1.bidder.AllProcessedBidResponsesHook - org.prebid.server.hooks.v1.auction.AuctionResponseHook In a module it is not necessary to implement all mentioned interfaces but only one (or several) required by your functionality. Each hook interface internally extends org.prebid.server.hooks.v1.Hook basic interface with methods should be implemented: + - `code()` - returns module code. - `call(...)` - returns result of hook invocation. ### Examples -1) To **update** the request in the `RawAuctionRequestHook` you would return: -``` -Future.succeededFuture( - InvocationResultImpl.builder() - .status(InvocationStatus.success) - .action(InvocationAction.update) - .payloadUpdate(payload -> - AuctionRequestPayloadImpl.of(payload.bidRequest().toBuilder() - .id("updated request ID") - .build())) - .build() -); -``` - -Please note that the `InvocationStatus` is only considered when the status is set to `InvocationStatus.success`. That means the `payloadUpdate` is only applied with `InvocationStatus.success` **and** `InvocationAction.update` - -2) To **reject** the request in the `RawAuctionRequestHook` you would return: -``` -Future.succeededFuture( - InvocationResultImpl.rejected(“The rejection reason”) -); -``` - -3) To supply [analytics tags](/prebid-server/developers/module-atags.html) in the `RawAuctionRequestHook` you would return: -``` -Future.succeededFuture( - InvocationResultImpl.builder() - ... - .analyticsTags(TagsImpl.of( - Collections.singletonList(ActivityImpl.of( - "device-id", - "success", - Collections.singletonList(ResultImpl.of( +1. To **update** the request in the `RawAuctionRequestHook` you would return: + + ```java + Future.succeededFuture( + InvocationResultImpl.builder() + .status(InvocationStatus.success) + .action(InvocationAction.update) + .payloadUpdate(payload -> + AuctionRequestPayloadImpl.of(payload.bidRequest().toBuilder() + .id("updated request ID") + .build())) + .build() + ); + ``` + + Please note that the `InvocationStatus` is only considered when the status is set to `InvocationStatus.success`. That means the `payloadUpdate` is only applied with `InvocationStatus.success` **and** `InvocationAction.update` + +2. To **reject** the request in the `RawAuctionRequestHook` you would return: + + ```java + Future.succeededFuture( + InvocationResultImpl.rejected(“The rejection reason”) + ); + ``` + +3. To supply [analytics tags](/prebid-server/developers/module-atags.html) in the `RawAuctionRequestHook` you would return: + + ```java + Future.succeededFuture( + InvocationResultImpl.builder() + ... + .analyticsTags(TagsImpl.of( + Collections.singletonList(ActivityImpl.of( + "device-id", "success", - mapper.mapper().createObjectNode() - .put("some-field", "some-value"), - AppliedToImpl.builder() - .impIds(Collections.singletonList("impId1")) - .request(true) - .build())))))) - ... - .build() -); -``` - -More test implementations for each hook can be found in unit-tests at https://github.com/prebid/prebid-server-java/tree/master/src/test/java/org/prebid/server/it/hooks folder. + Collections.singletonList(ResultImpl.of( + "success", + mapper.mapper().createObjectNode() + .put("some-field", "some-value"), + AppliedToImpl.builder() + .impIds(Collections.singletonList("impId1")) + .request(true) + .build())))))) + ... + .build() + ); + ``` + +More test implementations for each hook can be found in unit-tests at folder. ### Applying results asynchronously @@ -188,6 +195,16 @@ Thus, for any kind of blocking operations it is recommended to use a Vert.x buil To see how to proceed with async operations, please see similar PBS-Core functionality, for example Currency Conversion Service implementation (class “org.prebid.server.currency.CurrencyConversionService”). +### Available Functions + +#### Getting the localhost CPU + +To support modules that need to obtain information about the local CPU environment (e.g. a traffic-shaping), the code can call this function: + +```java +cpuLoadAverageStats.getCpuLoadAverage(); // returns a float +``` + ### Configuration It's possible to define default module configuration which can be read by the module at PBS startup. Please see the [Configuration](https://docs.google.com/document/d/1VP_pi7L5Iy3ikHMbtC2_rD5RZTVSc3OkTWKvtRS5x5Y/edit#heading=h.mh3urph3k1mk) section of the technical specification. @@ -208,7 +225,7 @@ Analytics adapters can receive these tags in a parameter that's been added to th To get analytics tag you need to go into: -``` +```text AuctionEvent -> AuctionContext -> HookExecutionContext @@ -218,11 +235,10 @@ AuctionEvent -> analyticsTags ``` -The AnalyticsTags object has activities with collection of org.prebid.server.hooks.v1.analytics.Result objects inside. Each Result has the values() method which returns com.fasterxml.jackson.databind.node.ObjectNode. +The AnalyticsTags object has activities with collection of org.prebid.server.hooks.v1.analytics.Result objects inside. Each Result has the values() method which returns com.fasterxml.jackson.databind.node.ObjectNode. It depends on the particular module implementation how to parse their analytics tags, since the internal structure is custom and depends on the module. Therefore, analytics modules that want to report on specific behavior need to be coded to know about that module. See the ortb2blocking module for an example of what analytics tags may be available. - ## Further Reading - [PBS Module Overview](/prebid-server/developers/add-a-module.html) diff --git a/prebid-server/developers/add-a-module.md b/prebid-server/developers/add-a-module.md index 502adf870e..c6263e096b 100644 --- a/prebid-server/developers/add-a-module.md +++ b/prebid-server/developers/add-a-module.md @@ -11,10 +11,6 @@ title: Prebid Server | Developers | Adding a Module This document guides you through the process of developing a module for host companies to plug into their instance of Prebid Server. We encourage you to look at existing modules for working examples. You can also ask us questions by [submitting a GitHub issue](https://github.com/prebid/prebid-server/issues/new). -{: .alert.alert-info :} -Modules are currently only supported in [PBS-Java](https://github.com/prebid/prebid-server-java). - - * TOC {:toc } @@ -23,7 +19,7 @@ Modules are currently only supported in [PBS-Java](https://github.com/prebid/pre The ability to add optional modules in [Prebid.js](/prebid/prebidjs.html) has been widely used, with dozens of interesting features forming a healthy ecosystem of vendor choice that's good for publishers and the industry. -Prebid Server (Java) supports a rich module interface that +Prebid Server supports a rich module interface that allows anyone to contribute functionality at predefined places along the request pipeline. Here's the general development process: @@ -58,7 +54,7 @@ without disclosing prominently on their documentation. Please review the [Module Rules](/dev-docs/module-rules.html) page. Here are some highlights: - a module can't add pixels to the creative without disclosure -- every module must obey privacy regulations: GDPR, CCPA, COPPA +- every module must obey privacy regulations: TCF-EU, CCPA, COPPA, USNat, TCF-CA, etc. - modules cannot create new bids. That is reserved for bid adapters. - modules must be configurable to make data available to all bidders. i.e. you can't make a module that works always and forever with just one bidder without prominent disclosure. @@ -74,10 +70,10 @@ Here's a description of the Stages of a PBS request that modules can tap into fo | Processed Auction Request | Any stored requests have been merged in and all PBS enrichments are done | auction, amp, video | Inject First Party Data, Channel determination, Bid floors, Bidder optimization | | Bidder Request | The request has been customized for a particular bidder in the auction | auction, amp, video | Bidder-specific bcat/badv, Bidder-specific deals | | Raw Bidder Response | Hook functions can get access to the unprocessed bidder response | auction, amp, video | Response validations | -| Processed Bidder Response | PBS has done its own validations on an individual bidder's response | auction, amp, video | Advanced CPM adjustments, Custom VAST macros | +| All Processed Bid Responses | All bids are back and PBS-core bid validations are done. | auction, amp, video | Creative validation, advanced bid validations. | | Auction Response | Last step before the response goes back to the client | auction, amp, video | Inject ad server targeting, alternate auction winner logic | -### 3. Figure out which Stages You're going to Hook Into +### 3. Figure Out Which Stages You're Going to Hook Into A module may be comprised of: @@ -86,7 +82,7 @@ A module may be comprised of: - optional external connections to data sources or other services Some modules may plug into only one endpoint and one stage of processing. Others may coordinate activity across multiple stages. For example, -this diagram illustrates the design of a module that's configured to plug into two stages of +this diagram illustrates the design of a module that's rather extremely configured to plug into all of the stages of the processing workflow: ![Prebid Server Modularity Architecture](/assets/images/prebid-server/module-example.png){:class="pb-xlg-img"} @@ -141,7 +137,17 @@ to the PBS host company. Examples: - modules may require a local SQL DB populated with application data - some modules may require access to local disk to read a security certificate -### 7. Think about Analytics Tags +### 7. Identify Sensitive Data Usage + +If your module either utilizes or supplies user-level data like User First Party Data or precise geographic information, it must adhere to the framework supplied by the [Activity Controls](/prebid-server/features/pbs-activitycontrols.html). + +For instance: +- if your module is going to supply user-level data (e.g. "job title") to bid adapters, it must check permissions for the `enrichUfpd` activity. +- if your module is going to forward the entire ORTB request to an endpoint, it must check the `transmitUfpd` and `transmitPreciseGeo` activity permissions. + +The details about how exactly to code this differs by platform. See the developer docs for Go and Java linked below. + +### 8. Think about Analytics Tags Analytics Tags (aka 'ATags') are a log mechanism provided by PBS-core to inform downstream modules about what's happened in the request so far. Use of the Analytics Tag structure @@ -157,19 +163,19 @@ that a given bidder is losing bid opportunities by not adhering to the auction p See the [Module Analytics Tag Conventions](/prebid-server/developers/module-atags.html) for more specific details about how to format ATags. -### 8. Write the Code, Config, and Unit Tests +### 9. Write the Code, Config, and Unit Tests The details of the implementation depend on the platform. - PBS-Java: see [Adding a PBS-Java module](/prebid-server/developers/add-a-module-java.html) -- PBS-Go: TBD +- PBS-Go: see [Adding a PBS-Go module](/prebid-server/developers/add-a-module-go.html) Other rules for open source PBS pull request: - Unit test coverage must exceed 90%. - A maintainer email address must be provided and be a group, not an individual. e.g. "support@example.com rather than jsmith@example.com -### 9. Write the Module Documentation +### 10. Write the Module Documentation Fork the [documentation repo](https://github.com/prebid/prebid.github.io) and create a file in /prebid-server/pbs-modules. You can start by copying one of the existing files. It should contain: @@ -178,9 +184,9 @@ create a file in /prebid-server/pbs-modules. You can start by copying one of the - Prerequisites: any necessary account activation, other required modules, etc. - Configuration: both init and runtime - Analytics Tag support -- Privacy Support: disclose whether the module has user privacy implications and support for GDPR, CCPA, etc. +- Privacy Support: disclose whether the module has user privacy implications and support for TCF-EU, TCF-CA, CCPA, MSPA, etc. -### 10. Submit the Pull Requests +### 11. Submit the Pull Requests When everthing checks out on your dev environment, submit the PRs for review. @@ -188,3 +194,4 @@ When everthing checks out on your dev environment, submit the PRs for review. - [Prebid Server Module List](/prebid-server/pbs-modules/index.html) - [PBS Module Analytics Tags Conventions](/prebid-server/developers/module-atags.html) +- [PBS Activity Controls](/prebid-server/features/pbs-activitycontrols.html) diff --git a/prebid-server/developers/add-a-privacy-module-java.md b/prebid-server/developers/add-a-privacy-module-java.md new file mode 100644 index 0000000000..f09bca96f9 --- /dev/null +++ b/prebid-server/developers/add-a-privacy-module-java.md @@ -0,0 +1,282 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Developers | Adding a Java Privacy Module +--- + +# Prebid Server - Adding a Java Privacy Module +{: .no_toc} + +* TOC +{:toc } + +## Overview + +This document details how to make a 'privacy module' for PBS-Java. This type of +module is not related to the [main workflow modules](/prebid-server/pbs-modules/). Rather, it's a specialized type of module that + +You will want to be familiar with the following background information: + +* [Privacy Modules](/prebid-server/developers/add-a-privacy-module.html) +* [Prebid Server Activity Controls](/prebid-server/features/pbs-activitycontrols.html) + +## Coding Standards + +The module’s code style should correspond to +the [PBS-Java project code style](https://github.com/prebid/prebid-server-java/blob/master/docs/developers/code-style.md). + +### Privacy Module Directory Layout + +The source code of your privacy module must be inside packages: + +```text +// Privacy Module provider +org.prebid.server.activity.infrastructure.creator.privacy.YOUR_PRIVACY_MODULE_NAME + +// Privacy Module implementation +org.prebid.server.activity.infrastructure.privacy.YOUR_PRIVACY_MODULE_NAME + +// Account config for your Privacy Module (if presented as a single class, then a separate package isn’t required) +org.prebid.server.settings.model.activity.privacy.YOUR_PRIVACY_MODULE_NAME +``` + +### Module Code + +The quick start is to take a look in three places: + +* the [USNat Privacy Module](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/activity/infrastructure/privacy/usnat) +* the [USNat Privacy Module creator](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/activity/infrastructure/creator/privacy/usnat) +* the [account config for USNat Privacy Module](https://github.com/prebid/prebid-server-java/blob/master/src/main/java/org/prebid/server/settings/model/activity/privacy/AccountUSNatModuleConfig.java) + +{: .alert.alert-info :} +The 'usnat' code is documented on the website as [usgen](/prebid-server/features/pbs-usgen.html) + +## Privacy Module interface + +Among the Prebid server processing workflow, there are several 'activities' that require permission from the Activity +Infrastructure to run. + +The available activities that the Activity Infrastructure can control can be found in the corresponding +enum: [Activity](https://github.com/prebid/prebid-server-java/blob/master/src/main/java/org/prebid/server/activity/Activity.java). + +Whenever a workflow asks permission to perform an activity, the configured rules will be processed. All rules implement +the `Rule` interface. In accordance with this, every privacy module implements `PrivacyModule` interface, which +inherits `Rule` interface, with methods should be implemented: + +* `proceed(...)` - returns one of the privacy module answers: `ALLOW`, `DISALLOW`, `ABSTAIN`. + +### Privacy Module example + +```java +public class MyPrivacyModule implements PrivacyModule { + + private final GppModel gppModel; + private final int forbiddenSection; + + private MyPrivacyModule(GppModel gppModel, int forbiddenSection) { + this.gppModel = gppModel; + this.forbiddenSection = forbiddenSection; + } + + @Override + public Result proceed(ActivityInvocationPayload activityInvocationPayload) { + return gppModel != null && gppModel.hasSection(forbiddenSection) + ? Result.DISALLOW + : Result.ABSTAIN; + } +} +``` + +## Privacy Module Creator Interface + +The lifecycle of a privacy module is defined by `PrivacyModuleCreator`. Possible life cycles: + +* one for the server - if the creator always returns the same privacy module that was created when the server started +* one for a period of time (cached) - (for example) if the creator will create a new privacy module every time the + associated account is updated +* one per request - if the creator always returns a new privacy module + +`PrivacyModuleCreator` consists of methods that must be implemented: + +* `qualifier()` - returns privacy module qualifier. +* `from(...)` - returns created privacy module. + +### Privacy Module Creator Example + +```java +public class MyPrivacyModuleCreator implements PrivacyModuleCreator { + + @Override + public PrivacyModuleQualifier qualifier() { + return PrivacyModuleQualifier.MY_PRIVACY_MODULE; + } + + @Override + public PrivacyModule from(PrivacyModuleCreationContext creationContext) { + final MyPrivacyModuleConfig moduleConfig = moduleConfig(creationContext); + final GppModel gppModel = creationContext.getGppContext().scope().getGppModel(); + + final List innerPrivacyModules = SetUtils.emptyIfNull(moduleConfig.getForbiddenSections()) + .stream() + .filter(Objects::nonNull) + .map(forbiddenSection -> new MyPrivacyModule(gppModel, forbiddenSection)) + .toList(); + + return new AndPrivacyModules(innerPrivacyModules); + } + + private static MyPrivacyModuleConfig moduleConfig(PrivacyModuleCreationContext creationContext) { + return (MyPrivacyModuleConfig) creationContext.getPrivacyModuleConfig(); + } +} +``` + +## Privacy Module Qualifier + +`PrivacyModuleQualifier` is an enumeration containing all possible unique names of the privacy modules supported by this +server instance. + +### Privacy Module Qualifier Example + +```java +public enum PrivacyModuleQualifier { + + // other qualifiers + + @JsonProperty(Names.MY_PRIVACY_MODULE) // required when adding MY_PRIVACY_MODULE + MY_PRIVACY_MODULE(Names.MY_PRIVACY_MODULE); // required when adding MY_PRIVACY_MODULE + + // fields and methods + + public static class Names { + + // other names + + public static final String MY_PRIVACY_MODULE = "privacy.my-module"; // required when adding MY_PRIVACY_MODULE + } +} + +``` + +## Privacy Module Account Configuration + +Any privacy module must be configured in the account configuration to affect Prebid server processing workflow. + +When adding a new privacy module, it is important to create an appropriate configuration class. The configuration class +must implement the `AccountPrivacyModuleConfig` interface, with methods should be implemented: + +* `getCode()` - returns privacy module qualifier. +* `enabled()` - returns boolean. `null` or `true` means that this privacy module is 'on'. + +IMPORTANT. Because the Prebid server can merge account configurations from different locations, make sure: + +```text +deserializeFromJson(serializeToJson(config object)) == config object +``` + +### Privacy Module Account Configuration Example + +```java +@Value(staticConstructor = "of") +public class MyPrivacyModuleConfig implements AccountPrivacyModuleConfig { + + @Accessors(fluent = true) + Boolean enabled; + + Set forbiddenSections; + + @Override + public PrivacyModuleQualifier getCode() { + return PrivacyModuleQualifier.MY_PRIVACY_MODULE; + } +} +``` + +```java +package org.prebid.server.settings.model.activity.privacy; + + +@JsonSubTypes({ + // other privacy modules + + @JsonSubTypes.Type( // relationship between configuration class and privacy module name + value = MyPrivacyModuleConfig.class, // configuration class + name = PrivacyModuleQualifier.Names.MY_PRIVACY_MODULE)}) // privacy module name +public sealed interface AccountPrivacyModuleConfig permits + // other privacy modules + + MyPrivacyModuleConfig { // configuration class must be listed after 'permits' keyword + + // methods +} +``` + +## Privacy Module Bean Configuration + +Privacy module beans must be inside the destined configuration class: `ActivityInfrastructureConfiguration.PrivacyModuleCreatorConfiguration` + +### Privacy Module Bean Configuration Example + +If there is only one bean associated with the privacy module: + +```java +@Configuration +static class PrivacyModuleCreatorConfiguration { + + // other privacy modules + + @Bean + MyPrivacyModuleCreator myPrivacyModuleCreator() { + return new MyPrivacyModuleCreator(); + } +} +``` + +If there are multiple beans associated with the privacy module: + +```java +@Configuration +static class PrivacyModuleCreatorConfiguration { + + // other privacy modules + + @Configuration + static class MyPrivacyModuleCreatorConfiguration { + + @Bean + MyPrivacyModuleDependency myPrivacyModuleDependency() { + return new MyPrivacyModuleDependency(); + } + + @Bean + MyPrivacyModuleCreator myPrivacyModuleCreator(MyPrivacyModuleDependency myPrivacyModuleDependency) { + return new MyPrivacyModuleCreator(myPrivacyModuleDependency); + } + } +} +``` + +## Adding support for trace log + +To be able to debug the Activity Infrastructure and be able to track interactions with your privacy module, it is recommended that your `PrivacyModule` implement the `Loggable` interface. + +`Loggable` consists of methods that must be implemented: + +* `asLogEntry(...)` - returns `JsonNode` that can represent any desired structure to include in the trace log. + +For example: + +```java +public class MyPrivacyModule implements PrivacyModule, Loggable { + + // privacy module code + + @Override + public JsonNode asLogEntry(ObjectMapper mapper) { + return TextNode.valueOf( + "%s forbidding %d section.".formatted( + MyPrivacyModule.class.getSimpleName(), + forbiddenSection)); + } +} +``` diff --git a/prebid-server/developers/add-a-privacy-module.md b/prebid-server/developers/add-a-privacy-module.md new file mode 100644 index 0000000000..f4cea9ba6f --- /dev/null +++ b/prebid-server/developers/add-a-privacy-module.md @@ -0,0 +1,131 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Developers | Adding a Privacy Module + +--- + +# Prebid Server - Adding a Privacy Module +{: .no_toc} + +{: .alert.alert-warning :} +This feature is currently only available in PBS-Java. + +* TOC +{:toc } + +## Overview + +Privacy Modules are different than [Request Modules](/prebid-server/developers/add-a-module.html). They work in this way: + +1. Privacy Modules are called by the [Activity Control System](/prebid-server/features/pbs-activitycontrols.html) +1. They are meant to use aspects of the request to determine whether a particular activity is `allowed`, `disallowed`, or `abstain`. + +Here are the use cases envisioned for Privacy Modules: + +* Prebid will publish privacy modules for major IAB privacy protocols such as the [US National Privacy Specification](/prebid-server/features/pbs-usgen.html). +* PBS host companies can develop custom versions of privacy modules for their publishers that may meet special legal requirements more efficiently. +* Anyone can contribute privacy modules in support of regulations not addressed by Prebid or the IAB. + +### Terminology + +* **PBS**: short for **P**re**b**id **S**erver +* **PBS-core**: The inner workings of Prebid Server -- not part of a module, bid adpater, or analytics adapter +* **PBS-Java**: the Java version of Prebid Server +* **PBS-Go**: the Go-Lang version of Prebid Server +* **Host Company**: the entity running the PBS cluster, e.g. one of the ones on [this list](https://prebid.org/product-suite/managed-services/). +* **Activity Controls**: a [centralized mechanism](/prebid-server/features/pbs-activitycontrols.html) for managing privacy-sensitive activities. +* **Privacy Module**: a block of code that plugs into Prebid Server that enhances the functionality of the Activity Controls. +* **Allow**: If the module returns this value, it has determined that the requested activity in the specified context is allowable. +* **Disallow**: If the module returns this value, it has determined that the requested activity in the specified context is **not** allowable. +* **Abstain**: If the module returns this value, it does not have a definitive answer about whether the requested activity in the specified context is allowable. + +## Building Your Privacy Module + +### 1. Define the Behavior With Your Lawyers + +As with any legally sensitive thing, you should have the desired behavior fully documented and signed off in conjunction with legal counsel. + +{: .alert.alert-warning :} +Prebid cannot guarantee that the Activity Controls and Privacy Modules enable all possible legal scenarios. Please submit an [issue](https://github.com/prebid/prebid-server/issues/new) to discuss +enhancements to this system. + +### 2. Review the Module Rules + +There are a number of things modules in general are not allowed to do +without disclosing prominently on their documentation. Please review +the [Module Rules](/dev-docs/module-rules.html) page. + +Privacy Modules are particularly constrained in what they can do. Basically all they can do is answer `allow`, `disallow`, or `abstain` to a request from an Activity Control. +They cannot make HTTP requests, log analytics, or affect the request/response in any way. + +### 2. Define a Module Code + +The module code is how Activity Control configuration will refer to this +privacy module. For example, if the module is named **host1.publisherA.emea**, +it could be activated in the `privacy` config in any of these ways: + +```javascript +{ + "privacy": { + "allowactivities": { + "ACTIVITY1": { + "privacyreg": ["*"] + }, + "ACTIVITY2": { + "privacyreg": ["host1.*"] + }, + "ACTIVITY3": { + "privacyreg": ["host1.publisherA.*"] + }, + "ACTIVITY4": { + "privacyreg": ["host1.publisherA.emea"] + } + } + } +} +``` + +To choose the name, you should consider how the publisher may want to invoke +the privacy modules that are available. + +* If you're not going to open source the privacy module, we recommend prefixing the name with your host company so it doesn't clash with open source modules as they become available. +* If the module is publisher-specific, we recommend placing the publisher name in the module code. + +### 3. Determine What Should be Configurable + +Your module may not need any configuration, or it may have a complex configuration. +Here are the kind of things to consider: + +* Does it need to identify or prioritize privacy parameters differently? (e.g. which consent and scope strings to use and prefer?) +* Does it need to provide different exceptions? (e.g. if a particular publisher wants to allow or disallow certain scenarios.) + +### 4. Write the Code, Config, and Unit Tests + +The details of the implementation depend on the platform. + +* PBS-Java: see [Adding a PBS-Java Privacy Module](/prebid-server/developers/add-a-privacy-module-java.html) +* PBS-Go: TBD + +If you plan on open sourcing your privacy module, other rules for open source PBS pull request: + +* Unit test coverage must exceed 90%. +* A maintainer email address must be provided and be a group, not an individual. e.g. rather than + +### 5. Write the Module Documentation + +If this is an open source module, fork the [documentation repo](https://github.com/prebid/prebid.github.io) and +create a file in /prebid-server/pbs-modules. You can start by copying one of the existing files. It should contain: + +* A description of the module functionality: why people might be interested in using it. +* Prerequisites: any necessary account activation, other required modules, etc. +* Configuration + +### 6. Submit the Pull Requests + +If open sourcing the module, submit the PRs for review when everything looks good in your test environment. + +## Further Reading + +* [PBS Activity Controls](/prebid-server/features/pbs-activitycontrols.html) +* [US Gen Privacy Module](/prebid-server/features/pbs-usgen.html) diff --git a/prebid-server/developers/add-new-bidder-go.md b/prebid-server/developers/add-new-bidder-go.md index 0f629d5003..e2bcf0c114 100644 --- a/prebid-server/developers/add-new-bidder-go.md +++ b/prebid-server/developers/add-new-bidder-go.md @@ -8,51 +8,83 @@ title: Prebid Server | Developers | Building a Bid Adapter (Go) # Prebid Server - New Bid Adapter (Go) {: .no_toc} -Thank you for contributing a bid adapter to the open source Prebid Server project. Each new adapter gives publishers more options for monetizing their inventory and strengthens the header bidding community. +Thank you for your valuable contribution of a bid adapter to the open source Prebid Server project. Each new adapter expands the monetization possibilities for publishers and provides greater options to maximize their inventory's potential. We truly appreciate your support in making this ecosystem thrive! -This document guides you through the process of developing a new bid adapter for your bidding server. We encourage you to look at [existing bid adapters](https://github.com/prebid/prebid-server/tree/master/adapters) for working examples and practical guidance. You can also ask us questions by [submitting a GitHub issue](https://github.com/prebid/prebid-server/issues/new). +This document guides you through the process of developing a new bid adapter for your bidding server. We encourage you to look at [existing bid adapters](https://github.com/prebid/prebid-server/tree/master/adapters) for working examples and practical guidance. You can ask us questions by [submitting a GitHub issue](https://github.com/prebid/prebid-server/issues/new). {: .alert.alert-info :} -There are two implementations of Prebid Server, [PBS-Go](https://github.com/prebid/prebid-server) and [PBS-Java](https://github.com/prebid/prebid-server-java). We recommend you build new adapters for PBS-Go and allow us to port it to PBS-Java within a couple of months. If you'd like to build both yourself, please also follow these [instructions for building an adapter in PBS-Java](/prebid-server/developers/add-new-bidder-java.html). - +There are two implementations of Prebid Server: [PBS-Go](https://github.com/prebid/prebid-server) and [PBS-Java](https://github.com/prebid/prebid-server-java). We recommend you build new adapters for PBS-Go and allow us to port it to PBS-Java within a couple of months. If you'd like to build both yourself, please also follow these [instructions for building an adapter in PBS-Java](/prebid-server/developers/add-new-bidder-java.html). * TOC {:toc } ## Overview -Bid adapters are responsible for translating an [OpenRTB 2.5 Bid Request](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=13) to your bidding server's protocol and mapping your server's response to an [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32). +Bid adapters are responsible for translating a 'Prebid-flavored' OpenRTB Bid Request to your bidding server's protocol and mapping your server's response to a Prebid-flavored response. + +"Prebid-flavored OpenRTB" means: + +1. [OpenRTB 2.6](https://github.com/InteractiveAdvertisingBureau/openrtb2.x) as defined by the IAB. +1. Certain Prebid extensions as defined in the [/auction endpoint documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html). -An OpenRTB 2.5 Bid Request contains one or more Impressions, each representing a single ad placement. An Impression may define multiple sizes and/or multiple ad formats. If your bidding server limits requests to a single ad placement, size, or format, then your adapter will need to split the Impression into multiple calls and merge the responses. +OpenRTB Bid Requests contain one or more impression objects, each representing a single ad placement. An impression may define multiple sizes and/or multiple ad formats. If your bidding server limits requests to a single ad placement, size, or format, then your adapter will need to split the impression into multiple calls and merge the responses. ## Plan Your Bid Adapter +The job of your bid adapter is to adapt. You'll need to think about currency, floors, mediatypes, and other details as noted below. + ### Choose A Name -You will need to choose a unique name for your bid adapter. Names should be written in lower case and may not contain special characters or emoji. If you already have a Prebid.js bid adapter, we encourage you to use the same name with the same bidder parameters. You may not name your adapter `all`, `context`, `data`, `general`, `prebid`, or `skadn` as those have special meaning in various contexts. Existing bid adapter names are [maintained here](https://github.com/prebid/prebid-server/blob/master/openrtb_ext/bidders.go#L37). +You will need to choose a unique name for your bid adapter. Names should be written in lower case and may not contain special characters or emoji. If you already have a Prebid.js bid adapter, we encourage you to use the same name with the same bidder parameters. You may not name your adapter `ae`, `all`, `context`, `data`, `general`, `gpid`, `prebid`, `skadn` or `tid` as those have special meaning in various contexts. Existing bid adapter names are [maintained here](https://github.com/prebid/prebid-server/blob/master/openrtb_ext/bidders.go#L31). We ask that the first 6 letters of the name you choose be unique among the existing bid adapters. This consideration helps with generating targeting keys for use by some ad exchanges, such as Google Ad Manager. There's no need to manually check, as this constraint is enforced by the [`TestBidderUniquenessGatekeeping`](https://github.com/prebid/prebid-server/blob/master/openrtb_ext/bidders_validate_test.go#L45) test. Throughout the rest of this document, substitute `{bidder}` with the name you've chosen. +### Consider Your Geography + +Most bidders run their auction endpoints in multiple data centers because their +business is continental or global. + +Prebid Server is open source software that is run by many host companies that may be calling +your bid adapter from various places. It may be useful to consider how you want to +communicate your geographic preferences to these companies. + +{: .alert.alert-info :} +Please don't bother publishers by asking them to enter a geographic location 'host' parameter. Most publishers do not have the tech to choose which of your regional endpoints to hit. + +These are the recommended technical solutions: + +1. Use a "Global Services Load Balancing" vendor so there's just one smart hostname that figures out where to send each user. Just do an internet search for "gslb services". +1. In your bidder yaml file, let the host companies know which regional endpoints you support. They can take care of mapping their regions to your regions. See the YAML file below for an example of how to communicate this. + +You should also consider entering geographic scoping information into your YAML file so +host companies can disable your bidder in regions where you're not going to bid. e.g. +bidders that are not GDPR-compliant probably won't bid much in Europe. It costs both you and the host company networking fees to send bid requests, so it's in +your interest to declare your scope of business. See below for syntax details. + ### Respect The Rules We are proud to run the Prebid Server project as a transparent and trustworthy header bidding solution. You are expected to follow our community's [code of conduct](https://prebid.org/code-of-conduct/) and [module rules](/dev-docs/module-rules.html) when creating your adapter and when interacting with others through issues, code reviews, and discussions. -**Please take the time to read our rules in full.** Below is a summary of some of the rules which apply to your Prebid Server bid adapter: - - Adapters must not modify bids from demand partners, except to either change the bid from gross to net or from one currency to another. - - Adapters must use the functions provided by the core framework for all external communication. Initiation of any form of network connection outside of what is provided by the core framework is strictly prohibited. No exceptions will be made for this rule. - - Adapters must support the creation of multiple concurrent instances. This means adapters may not mutate global or package scoped variables. - - Bidding server endpoints should prefer secure HTTPS to protect user privacy and should allow keep alive connections (preferably with HTTP/2 support) to increase host performance. - - Adapters must include maintainer information with a group email address for Prebid.org to contact for ongoing support and maintenance. - - Adapters must annotate the bid response with the proper media type, ideally based on the response from the bidding server. +**Please take the time to read the rules in full.** Below is a summary of some of the rules which apply to your Prebid Server bid adapter: + +* Adapters must include maintainer information with a group email address for Prebid.org to contact for ongoing support and maintenance. +* Your bidder's endpoint domain name cannot be fully variable. We will accept endpoint domains that include account IDs, but we do not like them, and Prebid Server host companies may disable adapters using this approach if there are technical issues with it. We will not accept hostnames that have a required dynamic element for the purpose of sending traffic to different geographic regions. +* If you have a client-side adapter, all parameters (including biddercodes and aliases) must be consistent between your client- and server-side adapters. This allows publishers to utilize the PBJS [s2sTesting module](/dev-docs/modules/s2sTesting.html). +* Adapters must not modify bids from demand partners, except to either change the bid from gross to net or from one currency to another. +* Adapters must use the functions provided by the core framework for all external communication. Initiation of any form of network connection outside of what is provided by the core framework is strictly prohibited. No exceptions will be made for this rule. +* Adapters must support the creation of multiple concurrent instances. This means adapters may not mutate global or package scoped variables. +* Bidding server endpoints should prefer secure HTTPS to protect user privacy and should allow keep alive connections (preferably with HTTP/2 support) to increase host performance. +* Adapters must annotate the bid response with the proper media type, ideally based on the response from the bidding server. +* Bid adapters must not create their own transaction IDs or overwrite the tids supplied by Prebid. {: .alert.alert-warning :} Failure to follow the rules will lead to delays in approving your adapter. If you'd like to discuss an exception to a rule, please make your request by [submitting a GitHub issue](https://github.com/prebid/prebid-server/issues/new). ### Support and Maintenance -You are expected to provide support and maintenance for the code you contribute to Prebid Server as part of your bid adapter. We ask that you proactively update your adapter when your bidding server introduces new features or breaking changes. +**You are expected to provide support and maintenance for the code you contribute to Prebid Server as part of your bid adapter.** We ask that you proactively update your adapter when your bidding server introduces new features or breaking changes. Occasionally, we'll introduce changes to the core framework as part of our ongoing maintenance and enhancement of the project. If this causes a compilation error or a performance impact to your adapter, we will update the affected portion of your bid adapter code and provide full unit test coverage of our changes. We will notify you via email if this happens and give you at least one week to review the PR and provide comments. Please understand that we will not wait for your explicit approval for these kinds of changes unless you respond to our email or comment on the PR. @@ -71,11 +103,18 @@ Our project is written in the [Go programming language](https://golang.org/). We ### Bidder Info -Let's begin with your adapter's bidder information YAML file. This file is required and contains your bid adapter's maintainer email address, [GDPR Global Vendor List (GVL) ID](https://iabeurope.eu/vendor-list-tcf-v2-0/), supported ad formats, user sync endpoints, and allows you to opt-out of video impression tracking. +Let's begin with your adapter's bidder information YAML file. This file is required and contains your bid adapter's maintainer email address, outgoing compression support, [GDPR Global Vendor List (GVL) ID](https://iabeurope.eu/tcf-for-vendors/), supported ad formats, user sync endpoints, and allows you to opt-out of video impression tracking. Create a file with the path `static/bidder-info/{bidder}.yaml` and begin with the following template: ```yaml +# We have the following regional endpoint domains: us-east and us-west +# Please deploy this config in each of your datacenters with the appropriate regional subdomain +endpoint: "http://REGION.example.com/openrtb2" +endpointCompression: gzip +geoscope: + - USA + - CAN maintainer: email: prebid-maintainer@example.com gvlVendorID: 42 @@ -93,6 +132,12 @@ capabilities: - video - audio - native + dooh: + mediaTypes: + - banner + - video + - audio + - native userSync: redirect: url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} @@ -100,18 +145,34 @@ userSync: ``` Modify this template for your bid adapter: -- Change the maintainer email address to a group distribution list on your ad server's domain. A distribution list is preferred over an individual mailbox to allow for robustness, as roles and team members naturally change. -- Change the `gvlVendorID` from the sample value of `42` to the id of your bidding server as registered with the [GDPR Global Vendor List (GVL)](https://iabeurope.eu/vendor-list-tcf-v2-0/), or remove this line entirely if your bidding server is not registered with IAB Europe. -- Change the `modifyingVastXmlAllowed` value to `false` if you'd like to opt-out of [video impression tracking](https://github.com/prebid/prebid-server/issues/1015), or remove this line entirely if your adapter doesn't support VAST video ads. -- Remove the `capabilities` (app/site) and `mediaTypes` (banner/video/audio/native) combinations which your adapter does not support. -- Follow the [User Sync Configuration](#user-sync-configuration) documentation below to configure the endpoints for your bid adapter, or remove the `userSync` section if not supported. + +* The endpoint can be static if you only have one data center or use a Global Load Balancer as described in 'Planning Your Adapter' above. +* Remove the `endpointCompression` value if your bidding server does not accept gzip compressed bid requests. Setting this value to `gzip` will save on network bandwidth at the expense of slightly increased cpu and memory usage for the host. +* The `geoscope` parameter is not currently read programmatically. Instead, it's intended to be used by PBS host companies to disable your adapter in geographic regions where you don't do business. However, we may make a module for this someday, so we ask that you follow this syntax for `geoscope`: + * YAML array + * Values can be either a 3-letter country code, "EEA", or "global". (EEA means European Economic Area) + * Values can be negated. e.g. "!EEA" +* Change the maintainer email address to a group distribution list on your ad server's domain. A distribution list is preferred over an individual mailbox to allow for robustness, as roles and team members naturally change. +* Change the `gvlVendorID` from the sample value of `42` to the id of your bidding server as registered with the [GDPR Global Vendor List (GVL)](https://iabeurope.eu/tcf-for-vendors/), or remove this line entirely if your bidding server is not registered with IAB Europe. +* If absolutely necessary, change the `modifyingVastXmlAllowed` value to `false` to opt-out of [video impression tracking](https://github.com/prebid/prebid-server/issues/1015). However, please note that Prebid Server host companies depend on this feature being enabled to track video analytics. This feature has been live for many years with no known problems. +* Remove the `capabilities` (app/site/dooh) and `mediaTypes` (banner/video/audio/native) combinations which your adapter does not support. (Note: 'dooh' is [Digital Out Of Home](/prebid-server/use-cases/pbs-dooh.html)) +* Add an `extra_info` field if you'd like to pass additional values that your adapter may need. See below for an example. +* Add the `disabled` flag and set it to true if you would like to unregister adapter from the core. It's enabled by default. +* Follow the [User Sync Configuration](#user-sync-configuration) documentation below to configure the endpoints for your bid adapter, or remove the `userSync` section if not supported. + +#### Additional Bidder Info Examples
        Example: Website with banner ads only. ```yaml +# global endpoint +endpoint: "http://auction.example.com/openrtb2" +endpointCompression: gzip +geoscope: + - global maintainer: - email: foo@foo.com + email: prebid-maintainer@example.com gvlVendorID: 42 capabilities: site: @@ -122,14 +183,16 @@ userSync: url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} userMacro: $UID ``` +
        Example: Website with banner ads only and not registered with IAB Europe. ```yaml +endpoint: "http://foo.com/openrtb2" maintainer: - email: foo@foo.com + email: prebid-maintainer@example.com capabilities: site: mediaTypes: @@ -139,14 +202,45 @@ userSync: url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} userMacro: $UID ``` +
        Example: Website or app with banner or video ads and video impression tracking. ```yaml +endpoint: "http://foo.com/openrtb2" +maintainer: + email: prebid-maintainer@example.com +endpointCompression: gzip +gvlVendorID: 42 +modifyingVastXmlAllowed: true +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video +userSync: + redirect: + url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} + userMacro: $UID +``` + +
        + +
        + Example: Extra info with json data. + +```yaml +endpoint: "http://foo.com/openrtb2" +extra_info: "{\"foo\":\"bar\"}" maintainer: - email: foo@foo.com + email: prebid-maintainer@example.com +endpointCompression: gzip gvlVendorID: 42 modifyingVastXmlAllowed: true capabilities: @@ -154,15 +248,51 @@ capabilities: mediaTypes: - banner - video + - audio + - native + site: + mediaTypes: + - banner + - video + - audio + - native +userSync: + redirect: + url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} + userMacro: $UID +``` + +
        + +
        + Example: Disable the adapter. + +```yaml +disabled: true +maintainer: + email: prebid-maintainer@example.com +endpointCompression: gzip +gvlVendorID: 42 +modifyingVastXmlAllowed: true +capabilities: + app: + mediaTypes: + - banner + - video + - audio + - native site: mediaTypes: - banner - video + - audio + - native userSync: redirect: url: https://foo.com/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} userMacro: $UID ``` +

        @@ -172,11 +302,10 @@ Prebid Server offers a federated [user sync](https://docs.prebid.org/prebid-serv The Bidder Info template above demonstrates configuration of a `redirect` user sync. The `url` points to an endpoint on your bidding server which will honor the privacy policies, replace the `userMacro` in the redirect url with the user's tracking id, and respond with an HTTP 302 redirect to that url. You may also specify an `iframe` endpoint which will return an HTML document to be rendered in an `iframe` on the user's device and use JavaScript to perform the redirect. You may omit the `{%raw%}{{.GDPR}}{%endraw%}`, `{%raw%}{{.GDPRConsent}}{%endraw%}`, and/or `{%raw%}{{.USPrivacy}}{%endraw%}` macros if they are not applicable to your legal situation. -If both `iframe` and `redirect` endpoints are provided, you must specify a `default` field with a value of either `iframe` or `redirect`, based on your preference. +If both `iframe` and `redirect` endpoints are provided, the `iframe` endpoint will be used by default. ```yaml userSync: - default: iframe iframe: url: https://foo.com/iframe/sync?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} userMacro: $UID @@ -185,7 +314,7 @@ userSync: userMacro: $UID ``` -If your bid adapter supports user sync and doesn't have a good default, you may optionally specify a `supports` array with the items `iframe` and/or `redirect` to inform Prebid Server hosts. Hosts will receive a warning on startup if a bid adapter supports user sync and isn't configured. Expect hosts to contact you at the maintainer email address in this file for instructions. +If your bid adapter supports user sync and doesn't have a good default endpoint, you may optionally specify a `supports` array with the items `iframe` and/or `redirect` to inform Prebid Server hosts. Hosts will receive a warning on startup if a bid adapter supports user sync and isn't configured. Expect hosts to contact you at the maintainer email address for instructions. ```yaml userSync: @@ -216,14 +345,14 @@ userSync: Your bid adapter might require extra information from the publisher to form a request to your bidding server. The bidder parameters JSON Schema codifies this information to allow Prebid Server to verify requests and to provide an API for configuration systems. -Publishers will provide extra information using an OpenRTB 2.5 Bid Request Extension, preferably at `request.imp[].ext.prebid.bidder.{bidder}` but also supported at `request.imp[].ext.{bidder}`. Prebid Server will validate the publisher information based on your schema and relocate the data to `request.imp[].ext.bidder`, regardless of your bidder name or the publisher's chosen location. +Publishers will provide extra information using an OpenRTB 2.x Bid Request Extension, preferably at `request.imp[].ext.prebid.bidder.{bidder}` but also supported at `request.imp[].ext.{bidder}`. Prebid Server will validate the publisher information based on your schema and relocate the data to `request.imp[].ext.bidder`, regardless of your bidder name or the publisher's chosen location. -We request you do not duplicate information already present in the [OpenRTB 2.5 Bid Request specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=13) or already part of an established Prebid convention. For example, your bidder parameters should not include first party data, bid floors, schain, video parameters, referrer information, or privacy consent including COPPA, CCPA, and GDPR TCF. For video parameters in particular, you must prefer the OpenRTB 2.5 Bid Request standard of `request.imp[].video`. +We request you do not duplicate information already present in the [OpenRTB 2.x Bid Request specification](https://github.com/InteractiveAdvertisingBureau/openrtb2.x) or already part of an established Prebid convention. For example, your bidder parameters should not include first party data, bid floors, schain, video parameters, referrer information, or privacy consent including COPPA, CCPA, and GDPR TCF. For video parameters in particular, you must prefer the OpenRTB 2.x Bid Request standard of `request.imp[].video`. {: .alert.alert-warning :} -You may not use an endpoint domain as a bidder parameter. Prebid Server is not an open proxy. If absolutely necessary, you may specify a portion of the domain as a parameter to support geo regions or account specific servers. However, this is discouraged and may degrade the performance of your adapter since the server needs to maintain more outgoing connections. Host companies may choose to disable your adapter if it uses a dynamically configured domain. +You may not try so set the full endpoint domain from a publisher-specified bidder parameter. Prebid Server is not an open proxy. If absolutely necessary, you may specify a *portion* of the domain as a parameter to support geo regions or account specific servers. However, this is discouraged and may degrade the performance of your adapter since the server needs to maintain more outgoing connections. Host companies may choose to disable your adapter if it uses a dynamically configured domain. -Create a file with the path `static/bidder-params/{bidder}.json` and use [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) to define your bidder parameters. Prebid Server requires this file for every adapter, even if yours doesn't require bidder parameters (see the 'no parameters' example at the end of this section). +Create a file with the path `static/bidder-params/{bidder}.json` and use [JSON Schema](https://json-schema.org/understanding-json-schema/) to define your bidder parameters. Prebid Server requires this file for every adapter, even if yours doesn't require bidder parameters (see the 'no parameters' example at the end of this section). Let's start with this example which defines one required `placementId` string parameter: @@ -244,9 +373,10 @@ Let's start with this example which defines one required `placementId` string pa "required": ["placementId"] } ``` + We encourage you to utilize the full features of [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) to narrowly define your bidder parameter data types. If you copy and paste these examples, please remember to change the `title` and `description` to refer to your bidder name instead of our fictional Foo example. -When choosing your parameter names, please consider aligning with the OpenRTB 2.5 standard by using lower case letters without camel casing or special characters. +When choosing your parameter names, please consider aligning with the OpenRTB 2.x standard by using lower case letters without camel casing or special characters. Properties in [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) are case sensitive. If you choose to specify multiple properties differing only by case for compatibility, we ask that you include the word 'preferred' in one of the descriptions to give a hint to third party configuration systems. @@ -265,6 +395,7 @@ In addition to the examples listed below, please refer to [existing bidder param "properties": {} } ``` +
        @@ -288,6 +419,7 @@ In addition to the examples listed below, please refer to [existing bidder param "required": ["placementId"] } ``` +
        @@ -315,6 +447,7 @@ In addition to the examples listed below, please refer to [existing bidder param "required": ["token"] } ``` +
        @@ -344,6 +477,7 @@ In addition to the examples listed below, please refer to [existing bidder param ] } ``` +
        @@ -373,6 +507,7 @@ In addition to the examples listed below, please refer to [existing bidder param ] } ``` +

        @@ -399,18 +534,19 @@ Please follow [Go's standard naming convention](https://golang.org/doc/effective ### Adapter Code -Now it's time to write the bulk of your bid adapter code. +Now it's time to write your bid adapter code. -Each adapter has its own directory (a 'package' in Go parlance) for all code and tests associated with translating an OpenRTB 2.5 Bid Request to your bidding server's protocol and mapping your server's response to an OpenRTB 2.5 Bid Response. The use of separate packages provide each adapter with its own naming scope to avoid conflicts and gives the freedom to organize files as you best see fit (although we make suggestions in this guide). +Each adapter has its own directory (a 'package' in Go parlance) for all code and tests associated with translating an OpenRTB 2.x Bid Request to your bidding server's protocol and mapping your server's response to an OpenRTB 2.x Bid Response. The use of separate packages provide each adapter with its own naming scope to avoid conflicts and gives the freedom to organize files as you best see fit (although we make suggestions in this guide). Create a file with the path `adapters/{bidder}/{bidder}.go`. Your bid adapter code will need to implement and export: -- The `adapters.Builder` method to create a new instance of the adapter based on the host configuration. -- The `adapters.Bidder` interface consisting of the `MakeRequests` method to create outgoing requests to your bidding server and the `MakeBids` method to create bid responses. + +* The `adapters.Builder` method to create a new instance of the adapter based on the host configuration. +* The `adapters.Bidder` interface consisting of the `MakeRequests` method to create outgoing requests to your bidding server and the `MakeBids` method to create bid responses. {: .alert.alert-info :} **ACCESS MODIFIERS:** Go has only two kinds of access modifiers, exported and private, which are scoped at the package level. The access modifier is encoded into the name of the type or method. Names starting with an upper case letter are exported whereas names starting with a lower case letter are private. Please only export the three required methods and keep everything else private. -Here is a reference implementation for a bidding server which uses the OpenRTB 2.5 protocol: +Here is a reference implementation for a bidding server which uses the OpenRTB 2.x protocol: ```go package foo @@ -420,7 +556,7 @@ import ( "fmt" "net/http" - "github.com/mxmCherry/openrtb/v15/openrtb2" + "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/adapters" "github.com/prebid/prebid-server/config" "github.com/prebid/prebid-server/errortypes" @@ -431,8 +567,8 @@ type adapter struct { endpoint string } -// Builder builds a new instance of the Foo adapter for the given bidder with the given config. -func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { +// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { bidder := &adapter{ endpoint: config.Endpoint, } @@ -449,11 +585,26 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte Method: "POST", Uri: a.endpoint, Body: requestJSON, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), } return []*adapters.RequestData{requestData}, nil } +func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { + if bid.Ext != nil { + var bidExt openrtb_ext.ExtBid + err := json.Unmarshal(bid.Ext, &bidExt) + if err == nil && bidExt.Prebid != nil { + return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type)) + } + } + + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse impression \"%s\" mediatype", bid.ImpID), + } +} + func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { if responseData.StatusCode == http.StatusNoContent { return nil, nil @@ -480,13 +631,19 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp)) bidResponse.Currency = response.Cur + var errors []error for _, seatBid := range response.SeatBid { for i, bid := range seatBid.Bid { - b := &adapters.TypedBid{ - Bid: &seatBid.Bid[i], - BidType: getMediaTypeForBid(bid), + bidType, err := getMediaTypeForBid(bid) + if err != nil { + errors = append(errors, err) + continue } - bidResponse.Bids = append(bidResponse.Bids, b) + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: bidType, + }) + } } return bidResponse, nil } @@ -501,8 +658,11 @@ This method may be called multiple times if the host has configured aliases of y The first argument, `bidderName`, is the name of the bidder being built. This may be the bidder name you've chosen or it may be an alias. Most adapters don't make use of the `bidderName`, but its provided by the core framework for situations where the adapter might need to do something special for aliases. The second argument, `config`, is all the configuration values set for your adapter. However, not all of this information is intended for use by the `Builder` method. The only two fields relevant here are `config.Endpoint` and `config.ExtraAdapterInfo`: -- `config.Endpoint` is the base url of your bidding server and may be interpreted as either a literal address or as a templated macro to support dynamic domains or dynamic paths. -- `config.ExtraAdapterInfo` is an optional setting may be used for any other values your adapter may need, such as an application token or publisher allow/deny list. You may interpret this string however you like, although JSON is a common choice. + +* `config.Endpoint` is the base url of your bidding server and may be interpreted as either a literal address or as a templated macro to support dynamic paths. +* `config.ExtraAdapterInfo` is an optional setting may be used for any other values your adapter may need, such as an application token or publisher allow/deny list. You may interpret this string however you like, although JSON is a common choice. + +The third argument, `server`, is a set of host configs. It can be passed in two different ways. One way is to pass this info in the auction request itself at the path `ext.prebid.server` (i.e. `ext.prebid.server.datacenter`). The second way is to pass this info as a configuration data structure. The `Builder` method is expected to return an error if either the `config.Endpoint` or the `config.ExtraAdapterInfo` values are invalid or cannot be parsed. Errors will be surfaced to the host during application startup as a fatal error. @@ -514,8 +674,8 @@ type adapter struct { endpointTemplate *template.Template } -// Builder builds a new instance of the Foo adapter for the given bidder with the given config. -func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { +// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { template, err := template.New("endpointTemplate").Parse(config.Endpoint) if err != nil { return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) @@ -527,6 +687,7 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters return bidder, nil } ``` +
        @@ -537,8 +698,8 @@ type extraInfo struct { token string } -// Builder builds a new instance of the Foo adapter for the given bidder with the given config. -func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { +// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { info, err := parseExtraInfo(config.ExtraAdapterInfo) if err != nil { return nil, err @@ -570,16 +731,17 @@ func buildDefaultExtraInfo() extraInfo { } } ``` +

        #### MakeRequests -The `MakeRequests` method is responsible for returning none, one, or many HTTP requests to be sent to your bidding server. Bid adapters are forbidden from directly initiating any form of network communication and must entirely rely upon the core framework. This allows the core framework to optimize outgoing connections using a managed pool and record networking metrics. The return type `adapters.RequestData` allows your adapter to specify the HTTP method, url, body, and headers. +The `MakeRequests` method is responsible for returning none, one, or many HTTP requests to be sent to your bidding server. Bid adapters are forbidden from directly initiating any form of network communication and must entirely rely upon the core framework. This allows the core framework to optimize outgoing connections using a managed pool and record networking metrics. The return type `adapters.RequestData` allows your adapter to specify the HTTP method, url, body, headers, and ids of the impressions in the request. This method is called once by the core framework for bid requests which have at least one valid Impression for your adapter. Impressions not configured for your adapter are not accessible. -The first argument, `request`, is the OpenRTB 2.5 Bid Request object. Extension information is stored as `json.RawMessage` byte arrays and must be unmarshalled and/or marshalled to be read and/or mutated. It is *critical* to understand that the `request` object contains pointers to shared memory. If your adapter needs to alter any data referenced by a pointer then you *must* first make a shallow copy. The only exception is for `request.Imp` and its elements, as these are already shallow copies. The exact same instance of the `request` object is also passed to the `MakeBids` method, so please be careful when mutating. It's safe to assume that `request.Imp[]` always contains at least one element and that the `request.Imp[].ext.bidder` was successfully validated per your bidder parameter JSON Schema. +The first argument, `request`, is the OpenRTB 2.x Bid Request object. Extension information is stored as `json.RawMessage` byte arrays and must be unmarshalled and/or marshalled to be read and/or mutated. It is *critical* to understand that the `request` object contains pointers to shared memory. If your adapter needs to alter any data referenced by a pointer then you *must* first make a shallow copy. The only exception is for `request.Imp` and its elements, as these are already shallow copies. The exact same instance of the `request` object is also passed to the `MakeBids` method, so please be careful when mutating. It's safe to assume that `request.Imp[]` always contains at least one element and that the `request.Imp[].ext.bidder` was successfully validated per your bidder parameter JSON Schema.
        Example: Mutating banner shared memory (make a copy). @@ -594,15 +756,15 @@ if request.Imp[i].W == nil && request.Imp[i].H == nil && len(request.Imp[i].Form request.Imp[i].Banner = &bannerCopy } ``` +

        The second argument, `requestInfo`, is for extra information and helper methods provided by the core framework. This includes: -- `requestInfo.PbsEntryPoint` to access the entry point of the bid request, commonly used to determine if the request is for AMP or for a [Long Form Video Ad Pod](/dev-docs/modules/adpod.html). -- `requestInfo.GlobalPrivacyControlHeader` to read the value of the `Sec-GPC` Global Privacy Control (GPC) header of the bid request. -- `requestInfo.ConvertCurrency` a method to perform currency conversions. - +* `requestInfo.PbsEntryPoint` to access the entry point of the bid request, commonly used to determine if the request is for AMP or for a [Long Form Video Ad Pod](/dev-docs/modules/adpod.html). +* `requestInfo.GlobalPrivacyControlHeader` to read the value of the `Sec-GPC` Global Privacy Control (GPC) header of the bid request. +* `requestInfo.ConvertCurrency` a method to perform currency conversions. The `MakeRequests` method is expected to return a slice (similar to a C# `List` or a Java `ArrayList`) of `adapters.RequestData` objects representing the HTTP calls to be sent to your bidding server and a slice of type `error` for any issues encountered creating them. If there are no HTTP calls or if there are no errors, please return `nil` for both return values. Please do not add `nil` items in the slices. @@ -632,6 +794,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte Method: "POST", Uri: a.endpoint, Body: requestJSON, + ImpIDs: []string{imp.ID}, } requests = append(requests, requestData) } @@ -681,17 +844,19 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte Method: "POST", Uri: a.endpoint, Body: requestJSON, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), } return []*adapters.RequestData{requestData}, nil } ``` +

        ##### Common Data -There are a several values of a bid that publishers expect to be populated. Some are defined by the OpenRTB 2.5 specification and some are defined by Prebid conventions. +There are a several values of a bid that publishers expect to be populated. Some are defined by the OpenRTB 2.x specification and some are defined by Prebid conventions. {: .table .table-bordered .table-striped } | Parameter | Definer | Path & Description @@ -713,24 +878,24 @@ For simplicity, adapters are expected to make net-price bids (e.g. "If this ad w #### Response -The `MakeBids` method is responsible for parsing the bidding server's response and mapping it to the [OpenRTB 2.5 Bid Response object model](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32). +The `MakeBids` method is responsible for parsing the bidding server's response and mapping it to the [OpenRTB 2.x Bid Response object model](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#objectbidresponse). This method is called for each response received from your bidding server within the bidding time window (`request.tmax`). If there are no requests or if all requests time out, the `MakeBids` method will not be called. {: .alert.alert-warning :} It's *imperative* to include all required information in the response for your bid to be accepted. Please avoid common mistakes, such as not specifying the bid currency and not properly detecting the media type from the bidding server response. -The first argument, `request`, is the exact same OpenRTB 2.5 Bid Request object provided to (and potentially mutated by) the `MakeRequests` method. The information in the `request` may be useful when detecting the media type. +The first argument, `request`, is the exact same OpenRTB 2.x Bid Request object provided to (and potentially mutated by) the `MakeRequests` method. The information in the `request` may be useful when detecting the media type. The second argument, `requestData`, is the exact same `adapters.RequestData` object returned by the `MakeRequests` method. It's rare for adapters to make use of this information, but it's provided for potential edge cases. The third argument, `responseData`, is the HTTP response received from your bidding server and contains the status code, body, and headers. If your bidding server replies with a GZIP encoded body, it will be automatically decompressed. -The `MakeBids` method is expected to return an `adapters.BidderResponse` object with one or more bids mapped from your bidding server's response. This may be as simple as decorating an OpenRTB 2.5 Bid Response with some Prebid Server metadata (such as the media type) or more complicated mapping logic depending on your server's response format. +The `MakeBids` method is expected to return an `adapters.BidderResponse` object with one or more bids mapped from your bidding server's response. This may be as simple as decorating an OpenRTB 2.x Bid Response with some Prebid Server metadata (such as the media type) or more complicated mapping logic depending on your server's response format. ##### Object Model -Please review the entire [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32) documentation to fully understand the response object model and expectations. We've summarized some common fields below. Data which is listed as required is enforced by the core framework and cannot be omitted. +Please review the entire [OpenRTB 2.x Bid Response](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#objectbidresponse) documentation to fully understand the response object model and expectations. We've summarized some common fields below. Data which is listed as required is enforced by the core framework and cannot be omitted. {: .table .table-bordered .table-striped } | BidderResponse Path | Scope | Description @@ -768,23 +933,28 @@ Either `.Bids[].BidVideo.PrimaryCategory` or `.Bids[].Bid.Cat` should be provide Prebid has introduced a standard object model for sharing granular bid response data with publishers, analytics, and reporting systems. We encourage adapters to provide as much information as possible in the bid response. {: .alert.alert-danger :} -Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for bid.ADomain and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid. +Bid metadata may be required in a future Prebid.js release. The AdvertiserDomains field and the DChain object are particularly useful. We recommend ensuring your adapter sets these fields or Prebid.js may reject your bid. {: .table .table-bordered .table-striped } | Path | Description | - | - -| `.NetworkID` | Bidder-specific network/DSP id. -| `.NetworkName` | Bidder-specific network/DSP name. -| `.AgencyID` | Bidder-specific agency id. -| `.AgencyName` | Bidder-specific agency name. +| `.AdvertiserDomains` | Domains for the landing page(s) aligning with the OpenRTB `adomain` field. | `.AdvertiserID` | Bidder-specific advertiser id. | `.AdvertiserName` | Bidder-specific advertiser name. +| `.AgencyID` | Bidder-specific agency id. +| `.AgencyName` | Bidder-specific agency name. | `.BrandID` | Bidder-specific brand id for advertisers with multiple brands. | `.BrandName` | Bidder-specific brand name. | `.DChain` | Demand chain object. +| `.DemandSource` | Bidder-specific demand source. Some adapters may functionally serve multiple SSPs or exchanges, and this specifies which. +| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe. +| `.NetworkID` | Bidder-specific network/DSP id. +| `.NetworkName` | Bidder-specific network/DSP name. +| `.RendererName` | Name of the desired renderer for the creative. +| `.RendererVersion` | Version of the desired renderer for the creative. | `.PrimaryCategoryID` | Primary IAB category id. | `.SecondaryCategoryIDs` | Secondary IAB category ids. -| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe. +| `.RendererUrl` | Dynamic renderer URL for use in outstream rendering

        @@ -806,26 +976,29 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R } func getBidMeta(bid *adapters.TypedBid) *openrtb_ext.ExtBidPrebidMeta { - // Not all fields are required. This example includes all fields for - // demonstration purposes. + // This example includes all fields for demonstration purposes. return &openrtb_ext.ExtBidPrebidMeta { - NetworkID: 1, - NetworkName: "Some Network Name", - AgencyID: 2, - AgencyName: "Some Agency Name", + AdvertiserDomains: []string{"Some Domain"}, AdvertiserID: 3, AdvertiserName: "Some Advertiser Name", - AdvertiserDomains: []string{"Some Domain"}, - DemandSource: "Some Demand Source", - DChain: json.RawMessage(`{Some Demand Chain JSON}`), + AgencyID: 2, + AgencyName: "Some Agency Name", BrandID: 4, BrandName: "Some Brand Name", + DChain: json.RawMessage(`{Some Demand Chain JSON}`), + DemandSource: "Some Demand Source", + MediaType: "banner", + NetworkID: 1, + RendererName: "Some Renderer", + RendererVersion: "1.0", + NetworkName: "Some Network Name", PrimaryCategoryID: "IAB-1", SecondaryCategoryIDs: []string{"IAB-2", "IAB-3"}, - MediaType: "banner", + RendererUrl: "https://example-renderer-url.com/path/render.js" } } ``` +

        @@ -881,30 +1054,27 @@ You need to provide default settings for your bid adapter. You can decide if you {: .alert.alert-warning :} **HOST SPECIFIC INFO:** The default endpoint must not be specific to any particular host, such as Xandr/AppNexus. We may ask you about suspicious looking ids during the review process. Please reach out to individual hosts if you need to set specialized configuration. -#### Enabled By Default +## Aliasing an Adapter -Edit the file `config/config.go` to register your default endpoint within the `SetupViper` method. If your bid adapter makes use of extra adapter info and you'd like to provide a good default value, you can do that here too. +If your bidding endpoint can support more than one biddercode, you shouldn't replicate +the whole adapter codebase. Rather, follow these steps to create a 'hardcoded' alias: -```go -func SetupViper(v *viper.Viper, filename string) { - ... - v.SetDefault("adapters.{bidder}.endpoint", "https://your.url/any/path") - v.SetDefault("adapters.{bidder}.extra_info", `{"your": "extra info"}`) - ... -} +1. Create a config yaml file in static/bidder-info - e.g. static/bidder-info/myalias.yaml +1. Add "aliasOf" in the config.yaml file with its value set to the name of the adapter you are creating an alias for + +```yaml +aliasOf: "appnexus" ``` -#### Disabled By Default +Notes: -Edit the file `config/config.go` to register your default endpoint within the `SetupViper` method. You may still provide a default endpoint or extra adapter info. +* The alias name must be unique for the first 6 chars as noted above for biddercodes. +* This process will be simplified someday. -```go -func SetupViper(v *viper.Viper, filename string) { - ... - v.SetDefault("adapters.{bidder}.disabled", "true") - ... -} -``` +{: .alert.alert-info :} +Note on aliases and TCF Global Vendor List IDs: if an alias entry does not have its own GVLID but wishes to claim GDPR support, +the documentation entry (The file in [https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders)) must list the GVLID of the main adapter with that company's name in parentheses. +Look for other doc entries containing an `aliasCode` metadata entry. ## Test Your Adapter @@ -935,7 +1105,8 @@ import ( func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.Bidder{Bidder}, config.Adapter{ - Endpoint: "http://whatever.url"}) + Endpoint: "http://whatever.url"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) if buildErr != nil { t.Fatalf("Builder returned unexpected error %v", buildErr) @@ -948,14 +1119,16 @@ func TestJsonSamples(t *testing.T) { You should use an obviously fake endpoint for your tests. There's no reason to use a real endpoint value. Please also note the `_test.go` file suffix is a required Go idiom. The Go test runner will look in these files for tests and the Go compiler will exclude test code from production binaries. Each test case should be written in its own JSON file with a succinct, yet descriptive, name of what's being tested. The files should be located in either: + * `adapters/{bidder}/{bidder}test/exemplary/` for straight forward "happy path" tests. We expect to see tests here for each supported media type. * `adapters/{bidder}/{bidder}test/supplemental` for tests which produce errors or cover more complicated scenarios. The format of a JSON test is as follows: + ```json { "mockBidRequest": { - «OpenRTB 2.5 Bid Request» + «OpenRTB 2.x Bid Request» }, "httpCalls": [{ "expectedRequest": { @@ -1006,7 +1179,8 @@ If your adapter supports template parsing, we recommend adding this failure test ```go func TestEndpointTemplateMalformed(t *testing.T) { _, buildErr := Builder(openrtb_ext.Bidder{Bidder}, config.Adapter{ - Endpoint: "{%raw%}{{Malformed}}{%endraw%}"}) + Endpoint: "{%raw%}{{Malformed}}{%endraw%}"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) assert.Error(t, buildErr) } @@ -1019,7 +1193,8 @@ func TestBadConfig(t *testing.T) { _, buildErr := Builder(openrtb_ext.Bidder{Bidder}, config.Adapter{ Endpoint: `http://it.doesnt.matter/bid`, ExtraAdapterInfo: `{foo:42}`, - }) + }, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) assert.Error(t, buildErr) } @@ -1028,7 +1203,8 @@ func TestEmptyConfig(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.Bidder{Bidder}, config.Adapter{ Endpoint: `http://it.doesnt.matter/bid`, ExtraAdapterInfo: ``, - }) + }, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) bidder{Bidder} := bidder.(*adapter) @@ -1086,6 +1262,7 @@ var invalidParams = []string{ `{"placementId": 42}`, } ``` + Please include tests for required fields, optional fields, conditional fields such as `oneOf`, regex filters, and data type mismatches. For example, if the field is defined as a string please include one invalid case for the wrong data type such as an integer in this example. There is no need to provide a combinatorial for every edge case possibility. We're looking for just enough test cases to build confidence. @@ -1095,12 +1272,14 @@ There is no need to provide a combinatorial for every edge case possibility. We' We'll verify your adapter works correctly on a technical level during the code review, but you'll need to perform manual end-to-end testing: 1. Build the project and start your server: + ```bash go build . ./prebid-server ``` -1. POST an OpenRTB 2.5 Bid Request with at least one Impression defined for your bid adapter with a supported media type. This is an example template for a banner ad. +1. POST an OpenRTB 2.x Bid Request with at least one Impression defined for your bid adapter with a supported media type. This is an example template for a banner ad. + ```bash curl --request POST \ --url 'https://localhost:8000/openrtb2/auction' \ @@ -1140,7 +1319,7 @@ We'll verify your adapter works correctly on a technical level during the code r If your bid adapter defines one or more user sync endpoints, you'll need to perform manual end-to-end testing of each endpoint using the following process: -1. [Save a User ID](https://docs.prebid.org/prebid-server/endpoints/pbs-endpoint-setuid.html) using the `key` of your user sync endpoint. This should default to your bidder name and is case sensitive. +1. [Save a User ID](https://docs.prebid.org/prebid-server/endpoints/pbs-endpoint-setuid.html) using the `key` of your user sync endpoint. This should default to your bidder name and is case sensitive. 1. Run a test auction (see the curl example above) and verify in the debug response that the outgoing `request.ext.debug.httpcalls` calls includes the User ID you saved in step 1. @@ -1150,19 +1329,20 @@ If you are having issues finding the root cause of user sync errors, please [sub Human readable documentation for bid adapters is required in the separate [prebid.github.io](https://github.com/prebid/prebid.github.io) repository. We will not merge your bid adapter until you've at least opened a documentation PR and comment with a link to it. -1. If you already have a Prebid.js bid adapter, update your existing bidder file in https://github.com/prebid/prebid.github.io/tree/master/dev-docs/modules to add the `pbs: true` variable in the header section. If your Prebid Server bidding parameters are different from your Prebid.js parameters, please include the differences in this document for publishers to be aware. -1. If you don't have a Prebid.js bid adapter, create a new file in https://github.com/prebid/prebid.github.io/tree/master/dev-docs/modules using this template: +1. If you already have a Prebid.js bid adapter, update your existing bidder file in [https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders) to add the `pbs: true` variable in the header section. If your Prebid Server bidding parameters are different from your Prebid.js parameters, please include the differences in this document for publishers to be aware. +1. If you don't have a Prebid.js bid adapter, create a new file in [https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders) using this template: -``` +```text --- layout: bidder title: {bidder} description: Prebid {Bidder} Bidder Adapter biddercode: {bidder} -gdpr_supported: true/false +tcfeu_supported: true/false gvl_id: 111 usp_supported: true/false coppa_supported: true/false +gpp_sids: tcfeu, tcfca, usnat, usstate_all, usp schain_supported: true/false dchain_supported: true/false userId: @@ -1172,12 +1352,15 @@ deals_supported: true/false floors_supported: true/false fpd_supported: true/false pbjs: true/false -pbs: true/false +pbs: true pbs_app_supported: true/false prebid_member: true/false +multiformat_supported: will-bid-on-any, will-bid-on-one, will-not-bid +ortb_blocking_supported: true/partial/false +privacy_sandbox: no or comma separated list of `paapi`, `topics` --- -### Note: +### Registration The Example Bidding adapter requires setup before beginning. Please contact us at setup@example.com @@ -1188,42 +1371,44 @@ The Example Bidding adapter requires setup before beginning. Please contact us a |---------------|----------|--------------|-----------|----------| | `placementId` | required | Placement ID | `'11111'` | `string` | ``` + Notes on the metadata fields: -- Add `pbs: true`. If you also have a [Prebid.js bid adapter](/dev-docs/bidder-adaptor.html), add `pbjs: true`. Default is false for both. -- If you're on the IAB's Global Vendor List, place your ID in `gvl_id`. No default. -- If you support the GDPR and have a GVL ID, you may add `gdpr_supported: true`. Default is false. -- If you support the US Privacy consentManagementUsp module, add `usp_supported: true`. Default is false. -- If you support one or more userId modules, add `userId: (list of supported vendors)`. Default is none. -- If you support video and/or native mediaTypes add `media_types: video, native`. Note that display is added by default. If you don't support display, add "no-display" as the first entry, e.g. `media_types: no-display, native`. No defaults. -- If you support COPPA, add `coppa_supported: true`. Default is false. -- If you support the [supply chain](/dev-docs/modules/schain.html) feature, add `schain_supported: true`. Default is false. -- If you support adding a demand chain on the bid response, add `dchain_supported: true`. Default is false. -- If your bidder doesn't work well with safeframed creatives, add `safeframes_ok: false`. This will alert publishers to not use safeframed creatives when creating the ad server entries for your bidder. No default. -- If your bidder supports mobile apps, set `pbs_app_supported: true`. No default value. -- If your bidder supports deals, set `deals_supported: true`. No default value. -- If your bidder supports floors, set `floors_supported: true`. No default value. -- If your bidder supports first party data, set `fpd_supported: true`. No default value. -- If you're a member of Prebid.org, add `prebid_member: true`. Default is false. +* Add `pbs: true`. If you also have a [Prebid.js bid adapter](/dev-docs/bidder-adaptor.html), add `pbjs: true`. Default is false for both. +* If you're on the IAB's Global Vendor List, place your ID in `gvl_id`. No default. +* If you support the IAB's TCF protocol and have a GVL ID, you may add `tcfeu_supported: true`. Default is false. +* If you support the US Privacy consentManagementUsp module, add `usp_supported: true`. Default is false. +* If you support one or more userId modules, add `userId: (list of supported vendors)`. Default is none. +* If you support video, native, or audio mediaTypes add `media_types: video, native, audio`. Note that display is added by default. If you don't support display, add "no-display" as the first entry, e.g. `media_types: no-display, native`. No defaults. +* If you support COPPA, add `coppa_supported: true`. Default is false. +* If you support sections within the IAB's GPP consent string, add `gpp_sids:' and then which sections you support: tcfeu, tcfca, usnat, usstate_all, usp +* If you support the [supply chain](/dev-docs/modules/schain.html) feature, add `schain_supported: true`. Default is false. +* If you support adding a demand chain on the bid response, add `dchain_supported: true`. Default is false. +* If your bidder doesn't work well with safeframed creatives, add `safeframes_ok: false`. This will alert publishers to not use safeframed creatives when creating the ad server entries for your bidder. No default. +* If your bidder supports mobile apps, set `pbs_app_supported: true`. No default value. +* If your bidder supports deals, set `deals_supported: true`. No default value. +* If your bidder supports floors, set `floors_supported: true`. No default value. +* If you support first party data, you must document what exactly is supported and then you may set `fpd_supported: true`. No default value. +* If you support any OpenRTB blocking parameters, you must document what exactly is supported and then you may set `ortb_blocking_supported` to ‘true’,’partial’, or ‘false’. No default value. In order to set ‘true’, you must support: bcat, badv, battr, and bapp. +* Let publishers know how you support multiformat requests -- those with more than one mediatype (e.g. both banner and video). Here are the options: will-bid-on-any, will-bid-on-one, will-not-bid +* If you're a member of Prebid.org, add `prebid_member: true`. Default is false. ## File Checklist -- Bidder Info - - `static/bidder-info/{bidder}.yaml` -- Bidder Parameters - - `static/bidder-params/{bidder}.json` - - `openrtb_ext/imp_{bidder}.go` - - `adapters/{bidder}/params_test.go` -- Adapter Code - - `adapters/{bidder}/{bidder}.go` - - `adapters/{bidder}/{bidder}_test.go` - - `adapters/{bidder}/{bidder}test/exemplary/*.json` - - `adapters/{bidder}/{bidder}test/supplemental/*.json` -- Register With The Core - - `openrtb_ext/bidders.go` - - `exchange/adapter_builders.go` -- Defaults - - `config/config.go` +* Bidder Info + * `static/bidder-info/{bidder}.yaml` +* Bidder Parameters + * `static/bidder-params/{bidder}.json` + * `openrtb_ext/imp_{bidder}.go` + * `adapters/{bidder}/params_test.go` +* Adapter Code + * `adapters/{bidder}/{bidder}.go` + * `adapters/{bidder}/{bidder}_test.go` + * `adapters/{bidder}/{bidder}test/exemplary/*.json` + * `adapters/{bidder}/{bidder}test/supplemental/*.json` +* Register With The Core + * `openrtb_ext/bidders.go` + * `exchange/adapter_builders.go` ## Contribute diff --git a/prebid-server/developers/add-new-bidder-java.md b/prebid-server/developers/add-new-bidder-java.md index 07250ee7f7..a0c4da4e79 100644 --- a/prebid-server/developers/add-new-bidder-java.md +++ b/prebid-server/developers/add-new-bidder-java.md @@ -8,51 +8,90 @@ title: Prebid Server | Developers | Adding a New Bidder # Prebid Server - Adding a New Bidder - Java {: .no_toc} -* TOC +- TOC {:toc } -Thank you for contributing a bid adapter to the open source Prebid Server project. Each new adapter gives publishers more options for monetizing their inventory and strengthens the header bidding community. +Thank you for your valuable contribution of a bid adapter to the open source Prebid Server project. Each new adapter expands the monetization possibilities for publishers and provides greater options to maximize their inventory's potential. We truly appreciate your support in making this ecosystem thrive! -This document guides you through the process of developing a new bid adapter for your bidding server. We encourage you to look at [existing bid adapters](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/bidder) for working examples and practical guidance. You can also ask us questions by [submitting a GitHub issue](https://github.com/prebid/prebid-server-java/issues/new). +This document guides you through the process of developing a new bid adapter for your bidding server. We encourage you to look at [existing bid adapters](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/bidder) for working examples and practical guidance. You can ask us questions by [submitting a GitHub issue](https://github.com/prebid/prebid-server-java/issues/new). {: .alert.alert-info :} -**NOTE:** There are two implementations of Prebid Server, [PBS-Go](https://github.com/prebid/prebid-server) and [PBS-Java](https://github.com/prebid/prebid-server-java). We recommend you build new adapters for PBS-Go and allow us to port it to PBS-Java within a couple of months. +**NOTE:** There are two implementations of Prebid Server: [PBS-Go](https://github.com/prebid/prebid-server) and [PBS-Java](https://github.com/prebid/prebid-server-java). We recommend you build new adapters for PBS-Go first, and then PBS-Java if you'd like. We port adapters from Go-to-Java, but not the other way around. +## Introduction -## Overview +Bid adapters are responsible for translating a 'Prebid-flavored' OpenRTB Bid Request to your bidding server's protocol and mapping your server's response to a Prebid-flavored response. -Bid adapters are responsible for translating an [OpenRTB 2.5 Bid Request](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=13) to your bidding server's protocol and mapping your server's response to an [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32). +"Prebid-flavored OpenRTB" means: -An OpenRTB 2.5 Bid Request contains one or more Impressions, each representing a single ad placement. An Impression may define multiple sizes and/or multiple ad formats. If your bidding server limits requests to a single ad placement, size, or format, then your adapter will need to split the Impression into multiple calls and merge the responses. +1. [OpenRTB 2.6](https://github.com/InteractiveAdvertisingBureau/openrtb2.x) as defined by the IAB. +1. Certain Prebid extensions as defined in the [/auction endpoint documentation](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html). + +OpenRTB Bid Requests contain one or more impression objects, each representing a single ad placement. An impression may define multiple sizes and/or multiple ad formats. If your bidding server limits requests to a single ad placement, size, or format, then your adapter will need to split the impression into multiple calls and merge the responses. ## Plan Your Bid Adapter ### Choose A Name -You will need to choose a unique name for your bid adapter. Names should be written in lower case and may not contain special characters or emoji. If you already have a Prebid.js bid adapter, we encourage you to use the same name with the same bidder parameters. You may not name your adapter `general`, `context`, or `prebid` as those have special meaning in various contexts. Existing bid adapter names are [maintained here](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/bidder). +You will need to choose a unique name for your bid adapter. Names should be written in lower case and may not contain special characters or emoji. If you already have a Prebid.js bid adapter, we encourage you to use the same name with the same bidder parameters. You may not name your adapter `all`, `context`, `data`, `general`, `prebid`, `skadn`, `tid`, `all` or `ae` as those have special meaning in various contexts. Existing bid adapter names are [maintained here](https://github.com/prebid/prebid-server-java/tree/master/src/main/java/org/prebid/server/bidder). We ask that the first 6 letters of the name you choose be unique among the existing bid adapters. This consideration helps with generating targeting keys for use by some ad exchanges, such as Google Ad Manager. Throughout the rest of this document, substitute `{bidder}` with the name you've chosen. +### Consider Your Geography + +Most bidders run their auction endpoints in multiple datacenters because their +business is continental or global. + +Prebid Server is open source software that is run by many host companies that may be calling +your bid adapter from various places. It may be useful to consider how you want to +communicate your geographic preferences to these companies. + +{: .alert.alert-info :} +Please don't bother publishers by asking them to enter a geographic location 'host' parameter. Most publishers do not have the tech to choose which of your regional endpoints to hit. + +These are the recommended technical solutions: + +1. Use a "Global Services Load Balancing" vendor so there's just one smart hostname that figures out where to send each user. Just do an internet search for "gslb services". +1. In your bidder yaml file, let the host companies know which regional endpoints you support. They can take care of mapping their regions to your regions. See the YAML file below for an example of how to communicate this. + +You should also consider entering geographic scoping information into your YAML file so +host companies can disable your bidder in regions where you're not going to bid. e.g. +bidders that are not GDPR-compliant probably won't bid much in Europe. It costs both you and the host company networking fees to send bid requests, so it's in +your interest to declare your scope of business. See below for syntax details. + ### Respect The Rules We are proud to run the Prebid Server project as a transparent and trustworthy header bidding solution. You are expected to follow our community's [code of conduct](https://prebid.org/code-of-conduct/) and [module rules](/dev-docs/module-rules.html) when creating your adapter and when interacting with others through issues, code reviews, and discussions. -**Please take the time to read our rules in full.** Below is a summary of some of the rules which apply to your Prebid Server bid adapter: +**Please take the time to read the rules in full.** Below is a summary of some of the rules which apply to your Prebid Server bid adapter: + +- Adapters must include maintainer information with a group email address for Prebid.org to contact for ongoing support and maintenance. +- Your bidder's endpoint domain name cannot be fully variable. We will accept endpoint domains that include account IDs, but we do not like them, and Prebid Server host companies may disable adapters using this approach if there are technical issues with it. We will not accept hostnames that have a required dynamic element for the purpose of sending traffic to different geographic regions. +- If you have a client-side adapter, all parameters (including biddercodes and aliases) must be consistent between your client- and server-side adapters. This allows publishers to utilize the PBJS [s2sTesting module](/dev-docs/modules/s2sTesting.html). - Adapters must not modify bids from demand partners, except to either change the bid from gross to net or from one currency to another. - Adapters must use the functions provided by the core framework for all external communication. Initiation of any form of network connection outside of what is provided by the core framework is strictly prohibited. No exceptions will be made for this rule. - Adapters must support the creation of multiple concurrent instances. This means adapters may not mutate global or package scoped variables. - Bidding server endpoints should prefer secure HTTPS to protect user privacy and should allow keep alive connections (preferably with HTTP/2 support) to increase host performance. -- Adapters must include maintainer information with a group email address for Prebid.org to contact for ongoing support and maintenance. - Adapters must annotate the bid response with the proper media type, ideally based on the response from the bidding server. +- Bid adapters must not create their own transaction IDs or overwrite the tids supplied by Prebid. {: .alert.alert-warning :} Failure to follow the rules will lead to delays in approving your adapter for inclusion in Prebid Server. If you'd like to discuss an exception to a rule, please make your request by [submitting a GitHub issue](https://github.com/prebid/prebid-server-java/issues/new). +### Multiformat + +Publishers are utilizing multiformat ad units more frequently, e.g. an impression object that contains both banner and video. It is important that your +adapter handle this scenario. Here are your options: + +1. Set `ortb.multiformat-supported: false` in your bidder YAML file. This will cause PBS to choose a format for you based on publisher configuration or discard any requests that are multiformat. +1. Or code your adapter to choose one of the available formats. e.g. "if both banner and video are present, always choose video". +1. Or code your adapter to make multiple requests to your auction endpoint. e.g. "if both banner and video are present, make two calls to the endpoint". + ### Ongoing Support and Maintenance -You are expected to provide support and maintenance for the code you contribute to Prebid Server as part of your bid adapter. We ask that you proactively update your adapter when your bidding server introduces new features or breaking changes. +**You are expected to provide support and maintenance for the code you contribute to Prebid Server as part of your bid adapter.** We ask that you proactively update your adapter when your bidding server introduces new features or breaking changes. Occasionally, we'll introduce changes to the core framework as part of our ongoing maintenance and enhancement of the project. If this causes a compilation error or a performance impact to your adapter, we will update the affected portion of your bid adapter code and provide full unit test coverage of our changes. We will notify you via email if this happens and give you at least one week to review the PR and provide comments. Please understand that we will not wait for your explicit approval for these kinds of changes unless you respond to our email or comment on the PR. @@ -82,7 +121,13 @@ Create a file with the path `static/bidder-info/{bidder}.yaml` and begin with th ```yaml adapters: yourBidderCode: - endpoint: http://possible.endpoint + # We have the following regional endpoint domains: us-east and us-west + # Please deploy this config in each of your datacenters with the appropriate regional subdomain + endpoint: http://REGION.example.com/openrtb2 + endpoint-compression: gzip (or none) + geoscope: + - USA + - CAN meta-info: maintainer-email: maintainer@email.com app-media-types: @@ -95,32 +140,57 @@ adapters: - video - audio - native + dooh-media-types: + - banner + - video + - audio + - native supported-vendors: vendor-id: your_vendor_id usersync: - url: your_bid_adapter_usersync_url - redirect-url: /setuid?bidder=yourBidderCode&gdpr={%raw%}{{gdpr}}{%endraw%}&gdpr_consent={%raw%}{{gdpr_consent}}{%endraw%}&us_privacy={%raw%}{{us_privacy}}{%endraw%} cookie-family-name: yourBidderCode - type: redirect - support-cors: false + iframe: + url: https://some-bidder-domain.com/usersync-url?gdpr={{gdpr}}&consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redirect={{redirect_url}} + uid-macro: 'YOURMACRO' + support-cors: false + redirect: + url: https://some-bidder-domain.com/usersync-url?gdpr={{gdpr}}&consent={{gdpr_consent}}&us_privacy={{us_privacy}}&redirect={{redirect_url}} + uid-macro: 'YOURMACRO' + support-cors: false ``` Modify this template for your bid adapter: + +- The endpoint can be static if you only have one datacenter or use a Global Load Balancer as described in 'Planning Your Adapter' above. +- The `geoscope` parameter is not currently read programmatically. Instead, it's intended to be used by PBS host companies to disable your adapter in geographic regions where you don't do business. However, we may make a module for this someday, so we ask that you follow this syntax for `geoscope`: + - YAML array + - Values can be either a 3-letter country code, "EEA", or "global". (EEA means European Economic Area) + - Values can be negated. e.g. "!EEA" - Change the maintainer email address to a group distribution list on your ad server's domain. A distribution list is preferred over an individual mailbox to allow for robustness, as roles and team members naturally change. -- Change the `modifying-vast-xml-allowed` value to `false` if you'd like to opt out of video impression tracking. It defaults to `true`. +- If absolutely necessary, change the `modifying-vast-xml-allowed` value to `false` to opt-out of [video impression tracking](https://github.com/prebid/prebid-server/issues/1015). However, please note that Prebid Server host companies depend on this feature being enabled to track video analytics. This feature has been live for many years with no known problems. - Change the `pbs-enforces-ccpa` to `false` if you'd like to disable ccpa enforcement. Defaults to `true`. -- Change the `vendor-id` value to id of your bidding server as registered with the [GDPR Global Vendor List (GVL)](https://iabeurope.eu/vendor-list-tcf-v2-0/). Leave this as `0` if you are not registered with IAB Europe. -- Remove the `capabilities` (app/site) and `mediaTypes` (banner/video/audio/native) combinations which your adapter does not support. +- Change the `vendor-id` value to id of your bidding server as registered with the [GDPR Global Vendor List (GVL)](https://iabeurope.eu/tcf-for-vendors/). Leave this as `0` if you are not registered with IAB Europe. +- Choose the `supported-vendors` constants: These constants should be unique. The list of existing vendor constants can be found [here](https://github.com/prebid/prebid-server-java/blob/master/src/main/java/org/prebid/server/bidder/ViewabilityVendors.java). +- Remove the `capabilities` (app/site/dooh) and `mediaTypes` (banner/video/audio/native) combinations which your adapter does not support. (Note: 'dooh' is [Digital Out Of Home](/prebid-server/use-cases/pbs-dooh.html)) +- If your auction endpoint supports gzip compression, setting 'endpoint-compression' to 'gzip' will save on network fees. + +If you does not support user syncing, you can remove `usersync` section of configuration. + - Change the `cookie-family-name` to the name which will be used for storing your user sync id within the federated cookie. Please keep this the same as your bidder name. - If you implemented a user syncer, you'll need to provide a default endpoint. - The user sync endpoint is composed of two main parts, the url of your user syncer and a redirect back(redirect-url) to Prebid Server. The url of your user syncer is responsible for reading the user id from the client's cookie and redirecting to Prebid Server with a user id macro resolved. +- Choose appropriate section for your usersync type(iframe/redirect). If both iframe and redirect endpoints are provided, the iframe endpoint will be used by default. + +In appropriate usersync section: + +- Change the `url` to url of your usersync endpoint +- Change the `uid-macro` to macro that will be placed in callback endpoint, to be resolved by your usersyncer. Defaults to empty string. +- Change the `support-cors` to true if your endpoint supports cors. + +The url of your user syncer can make use of the following macros which will be resolved by Prebid Server before sending the url to your server: -The url of your user syncer can make use of the following privacy policy macros which will be resolved by Prebid Server before sending the url to your server: - `{%raw%}{{us_privacy}}{%endraw%}`: Client's CCPA consent string. - `{%raw%}{{gdpr}}{%endraw%}`: Client's GDPR TCF enforcement flag. - `{%raw%}{{gdpr_consent}}{%endraw%}`: Client's GDPR TCF consent string. - -- Change the `usersync:type` value to `redirect` or `iframe` specific to your bidder. +- `{%raw%}{{redirect_url}}{%endraw%}`: Url to redirect back to Prebid Server. ### Default bidder configuration @@ -137,6 +207,7 @@ adapter-defaults: ``` There are also some default properties which can't be overridden in adapter-defaults, but rather in particular adapter's config: + - `aliases`: Defaults to empty - `deprecated-names`: Defaults to empty - `extra-info`: Defaults to empty @@ -145,6 +216,7 @@ There are also some default properties which can't be overridden in adapter-defa If you want to add bidder that is an alias of existing bidder, you need just to update configuration of parent bidder: Example of adding bidder alias: + ```yaml adapters: yourBidderCode: @@ -165,7 +237,7 @@ adapters: Aliases are configured by adding child configuration object at `adapters.yourBidderCode.aliases.yourBidderAlias` Aliases support the same configuration options that their bidder counterparts support except `aliases` (i.e. it's not possible -to declare alias of an alias). +to declare alias of an alias). {: .alert.alert-warning :} **Aliases cannot declare support for media types not supported by their parent bidders**
        @@ -173,26 +245,31 @@ However aliases could narrow down media types they support.
        For example: if the bidder is written to not support native site requests, then an alias cannot magically decide to change that; However, if a bidder supports native site requests, and the alias does not want to for some reason, it has the ability to remove that support. +{: .alert.alert-info :} +Note on aliases and TCF Global Vendor List IDs: if an alias entry does not have its own GVLID but wishes to claim GDPR support, +the documentation entry (The file in [github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders)) must list the GVLID of the main adapter with that company's name in parentheses. +Look for other doc entries containing an `aliasCode` metadata entry. + ### Bidder Parameters Your bid adapter might require extra information from the publisher to form a request to your bidding server. The bidder parameters JSON Schema codifies this information to allow Prebid Server to verify requests and to provide an API for third party configuration systems. -Publishers will provide extra information using an OpenRTB 2.5 Bid Request Extension, preferably at `request.imp[].ext.prebid.bidder.{bidder}` but also supported at `request.imp[].ext.{bidder}`. Prebid Server will validate the publisher information based on your schema and relocate the data to `request.imp[].ext.bidder`, regardless of your bidder name or the publisher's chosen location. +Publishers will provide extra information using an OpenRTB 2.x Bid Request Extension, preferably at `request.imp[].ext.prebid.bidder.{bidder}` but also supported at `request.imp[].ext.{bidder}`. Prebid Server will validate the publisher information based on your schema and relocate the data to `request.imp[].ext.bidder`, regardless of your bidder name or the publisher's chosen location. -We request that you do not duplicate information that is already present in the [OpenRTB 2.5 Bid Request specification](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=13) or is already part of an established Prebid convention. For example, your bidder parameters should not include first party data, bid floors, schain, video parameters, referrer information, or privacy consent including COPPA, CCPA, and GDPR TCF. For video parameters in particular, you must prefer the OpenRTB 2.5 Bid Request standard of `request.imp[].video`. +We request that you do not duplicate information that is already present in the [OpenRTB 2.x request](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md) or is already part of an established Prebid convention. For example, your bidder parameters should not include first party data, bid floors, schain, video parameters, referrer information, or privacy consent including COPPA, CCPA, and GDPR TCF. For video parameters in particular, you must prefer the OpenRTB 2.x Bid Request standard of `request.imp[].video`. {: .alert.alert-warning :} -**ENDPOINT NOTE:** You may not use an endpoint domain as a bidder parameter. Prebid Server is not an open proxy. If absolutely necessary, you may specify a portion of the domain as a parameter to support geo regions or account specific servers. However, this is discouraged and may degrade the performance of your adapter since the server needs to maintain more outgoing connections. Host companies may choose to disable your adapter if it uses a dynamically configured domain. +**ENDPOINT NOTE:** You may not try so set the full endpoint domain from a publisher-specified bidder parameter. Prebid Server is not an open proxy. If absolutely necessary, you may specify a *portion* of the domain as a parameter to support geo regions or account specific servers. However, this is discouraged and may degrade the performance of your adapter since the server needs to maintain more outgoing connections. Host companies may choose to disable your adapter if it uses a dynamically configured domain. -Create a file with the path `static/bidder-params/{bidder}.json` using [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) to define your bidder parameters. Prebid Server requires this file for every adapter, even if yours doesn't require bidder parameters (see the 'no parameters' example at the end of this section). +Create a file with the path `static/bidder-params/{bidder}.json` using [JSON Schema](https://json-schema.org/understanding-json-schema/) to define your bidder parameters. Prebid Server requires this file for every adapter, even if yours doesn't require bidder parameters (see the 'no parameters' example at the end of this section). Let's start with this example which defines one required `placementId` string parameter: ```json { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Foo Adapter Params", - "description": "A schema which validates params accepted by the Foo adapter", + "title": "BidderA Adapter Params", + "description": "A schema which validates params accepted by the BidderA adapter", "type": "object", "properties": { @@ -205,9 +282,10 @@ Let's start with this example which defines one required `placementId` string pa "required": ["placementId"] } ``` -We encourage you to utilize the full features of [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) to narrowly define your bidder parameter data types. If you copy and paste these examples, please remember to change the `title` and `description` to refer to your bidder name instead of our fictional Foo example. -When choosing your parameter names, please consider aligning with the OpenRTB 2.5 standard by using lower case letters without camel casing or special characters. +We encourage you to utilize the full features of [JSON Schema](https://spacetelescope.github.io/understanding-json-schema/) to narrowly define your bidder parameter data types. If you copy and paste these examples, please remember to change the `title` and `description` to refer to your bidder name instead of our fictional BidderA example. + +When choosing your parameter names, please consider aligning with the OpenRTB 2.x standard by using lower case letters without camel casing or special characters. In addition to the examples listed below, please refer to [existing bidder parameter files](https://github.com/prebid/prebid-server-java/tree/master/src/main/resources/static/bidder-params) for guidance. @@ -217,13 +295,14 @@ In addition to the examples listed below, please refer to [existing bidder param ```json { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Foo Adapter Params", - "description": "A schema which validates params accepted by the Foo adapter", + "title": "BidderA Adapter Params", + "description": "A schema which validates params accepted by the BidderA adapter", "type": "object", "properties": {} } ``` +
        @@ -232,8 +311,8 @@ In addition to the examples listed below, please refer to [existing bidder param ```json { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Foo Adapter Params", - "description": "A schema which validates params accepted by the Foo adapter", + "title": "BidderA Adapter Params", + "description": "A schema which validates params accepted by the BidderA adapter", "type": "object", "properties": { @@ -247,6 +326,7 @@ In addition to the examples listed below, please refer to [existing bidder param "required": ["placementId"] } ``` +
        @@ -255,8 +335,8 @@ In addition to the examples listed below, please refer to [existing bidder param ```json { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Foo Adapter Params", - "description": "A schema which validates params accepted by the Foo adapter", + "title": "BidderA Adapter Params", + "description": "A schema which validates params accepted by the BidderA adapter", "type": "object", "properties": { @@ -274,6 +354,7 @@ In addition to the examples listed below, please refer to [existing bidder param "required": ["token"] } ``` +
        @@ -282,8 +363,8 @@ In addition to the examples listed below, please refer to [existing bidder param ```json { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Foo Adapter Params", - "description": "A schema which validates params accepted by the Foo adapter", + "title": "BidderA Adapter Params", + "description": "A schema which validates params accepted by the BidderA adapter", "type": "object", "properties": { @@ -303,6 +384,7 @@ In addition to the examples listed below, please refer to [existing bidder param ] } ``` +

        @@ -334,17 +416,17 @@ public class ExtImp{bidder}{ Please follow [Java standard naming convention](https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html) for the field names (particularly for acronyms) and use `` `@JsonProperty` `` attributes to specify the JSON name, matching exactly what you defined in the bidder parameters JSON Schema. Please keep in mind that JSON is case sensitive. - ### Adapter Code -Now it's time to write the bulk of your bid adapter code. +Now it's time to write your bid adapter code. -Each adapter has its own directory (a 'package' in java parlance) for all code and tests associated with translating an OpenRTB 2.5 Bid Request to your bidding server's protocol and mapping your server's response to an OpenRTB 2.5 Bid Response. The use of separate packages provide each adapter with its own naming scope to avoid conflicts and gives the freedom to organize files as you best see fit (although we make suggestions in this guide). +Each adapter has its own directory (a 'package' in java parlance) for all code and tests associated with translating an OpenRTB 2.x Bid Request to your bidding server's protocol and mapping your server's response to an OpenRTB 2.x Bid Response. The use of separate packages provide each adapter with its own naming scope to avoid conflicts and gives the freedom to organize files as you best see fit (although we make suggestions in this guide). Create a file with the path `org.prebid.server.bidder.{bidder}/{bidder}Bidder.java`. Your bid adapter code will need to implement Bidder interface where `T` is a model which will represent HttpRequest body. -- The `Bidder` interface consisting of the `MakeRequests` method to create outgoing requests to your bidding server and the `MakeBids` method to create bid responses. -Here is a reference implementation for a bidding server which uses the OpenRTB 2.5 protocol: +- The `Bidder` interface consisting of the `MakeHttpRequests` method to create outgoing requests to your bidding server and the `MakeBids` method to create bid responses. + +Here is a reference implementation for a bidding server which uses the OpenRTB 2.x protocol: ```java package org.prebid.server.bidder.{bidder}; @@ -389,20 +471,20 @@ public class {bidder}Bidder implements Bidder { @Override public Result>> makeHttpRequests(BidRequest request) { - return Result.of(Collections.singletonList(HttpRequest.builder() + return Result.withValue(HttpRequest.builder() .method(HttpMethod.POST) .uri(endpointUrl) .headers(HttpUtil.headers()) .payload(request) .body(mapper.encode(request)) - .build()), Collections.emptyList()); + .build())); } @Override public final Result> makeBids(HttpCall httpCall, BidRequest bidRequest) { try { final BidResponse bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); - return Result.of(extractBids(httpCall.getRequest().getPayload(), bidResponse), Collections.emptyList()); + return Result.withValues(extractBids(httpCall.getRequest().getPayload(), bidResponse)); } catch (DecodeException | PreBidException e) { return Result.withError(BidderError.badServerResponse(e.getMessage())); } @@ -446,14 +528,13 @@ public class {bidder}Bidder implements Bidder { ``` +#### MakeHttpRequests -#### MakeRequests - -The `MakeRequests` method is responsible for returning zero or more HTTP requests to be sent to your bidding server. Bid adapters are forbidden from directly initiating any form of network communication and must entirely rely upon the core framework. This allows the core framework to optimize outgoing connections using a managed pool and record networking metrics. The return type `adapters.RequestData` allows your adapter to specify the HTTP method, url, body, and headers. +The `MakeHttpRequests` method is responsible for returning zero or more HTTP requests to be sent to your bidding server. Bid adapters are forbidden from directly initiating any form of network communication and must entirely rely upon the core framework. This allows the core framework to optimize outgoing connections using a managed pool and record networking metrics. The return type `adapters.RequestData` allows your adapter to specify the HTTP method, url, body, headers, and ids of the impressions in the request. This method is called once by the core framework for bid requests which have at least one valid Impression for your adapter. Impressions not configured for your adapter will be removed and are not accessible. -The argument, `request`, is the OpenRTB 2.5 Bid Request object. Extension information is stored as `com.fasterxml.jackson.databind.node.ObjectNode` byte arrays and must be converted from node to be read and/or mutated. It is *critical* to understand that the `request` object contains pointers to shared memory. If your adapter needs to alter any data referenced by a pointer then you *must* first make a shallow copy(you can do it by using toBuilder() method on model you want to change, but remember about objects like Lists and always create copy's of this data types). The exact same instance of the `request` object is also passed to the `MakeBids` method, so please be careful when mutating. It's safe to assume that `request.Imp[]` always contains at least one element and that the `request.Imp[].ext.bidder` was successfully validated by your bidder parameter JSON Schema. +The argument, `request`, is the OpenRTB 2.x Bid Request object. Extension information is stored as `com.fasterxml.jackson.databind.node.ObjectNode` byte arrays and must be converted from node to be read and/or mutated. It is *critical* to understand that the `request` object contains pointers to shared memory. If your adapter needs to alter any data referenced by a pointer then you *must* first make a shallow copy(you can do it by using toBuilder() method on model you want to change, but remember about objects like Lists and always create copy's of this data types). The exact same instance of the `request` object is also passed to the `MakeBids` method, so please be careful when mutating. It's safe to assume that `request.Imp[]` always contains at least one element and that the `request.Imp[].ext.bidder` was successfully validated by your bidder parameter JSON Schema.
        Example: Mutating banner shared memory (make a copy). @@ -468,10 +549,11 @@ The argument, `request`, is the OpenRTB 2.5 Bid Request object. Extension inform return imp.toBuilder().banner(modifiedBanner).build(); } ``` +

        -The `MakeRequests` method is expected to return a `List` object representing the HTTP calls to be sent to your bidding server and a `List errors` for any issues encountered creating them. If there are no HTTP calls or if there are no errors, please use different methods in `Result` class specific to your case. +The `MakeHttpRequests` method is expected to return a `List` object representing the HTTP calls to be sent to your bidding server and a `List errors` for any issues encountered creating them. If there are no HTTP calls or if there are no errors, please use different methods in `Result` class specific to your case. An Impression may define multiple sizes and/or multiple ad formats. If your bidding server limits requests to a single ad placement, size, or format, then your adapter will need to split the Impression into multiple calls and merge the responses. @@ -496,6 +578,7 @@ An Impression may define multiple sizes and/or multiple ad formats. If your bidd return Result.withValues(httpRequests); } ``` +

        @@ -503,7 +586,7 @@ If your bidding server supports multiple currencies, please be sure to pass thro Please ensure you forward the bid floor (`request.imp[].bidfloor`) and bid floor currency (`request.imp[].bidfloorcur`) values to your bidding server for enforcement. -There are a several values of a bid request that publishers may supply that your adapter and endpoint should be aware of. Some are defined by the OpenRTB 2.5 specification and some are defined by Prebid conventions: +There are a several values of a bid request that publishers may supply that your adapter and endpoint should be aware of. Some are defined by the OpenRTB 2.x specification and some are defined by Prebid conventions: {: .table .table-bordered .table-striped } | Parameter | Definer | Path & Description @@ -511,7 +594,7 @@ There are a several values of a bid request that publishers may supply that your | CCPA | OpenRTB | `request.regs.ext.us_privacy`
        The publisher is specifying the California Consumer Privacy Act consent string. | COPPA | OpenRTB | `request.regs.ext.us_privacy`
        The publisher is specifying the Children's Online Privacy Protection flag. | ATTS | OpenRTB | `request.device.ext.atts`
        The [App Tracking Transparency Status](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/skadnetwork.md#object-bidrequestdeviceext) set on the device (iOS only). -| SKAdNetwork | OpenRTB | `request.imp[].ext.skadn`
        The [SKAdNetwork](https://github.com/prebid/prebid-mobile-ios/issues/342) signaling to support mobile attribution when a user's IDFA is unavailable for iOS traffic. +| SKAdNetwork | OpenRTB | `request.imp[].ext.skadn`
        The [SKAdNetwork](https://github.com/prebid/prebid-mobile-ios/issues/342) signaling to support mobile attribution when a user's IDFA is unavailable for iOS traffic. | Currency | OpenRTB |`request.cur`
        The publisher is specifying the desired bid currency. The Prebid Server default is USD. | [Debug](https://github.com/prebid/prebid-server/issues/745) | Prebid | `request.ext.prebid.debug`
        The publisher is requesting verbose debugging information from Prebid Server. | [First Party Data (FPD)](https://docs.prebid.org/prebid-server/features/pbs-fpd.html)| Prebid | `request.imp[].ext.context.data.*`, `request.app.ext.data.*`, `request.site.ext.data.*`, `request.user.ext.data.*`
        The publisher may provide first party data (e.g. keywords). @@ -520,7 +603,8 @@ There are a several values of a bid request that publishers may supply that your | Supply Chain | OpenRTB | `request.source.ext.schain`
        The publisher's declaration of all parties who are selling or reselling the bid request. | Test | OpenRTB | `request.test`
        The publisher is sending non-production traffic which also enables verbose debugging information from Prebid Server. | Video | OpenRTB | `request.imp[].video`
        The publisher is specifying video ad requirements or preferences. -| Rewarded inventory | OpenRTB | `request.imp[].ext.prebid.is_rewarded_inventory`
        Signal to indicate the inventory is rewarded. +| Rewarded inventory | OpenRTB | `request.imp[].ext.prebid.is_rewarded_inventory`
        Signal to indicate the inventory is rewarded. +| Digital Services Act (DSA) | OpenRTB | `request.regs.ext.dsa`
        The publisher will indicate that a transaction is subject to DSA and whether they will render the required transparency information themselves. ##### Request compression @@ -537,7 +621,7 @@ private static MultiMap resolveHeaders() { #### Response -The `MakeBids` method in your adapter is responsible for parsing the bidding server's response and mapping it to the [OpenRTB 2.5 Bid Response object model](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32). +The `MakeBids` method in your adapter is responsible for parsing the bidding server's response and mapping it to the [OpenRTB 2.x Bid Response](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#objectbidresponse). This method is called for each response received from your bidding server within the bidding window (`request.tmax`). If there are no requests or if all requests time out, the `MakeBids` method will not be called. @@ -546,11 +630,11 @@ It's *imperative* to include all required information in the response for your b The first argument, `HttpCall`, is the HTTP response received from your bidding(contains the status code, body, and headers) and also specific to your bid `HttpRequest` request. If your bidding server replies with a GZIP encoded body, it will be automatically decompressed. -The second argument, `request`, is the exact same OpenRTB 2.5 Bid Request object provided to (and potentially mutated by) the `MakeRequests` method. The information in the `request` may be useful when detecting the media type. +The second argument, `request`, is the exact same OpenRTB 2.x Bid Request object provided to (and potentially mutated by) the `MakeRequests` method. The information in the `request` may be useful when detecting the media type. -The `MakeBids` method is expected to return an `Result` object with one or more bids mapped from your bidding server's response. This may be as simple as decorating an OpenRTB 2.5 Bid Response with a some Prebid Server metadata (such as the media type) or more complicated mapping logic depending on your server's response format. +The `MakeBids` method is expected to return an `Result` object with one or more bids mapped from your bidding server's response. This may be as simple as decorating an OpenRTB 2.x Bid Response with a some Prebid Server metadata (such as the media type) or more complicated mapping logic depending on your server's response format. -Please review the entire [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=32) documentation to fully understand the response object model and expectations. We've summarized some common fields below. Data which is listed as required is enforced by the core framework and cannot be omitted. +Please review the entire [OpenRTB 2.x Bid Response](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#objectbidresponse) documentation to fully understand the response object model and expectations. We've summarized some common fields below. Data which is listed as required is enforced by the core framework and cannot be omitted. {: .table .table-bordered .table-striped } | BidderResponse Path | Scope | Description @@ -566,6 +650,7 @@ Please review the entire [OpenRTB 2.5 Bid Response](https://www.iab.com/wp-conte | `.Bids[].Bid.W` | Optional | Width of the creative in pixels. | `.Bids[].Bid.H` | Optional | Height of the creative in pixels. | `.Bids[].Bid.Ext.Prebid.Meta` | Optional | Embedded JSON containing Prebid metadata (see below) or custom information. +| `.Bids[].Bid.Ext.Dsa` | Optional | Embedded JSON containing DSA Transparency information (see below). {: .alert.alert-info :} We recommend resolving creative OpenRTB macros in your adapter. Otherwise, AUCTION_PRICE will eventually get resolved by the [Prebid Universal Creative](https://github.com/prebid/prebid-universal-creative), but by then the bid price will be in the ad server currency and quantized by the price granularity. @@ -583,60 +668,106 @@ If you'd like to support Long Form Video Ad Pods, then you'll need to provide th {: .alert.alert-info :} Either `.Bids[].BidVideo.PrimaryCategory` or `.Bids[].Bid.Cat` should be provided. -Prebid has historically struggled with sharing granular bid response data with publishers, analytics, and reporting systems. To address this, we've introduced a standard object model. We encourage adapters to provide as much information as possible in the bid response. +##### Metadata + +In order to share granular bid response data with publishers, analytics, and reporting systems, we've introduced a standard object model. We encourage adapters to provide as much information as possible in the bid response. {: .alert.alert-danger :} -Bid metadata will be *required* in Prebid.js 5.X+ release, specifically for bid.ADomain and MediaType. We recommend making sure your adapter sets these values or Prebid.js may throw out the bid. +Bid metadata may be required in a future Prebid.js release. The AdvertiserDomains field and the DChain object are particularly useful. We recommend ensuring your adapter sets these fields or Prebid.js may reject your bid. + +{: .table .table-bordered .table-striped } +| Path | Description +| - | - +| `.AdvertiserDomains` | Domains for the landing page(s) aligning with the OpenRTB `adomain` field. +| `.AdvertiserID` | Bidder-specific advertiser id. +| `.AdvertiserName` | Bidder-specific advertiser name. +| `.AgencyID` | Bidder-specific agency id. +| `.AgencyName` | Bidder-specific agency name. +| `.BrandID` | Bidder-specific brand id for advertisers with multiple brands. +| `.BrandName` | Bidder-specific brand name. +| `.DChain` | Demand chain object. +| `.DemandSource` | Bidder-specific demand source. Some adapters may functionally serve multiple SSPs or exchanges, and this specifies which. +| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe. +| `.NetworkID` | Bidder-specific network/DSP id. +| `.NetworkName` | Bidder-specific network/DSP name. +| `.RendererName` | Name of the desired renderer for the creative. +| `.RendererVersion` | Version of the desired renderer for the creative. +| `.RendererUrl` | Url of the desired renderer for the creative. +| `.PrimaryCategoryID` | Primary IAB category id. +| `.SecondaryCategoryIDs` | Secondary IAB category ids. + +##### DSA + +See the [IAB's DSA protocol](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/extensions/community_extensions/dsa_transparency.md) for background information. + +This response object allows DSPs to provide publishers with requested transparency and render information. Your bid adapter should place it in the standard ORTB location. The Java object is .Bids[].Bid.Ext.Dsa. Fields within this object: {: .table .table-bordered .table-striped } -| Path | Description | -| - | - | -| `.NetworkID` | Bidder-specific network/DSP id | -| `.NetworkName` | Bidder-specific network/DSP name | -| `.AgencyID` | Bidder-specific agency id | -| `.AgencyName` | Bidder-specific agency name | -| `.AdvertiserID` | Bidder-specific advertiser id | -| `.AdvertiserName` | Bidder-specific advertiser name | -| `.BrandID` | Bidder-specific brand id for advertisers with multiple brands | -| `.BrandName` | Bidder-specific brand name | -| `.dchain` | Demand Chain Object -| `.PrimaryCategoryID` | Primary IAB category id | -| `.SecondaryCategoryIDs` | Secondary IAB category ids | -| `.MediaType` | Either `banner`, `audio`, `video`, or `native`. This is used in the scenario where a bidder responds with a mediatype different than the stated type. e.g. native when the impression is for a banner. One use case is to help publishers determine whether the creative should be wrapped in a safeframe. | +| Path | Description +| - | - +| `.Behalf` | A name of whose behalf the ad is displayed. +| `.Paid` | A name of who paid for the ad. +| `.Adrender` | Flag to indicate that buyer/advertiser will render their own DSA transparency information inside the creative. +| `.Transparency` | The domains of the entities that applied user parameters and the parameters they applied.

        -### Simple Bidder Creation -Remember if your bidder does not have much specific logic beyond standard OpenRTB 2.5, you don't have to implement `Bidder` -but could choose to extend OpenrtbBidder(where T is ImpExt type), which already implements Bidder and has a default implementation of different methods. You can override each of them with your own implementation as needed. +#### Better Analytics -Here is the list of methods in OpenrtbBidder which you can override: +The [seatnonbid](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#seat-non-bid) feature allows analytics adapters to piece together what happened in the auction when there's not a bid. This can be helpful to everyone involved: the publisher can get insight into why a bidder might not be bidding, which might lead them to update bid parameters or otherwise fix a setup problem. -1) `void validateRequest(BidRequest bidRequest)` - - A hook for bidder-specific request validation if any is required. +To implement this enhanced analytics, bidders just need to link errors and non-bids to a specific impression id: +1. Provide impression ids that are covered by particular http request to bidder endpoint: + When bidder creates http requests in `makeHttpRequests` method of bidder adapter class, utilize `.impIds(Set)` method of `HttpRequest` class. (hint, if bidder uses ortb as its main protocol it can utilize `impIds` method of `BidderUtil` class), for example:
        -2) `Imp modifyImp(Imp imp, T impExt)` - - A hook for bidder-specific impression changes, impression validation and impression extension validation if any are required + ```java + HttpRequest.builder() + .method(HttpMethod.POST) + .uri(uri) + .body(mapper.encodeToBytes(bidRequest)) + .headers(headers) + .payload(bidRequest) + .impIds(BidderUtil.impIds(bidRequest)) + .build(); + ``` + or more generic case:
        -3) `void modifyRequest(BidRequest bidRequest, BidRequest.BidRequestBuilder requestBuilder, List> impsWithExts)` - - A hook for any request changes other than Imps (although Impressions can be modified as well) + ```java + HttpRequest.builder() + .method(HttpMethod.POST) + .uri(uri) + .body(mapper.encodeToBytes(bidRequest)) + .headers(headers) + .payload(bidRequest) + .impIds(Set.of(impId1, impId2)) + .build(); + ``` +2. When bidder drops impression in `makeHttpRequests` or bid in `makeBids` methods in bidder adapter class, and emits error, it should provide ids of impressions that particular error covers. Bidder adapter can do this by utilizing `BidderError.of(String message, Type type, Set impIds)` method of `BidderError` class, or by creating/using specialized methods of this class, for example: -4) `BidType getBidType(String impId, List imps)` - - A hook for resolving bidder-specific bid type. + ```java + BidderError.rejectedIpf( + "Bid with id '%s' was rejected by floor enforcement: price %s is below the floor %s" + .formatted(bid.getId(), price, floor), impId); + ``` ---- -Using this class(OpenrtbBidder), you can define whether the outgoing -requests can contain multiple impressions (`RequestCreationStrategy.SINGLE_REQUEST`) or whether each each request should have only one impression (`RequestCreationStrategy.REQUEST_PER_IMP`). Pass this value to parent constructor as the second argument. + (Note: list of specialized methods like this will increase as needed, but bidders can contribute by extending this list.)

        or more generic case:
        -Check the class file to find which methods are overridable. + ```java + BidderError.of( + "Impression with id '%s' was dropped due to ...".formatted(impId), + BidderError.Type.bad_input, + Collections.sinleton(impId)); + ``` -### Create Config Class +Note: If bidder provides PBS with impression id that was not present in provided `BidRequest`, PBS will just ignore it. + +### Create Config Class Go to `org.prebid.server.spring.config.bidder` and create new class `Configuration{bidder}` -with the following content +with the following content ```java package org.prebid.server.spring.config.bidder; @@ -645,13 +776,9 @@ import org.prebid.server.bidder.BidderDeps; import org.prebid.server.bidder.{bidder}.{bidder}Bidder; import org.prebid.server.json.JacksonMapper; import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; -import org.prebid.server.spring.config.bidder.model.UsersyncConfigurationProperties; import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; -import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; import org.prebid.server.spring.env.YamlPropertySourceFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -665,18 +792,7 @@ import javax.validation.constraints.NotBlank; public class {bidder}Configuration { private static final String BIDDER_NAME = "{bidder}"; - - @Value("${external-url}") - @NotBlank - private String externalUrl; - - @Autowired - private JacksonMapper mapper; - - @Autowired - @Qualifier("{bidder}ConfigurationProperties") - private BidderConfigurationProperties configProperties; - + @Bean("{bidder}ConfigurationProperties") @ConfigurationProperties("adapters.{bidder}") BidderConfigurationProperties configurationProperties() { @@ -684,14 +800,14 @@ public class {bidder}Configuration { } @Bean - BidderDeps {bidder}BidderDeps() { - final UsersyncConfigurationProperties usersync = configProperties.getUsersync(); - + BidderDeps{bidder}BidderDeps(BidderConfigurationProperties {bidder}ConfigurationProperties, + @NotBlank @Value("${external-url}") String externalUrl, + JacksonMapper mapper) { + return BidderDepsAssembler.forBidder(BIDDER_NAME) - .withConfig(configProperties) - .bidderInfo(BidderInfoCreator.create(configProperties)) - .usersyncerCreator(UsersyncerCreator.create(usersync, externalUrl)) - .bidderCreator(() -> new {bidder}Bidder(configProperties.getEndpoint(), mapper)) + .withConfig({bidder}ConfigurationProperties) + .usersyncerCreator(UsersyncerCreator.create(externalUrl)) + .bidderCreator(config -> new {bidder}Bidder(config.getEndpoint(), mapper)) .assemble(); } } @@ -709,58 +825,155 @@ Here are 3 key points to consider: If you need to convert floor prices from one currency into something your endpoint expects, you can use the convertCurrency function from CurrencyConversionService component. -1) Inject CurrencyConversionService to your {bidder}Configuration class and pass it to your bidder constructor. +1. Inject CurrencyConversionService to your {bidder}Configuration class and pass it to your bidder constructor. -```java -@Autowired -private CurrencyConversionService currencyConversionService; + ```java + @Autowired + private CurrencyConversionService currencyConversionService; -... + ... -.bidderCreator(() -> new {bidder}Bidder(configProperties.getEndpoint(), currencyConversionService, mapper)) -``` + .bidderCreator(() -> new {bidder}Bidder(configProperties.getEndpoint(), currencyConversionService, mapper)) + ``` -2) Create additional class variable `private final CurrencyConversionService currencyConversionService;` and update constructor in your {bidder}Bidder class to set this variable. +2. Create additional class variable `private final CurrencyConversionService currencyConversionService;` and update constructor in your {bidder}Bidder class to set this variable. -```java -private final CurrencyConversionService currencyConversionService; -private final String endpointUrl; -private final JacksonMapper mapper; + ```java + private final CurrencyConversionService currencyConversionService; + private final String endpointUrl; + private final JacksonMapper mapper; -public {bidder}Bidder(String endpointUrl, CurrencyConversionService currencyConversionService, JacksonMapper mapper) { - this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); - this.currencyConversionService = Objects.requireNonNull(currencyConversionService); - this.mapper = Objects.requireNonNull(mapper); - } -``` + public {bidder}Bidder(String endpointUrl, CurrencyConversionService currencyConversionService, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.currencyConversionService = Objects.requireNonNull(currencyConversionService); + this.mapper = Objects.requireNonNull(mapper); + } + ``` -3) Use `currencyConversionService.convertCurrency(BigDecimal price, BidRequest bidRequest, String fromCurrency, String toCurrency)` for currency converting in {bidder}Bidder class. +3. Use `currencyConversionService.convertCurrency(BigDecimal price, BidRequest bidRequest, String fromCurrency, String toCurrency)` for currency converting in {bidder}Bidder class. -
        - Example: Updating bidFloor currency. +
        + Example: Updating bidFloor currency. -```java - private Imp makeImp(Imp imp, BidRequest bidRequest) { - return imp.toBuilder().bidfloor(resolveBidFloor(imp, bidRequest)).build(); - } + ```java + private Imp makeImp(Imp imp, BidRequest bidRequest) { + return imp.toBuilder().bidfloor(resolveBidFloor(imp, bidRequest)).build(); + } - private BigDecimal resolveBidFloor(Imp imp, BidRequest bidRequest) { - final String bidFloorCurrency = resolveBidFloorCurrency(imp); - final BigDecimal bidFloor = imp.getBidfloor(); - return convertBidFloorCurrency(imp, bidRequest, bidFloor, bidFloorCurrency); - } - - private BigDecimal convertBidFloorCurrency(Imp imp, BidRequest bidRequest, BigDecimal bidFloor, String bidFloorCurrency) { - try { - return currencyConversionService.convertCurrency(bidFloor, bidRequest, - bidFloorCurrency, "NEEDED_CURRENCY"); - } catch (PreBidException ex) { - throw new PreBidException(String.format("Failed to convert bidfloor with a reason: %s", ex.getMessage())); + private BigDecimal resolveBidFloor(Imp imp, BidRequest bidRequest) { + final String bidFloorCurrency = resolveBidFloorCurrency(imp); + final BigDecimal bidFloor = imp.getBidfloor(); + return convertBidFloorCurrency(imp, bidRequest, bidFloor, bidFloorCurrency); + } + + private BigDecimal convertBidFloorCurrency(Imp imp, BidRequest bidRequest, BigDecimal bidFloor, String bidFloorCurrency) { + try { + return currencyConversionService.convertCurrency(bidFloor, bidRequest, + bidFloorCurrency, "NEEDED_CURRENCY"); + } catch (PreBidException ex) { + throw new PreBidException(String.format("Failed to convert bidfloor with a reason: %s", ex.getMessage())); + } } - } -``` -
        -

        + ``` + +
        +

        + +### Price Floors + +Prebid server manages the OpenRTB floors values (imp.bidfloor and imp.bidfloorcur) at the core level using the [Price Floors feature](/prebid-server/features/pbs-floors.html). Minimally, bid adapters are expected to read these values and pass them to the endpoint. + +However, as described in the feature documentation, some adapters may benefit from access to more granular values. The primary use case is for multi-format as [detailed in the document](/prebid-server/features/pbs-floors.html#bid-adapter-floor-interface). To implement this, you may use the overloaded `getFloor()` function which can use more specific values for certain fields. + +Here are the instructions: + +1. Inject `PriceFloorResolver` to your {bidder}Configuration class and pass it to your bidder constructor. + + ```java + BidderDeps {bidder}BidderDeps(BidderConfigurationProperties {bidder}ConfigurationProperties, + @NotBlank @Value("${external-url}") String externalUrl, + PriceFloorResolver floorResolver, + JacksonMapper mapper) { + + ... + + .bidderCreator(() -> new {bidder}Bidder(configProperties.getEndpoint(), floorResolver, mapper)) + ``` + +2. Create an additional class variable `private final PriceFloorResolver floorResolver` and update constructor in your {bidder}Bidder class to set this variable. + + ```java + private final PriceFloorResolver floorResolver; + private final String endpointUrl; + private final JacksonMapper mapper; + + public {bidder}Bidder(String endpointUrl, PriceFloorResolver floorResolver, JacksonMapper mapper) { + this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl)); + this.floorResolver = Objects.requireNonNull(floorResolver); + this.mapper = Objects.requireNonNull(mapper); + } + ``` + +3. Use `floorResolver.resolve(BidRequest bidRequest, + PriceFloorRules floorRules, + Imp imp, + ImpMediaType mediaType, + Format format, + List warnings)` for resolving specific floor values in your {bidder}Bidder class. + +
        + Example: Updating bidFloor values. + + ```java + private Imp makeImp(Imp imp, BidRequest bidRequest) { + final PriceFloorResult priceFloorResult = resolvePriceFloors( + bidRequest, + imp, // com.iab.openrtb.request.Imp + specificMediatype, // org.prebid.server.proto.openrtb.ext.request.ImpMediaType + specificFormat, // com.iab.openrtb.request.Format (size) + priceFloorsWarnings); + + return imp.toBuilder() + .bidfloor(ObjectUtil.getIfNotNull(priceFloorResult, PriceFloorResult::getFloorValue)) + .bidfloorcur(ObjectUtil.getIfNotNull(priceFloorResult, PriceFloorResult::getCurrency)) + .build(); + } + + private PriceFloorResult resolvePriceFloors(BidRequest bidRequest, + Imp imp, + ImpMediaType mediaType, + Format format, + List warnings) { + + return floorResolver.resolve( + bidRequest, + extractFloorRules(bidRequest), + imp, + mediaType, + format, + warnings); + } + ``` + +
        + +4. Let the Price Floors feature know about the floors you're using. To do that, enrich BidderBid with `priceFloorInfo` + + ```java + private static BidderBid createBidderBid(Bid bid, Imp imp, BidType bidType, String currency) { + + return BidderBid.builder() + .bid(bid) + .type(bidType) + .bidCurrency(currency) + .priceFloorInfo(imp != null ? PriceFloorInfo.of(imp.getBidfloor(), imp.getBidfloorcur()) : null) + .build(); + } + ``` + +

        + +5. Test: ## Test Your Adapter @@ -777,28 +990,27 @@ This command will prepare code style checks, compile, run test and create jar fi Create class `{bidder}BidderTest` in the same package as your `{bidder}Bidder` class, but in test directory. Here you should add unit tests to your bid code. Try to create models by using following methods specified to your case in your test class - ```java private static BidRequest givenBidRequest( - Function bidRequestCustomizer, - Function impCustomizer) { + UnaryOperator bidRequestCustomizer, + UnaryOperator impCustomizer) { return bidRequestCustomizer.apply(BidRequest.builder() .imp(singletonList(givenImp(impCustomizer)))) .build(); } - private static BidRequest givenBidRequest(Function impCustomizer) { + private static BidRequest givenBidRequest(UnaryOperator impCustomizer) { return givenBidRequest(identity(), impCustomizer); } - private static Imp givenImp(Function impCustomizer) { + private static Imp givenImp(UnaryOperator impCustomizer) { return impCustomizer.apply(Imp.builder() .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImp{bidder}.of(param, secondParam))))) .build(); } - private static BidResponse givenBidResponse(Function bidCustomizer) { + private static BidResponse givenBidResponse(UnaryOperator bidCustomizer) { return BidResponse.builder() .seatbid(singletonList(SeatBid.builder().bid(singletonList(bidCustomizer.apply(Bid.builder()).build())) .build())) @@ -814,7 +1026,8 @@ private static BidRequest givenBidRequest( ``` ### Bidder Integration Tests -Go to `test-application.properties` file and add folowing properties +Go to `test-application.properties` file and add following properties + ```yaml adapters.{bidder}.enabled=true adapters.{bidder}.endpoint=http://localhost:8090/{bidder}-exchange @@ -824,278 +1037,251 @@ adapters.{bidder}.usersync.url=//{bidder}-usersync Go to test resources `org.prebid.server.it.openrtb2` and create directory with `{bidder}` name. Add files with content specific to your case: -1) `test-auction-{bidder}-request.json` -```json -{ - "id": "tid", - "imp": [ +1. `test-auction-{bidder}-request.json` + + ```json { - "id": "impId001", - "banner": { - "format": [ - { - "w": 300, - "h": 250 + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "{bidder}": { + "param": "paramValue" + } } - ] + } + ], + "device": { + "pxratio": 4.2, + "dnt": 2, + "language": "en", + "ifa": "ifaId" }, - "ext": { - "{bidder}": { - "param": "paramValue" + "site": { + "publisher": { + "id": "publisherId" } - } - } - ], - "device": { - "pxratio": 4.2, - "dnt": 2, - "language": "en", - "ifa": "ifaId" - }, - "site": { - "publisher": { - "id": "publisherId" - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "ext": { - "prebid": { - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 + }, + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] } - ] + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000 } }, - "cache": { - "bids": {} - }, - "auctiontimestamp": 1000 - } - }, - "regs": { - "ext": { - "gdpr": 0 + "regs": { + "ext": { + "gdpr": 0 + } + } } - } -} -``` -2) `test-auction-{bidder}-response.json` -```json -{ - "id": "tid", - "seatbid": [ + ``` + +2. `test-auction-{bidder}-response.json` + + ```json { - "bid": [ + "id": "tid", + "seatbid": [ { - "id": "bid001", - "impid": "impId001", - "price": 3.33, - "adm": "adm001", - "adid": "adid001", - "cid": "cid001", - "crid": "crid001", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "3.30", - "hb_size_{bidder}": "300x250", - "hb_bidder_{bidder}": "{bidder}", - "hb_cache_path": "{{ cache.path }}", - "hb_size": "300x250", - "hb_cache_host_{bidder}": "{{ cache.host }}", - "hb_cache_path_{bidder}": "{{ cache.path }}", - "hb_cache_id_{bidder}": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "hb_bidder": "{bidder}", - "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "hb_pb_{bidder}": "3.30", - "hb_cache_host": "{{ cache.host }}" - }, - "cache": { - "bids": { - "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", - "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adm": "adm001", + "adid": "adid001", + "cid": "cid001", + "crid": "crid001", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner", + "targeting": { + "hb_pb": "3.30", + "hb_size_{bidder}": "300x250", + "hb_bidder_{bidder}": "{bidder}", + "hb_cache_path": "{{ cache.path }}", + "hb_size": "300x250", + "hb_cache_host_{bidder}": "{{ cache.host }}", + "hb_cache_path_{bidder}": "{{ cache.path }}", + "hb_cache_id_{bidder}": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_bidder": "{bidder}", + "hb_cache_id": "f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "hb_pb_{bidder}": "3.30", + "hb_cache_host": "{{ cache.host }}" + }, + "cache": { + "bids": { + "url": "{{ cache.resource_url }}f0ab9105-cb21-4e59-b433-70f5ad6671cb", + "cacheId": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" + } + } } } } - } + ], + "seat": "{bidder}", + "group": 0 } ], - "seat": "{bidder}", - "group": 0 + "cur": "USD", + "ext": { + "responsetimemillis": { + "{bidder}": " {bidder}.response_time_ms }}", + "cache": "{{ cache.response_time_ms }}" + }, + "prebid": { + "auctiontimestamp": 1000 + }, + "tmaxrequest": 5000 + } } - ], - "cur": "USD", - "ext": { - "responsetimemillis": { - "{bidder}": " {bidder}.response_time_ms }}", - "cache": "{{ cache.response_time_ms }}" - }, - "prebid": { - "auctiontimestamp": 1000 - }, - "tmaxrequest": 5000 - } -} -``` + ``` -3) `test-{bidder}-bid-request.json` -```json -{ - "id": "tid", - "imp": [ +3. `test-{bidder}-bid-request.json` + + ```json { - "id": "impId001", - "banner": { - "format": [ - { - "w": 300, - "h": 250 + "id": "tid", + "imp": [ + { + "id": "impId001", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "param": "paramValue" + } } - ] - }, - "ext": { - "bidder": { - "param": "paramValue" } - } - } - ], - "site": { - "domain": "example.com", - "page": "http://www.example.com", - "publisher": { - "id": "publisherId" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "dnt": 2, - "ip": "193.168.244.1", - "pxratio": 4.2, - "language": "en", - "ifa": "ifaId" - }, - "user": { - "buyeruid" : "BTW-UID" - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "source": { - "fd": 1, - "tid": "tid" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "ext": { - "prebid": { - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] + ], + "site": { + "domain": "example.com", + "page": "http://www.example.com", + "publisher": { + "id": "publisherId" }, - "includewinners": true, - "includebidderkeys": true + "ext": { + "amp": 0 + } + }, + "device": { + "ua": "userAgent", + "dnt": 2, + "ip": "193.168.244.1", + "pxratio": 4.2, + "language": "en", + "ifa": "ifaId" + }, + "user": { + "buyeruid" : "BTW-UID" }, - "cache": { - "bids": {} + "at": 1, + "tmax": 5000, + "cur": [ + "USD" + ], + "source": { + "fd": 1, + "tid": "tid" + }, + "regs": { + "ext": { + "gdpr": 0 + } }, - "auctiontimestamp": 1000, - "channel" : { - "name" : "web" + "ext": { + "prebid": { + "targeting": { + "pricegranularity": { + "precision": 2, + "ranges": [ + { + "max": 20, + "increment": 0.1 + } + ] + }, + "includewinners": true, + "includebidderkeys": true + }, + "cache": { + "bids": {} + }, + "auctiontimestamp": 1000, + "channel" : { + "name" : "web" + } + } } } - } -} -``` -4) `test-{bidder}-bid-response.json` -```json -{ - "id": "tid", - "seatbid": [ + ``` + +4. `test-{bidder}-bid-response.json` + + ```json { - "bid": [ + "id": "tid", + "seatbid": [ { - "id": "bid001", - "impid": "impId001", - "price": 3.33, - "adid": "adid001", - "crid": "crid001", - "cid": "cid001", - "adm": "adm001", - "h": 250, - "w": 300 + "bid": [ + { + "id": "bid001", + "impid": "impId001", + "price": 3.33, + "adid": "adid001", + "crid": "crid001", + "cid": "cid001", + "adm": "adm001", + "h": 250, + "w": 300 + } + ] } ] } - ] -} - -``` -5) `test-cache-{bidder}-request.json` -```json -{ - "puts": [ - { - "type": "json", - "value": { - "id": "bid001", - "impid": "impId001", - "price": 3.33, - "adm": "adm001", - "adid": "adid001", - "cid": "cid001", - "crid": "crid001", - "w": 300, - "h": 250 - } - } - ] -} -``` - -6) `test-cache-{bidder}-response.json` -```json -{ - "responses": [ - { - "uuid": "f0ab9105-cb21-4e59-b433-70f5ad6671cb" - } - ] -} -``` - + ``` Create class `{bidder}Test`in test directory in package `org.prebid.server.it`. Extend `IntegrationTest` class with following content + ```java package org.prebid.server.it; @@ -1103,8 +1289,6 @@ import io.restassured.response.Response; import org.json.JSONException; import org.junit.Test; import org.junit.runner.RunWith; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException; @@ -1114,7 +1298,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static io.restassured.RestAssured.given; import static java.util.Collections.singletonList; @RunWith(SpringRunner.class) @@ -1124,37 +1307,19 @@ public class {bidder}Test extends IntegrationTest { public void openrtb2AuctionShouldRespondWithBidsFrom{bidder}() throws IOException, JSONException { // given WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/{bidder}-exchange")) - .withHeader("Accept", equalTo("application/json")) - .withHeader("Content-Type", equalTo("application/json;charset=UTF-8")) .withRequestBody(equalToJson(jsonFrom("openrtb2/{bidder}/test-{bidder}-bid-request.json"))) .willReturn(aResponse().withBody(jsonFrom("openrtb2/{bidder}/test-{bidder}-bid-response.json")))); - // pre-bid cache - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) - .withRequestBody(equalToJson(jsonFrom("openrtb2/{bidder}/test-cache-{bidder}-request.json"))) - .willReturn(aResponse().withBody(jsonFrom("openrtb2/{bidder}/test-cache-{bidder}-response.json")))); - // when - final Response response = given(SPEC) - .header("Referer", "http://www.example.com") - .header("X-Forwarded-For", "193.168.244.1") - .header("User-Agent", "userAgent") - .header("Origin", "http://www.example.com") - // this uids cookie value stands for {"uids":{"{bidder}":"BTW-UID"}} - .cookie("uids", "eyJ1aWRzIjp7ImJldHdlZW4iOiJCVFctVUlEIn19") - .body(jsonFrom("openrtb2/{bidder}/test-auction-{bidder}-request.json")) - .post("/openrtb2/auction"); + final Response response = responseFor("openrtb2/{bidder}/test-auction-{bidder}-request.json", + Endpoint.OPENRTB2_AUCTION); // then - final String expectedAuctionResponse = openrtbAuctionResponseFrom( - "openrtb2/{bidder}/test-auction-{bidder}-response.json", - response, singletonList("{bidder}")); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), JSONCompareMode.NON_EXTENSIBLE); + assertJsonEquals("openrtb2/{bidder}/test-auction-{bidder}-response.json", response, singletonList("{bidder}")); } } - ``` + Uids for cookie you can create using [this link](https://www.base64encode.org/) ### Manual Tests @@ -1173,19 +1338,21 @@ The next time you use `/openrtb2/auction`, the OpenRTB request sent to your Bidd Human readable documentation for bid adapters is required in the separate [prebid.github.io](https://github.com/prebid/prebid.github.io) repository. We will not merge your bid adapter until you've at least opened a documentation PR and comment with a link to it. -1. If you already have a Prebid.js bid adapter, update your existing bidder file in https://github.com/prebid/prebid.github.io/tree/master/dev-docs/modules to add the `pbs: true` variable in the header section. If your Prebid Server bidding parameters are different from your Prebid.js parameters, please include the differences in this document for publishers to be aware. -1. If you don't have a Prebid.js bid adapter, create a new file in https://github.com/prebid/prebid.github.io/tree/master/dev-docs/modules using this template: +1. If you already have a Prebid.js bid adapter, update your existing bidder file in [github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders) to add the `pbs: true` variable in the header section. If your Prebid Server bidding parameters are different from your Prebid.js parameters, please include the differences in this document for publishers to be aware. +1. If you don't have a Prebid.js bid adapter, create a new file in [github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders](https://github.com/prebid/prebid.github.io/tree/master/dev-docs/bidders) using this template: -``` +```markdown --- layout: bidder title: {bidder} description: Prebid {Bidder} Bidder Adapter biddercode: {bidder} -gdpr_supported: true/false +tcfeu_supported: true/false gvl_id: 111 +dsa_supported: true/false usp_supported: true/false coppa_supported: true/false +gpp_sids: tcfeu, tcfca, usnat, usstate_all, usp schain_supported: true/false dchain_supported: true/false userId: @@ -1198,9 +1365,12 @@ pbjs: true/false pbs: true/false pbs_app_supported: true/false prebid_member: true/false +multiformat_supported: will-bid-on-any, will-bid-on-one, will-not-bid +ortb_blocking_supported: true/partial/false +privacy_sandbox: no or comma separated list of `paapi`, `topics` --- -### Note: +### Registration The Example Bidding adapter requires setup before beginning. Please contact us at setup@example.com @@ -1211,25 +1381,30 @@ The Example Bidding adapter requires setup before beginning. Please contact us a |---------------|----------|--------------|-----------|----------| | `placementId` | required | Placement ID | `'11111'` | `string` | ``` + Notes on the metadata fields: + - Add `pbs: true`. If you also have a [Prebid.js bid adapter](/dev-docs/bidder-adaptor.html), add `pbjs: true`. Default is false for both. - If you're on the IAB's Global Vendor List, place your ID in `gvl_id`. No default. -- If you support GDPR and have a GVL ID, you may add `gdpr_supported: true`. Default is false. -- If you support the US Privacy consentManagementUsp module, add `usp_supported: true`. Default is false. +- If you support the IAB's TCF-EU consent string format and have a GVL ID, you may add `tcfeu_supported: true`. Default is false. +- If you support the IAB's US Privacy consent string format, add `usp_supported: true`. Default is false. - If you support one or more userId modules, add `userId: (list of supported vendors)`. Default is none. -- If you support video and/or native mediaTypes add `media_types: video, native`. Note that display is added by default. If you don't support display, add "no-display" as the first entry, e.g. `media_types: no-display, native`. No defaults. -- If you support COPPA, add `coppa_supported: true`. Default is false. +- If you support video, native, or audio mediaTypes add `media_types: video, native, audio`. Note that display is added by default. If you don't support display, add "no-display" as the first entry, e.g. `media_types: no-display, native`. No defaults. +- If you support the COPPA flag, add `coppa_supported: true`. Default is false. +- If you support sections within the IAB's GPP consent string, add `gpp_sids:' and then which sections you support: tcfeu, tcfca, usnat, usstate_all, usp - If you support the [supply chain](/dev-docs/modules/schain.html) feature, add `schain_supported: true`. Default is false. - If you support adding a demand chain on the bid response, add `dchain_supported: true`. Default is false. - If your bidder doesn't work well with safeframed creatives, add `safeframes_ok: false`. This will alert publishers to not use safeframed creatives when creating the ad server entries for your bidder. No default. - If your bidder supports mobile apps, set `pbs_app_supported`: true. No default value. - If your bidder supports deals, set `deals_supported: true`. No default value. - If your bidder supports floors, set `floors_supported: true`. No default value. -- If your bidder supports first party data, set `fpd_supported: true`. No default value. +- If you support first party data, you must document what exactly is supported and then you may set `fpd_supported: true`. No default value. +- If you support any OpenRTB blocking parameters, you must document what exactly is supported and then you may set `ortb_blocking_supported` to ‘true’,’partial’, or ‘false’. No default value. In order to set ‘true’, you must support: bcat, badv, battr, and bapp. +- Let publishers know how you support multiformat requests -- those with more than one mediatype (e.g. both banner and video). Here are the options: will-bid-on-any, will-bid-on-one, will-not-bid - If you're a member of Prebid.org, add `prebid_member: true`. Default is false. - ## File Checklist + - Bidder Configs - `resources/bidder-config/{bidder}.yaml` - `resources/org/prebid/server/it/test-application.properties` (test directory) @@ -1239,20 +1414,18 @@ Notes on the metadata fields: - Adapter Code - `org/prebid/server/bidder/{bidder}/{bidder}Bidder.java` - `org/prebid/server/bidder/{bidder}/{bidder}BidderTest.java` (test directory) - - `org/prebid/server/it/{bidder}Test.java` (test directory) - Integration test files + - `org/prebid/server/it/{bidder}Test.java` (test directory) - `resources/org/prebid/server/it/openrtb2/{bidder}/test-auction-{bidder}-request.json` (test directory) - `resources/org/prebid/server/it/openrtb2/{bidder}/test-auction-{bidder}-response.json` (test directory) - `resources/org/prebid/server/it/openrtb2/{bidder}/test-{bidder}-bid-request.json` (test directory) - `resources/org/prebid/server/it/openrtb2/{bidder}/test-{bidder}-bid-response.json` (test directory) - - `resources/org/prebid/server/it/openrtb2/{bidder}/test-cache-{bidder}-request.json` (test directory) - - `resources/org/prebid/server/it/openrtb2/{bidder}/test-cache-{bidder}-response.json` (test directory) - Register With The Core - `org/prebid/server/spring/config/bidder/{bidder}Configuration.java` ## Contribute -Whew! You're almost done. Thank you for taking the time to develop a Prebid Server bid adapter. When you're ready, [contribute](https://github.com/prebid/prebid-server-java/blob/master/docs/contributing.md) your new bid adapter by opening a PR to the [PBS-Java GitHub repository](https://github.com/prebid/prebid-server-java) with the name "New Adapter: {Bidder}". +Whew! You're almost done. Thank you for taking the time to develop a Prebid Server bid adapter. When you're ready, [contribute](https://github.com/prebid/prebid-server-java/blob/master/docs/developers/contributing.md) your new bid adapter by opening a PR to the [PBS-Java GitHub repository](https://github.com/prebid/prebid-server-java) with the name "New Adapter: {Bidder}". {: .alert.alert-warning :} You don't need to ask permission or open a GitHub issue before submitting an adapter. diff --git a/prebid-server/developers/module-atags.md b/prebid-server/developers/module-atags.md index 483e68af3d..f855805fc3 100644 --- a/prebid-server/developers/module-atags.md +++ b/prebid-server/developers/module-atags.md @@ -210,7 +210,7 @@ of the actual object will differ in PBS-Java and PBS-Go. "invocationresults": { "hookid": { ... } "analyticstags": [{ - ... + ... ] } ] diff --git a/prebid-server/developers/pbs-build-an-analytics-adapter.md b/prebid-server/developers/pbs-build-an-analytics-adapter.md index bb76a0b8e1..2492a872ba 100644 --- a/prebid-server/developers/pbs-build-an-analytics-adapter.md +++ b/prebid-server/developers/pbs-build-an-analytics-adapter.md @@ -62,7 +62,7 @@ In order to make Prebid Server aware of the new analytics module it needs to be ### Example {:.no_toc} -The [log module](https://github.com/prebid/prebid-server-java/blob/master/src/main/java/org/prebid/server/analytics/LogAnalyticsReporter.java) is provided as an example. This module will write dummy messages to a log. +The [log module](https://github.com/prebid/prebid-server-java/blob/c5e7782b15c3bd47267a9268fd25a21a8bf34d98/src/main/java/org/prebid/server/analytics/reporter/log/LogAnalyticsReporter.java) is provided as an example. This module will write dummy messages to a log. It can be configured with: diff --git a/prebid-server/developers/pbs-cookie-sync.md b/prebid-server/developers/pbs-cookie-sync.md index dc739375db..96bcb5e483 100644 --- a/prebid-server/developers/pbs-cookie-sync.md +++ b/prebid-server/developers/pbs-cookie-sync.md @@ -21,8 +21,8 @@ that they can be sent to each demand source as part of auction calls. Prebid Server stores bidder IDs in the `uids` cookie in the host domain. For example: -``` -{"uids":{},"tempUIDs":{"adnxs":{"uid":"4722255122219375043","expires":"2020-07-30T22:10:28.961Z"},"triplelift":{"uid":"9328941297032053459","expires":"2020-07-30T22:10:33.496Z"},"yieldone":{"uid":"8c41c3b1-ce22-44fd-9bd7-454cd79e3c91","expires":"2020-07-30T22:10:33.229Z"},"ix":{"uid":"XlV6w9HM6LYAAHx2YJ4AAACZ&476","expires":"2020-07-30T22:10:31.916Z"},"yieldmo":{"uid":"ge515bd6c7da71cdc98a","expires":"2020-07-30T22:10:32.569Z"},"adform":{"uid":"1707054018971720697","expires":"2020-07-30T22:10:30.453Z"},"brightroll":{"uid":"y-S8Fq5QZ1lwWKPeXdoZ9vSeZx47maINFrJeY53pDtokA2FlaPmwvrJg--","expires":"2020-07-30T22:10:29.867Z"},"consumable":{"uid":"ue1-sb1-aa634f4b-d618-4378-b8c3-9baa56dcb91a","expires":"2020-07-30T22:10:28.07Z"},"pubmatic":{"uid":"2ECE1904-7EB2-4C38-98A4-38E97535AA9C","expires":"2020-07-30T22:10:27.559Z"},"rubicon":{"uid":"KACWYIER-P-59CH","expires":"2020-07-30T22:22:42.432Z"},"pulsepoint":{"uid":"dcxvyKqDV5VV","expires":"2020-07-30T22:10:26.915Z"},"sovrn":{"uid":"bad97f98b08c9204fe6b9826","expires":"2020-07-30T22:10:25.588Z"},"openx":{"uid":"f1f4ac13-99f8-46da-82f8-b52c29b378e0","expires":"2020-07-30T22:10:25.93Z"}},"bday":"2020-05-18T20:01:18.934Z"} +```javascript +{"uids":{},"tempUIDs":{"adnxs":{"uid":"4722255122219375043","expires":"2020-07-30T22:10:28.961Z"},"triplelift":{"uid":"9328941297032053459","expires":"2020-07-30T22:10:33.496Z"},"yieldone":{"uid":"8c41c3b1-ce22-44fd-9bd7-454cd79e3c91","expires":"2020-07-30T22:10:33.229Z"},"ix":{"uid":"XlV6w9HM6LYAAHx2YJ4AAACZ&476","expires":"2020-07-30T22:10:31.916Z"},"yieldmo":{"uid":"ge515bd6c7da71cdc98a","expires":"2020-07-30T22:10:32.569Z"},"adform":{"uid":"1707054018971720697","expires":"2020-07-30T22:10:30.453Z"},"consumable":{"uid":"ue1-sb1-aa634f4b-d618-4378-b8c3-9baa56dcb91a","expires":"2020-07-30T22:10:28.07Z"},"pubmatic":{"uid":"2ECE1904-7EB2-4C38-98A4-38E97535AA9C","expires":"2020-07-30T22:10:27.559Z"},"rubicon":{"uid":"KACWYIER-P-59CH","expires":"2020-07-30T22:22:42.432Z"},"pulsepoint":{"uid":"dcxvyKqDV5VV","expires":"2020-07-30T22:10:26.915Z"},"sovrn":{"uid":"bad97f98b08c9204fe6b9826","expires":"2020-07-30T22:10:25.588Z"},"openx":{"uid":"f1f4ac13-99f8-46da-82f8-b52c29b378e0","expires":"2020-07-30T22:10:25.93Z"}}} ``` ## Setting the uids Cookie @@ -33,73 +33,88 @@ Here's how these IDs get placed in the cookie from Prebid.js: ![Prebid Server Cookie Sync](/assets/images/prebid-server/pbs-cookie-sync.png){:class="pb-lg-img"} +1. Prebid.js starts by calling the Prebid Server [`/cookie_sync`](/prebid-server/endpoints/pbs-endpoint-cookieSync.html), letting it know which server-side bidders will be participating in the header bidding auction. -1) Prebid.js starts by calling the Prebid Server [`/cookie_sync`](/prebid-server/endpoints/pbs-endpoint-cookieSync.html), letting it know which server-side bidders will be participating in the header bidding auction. - -``` -POST https://prebid-server.example.com/cookie_sync + ```text + POST https://prebid-server.example.com/cookie_sync -{"bidders":["bidderA","bidderB"], "gdpr":1, "gdpr_consent":"...", "us_privacy": "..."} -``` + {"bidders":["bidderA","bidderB"], "gdpr":1, "gdpr_consent":"...", "us_privacy": "..."} + ``` -2) If privacy regulations allow, Prebid Server will look at the `uids` cookie in the host domain and determine whether any bidders are missing or need to be refreshed. It responds with an array of pixel syncs. e.g. +2. If privacy regulations allow, Prebid Server will look at the `uids` cookie in the host domain and determine whether any bidders are missing or need to be refreshed. It responds with an array of pixel syncs. e.g. -``` -{"status":"ok","bidder_status":[{"bidder":"bidderA","no_cookie":true,"usersync":{"url":"//biddera.com/getuid?https%3A%2F%2Fprebid-server.example.com%2Fsetuid%3Fbidder%3DbidderA%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D%24UID","type":"redirect","supportCORS":false}},{"bidder":"bidderB","no_cookie":true,"usersync":{"url":"https://bidderB.com/u/match?gdpr=&euconsent=&us_privacy=&redir=https%3A%2F%2Fprebid-server.example.com%2Fsetuid%3Fbidder%3DbidderB%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D","type":"redirect","supportCORS":false}}]} -``` + ```javascript + {"status":"ok","bidder_status":[{"bidder":"bidderA","no_cookie":true,"usersync":{"url":"//biddera.com/getuid?https%3A%2F%2Fprebid-server.example.com%2Fsetuid%3Fbidder%3DbidderA%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D%24UID","type":"redirect","supportCORS":false}},{"bidder":"bidderB","no_cookie":true,"usersync":{"url":"https://bidderB.com/u/match?gdpr=&euconsent=&us_privacy=&redir=https%3A%2F%2Fprebid-server.example.com%2Fsetuid%3Fbidder%3DbidderB%26gdpr%3D%26gdpr_consent%3D%26us_privacy%3D%26uid%3D","type":"redirect","supportCORS":false}}]} + ``` -3) When it receives the response, Prebid.js loops through each element of `bidder_status[]`, dropping a pixel for each `bidder_status[].usersync.url`. +3. When it receives the response, Prebid.js loops through each element of `bidder_status[]`, dropping a pixel for each `bidder_status[].usersync.url`. -4) The bidder-specific endpoints read the users' cookie for the bidder's domain and respond with a redirect back to Prebid Server's [`/setuid` endpoint](/prebid-server/endpoints/pbs-endpoint-setuid.html) +4. The bidder-specific endpoints read the users' cookie for the bidder's domain and respond with a redirect back to Prebid Server's [`/setuid` endpoint](/prebid-server/endpoints/pbs-endpoint-setuid.html) . This allows that endpoint to read the 3rd party cookie and reflect it back to Prebid Server. Note that if this user doesn't yet have an ID in that 3rd party domain, the sync endpoint is expected to create one. -5) When the browser receives this redirect, it contacts Prebid Server, which will once again check the privacy settings and if allowed, update the `uids` cookie. +5. When the browser receives this redirect, it contacts Prebid Server, which will once again check the privacy settings and if allowed, update the `uids` cookie. ### Setting the uids cookie from AMP Cookie sync for AMP works in a way quite similar to Prebid.js. -1) The Prebid Server hosting company places a modified version of the `load-cookie` script onto a CDN. This script is part of the [Prebid Universal Creative](https://github.com/prebid/prebid-universal-creative/blob/master/src/cookieSync.js) repo. +1. The Prebid Server hosting company places the [load-cookie.html](#manually-initiating-a-sync) file onto a CDN. This script is part of the [Prebid Universal Creative](https://github.com/prebid/prebid-universal-creative/blob/master/src/cookieSync.js) repo. -{: .alert.alert-warning :} -The only two values currently valid for 'endpoint' are 'appnexus' and 'rubicon' -- other host companies should update their copy to include their endpoint. + See [the AMP implementation guide](/dev-docs/show-prebid-ads-on-amp-pages.html#user-sync) for more information. -See [the AMP implementation guide](/dev-docs/show-prebid-ads-on-amp-pages.html#user-sync) for more information. +2. The publisher places the 'load-cookie' iframe into the page: -2) The publisher places the 'load-cookie' script into the page: + ```html + + + + ``` -``` - - - -``` + {: .alert.alert-info :} + If the publisher has an AMP Consent Management Platform, they should use `load-cookie-with-consent.html`. + +3. At runtime, the `load-cookie` script just calls the Prebid Server /cookie_sync endpoint. The rest works similar to what's described for Prebid.js above. One difference is that the bidders are not known on the AMP page so those aren't passed. Another difference is that AMP doesn't support iframe syncs, so load-cookie passes instructions to PBS so only pixel syncs are returned. -{: .alert.alert-info :} -If the publisher has an AMP Consent Management Platform, they should use `load-cookie-with-consent.html`. +### Cooperative Syncing -3) At runtime, the `load-cookie` script just calls the Prebid Server /cookie_sync endpoint. The rest works the same as described for Prebid.js above. +Prebid Server supports a 'Cooperative Syncing' mode where all enabled bidders may be returned in a sync request even if they aren't on this particular page. This allows bidders to get their IDs in place for the next page where they are utilized. +Cooperative syncing can be configured at the host level. See the doc for [PBS-Java](https://github.com/prebid/prebid-server-java/blob/master/docs/config-app.md) and [PBS-Go](https://github.com/prebid/prebid-server/blob/master/config/usersync.go). + +This is how to control the coop syncing behavior from Prebid.js: + +```javascript +pbjs.setConfig({ + s2sConfig: { + ... + coopSync: true, + userSyncLimit: 5 + ... + } +}); +``` ## Bidder Instructions for Building a Sync Endpoint Building a sync endpoint is optional -- there is no benefit from ID syncing for mobile-only bidders. For browser-based bidding, ID syncing can help improve buyer bid rate. There are two main options a bidder can choose to support: -- redirect: the client will drop an IMG tag into the page, then call the bidder's URL which needs to redirect to the Prebid Server /setuid endpoint. -- iframe: the client will drop an IFRAME tag into the page, then call the bidder's URL which responds with HTML and Javascript that calls the Prebid Server /setuid endpoint at some point. +* redirect: the client will drop an IMG tag into the page, then call the bidder's URL which needs to redirect to the Prebid Server /setuid endpoint. +* iframe: the client will drop an IFRAME tag into the page, then call the bidder's URL which responds with HTML and Javascript that calls the Prebid Server /setuid endpoint at some point. Bidders must implement an endpoint under their domain which accepts an encoded URI for redirects. This URL should be able to accept privacy parameters: -- gdpr: if 0, declares this request isn't in GDPR scope. If 1, declares it is in scope. Otherwise indeterminate. -- gdpr_consent: the TCF1 or TCF2 consent string. This is unpadded base64-URL encoded. -- us_privacy: the IAB US Privacy string +* gdpr: if 0, declares this request isn't in GDPR scope. If 1, declares it is in scope. Otherwise indeterminate. +* gdpr_consent: the TCF1 or TCF2 consent string. This is unpadded base64-URL encoded. +* us_privacy: the IAB US Privacy string The specific attributes can differ for your endpoint. For instance, you could choose to receive gdprConsent rather than gdpr_consent. Here's an example that shows the privacy macros as configured in PBS-Go: -``` + +```yaml userSync: redirect: url: https://some-bidder-domain.com/usersync-url?gdpr={%raw%}{{.GDPR}}{%endraw%}&consent={%raw%}{{.GDPRConsent}}{%endraw%}&us_privacy={%raw%}{{.USPrivacy}}{%endraw%}&redirect={%raw%}{{.RedirectURL}}{%endraw%} @@ -107,11 +122,14 @@ userSync: ``` PBS-Java uses slightly different macros in the bidder config: -``` + +```yaml usersync: - url: https://some-bidder-domain.com/usersync-url?gdpr={%raw%}{{gdpr}}&gdpr_consent={{gdpr_consent}}&us_privacy={{us_privacy}}{%endraw%}&redirectUri= - redirect-url: /setuid?bidder=acuityads&gdpr={%raw%}{{gdpr}}{%endraw%}&gdpr_consent={%raw%}{{gdpr_consent}}{%endraw%}&us_privacy={%raw%}{{us_privacy}}{%endraw%}&uid=YOURMACRO + redirect: + url: https://some-bidder-domain.com/usersync-url?gdpr={%raw%}{{gdpr}}{%endraw%}&consent={%raw%}{{gdpr_consent}}{%endraw%}&us_privacy={%raw%}{{us_privacy}}{%endraw%}&gpp={%raw%}{{gpp}}{%endraw%}&gpp_sid={%raw%}{{gpp_sid}}{%endraw%}&redirect={%raw%}{{redirect_url}}{%endraw%} + uid-macro: YOURMACRO ``` + In either case, the {%raw%}{{...}}{%endraw%} macros are resolved by PBS. {: .alert.alert-warning :} @@ -127,8 +145,42 @@ Here's how this all comes together: Then the next time the client then calls `www.prebid-domain.com/openrtb2/auction`, the ID for `mybidder` will be available in the Cookie. Prebid Server will then stick this value into `request.user.buyeruid` in the OpenRTB request it sends to `mybidder`'s bid adapter. +## Manually initiating a sync + +Where Prebid.js isn't present, like in the AMP scenario, the call to /cookie_sync doesn't happen automatically. +If there are scenarios where Prebid.js isn't around to initiate the /cookie_sync call, publishers can choose to put an iframe on their page. +Here's how you could invoke it with an iframe: + +```html +
        + +

        +Notes: + +- [Prebid.js Price Floors Module](/dev-docs/modules/floors.html#overview) +- [Price Floors in Prebid Server](/prebid-server/features/pbs-floors.html#prebid-server--features--price-floors) +- [Prebid Floor Service Providers](/dev-docs/modules/floors.html#floors-providers) +- [Transcript of this video](/dev-docs/floors-video-overview.html) + +## How Floors work in Prebid Server + +Here's the high level picture of what's happening in Prebid Server to support floors: + +![Floors High Level](/assets/images/prebid-server/pbs-floors-basic.png){:class="pb-xlg-img"} + +1. Account configuration enables the floors feature. +2. If configured to do so, floors data is periodically updated from a defined URL specific to an account. A "Floors Provider" service is expected to conform to Prebid floors schema v2. Note that using a vendor service is optional: floor data can be provided on the request. +3. The main communication path for the calculated floor is the OpenRTB `imp.bidfloor` field, which is sent to each bid adapter in the auction. + +{: .alert.alert-info :} +Vendor services generally calculate floors with optimization algorithms fed by an analytics adapter. +Floors data is expected to be updated hourly, or perhaps once per day. +It is best practice is to avoid a "hardcode-and-forget" method of setting floors. +If a publisher doesn't want to utilize a floors service, they should commit to periodically reviewing manually-defined numbers. + +Drilling down one level into some detail, the PBS Floors feature has several main parts that work together: + +![Prebid Server Architecture](/assets/images/prebid-server/pbs-floors-detailed.png){:class="pb-xlg-img"} + +1. The **floor fetching** component should be thought of as an event-driven service that periodically polls a vendor to retrieve updated floors data specific for each account. +2. The **floor signaling** component parses the floors data and determines the actual floor for each ORTB imp object in the auction. The floors data could come from: (a) the request/stored-request or (b) an external floors provider +3. The best floor number is passed to the bid adapter on imp.bidfloor with the currency defined by imp.bidfloorcur. Certain bid adapters may be able to support more sophisticated floors for scenarios like multi-format. Due to bidder-specific [bid adjustment](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bid-adjustments) feature, each bid adapter may see a different floor value. +4. The **floor enforcement** component verifies that each bid has met the floor for that adapter after currency and bid adjustments. +5. Finally, analytics adapters have access to all the floors data. This can be used to feed optimization algorithms. + +The following sections go through each of the floor components. + +## Dynamic Floor Fetching + +The Prebid Server host company and publisher +may optionally decide to work with an external vendor to provide optimized floors. + +Setting up the service is straightforward: + +- Choose a vendor. See the [floors provider list](/dev-docs/modules/floors.html#floors-providers) in the Prebid.js documentation. +- Work with that vendor to determine the details: the schema, period, and other configurable values. +- Obtain a URL from the vendor for each publisher account. This URL should be a file on a CDN or otherwise be available within a few seconds around the globe. +- Define the URL in the account-specific configuration. + +That's it. Here's how fetching works: + +1. **Retrieve floors** - On the first request from the account, the Floor Fetching component will notice that it needs to obtain floors data from the vendor and will start a separate +thread to read data from the URL. (Note: this means the first request from each account will not have floors data available.) +1. **Cache floor data** - The floors data will be cached in Prebid Server memory for a defined period. +1. **Poll for updated data** - Once it's time to poll for new data, the next request from that account will trigger a refresh of floor data. +1. **Expire stale data** - If the data ever gets more stale than a configured age, it will be flagged as invalid. +1. **Surface data problems** - Operational metrics and log entries are made when there are problems obtaining floors data. + +## Floor Signaling + +Floor signaling is the process that determines which floor value to send to each bid adapter. Here's what it does for each auction: + +1. **Confirm floors are enabled** - make sure floors are enabled for Prebid Server, the account, and the request. If any of them are disabled, don't process floors. Instead, any original imp.bidfloor is passed through to bid adapters unmodified. +1. **Determine which floor data to use** + 1. First, use floor data cached from a floors vendor if one was configured. This is the data retrieved in the fetch step above. + 1. If there's no valid data cached, then use floor data defined in the request (or stored-request) in `ext.prebid.floors`. + 1. Finally, if no floor rules are available, the incoming imp.bidfloor can still be used and adjusted as needed for bid adjustment and currency. +1. **Process skipRate** - choose a random number. If it's greater than the skipRate, bypass floor signaling. Set ext.prebid.floors.skipped to true. This allows for A/B testing for the effectiveness of floors. +1. **Process the floor rules** - see below for details. +1. **Prepare downstream data** + 1. Update imp[].bidfloor and bidfloorcur with the appropriate values. These are standard OpenRTB fields that should be used by bid adapters to communicate the floor to their endpoints. + 1. If dynamic floor rules were utilized, overwrite the request ext.prebid.floors with the specific source and model being used so downstream entities all know which data was used to process floor rules. + 1. Update imp[].ext.prebid.floors with impression-specific values: the floorRule and floorRuleValue used to set the imp.bidfloor + 1. Set values for analytics adapters: enabled, location, skipped, fetchStatus. +1. **Prepare bidder-specific values** - for bidders with [cpm adjustments](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bid-adjustments), update imp[].bidfloor with the appropriate value. + +The default way that bid adapters receive the floor is just the OpenRTB standard `bidfloor` (and `bidfloorcur`). +But floors may actually be richer than a single value. For instance, in a multi-format impression, +there could be a floor for banner and a separate floor for video. Unfortunately, OpenRTB 2.5/2.6 don't support bidfloor at the mediaType level, so most bidders don't support that distinction either. However, +Prebid Server offers a way for bid adapters to distinguish between +mediatypes, sizes, and other details if they support it. See the [Bid Adapter Floor Interface](/prebid-server/features/pbs-floors.html#bid-adapter-floor-interface) section below. + +## Floor Enforcement + +The enforcement stage of the Floors feature validates bid responses from the adapters. + +1. **Let bid adjustments happen as usual** - if the [cpm adjustments](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#bid-adjustments) feature is active, PBS-core runs it as usual. +1. **Confirm floor enforcement is enabled** + 1. Checks whether the Signaling stage was active. i.e. if skipRate applied to signaling, it applies to the Enforcement stage as well. + 1. Check ext.prebid.floors.enforcement.enforcePBS. If defined and false, bypass enforcement. + 1. If Signaling was active, check the enforceRate. If specified, choose a random number, and if it's greater than the enforceRate value, don't verify bid values. +1. **Enforce** + 1. Normalize bid currency against the floor currency + 1. Confirm the bid is greater than or equal to the floor + 1. If not, reject the bid and flag it: + 1. Add a warning when in debug mode + 1. Send a 'rejected-due-to-floors' status to analytics adapters + 1. Log a sampled metric so the host company can follow up with bidders that aren't adhering to the floors. + +## Floor Data + +Prebid Server floors data must always be formatted using the [Schema 2](/dev-docs/modules/floors.html#schema-2) format supported by Prebid.js. +There a few fields supported by Prebid Server not supported in Prebid.js, but it's +completely backwards-compatible -- PBS will accept and process any Prebid.js floors data formatted in Schema 2. + +### Defining Floor data + +As described in the [Signaling](#floor-signaling) section above, floor data may be defined in several ways. Here's the order of priority: + +1. Dynamic data - if PBS finds recent (non-expired) floors data from a dynamic floors vendor, that takes precedence. +1. Request data - ext.prebid.floors may be specified in the client-request or in a stored-request. +1. Default floor - finally, the publisher may specify request imp.bidfloor as an overal default in case no other floors info is present. + +Here's an example of floors data coming in on the request: + +```json +{ + ... + "ext": { + "prebid": { + "floors": { + "floorMin": 1.00, + "floorMinCur": "USD", + ... + "data": { + "modelGroups": [{ + ... + }] + } + } + } + } +} +``` + +### Dynamic Floor Providers + +If you're a vendor looking to provide dynamic floors data via +Prebid Server, it's possible to use the same system +you're using for Prebid.js. Or you may want to take advantage of +the additional dimensions available. + +You'll need to work with the Prebid Server host company on how to get the analytics. +It may be necessary to build a [server-side analytics adapter](/prebid-server/developers/pbs-build-an-analytics-adapter.html) in order +to get data about which models were used, skipRate effectiveness, etc. + +At this time, floors analytics data (e.g. skipped) is not passed back to the client. +The expectation is that +Publishers will use this floors feature mainly for mobile app and AMP scenarios. +It's assumed that Web sites running Prebid.js will utilize the client-side module and analytics. +If the community requires client-side analytics for floors, +please [open an issue](https://github.com/prebid/prebid-server/issues) with as much detail as you can about the requirements. + +{: .alert.alert-info :} +Note: when producing a floors file, be aware that the entire contents are mered under +the 'data' object of [Schema 2](/dev-docs/modules/floors.html#schema-2). i.e. +the file should not contain the 'data' object, just attributes of the 'data' object. + +### Processing Floor Rules + +To understand how floor rules look and operate, see the [rules selection process](/dev-docs/modules/floors.html#rule-selection-process) in the Prebid.js floors module doc. + +### Floor Schema Dimensions + +These are the fields that can be used in defining the rules. The ones highlighed in **bold** are +supported only in Prebid Server, not in Prebid.js. + +{: .table .table-bordered .table-striped } +| Dimension | Type | Example | How it works | +|---+---+---+---| +| **siteDomain** | string | "level4.level3.example.com" | This is the full site domain. The value in the floor rule is compared to ORTB {site,app,dooh}.domain | +| **pubDomain** | string | "example.com" or "example.co.uk" | This is the publisher's base domain. It's compared to {site,app,dooh}.publisher.domain | +| domain | string | "example.com" | This is the robust way to check either the full domain or the base domain. It's compared against {site,app,dooh}.domain and {site,app,dooh}.publisher.domain. If any of them match this part of the rule matches. | +| **bundle** | string | "org.prebid.drprebid" | This value in the rule is compared to ORTB app.bundle | +| **channel** | string | "app" | This rule value is compared against ORTB ext.prebid.channel.name | +| mediaType | string | "video" | If more than one of the following ORTB objects exists, only the "*" rule value will match: imp.banner, imp.video, imp.native, imp.audio. Otherwise: {::nomarkdown}

        • the "banner" rule value will match if imp.banner exists.
        • the "video-outstream" rule value will match if imp.video exists and imp.video.placement is not 1
        • the "video-instream" rule value will match if imp.video exists and imp.video placement exists and is 1
        • the "video" rule value is treated as "video-instream" above.
        • the "native" rule value will match if imp.native exists
        • the "audio" rule value will match if imp.audio exists
        {:/} | +| size | string | "300x250" | {::nomarkdown}
        • if ORTB imp.banner exists and only one size exists in imp.banner.format, then the rule value is matched against imp.banner.format[0].w and imp.banner.format[0].h
        • else if ORTB imp.banner exists and there's no imp.banner.format, then match the rule value against imp.banner.w and imp.banner.h
        • else if ORTB imp.video exists, match the rule value against imp.video.w and imp.video.h
        • Otherwise the size rule value only matches the "*" condition
        {:/} | +| gptSlot | string | "/111/homepage" | if imp.ext.data.adserver.name=="gam" then compare the rule value against imp.ext.data.adserver.adslot. Otherwise compare the rule value against imp.ext.data.pbadslot | +| **pbAdSlot** | string | "/111/homepage#div1" | Compare the rule value against imp.ext.data.pbadslot | +| **country** | string | "USA" | Compare the rule value against device.geo.country (ISO-3166-1-alpha-3) | +| **deviceType** | string | "desktop", "phone", "tablet" | This is a very simple device-type algorithm: {::nomarkdown}
        • if ORTB device.ua is not present, only rules specifying a wildcard deviceType will match. In other words, there's no default value unless device.ua exists.
        • otherwise, match a rule value of "phone" if UA matches one of these patterns: "Phone", "iPhone", "Android.*Mobile", "Mobile.*Android"
        • otherwise, match a rule value of "tablet" if UA matches one of these: "tablet", "iPad", "Windows NT.*touch", "touch.*Windows NT", "Android"
        • otherwise assume the rule value "desktop" matches all other user agent strings.
        {:/} | + +Note that these schema dimensions are coded into the floors feature. If you need +another attribute to break out rules, please submit a code pull request with +an enhancement. + +Here's an example of some rules using PBS-specific schema dimensions: + +```json +{ + ... + "data": { + "floorProvider": "providerA", + "currency": "USD", + "modelGroups": [{ + "modelWeight": 50, + "modelVersion": "111111", + "schema": { + "fields": ["country", "mediaType", "deviceType"], + "delimiter": "|" + }, + "values": { + "usa|banner|tablet": 0.50, // banners on tablets from the US + "can|video-outstream|desktop": 0.75, // outstream on Canadian desktops + ... + }, + "default": 0.01 + }, { + .... + ]} + } + ... +``` + +## Floor Configuration + +The floors feature gives publishers and host companies a fair amount of control over how it operates. + +Here are the configurable items: + +{: .table .table-bordered .table-striped } +| Config | Type | Default | Description | +|---+---+---+---| +| enabled | boolean | true | Master switch for turning off the floors feature for this account. | +| enforce-floors-rate | integer | 100 | Default value for the enforceRate attribute. | +| adjust-for-bid-adjustment | boolean | true | Default value for the enforcement.bidAdjustment attribute. | +| enforce-deal-floors | boolean | false | Default value for the enforcement.floorDeals attribute. | +| fetch.enabled | boolean | false | Turns on the polling of an external dynamic floor data source. | +| fetch.url | string | - | URL for the external dynamic floor data source. | +| fetch.timeout-ms | integer | 3000 | How long to wait for the dynamic floor data source. | +| fetch.max-file-size-kb | integer | 100 | How big can the rule data get before being rejected. Helps protect memory problems. | +| fetch.max-rules | integer | 1000 | How many rules is too many. Helps protect processing time. | +| fetch.max-age-sec | integer | 86400 | How long is dynamically fetched data considered usable? | +| fetch.period-sec | integer | 3600 | How often between attempts to poll for updated data? | +| use-dynamic-data | boolean | true | Can be used as an emergency override to start ignoring dynamic floors data if something goes wrong. | + +The precise details of configuration may differ for PBS-Java vs PBS-Go. See the configuration document for your platform. + +## Bid Adapter Floor Interface + +Most bid adapters will not need to do anything special to obtain floors. They can +just read imp.bidfloor and imp.bidfloorcur, converting currency as needed. + +However, there are some use cases where advanced adapters might want to +get more granular access to floors data: + +- In a multi-format impression object, some adapters may choose to split the imp into two requests to their endpoint. e.g. one for video with a video floor, one for banner with a banner floor. +- The endpoint may be capable of receiving a floor value for each different size. This is not part of the ORTB spec, but might be something an endpoint could handle. + +Let's look at the first use case in more detail. When the Floors Signaling component +sees multiple media types in a single impression, it will always choose a "*"-valued rule for mediaType. Say we have this rule scenario: + +```json +{ + "data": { + "currency": "USD", + "modelGroups": [{ + ... + "schema": { + "fields": ["country", "mediaType"], + "delimiter": "|" + }, + "values": { + "usa|banner": 0.50, + "usa|video-outstream": 0.75, + "usa|video-instream": 0.99, + "usa|*": 0.99, + ... + }, + "default": 0.01 + }, { + ... + }] + } +} +``` + +And say this is the request: + +```json +{ + "imp": { + "banner": { + ... + }, + "video": { + "placement": 1, + ... + } + } +} +``` + +The Floors Signaling component sees that both banner and video are present, +so will only match the "*" rule for mediaType. In other words, it will set +imp.bidfloor to 0.99 in this scenario. +But if a bidder only supports banner, the 0.99 floor is higher than necessary. +It would be easier to meet the 0.50 floor for banners. + +To address this, a special floor function enables adapters to retrieve more granular +floor values for each impression in the auction. Due to the complexity of the rule system, deriving the correct floor would be a difficult task without this function. + +See the developer bid adapter documentation for details: + +- [PBS-Go](/prebid-server/developers/add-new-bidder-go.html) +- [PBS-Java](/prebid-server/developers/add-new-bidder-java.html) + +## Analytics Adapters + +To get floors information, developers of an analytics adapter will need to +pull data from both the bidrequest object and bidresponse object. + +In most scenarios, floor data is all in the bidrequest object, specifically in the ext.prebid.floors object. See [Schema 2](/dev-docs/modules/floors.html#schema-2) for the available fields. + +Here are some scenarios where looking at the bid response level data is used: + +- when the Floors feature rejects a bid because it didn't meet the floor +- when a bidder's floor was adjusted due to bidAdjustmentFactor +- when a bidder uses the getFloor() function to determine a custom floor + +Check the bid response object for this data: + +{: .table .table-bordered .table-striped } +| Field | Type | Description | +|---+---+---| +| bidAdjustment | boolean | Used to record if the bid floor was CPM adjusted based on the bidAdjustmentFactor provided in the bidRequest | +| floorCurrency | string | Currency of the floor matched. Only specified if the bidder calls getFloor. | +| floorRule | string | The matching rule for the given bidResponse. Only needed if the bidder calls getFloor(). | +| floorRuleValue | float | Rule floor selected. This is to differentiate between the floor bound to the selected rule and the OpenRTB bidfloor (if available). Only needed if the bidder calls getFloor(). | +| floorValue | float | The value of the floor enforced for this bidder. This will be the greater of the OpenRTB bidfloor and floorRuleValue. Only needed if the bidder calls getFloor or if the floor was adjusted due to bidCpmAdjustments. | + +See the [developer's guide to building an analytics adapter](/prebid-server/developers/pbs-build-an-analytics-adapter.html) for more details, and see existing code as an example. + +## Related Reading + +- [Prebid.js Floors module](/dev-docs/modules/floors.html) +- [Floor Provider Vendor list](/dev-docs/modules/floors.html#floors-providers) diff --git a/prebid-server/features/pbs-fpd.md b/prebid-server/features/pbs-fpd.md index 082c28099e..da927b93d9 100644 --- a/prebid-server/features/pbs-fpd.md +++ b/prebid-server/features/pbs-fpd.md @@ -4,10 +4,10 @@ sidebarType: 5 title: First Party Data - Prebid Server --- -# First Party Data - Prebid Server +# Prebid Server First Party Data {: .no_toc} -* TOC +- TOC {:toc} Prebid allows publishers to supply attributes related to their content @@ -15,21 +15,29 @@ and users, and to apply permissions so only certain bidders are allowed to access those attributes. {: .alert.alert-warning :} -For now, this feature is only supported in PBS-Java and these conventions aren't implemented by all adapters. Please +For now, these conventions aren't implemented by all adapters. Please check with each of your bidders to make sure they're reading first party data from the standard Prebid locations. ## How It Works -Each of the three main sources of Prebid Server traffic will place -First Party Data in the OpenRTB JSON in several places: +Each source of Prebid Server traffic will place +First Party Data in the OpenRTB JSON in several locations: {: .table .table-bordered .table-striped } | OpenRTB Attribute | Description | Prebid.js Source | SDK Source | AMP Source | | --- | --- | --- | --- | --- | | site.ATTR | Only standard OpenRTB attributes should be here: name, domain, cat, sectioncat, pagecat, page, ref, search, keywords. | config ortb2.site.ATTR | n/a | Stored Request | | site.ext.data.ATTR | Any other site-related attributes should go here. | config ortb2.site.ext.data | n/a | Stored Request | +| site.keywords | Site keywords | config ortb2.site.keywords | n/a | Stored Request | +| site.content.data | Contextual Seller Defined Data segments | config ortb2.site.content.data | n/a | n/a | | app.ext.data.ATTR | Any app-related attributes should go here. | n/a | Targeting addContextData() | n/a | +| app.keywords | App keywords | n/a | Targeting addContextKeywords() | n/a | +| app.content.data | Contextual Seller Defined Data segments | config ortb2.app.content.data | setRTBConfig() | n/a | +| dooh.ext.data.ATTR | Any dooh-related attributes should go here. | n/a | n/a | n/a | +| dooh.keywords | DOOH keywords | n/a | n/a | n/a | +| dooh.content.data | Contextual Seller Defined Data segments | n/a | n/a | n/a | +| user.keywords | User keywords | config ortb2.user.keywords | addUserKeywords | n/a | | user.ATTR | Only standard OpenRTB attributes should be here: yob, gender, keywords. | config ortb2.user.ATTR | n/a | n/a | | user.ext.data.ATTR | Any other user-related attributes should go here. | config ortb2.user.ext.data.ATTR | Targeting addUserData() | n/a | | imp[].ext.data.ATTR | AdUnit-specific attributes should go here. | AdUnit.ortb2.ext.data | AdUnit addContextData() | AMP targeting attribute or Stored Request | @@ -45,10 +53,19 @@ Note that Prebid.js directly supports the [`setBidderConfig`](/dev-docs/publishe bidder-specific first party data, while SDK only supports the `ext.prebid.data.bidders[]` approach with an in-app call. Both SDK and AMP can have the stored request define bidder FPD permissions. +## Seller Defined Audience (SDA) + +Many publishers utlize data segments that apply to context and audience. See the Prebid.js writeup on [Segments and Taxonomy](/features/firstPartyData.html#segments-and-taxonomy) for more information. + +Prebid Server supports these values in `user.data` and `{site,app,dooh}.content.data`. + +Note that 'Topics' in Google's Privacy Sandbox are implemented in Prebid as user-related SDA segments with segtaxes in the range 600-609. + ## OpenRTB Examples In this example, only BidderA has access to the global first party data: -``` + +```json { ext: { prebid: { @@ -67,8 +84,6 @@ In this example, only BidderA has access to the global first party data: }, user: { keywords: "", - gender: "", - yob: 1999, geo: {}, ext: { data: { @@ -90,7 +105,8 @@ In this example, only BidderA has access to the global first party data: ``` This example shows an array of bidder-specific config: -``` + +```json { ext: { prebid: { diff --git a/prebid-server/features/pbs-interstitials.md b/prebid-server/features/pbs-interstitials.md index 1bd83d12fd..4ea307ba8c 100644 --- a/prebid-server/features/pbs-interstitials.md +++ b/prebid-server/features/pbs-interstitials.md @@ -8,7 +8,7 @@ title: Prebid Server | Features | Interstitials # Prebid Server | Features | Interstitials Support for interstitial ads is enabled with the addition of two fields to the OpenRTB request: `device.ext.prebid.interstitial.minwidthperc` -and `device.ext.interstial.minheightperc` The values will be numbers that indicate the minimum allowed +and `device.ext.interstitial.minheightperc` The values will be numbers that indicate the minimum allowed size for the ad, as a percentage of the base side. For example, a width of 600 and "minwidthperc": 60 would allow ads with widths from 360 to 600 pixels inclusive. diff --git a/prebid-server/features/pbs-native.md b/prebid-server/features/pbs-native.md new file mode 100644 index 0000000000..b87606c6be --- /dev/null +++ b/prebid-server/features/pbs-native.md @@ -0,0 +1,20 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Features | Native Support + +--- + +# Prebid Server | Features | Native Support + +Support for the Native format in Prebid Server is simple: + +1. Bid adapters that support the native format must declare it in their static config. In PBS-Go, this is capabilities.{site,app}.mediaTypes. For PBS-Java it's adapters.BIDDER.meta-info.{site,app}-media-types. +2. Prebid Server checks that imp[].native.assets are valid. It will automatically add sequential IDs as needed. +3. It passes the imp[].native object through to bid adapters that support native. +4. When receiving a native bid response, PBS checks that each asset in the response carries a `type`. If it does not, PBS helpfully links the assetIds in the request and response and adds the original asset type to the response. +5. When this bid is chosen as the winner, the Prebid Universal Creative uses the type for proper rendering. + + +## Related Reading +- [Prebid Native Format](/formats/native.html) diff --git a/prebid-server/features/pbs-privacy.md b/prebid-server/features/pbs-privacy.md index bc83cc5a6c..727aa94259 100644 --- a/prebid-server/features/pbs-privacy.md +++ b/prebid-server/features/pbs-privacy.md @@ -10,32 +10,36 @@ title: Prebid Server | Features | Privacy * TOC {:toc} +{% include legal-warning.html %} + +## Prebid Server Activity Control Infrastructure + +Prebid Server supports a mechanism for Publisher control for overriding privacy-sensitive activities. See the [Activity Controls](/prebid-server/features/pbs-activitycontrols.html) for more information. + +Note that Activity Controls are currently not well integrated with other privacy features, but that will change as these features mature. + ## Mobile 'Limit Ad Tracking' flag If PBS receives 'device.lmt' flag in the OpenRTB request, it does the following anonymization: -- Mask take off the last byte of the IPv4 address and anonymize IPv6 addresses -- Removes user.id and user.buyeruid -- Removes the request.device.ifa attribute -- Rounds the request.device.geo. {lat,lon} to two decimal places +* Mask take off the last byte of the IPv4 address and anonymize IPv6 addresses +* Removes user.id and user.buyeruid +* Removes the request.device.ifa attribute +* Rounds the request.device.geo. {lat,lon} to two decimal places ## GDPR Prebid Server host companies and publishers have the ability to control the enforcement activities that take place. -The enforcement strategy changed significantly between TCF 1.1 and TCF 2.0. [TCF2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md) is a +The enforcement strategy changed significantly between TCF 1.1 and TCF 2.0. [TCF2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20Consent%20string%20and%20vendor%20list%20formats%20v2.md) is a more nuanced and stricter policy. {: .alert.alert-info :} -If a Prebid Server host company wants to support GDPR, they must currently [register for the IAB Global Vendor List](https://register.consensu.org/). +If a Prebid Server host company wants to support GDPR, they must currently [register for the IAB Global Vendor List](https://register.consensu.org/). The user must provide legal basis for the host company to read/write cookies or `/cookie_sync` will return an empty response with no syncs and `/setuid` will fail. -### TCF 1.1 - -No longer supported by Prebid Server. - -### TCF 2.0 +### TCF 2.0 and 2.2 If Prebid server determines the user is in GDPR scope, then consent is independently tested for each 'Purpose' with different consequences for each: @@ -46,36 +50,105 @@ for each 'Purpose' with different consequences for each: | Responding to /cookie-sync requests | Purpose 1 (Device Access) | | Setting a cookie on /setuid requests | Purpose 1 (Device Access) | | Conducting auctions | Purpose 2 (Basic Ads) | -| Passing User IDs into an auction | Any Purpose 2-10. User IDs are important for more than personalizing ads - they can be used in frequency capping, building profiles, counting unique users, etc. So Prebid Server should pass User IDs through the auction if any of Purposes 2-10 pass the legal basis test. | +| Passing User IDs into an auction | Any Purpose 2-10. User IDs are important for more than personalizing ads - they can be used in frequency capping, building profiles, counting unique users, etc. So Prebid Server should pass User IDs through the auction if any of Purposes 2-10 pass the legal basis test. In PBS-Java 2.12 and later, accounts can set configuration which requires user P4 consent before extended IDs can be passed. | | Invoke an analytics adapter | Purpose 7 | | Pass the user’s precise geographic information into auctions | Special Feature 1 | More details are available in the [Prebid Support for TCF2](https://docs.google.com/document/d/1fBRaodKifv1pYsWY3ia-9K96VHUjd8kKvxZlOsozm8E/edit#) reference and in the [Prebid Server GDPR Reference](https://docs.google.com/document/d/1g0zAYc_EfqyilKD8N2qQ47uz0hdahY-t8vfb-vxZL5w/edit#). +Note: TCF 2.2 strings are processed exactly the same as TCF 2.0 strings. The only difference from a Prebid perspective is that the +Global Vendor List is stored on a slightly different path. This new path is supported by PBS-Go 0.260 and PBS-Java 1.123. + ### Host Company GDPR Configuration There are a number of GDPR configuration settings that PBS Host Companies must consider: -- **GDPR enabled** - Allows the host company to turn off GDPR support. Default setting is enabled=true. -- **Default GDPR applies** - How Prebid Server should respond if the incoming request doesn't have the `gdpr` flag. (Note: this config is currently called `gdpr.default_value` in PBS-Go and `gdpr.default-value` in PBS-Java.) -- **Host company GVL ID** - Currently PBS requires the host company to have a GVL-ID or the setting of the `uids` cookie in GDPR scope will fail. -- **GDPR enforcement flags** - for each Purpose -- **Host Cookie TTL** - The default expiration time of the `uids` cookie set in the host company domain should be defined to match what's in the TCF 2.1 `maxCookieAgeSeconds` GVL field. (This is the host-cookie.ttl-days setting in both Go and Java.) +* **GDPR enabled** - Allows the host company to turn off GDPR support. Default setting is enabled=true. +* **Default GDPR applies** - How Prebid Server should respond if the incoming request doesn't have the `gdpr` flag. (Note: this config is currently called `gdpr.default_value` in PBS-Go and `gdpr.default-value` in PBS-Java.) +* **Host company GVL ID** - Currently PBS requires the host company to have a GVL-ID or the setting of the `uids` cookie in GDPR scope will fail. +* **GDPR enforcement flags** - for each Purpose +* **Host Cookie TTL** - The default expiration time of the `uids` cookie set in the host company domain should be defined to match what's in the TCF 2.1 `maxCookieAgeSeconds` GVL field. (This is the host-cookie.ttl-days setting in both Go and Java.) The specific details vary between [PBS-Go](https://github.com/prebid/prebid-server/blob/master/config/config.go) and [PBS-Java](https://github.com/prebid/prebid-server-java/blob/master/docs/config-app.md), so check the version-specific documentation for more information. +## DSA + +The Digital Services Act (DSA) in the EU requires that end users of "very large online platforms" be able to understand whether any of their personal data was used in targeting a particular ad. At a high level, it's similar to the ancient "Ad Choices" program where users were supposed to be able to understand why they were seeing the particular ads. + +See the IAB's [DSA document](https://iabtechlab.com/blog/iab-tech-lab-releases-for-public-comment-specification-for-dsa-transparency/) for background. + +Basically, the OpenRTB request and response have new objects defined [in the ORTB extension](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/extensions/community_extensions/dsa_transparency.md). + +```text +Request: $.regs.ext.dsa +Response: $.seatbid.bid.ext.dsa +``` + +Prebid Server supports passing these fields through the bidstream and it does validations +on the bid responses to make sure they contain publisher-required values. + +In general, publishers are responsible for creating the DSA object in Prebid.js, but in some use cases, they can't, including App and AMP. In addition, some Publishers might find it difficult to update their Prebid.js configuration across a broad network of sites in a short period. + +Prebid Server host companies can help resolve this by updating stored requests, but making a broad update across potentially thousands of DB entries can be difficult or undesirable. So PBS-Java also supports account-level +configuration to have Prebid Server inject a default DSA object. e.g. + +```yaml +privacy: + dsa: + default: > + { + "required": 1, + "pubrender": 1, + "datatopub": 1, + "transparency": [{ + "domain": "example.com", + "params":[1] + }] + } + gdpr-only: true +``` + +1. If regs.ext.dsa exists and is not null, use that. +2. else, if privacy.dsa.default exists and is not null: + 1. If privacy.dsa.gdpr-only is false (defaults to false) copy the default value into regs.ext.dsa. Done. + 2. If privacy.dsa.gdpr-only is true (defaults to false) check the internal_gdpr flag, and if true, copy the default value into regs.ext.dsa. Done. + +## GPP + +The IAB's [Global Privacy Platform](https://iabtechlab.com/gpp/) is container for +privacy regulations aimed at helping the ad tech ecosystem bring disparate reguations +under one communication path. + +Prebid Server support for this protocol: + +1. Passthrough - GPP parameters are forwarded through auction and usersync signals. In ORTB 2.6, these are regs.gpp and regs.gpp_sid. For url protocols, look for `gpp` and `gpp_sid`. +1. GPP as a TCF and USP wrapper - PBS parses the GPP container for TCF2 and USP strings, extracting them to the original ORTB location. +1. (done for PBS-Java) GPP infrastructure - the ability to plug new regulations into PBS, and the first sub-module, the [US General Privacy Module](/prebid-server/features/pbs-usgen.html). + +## MSPA / US National Privacy + +See [Prebid MSPA Support](/features/mspa-usnat.html) for more info. + +There are two modules offered by Prebid Server to process GPP string sections 7-12: + +1. The [USGen Privacy Module](/prebid-server/features/pbs-usgen.html) is a high +performance option for interpreting the GPP strings as described in the [Prebid MSPA reference](/features/mspa-usnat.html). (PBS-Java only) +1. The [US Custom Logic Privacy Module](/prebid-server/features/pbs-uscustomlogic.html) is a flexible way for publishers to define their own interpretation of GPP string sections 7-12. + +Also note that publishers can consider utilizing [Activity Controls](/prebid-server/features/pbs-activitycontrols.html). For PBS-Java, the `gppSid`, `geo`, and `gpc` conditions may be useful tools within a compliance strategy. + ## COPPA The [Children's Online Privacy Protection Act (COPPA)](https://www.ftc.gov/enforcement/rules/rulemaking-regulatory-reform-proceedings/childrens-online-privacy-protection-rule) is a law in the US which imposes certain requirements on operators of websites or online services directed to children under 13 years of age, and on operators of other websites or online services that have actual knowledge that they are collecting personal information online from a child under 13 years of age. If `regs.coppa` is set to '1' on the OpenRTB request, the following anonymization actions take place before going to the adapters: -- Removes all ID fields: device.ifa, device.macsha1, device.macmd5, device.dpidsha1, device.dpidmd5, device.didsha1, device.didmd5 -- Truncate ip field - remove lowest 8 bits. -- Truncate ipv6 field - remove lowest 32 bits. -- Remove geo.lat, geo.lon. geo.metro, geo.city, and geo.zip -- Remove user.id, user.buyeruid, user.yob, and user.gender +* Removes all ID fields: device.ifa, device.macsha1, device.macmd5, device.dpidsha1, device.dpidmd5, device.didsha1, device.didmd5 +* Truncate ip field - remove lowest 8 bits. +* Truncate ipv6 field - anonymize as noted below. +* Remove geo.lat, geo.lon. geo.metro, geo.city, and geo.zip +* Remove user.id, user.buyeruid, user.yob, and user.gender ## CCPA / US-Privacy @@ -85,15 +158,20 @@ this state-specific rule into a [US Privacy](https://iabtechlab.com/standards/cc If `regs.ext.us_privacy` is parsed to find that the user has opted-out of a "sale", the following anonymization steps are taken: -- Mask the last byte of the IPv4 address and anonymize IPv6 addresses -- Removes user.id and user.buyeruid -- Removes the request.device.ifa attribute -- Rounds the request.device.geo. {lat,lon} to two decimal places +* Mask the last byte of the IPv4 address and anonymize IPv6 addresses +* Removes user.id and user.buyeruid +* Removes the request.device.ifa attribute +* Rounds the request.device.geo. {lat,lon} to two decimal places ## Global Privacy Control In support of the [Global Privacy Control](https://globalprivacycontrol.org/), Prebid Server passes the `Sec-GPC` HTTP header through to bid adapters. It -does not currently take action on this header. +does not currently take action on this header by default. + +A publisher can utilize Activity Controls to link anonymization actions +to the precence of the GPC flag. See the `gpc` rule condition in the +[Activity Controls](/prebid-server/features/pbs-activitycontrols.html) for +more information. ## DNT @@ -105,10 +183,10 @@ We may reconsider this position if community members provide evidence that the f IPv6 addresses may be anonymized differently for Prebid Server host companies depending on how they've configured the server: -- There's a setting to mask the network portion of the IPv6 address when anonymization is called for. It defaults to 56 bits, meaning the rightmost 8 bits of the network is removed in these scenarios. -- There's another setting to remove a number of bits in the MAC address portion of the IPv6 address regardless of whether it's a situation that calls for explicit privacy or not. This setting defaults to removing all 64 bits of the MAC address. +* There's a setting to mask the network portion of the IPv6 address when anonymization is called for. It defaults to 56 bits, meaning the rightmost 8 bits of the network is removed in these scenarios. +* There's another setting to remove a number of bits in the MAC address portion of the IPv6 address regardless of whether it's a situation that calls for explicit privacy or not. This setting defaults to removing all 64 bits of the MAC address. ## Related Topics -- [Prebid Server Feature Matrix](/prebid-server/features/pbs-feature-idx.html) -- [Prebid Server GDPR Requirements](https://docs.google.com/document/d/1g0zAYc_EfqyilKD8N2qQ47uz0hdahY-t8vfb-vxZL5w/edit#) +* [Prebid Server Feature Matrix](/prebid-server/features/pbs-feature-idx.html) +* [Prebid Server GDPR Requirements](https://docs.google.com/document/d/1g0zAYc_EfqyilKD8N2qQ47uz0hdahY-t8vfb-vxZL5w/edit#) diff --git a/prebid-server/features/pbs-storedreqs-go.md b/prebid-server/features/pbs-storedreqs-go.md index 1b75183eaa..92b8bb4e63 100644 --- a/prebid-server/features/pbs-storedreqs-go.md +++ b/prebid-server/features/pbs-storedreqs-go.md @@ -13,7 +13,8 @@ Configure your server to read stored requests from the filesystem: ```yaml stored_requests: - filesystem: true + filesystem: + enabled: true ``` Choose an ID to reference your stored request data. Throughout this doc, replace {id} with the ID you've chosen. @@ -36,8 +37,12 @@ Add the file `stored_requests/data/by_id/stored_imps/{id}.json` and populate it ] }, "ext": { - "appnexus": { - "placementId": 12883451 + "prebid": { + "bidder": { + "appnexus": { + "placement_id": 12883451 + } + } } } } @@ -90,8 +95,12 @@ You can also store _part_ of the Imp on the server. For example: ] }, "ext": { - "appnexus": { - "placementId": 12883451 + "prebid": { + "bidder": { + "appnexus": { + "placement_id": 12883451 + } + } } } } diff --git a/prebid-server/features/pbs-storedreqs-java.md b/prebid-server/features/pbs-storedreqs-java.md new file mode 100644 index 0000000000..d9249deb78 --- /dev/null +++ b/prebid-server/features/pbs-storedreqs-java.md @@ -0,0 +1,301 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Features | Setting Up Stored Requests for Java + +--- + +# Prebid Server | Features | Setting Up Stored Requests for Java +{: .no_toc} + +* TOC +{:toc } + +## Overview + +There are two different kinds of stored requests: +- **impression-level stored requests**: these are scoped to the contents of a single OpenRTB `imp` object. Prebid Server defines these in imp[].ext.prebid.storedrequest. +- **top-level stored requests**: these are scoped to the entire OpenRTB package, and is where you can place details in ext.prebid, tmax, site, etc. It is not recommended to place imp objects in this type of stored request. Prebid Server defines these in ext.prebid.storedrequest. + +## PBS-Java Stored Request Quickstart + +Stored requests can be placed in the database or files. See below for how to set up the database. This guide assumes that new Prebid Server host companies will start with files. + +Configure your server to read stored requests from the filesystem: + +```yaml +settings: + filesystem: + settings-filename: sample-app-settings.yaml + stored-requests-dir: stored_requests + stored-imps-dir: stored_imps +``` + +Choose an ID to reference your stored request data. Throughout this doc, replace {id} with the ID you've chosen. + +Add the file `stored_imps/{id}.json` and populate it with some [imp](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf#page=17) data. This will create an impression-level stored request. + +```json +{ + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "appnexus": { + "placement_id": 10433394 + } + } + } + } +} +``` + +Start your server and then `POST` to [`/openrtb2/auction`](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html) with your chosen ID. + +```json +{ + "id": "test-request-id", + "imp": [ + { + "ext": { + "prebid": { + "storedrequest": { + "id": "{id}" + } + } + } + } + ] +} +``` + +The auction will occur as if the HTTP request had included the content from `stored_requests/{id}.json` instead. + +## Partial Stored Impression-level Requests + +You can also store _part_ of the `imp` on the server. For example: + +```json +{ + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "prebid": { + "bidder": { + "appnexus": { + "placement_id": 10433394 + } + } + } + } +} +``` + +This is not _fully_ legal OpenRTB `imp` data, since it lacks an `id`. + +However, incoming HTTP requests can fill in the missing data to complete the OpenRTB request: + +```json +{ + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "ext": { + "prebid": { + "storedrequest": { + "id": "{id}" + } + } + } + } + ] +} +``` + +If the Stored Request and the HTTP request have conflicting properties, +they will be resolved with a [JSON Merge Patch](https://tools.ietf.org/html/rfc7386). +HTTP request properties will overwrite the Stored Request ones. + +## Top-Level Stored Requests + +So far, our examples have only used impression-level data. However, Stored Requests +are also allowed at the top level at ext.prebid.storedrequest. +These work exactly the same way, but support storing properties like timeouts and price granularity. + +For example, assume the following `stored-requests/{id}.json`: + +```json +{ + "tmax": 1000, + "ext": { + "prebid": { + "targeting": { + "pricegranularity": "low" + } + } + } + } +``` + +Then HTTP request like: + +```json +{ + "id": "test-request-id", + "imp": [ + "Any valid Imp data in here" + ], + "ext": { + "prebid": { + "storedrequest": { + "id": "{id}" + } + } + } +} +``` + +will produce the same auction as if the HTTP request had been: + +```json +{ + "id": "test-request-id", + "tmax": 1000, + "imp": [ + "Any valid Imp data in here" + ], + "ext": { + "prebid": { + "targeting": { + "pricegranularity": "low" + } + } + } +} +``` + +Prebid Server does allow both top-level and impression-level stored requests in the same HTTP Request. +The top-level stored request will be applied first, and then the impression-level stored request. + +**Beware**: Stored Request data will not be applied recursively. +If a Stored BidRequest includes Imps with their own Stored Request IDs, then the data for the contained Stored Imps will not be resolved. + +**Note**: However, stored requests may contain [storedresponses](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-responses). + +## Alternate backends + +Stored Requests do not need to be saved to files. Other backends are supported with different +[configuration options](https://github.com/prebid/prebid-server-java/blob/master/docs/config.md). + +### Database backend + +For PostgreSQL: +```yaml +settings: + database: + type: postgres +``` + +For MySQL: +```yaml +settings: + database: + type: mysql +``` + +The select query columns of `stored-requests-query` and `amp-stored-requests-query` properties should correspond to the specific format: +- first column: account ID, which is used to make sure that storedrequests are unique to the account +- second column: ID of stored data item +- third column: value of stored data item. +- forth column: type of stored data item. Can be `request` for stored requests or `imp` for stored impressions. + +### HTTP backend + +```yaml +settings: + http: + endpoint: http://stored-requests.prebid.com + amp_endpoint: http://stored-requests.prebid.com?amp=true +``` + +Note: HTTP backend implementation always gives an empty result (with "Not supported" error inside) +for obtaining the `Account` or `AdUnitConfig` by ID for the legacy [auction](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html) endpoint. + +Full list of application configuration options can be found [here](https://github.com/prebid/prebid-server-java/blob/master/docs/config-app.md). + +If you need support for a backend that you don't see, please [contribute it](https://github.com/prebid/prebid-server-java/blob/master/docs/developers/contributing.md). + +## Caches and updates + +Stored Request data can also be cached or updated while PBS is running. +Conceptually, Stored Request data is managed by the following components in the code: + +**ApplicationSettings**: Implementations of this interface pull data directly from a backend. +**SettingsCache**: Duplicates data which the ApplicationSettings _could_ find so that it can be accessed more quickly. +**CacheNotificationListener**: Provides interface apply changes to Stored Request data. + +ApplicationSettings and methods of updating Stored Request data at runtime can also be chosen +in the the app config. +At least one ApplicationSettings is _required_ to make use of Stored Requests. + +If more than one ApplicationSettings is defined, they will be ordered and used as fallback data sources. +This isn't a great idea for Prod in the long-term, but may be useful temporarily if you're trying +to transition from one backend to another. + +CacheNotificationListener is used to Save or Invalidate values from the cache. + +Here is an example configuration file which looks for Stored Requests first from Postgres, and then from an HTTP endpoint. +It will use an in-memory LRU cache to store data locally, and poll another HTTP endpoint to listen for updates. + +```yaml +settings: + database: + type: postgres + host: localhost + port: 5432 + dbname: database-name + user: username + password: password + stored-requests-query: SELECT accountId, reqid, requestData, 'request' as dataType FROM stored_requests WHERE reqid IN (%REQUEST_ID_LIST%) UNION ALL SELECT accountId, impid, impData, 'imp' as dataType FROM stored_requests WHERE impid IN (%IMP_ID_LIST%) + amp-stored-requests-query: SELECT accountId, reqid, requestData, 'request' as dataType FROM stored_requests WHERE reqid IN (%REQUEST_ID_LIST%) + http: + endpoint: http://stored-requests.prebid.com + amp-endpoint: http://stored-requests.prebid.com?amp=true + in-memory-cache: + cache-size: 10000 + ttl-seconds: 360 + http-update: + endpoint: http://stored-requests.prebid.com + amp-endpoint: http://stored-requests.prebid.com?amp=true + refresh-rate: 60000 + timeout: 2000 +``` + +Refresh rate can be negative or zero - in such case the data will be fetched once and never updated. + +## Related Reading +- [Stored Responses](/prebid-server/endpoints/openrtb2/pbs-endpoint-auction.html#stored-responses) +- [Hosting a PBS database](/prebid-server/hosting/pbs-database.html) diff --git a/prebid-server/features/pbs-storedreqs.md b/prebid-server/features/pbs-storedreqs.md index 822b9b5237..07abc13071 100644 --- a/prebid-server/features/pbs-storedreqs.md +++ b/prebid-server/features/pbs-storedreqs.md @@ -43,4 +43,4 @@ See the [AMP Use Case reference](/prebid-server/use-cases/pbs-amp.html) for spec Details for setting up: - [PBS-Go Stored Requests](/prebid-server/features/pbs-storedreqs-go.html) -- [PBS-Java Stored Requests](https://github.com/prebid/prebid-server-java/blob/master/docs/developers/stored-requests.md) +- [PBS-Java Stored Requests](/prebid-server/features/pbs-storedreqs-java.html) diff --git a/prebid-server/features/pbs-uscustomlogic.md b/prebid-server/features/pbs-uscustomlogic.md new file mode 100644 index 0000000000..3006aa681f --- /dev/null +++ b/prebid-server/features/pbs-uscustomlogic.md @@ -0,0 +1,307 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Features | Privacy | US Custom Logic +--- + +# Prebid Server US Custom Logic Privacy Module +{:.no_toc} + +{: .alert.alert-warning :} +This feature is currently only available in PBS-Java. + +- TOC +{:toc} + +{% include legal-warning.html %} + +## Overview + +This module provides a way for publishers to define a custom interpretion for GPP strings in Sections 7-12. +If the publisher is satisfied with Prebid's interpretation of GPP SIDs 7-12 as defined in +[Prebid Multi-State Privacy Agreement Support](/features/mspa-usnat.html), it's recommended +that they utilze the [US Gen Privacy Module](/prebid-server/features/pbs-usgen.html) instead of this one. + +This module lets publishers define GPP string interpretation with a powerful general syntax +called [JsonLogic](https://jsonlogic.com/). At high traffic volumes with complex interpretion logic, +the Prebid Server Host Company may want to monitor compute resource utilization consumed by use +of this feature. Another option would be to build a [custom privacy module](/prebid-server/developers/add-a-privacy-module.html). + +The use cases for this module are the same as for the `US Gen Privacy Module`: + +- Is bidderA allowed to participate in this auction? +- Is bidderB allowed to receive User First Party Data? +- Is moduleM allowed to enrich the request with EIDs? + +The difference is that instead of the GPP interpretation logic being coded into the module, +it allows publishers and their lawyers to come up with their own interpretations. As you'll see, this is powerful but complicated. + +## Using the US Custom Logic Privacy Module + +Some decisions are needed to activate the module within Prebid Server: + +1. The PBS host company needs to decide whether to enable this privacy module globally, per-account, or both. +1. The host company also needs to decide whether to link this privacy module to Activity Controls globally. +1. Publishers may ask the host company to override Activity Control defaults, including which activities use the module. + +### Enabling the US Custom Logic Module + +The US Custom Logic Privacy Module is included in PBS-Java 1.130, but is not activated until it's placed +in the global or account-level config in a `privacy.modules` object. + +Here's an example: + +```json +{ + "privacy": { + "modules": [{ + "code": "iab.uscustomlogic", + "config": { + ... see below for examples ... + } + }], + "allowactivities": { + "ACTIVITY": { + "default": true, + "rules": [{ + "privacyreg": ["*"] // causes the Activity Control to call all defined privacy modules + }] + } +} +``` + +### US Custom Logic Privacy Module Parameters + +Here are the parameters allowed in the module's `config` section. See below for examples. + +{: .table .table-bordered .table-striped } +| Parameter | Type | Scope | Description | +|------|------|-------------| +| sids | array of integer | required | Process only the named section IDs. | +| normalizeFlags | boolean | optional | Convert the state SIDs 8-12 into SID 7 fields as described in the [Prebid MSPA reference](/features/mspa-usnat.html). Defaults to `true`. | +| activityConfig | array of objects | required | Defines what processing to do. | +| activityConfig[].activities | array of strings | required | Defines which activity or activities are in scope for this array entry. | +| activityConfig[].restrictIfTrue | object | required | [JsonLogic](https://jsonlogic.com) rules object. | + +### JsonLogic Data Fields + +{: .alert.alert-info :} +Tip: Scroll down to the example to see what a JsonLogic rule (the `restrictIfTrue` field) looks like. The config only needs to contain the JsonLogic rule -- the module will create the JsonLogic data +from the GPP string. + +The way [JsonLogic](https://jsonlogic.com) works is that you supply two JSON objects: + +1. A set of rules. This defines boolean logic with many operators. For this module, the configuration defines the rules in the `restrictIfTrue` field. +1. A set of data. The module parses the GPP string and creates a set of attribute-value pairs for each flag defined in the GPP section. + +The specific fields produced by the module that can be referred to in a rule are based on the IAB's definition of each SID. The only difference is that array fields simply have a number appended since JsonLogic doesn't support arrays. + +These are the fields that can be referenced in the JsonLogic rule: + +- MspaServiceProviderMode +- MspaCoveredTransaction +- MspaOptOutOptionMode +- Gpc +- SaleOptOutNotice +- SaleOptOut +- SharingNotice +- SharingOptOutNotice +- SharingOptOut +- TargetedAdvertisingOptOutNotice +- TargetedAdvertisingOptOut +- KnownChildSensitiveDataConsents1 +- KnownChildSensitiveDataConsents2 +- PersonalDataConsents +- SensitiveDataProcessingOptOutNotice +- SensitiveDataLimitUseNotice +- SensitiveDataProcessing1 +- SensitiveDataProcessing2 +- SensitiveDataProcessing3 +- SensitiveDataProcessing4 +- SensitiveDataProcessing5 +- SensitiveDataProcessing6 +- SensitiveDataProcessing7 +- SensitiveDataProcessing8 +- SensitiveDataProcessing9 + +See the IAB technical specifications for the definition and values allowed for each field. e.g. [GPP Extension: IAB Privacy’s US National Privacy Technical Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md) + +### Linking the module to Activities + +The US Custom Logic Privacy Module will not operate within the PBS workflow unless it's called by the Activity Control system. e.g. + +```javascript +{ + "privacy": { + "allowactivities": { + "ACTIVITY": { + "default": true, + "rules": [{ + "privacyreg": ["*"] // this causes the Activity Control to call this module + },{ + ... more rules ... + }] + } + } + } +} +``` + +### Example 1 - Handle GPC and 'sensitive data' differently + +Again, publishers will only use this module if their lawyers disagree with Prebid's default +interpretation of the US National or US State GPP strings. + +As one example, Prebid interprets the Global Privacy Control (GPC) flag as a strong privacy signal that disables many GPP +privacy-related activities. Say a publisher's lawyers want to allow the `transmitUfpd` activity to operate in the US even when the GPC flag is set to true. In addition, they've declared that +they don't operate in any "sensitive data" category, so wish to remove those elements from +interpretation. + +Here's an example config: + +```json +{ + "privacy": + { + "modules": [{ + "code": "iab.uscustomlogic", + "config": { + "sids": [7,8,9,10,11,12], + "normalizeFlags": true, + "activityConfig": [{ + "activities": ["transmitUfpd"], + "restrictIfTrue": { + "or": [ + { "==": [{"var": "MspaServiceProviderMode"},1] }, + { "and": [ + { "==": [{"var": "MspaServiceProviderMode"},2] }, + { "or": [ + { "==": [{"var": "SaleOptOut"},1] }, + { "==": [{"var": "SaleOptOutNotice"},2] }, + { "==": [{"var": "SharingNotice"},2] }, + { "==": [{"var": "SharingOptOut"},1] }, + { "==": [{"var": "TargetedAdvertisingOptOutNotice"},2] }, + { "==": [{"var": "TargetedAdvertisingOptOut"},1] }, + { "!=": [{"var": "KnownChildSensitiveDataConsents1"},0] }, + { "!=": [{"var": "KnownChildSensitiveDataConsents2"},0] }, + { "==": [{"var": "PersonalDataConsents"},2] } + ]} + ]} + ]} + }] + } + },{ + "code": "iab.usgen", + "config": { skipSids: [] } + }], + "allowactivities": { + "transmitUfpd": { + "default": false, + "rules": [{ + "privacyreg": ["iab.uscustomlogic"] + }] + }, + "transmitPreciseGeo": { + "default": false, + "rules": [{ + "privacyreg": ["iab.usgen"] + }] + } + } + } +} +``` + +Notes: + +- In this example, only one activity uses the custom logic. Other activities utilize the conventions coded into the iab.usgen module. +- It would be possible to link each activity to different parsing logic + +### Example 2 - Process Native GPP SID 11 Flags + +In this example, a publisher's lawyers have determined that Prebid's normalization of Utah (SID 11) to the US National (SID 7) equivalents should not be used. This is somewhat contrived, but illustrates that you can operate +on non-normalized GPP flags. + +```javascript +{ + "privacy": + { + "modules": [{ + "code": "iab.uscustomlogic", + "config": { + "sids": [11], + "normalizeFlags": false, // note: normalization to SID 7 not performed + "activityConfig": [{ + "activities": ["transmitUfpd"], + "restrictIfTrue": { + ... JsonLogic Rule refers to Utah-definitions ... + ... e.g. SensitiveDataProcessing3 and SensitiveDataProcessing4 are reversed ... + },{ + ... other activities ... + }] + } + },{ + "code": "iab.usgen", + "config": { + "skipSids": [11] + } + }], + "allowactivities": { + "transmitUfpd": { + "default": false, + "rules": [{ + "privacyreg": ["*"] + }] + }, + ... other activities ... + } + } +} +``` + +### Module Processing + +Here's how the module works when called by an Activity Control: + +1. Gather GPP data + 1. GPP string comes from `regs.gpp` + 1. The GPP SIDs come from `regs.gpp_sid`. This is an array of integers. +1. Check the GPP SIDs to see if this request is in-scope + 1. If there are no GPP SIDs, return `abstain`. +1. For each GPP SID defined in the request + 1. If the SID is < 7 or > 12, go on to the next SID + 1. Else if the SID is not on the sids list, go on to the next SID + 1. Else pull that section of out the GPP string and process it + 1. If the normalizeFlags option is true and the SID is 8-12, normalize the flags to the SID 7 form as described in the Prebid [MSPA/USNat reference](/features/mspa-usnat.html). + 1. Find the current activity. If found, run the JsonLogic in the `restrictIfTrue` section as the rule, and pass in the GPP SID flags as the data. If the result is true, then "allow=false". + 1. On first "allow: false" immediately return `allow: false` to the Activity Control system. + 1. Continue until all SIDs are processed or skipped. +1. If any SID returns "allow: true", return `allow: true` to the Activity Control system +1. Otherwise return `abstain` + +### Limits + +Because the module config is not an array, it is not be possible to create +rules that apply to each US state's non-normalized GPP flags for the same activity. + +Supporting this scenario would require a PBS Host Company to build a custom privacy module. + +### Troubleshooting + +Additional information about the outcoming of privacy module processing can be obtained by setting `ext.prebid.trace: "basic"`. + +It may be useful to use the [JsonLogic tool](https://jsonlogic.com/play.html) to confirm the desired logic: + +1. Enter a rule just as you would for the `restrictIfTrue` object. +1. Enter a simple JSON object containing the desired values of the GPP flags. + +Here's a screenshot showing the usage of that tool: + +![JsonLogic Screenshot](/assets/images/prebid-server/json-logic-screenshot.png){:class="pb-xlg-img"} + +## Related Topics + +- [Prebid Multi-State Privacy Agreement Support](/features/mspa-usnat.html) +- [US General Privacy Module](/prebid-server/features/pbs-usgen.html) +- [Activity Control system](/prebid-server/features/pbs-activitycontrols.html) +- [IAB US National Privacy Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md) diff --git a/prebid-server/features/pbs-usgen.md b/prebid-server/features/pbs-usgen.md new file mode 100644 index 0000000000..254fb5c427 --- /dev/null +++ b/prebid-server/features/pbs-usgen.md @@ -0,0 +1,160 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Features | Privacy | US General +--- + +# Prebid Server US General Privacy Module +{:.no_toc} + +{: .alert.alert-warning :} +This feature is currently only available in PBS-Java. + +* TOC +{:toc} + +{% include legal-warning.html %} + +## Overview + +This document covers how to configure the `US General Privacy Module` for Prebid Server. + +See the [Prebid Multi-State Privacy Agreement Support](/features/mspa-usnat.html) page for +details on how specifically GPP strings are processed. This module interprets the strings +as defined in that document. If a publisher wishes to override the interpretation coded into +this module, there are two options: + +1. Utilize the [US Custom Logic Privacy Module](/prebid-server/features/pbs-uscustomlogic.html). This lets publishers define their own interpretation in JSONLogic format. +1. Or, if optimizing performance is a concern, the Prebid Server Host Company might choose to build a custom privacy module that implements the desired string interpretation. + +"`USGen`" is a 'privacy module' called by the [Activity Control system](/prebid-server/features/pbs-activitycontrols.html) for a specific scenario. e.g. + +* Is bidderA allowed to participate in this auction? +* Is bidderB allowed to receive User First Party Data? +* Is moduleM allowed to enrich the request with EIDs? + +This module's job is figure out from the GPP strings whether or not the activity should be +allowed. Unlike the similarly-named [Prebid.js USNat module](/dev-docs/modules/gppControl_usnat.html), +this module also supports the US states defined by the IAB as having slightly +different protocols. i.e. while the Prebid.js module only processes GPP Section (SID) 7, this Prebid Server +module processes SIDs 7-12. That's why we call it "US General" rather than "US National", +which implies SID 7. + +## Using the US General Privacy Module + +Here are the steps need to activate the module within Prebid Server: + +1. The PBS host company needs to decide whether to enable this privacy module globally, per-account, or both. +1. The host company needs to decide whether to link this privacy module to Activity Controls globally. +1. Publishers may ask the host company to override Activity Control defaults, including which activities use the USGen privacy module. + +### Enabling the USGen Module + +The USGen privacy module is included in PBS-Java 1.126, but is not activated until it's placed +in the global or account-level config in a `privacy.modules` object. + +Here's an example: + +```json +{ + "privacy": { + "modules": [{ + "code": "iab.usgeneral", // the USNat module's code + "config": { + "skipSids": [9] + } + }] + } +} +``` + +### USGen Privacy Module Parameters + +{: .table .table-bordered .table-striped } +| Parameter | Type | Scope | Description | +|------|------|-------------| +| skipSids | array of integer | Optional | Do not process the named section IDs. | + +By default the module will process GPP SIDs 7-12. The `skipSids` +parameter allows the publisher to define a different processing flow for different GPP SIDs. + +### Linking the USGen module to Activities + +The USGen Privacy Module will not operate within the PBS workflow unless it's called by the Activity Control system. e.g. + +```javascript +{ + "privacy": { + "allowactivities": { + "ACTIVITY": { + "default": true, + "rules": [{ + "privacyreg": ["*"] // this causes the Activity Control to call this module + },{ + ... more rules ... + }] + } + } + } +} +``` + +### USGen Privacy Module Processing + +Here's how the module works when called by an Activity Control: + +1. Gather GPP data + 1. GPP string comes from `regs.gpp` + 1. The GPP SIDs come from `regs.gpp_sid`. This is an array of integers. +1. Check the GPP SIDs to see if this request is in-scope + 1. If there are no GPP SIDs, return `abstain`. +1. For each GPP SID defined in the request + 1. If the SID is < 7 or > 12, go on to the next SID + 1. Else if the SID is on the skipSids list, go on to the next SID + 1. Else pull that section of out the GPP string and process it + 1. If the SID is 8-12, "normalize" the flags to the SID 7 form as described in the Prebid [MSPA/USNat reference](/features/mspa-usnat.html). + 1. Depending on the Activity, compare the string's flags as described in the Prebid MSPA/USNat reference. + 1. On first "allow: false" immediately return `allow: false` to the Activity Control system. + 1. Continue until all SIDs are processed or skipped. +1. If any SID returns "allow: true", return `allow: true` to the Activity Control system +1. Otherwise return `abstain` + +### Example - Alternate Processing for California + +In this scenario, a host company has created a special module for a publisher implementing +custom processing logic. The publisher wants to process GPP SIDs 7,9-12 with the default +Prebid approach, but they want to process SID 8 with this custom module. + +```javascript +{ + "privacy": { + "modules": [{ + "code": "iab.usgeneral", // the USNat module's code + "config": { + "skipSids": [8] + } + },{ + "code": "publisherP.specialCAprocessing" // only activates for SID 8 + }], + "allowactivities": { + "ACTIVITY": { + "default": true, + "rules": [{ + "privacyreg": ["*"] + }] + } + } + } +} +``` + +### Troubleshooting + +Additional information about the outcoming of privacy module processing can be obtained by setting `ext.prebid.trace: "basic"`. + +## Related Topics + +* [Prebid Multi-State Privacy Agreement Support](/features/mspa-usnat.html) +* [US Custom Logic Privacy Module](/prebid-server/features/pbs-uscustomlogic.html) +* [Activity Control system](/prebid-server/features/pbs-activitycontrols.html) +* [IAB US National Privacy Specification](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform/blob/main/Sections/US-National/IAB%20Privacy%E2%80%99s%20National%20Privacy%20Technical%20Specification.md) diff --git a/prebid-server/features/pg/pbs-pg-bidder.md b/prebid-server/features/pg/pbs-pg-bidder.md deleted file mode 100644 index 4d456606a6..0000000000 --- a/prebid-server/features/pg/pbs-pg-bidder.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Building a PG Bidder ---- - -# Building a Programmatic Guaranteed Bidder -{: .no_toc} - -* TOC -{:toc} - -## What is a PG Bidder? - -The architecture of Prebid Programmatic Guaranteed (PG) is inherently multi-vendor. A PG `Host Company` runs a global distributed cluster of Prebid Servers. These servers handle the 'real-time' requests... those that need to have millisecond response times. They also run a couple of backend servers that help manage the PG line items. One of them -is called the `General Planner`. The General Planner can connect out to multiple sources of PG Line Items, and that's where you come in -- as a PG Bidder, you can contribute PG Line Items into the auction ecosystem for the publishers who utilize the Host Company's installation. -Here's a diagram from the [white paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf). - -![PG High Level Framework](/assets/images/prebid-server/pg/pg-arch-2.png){: .pb-lg-img :} - -1. The PG Host Company runs clusters of Prebid Servers that receive requests from publishers. -2. Prebid Servers look up additional data for use in targeting. -3. The General Planner queries your PG Bidder endpoint and allocates your line items across the Prebid Server clusters. -4. The `Delivery Stats Service` is available for PG Bidders to obtain up-to-date reports on how line items are delivering. -5. The `Dimension Value API` should be used by bidders to create targeting values. -6. Each PG Bidder has it's own logic for pacing their line items in 1 or 5-minute increments called "plans". -7. The publisher or a service team enter the PG Line Items into the PG Bidder's user interface. - -Notes: -- It's possible that you could deliver PG Line Items through more than one PG Host Company. -- It it the responsibility of the PG Bidder to manage their own finance arrangements with each Publisher. -- It's possible that the Host Company may charge a fee to deliver PG Line Items through their infrastructure. - -## What's involved in building a PG Bidder? - -These are the high level steps for how to develop a PG Bidder and plug it into a Host Company's implementation. - -1. Contact a PG Host Company to make sure they're ready to incorporate a new PG Bidder. They may have additional requirements. -1. Obtain access to the Host Company's Dimension Value API and Delivery Stats server. You will receive a "biddercode" similar to the codes used in Prebid.js. e.g. "pgExample". -1. Develop a User Interface for the customer to enter PG info: date range, targeting details, price, and pacing details. The targeting information comes from the Host Company's Dimension Value API. -1. Develop a pacing algorithm that uses data from the Host Company's Delivery Stats server and your own data stores. -1. Develop a report that uses data from the Host Company's Delivery Stats server and your own data stores. -1. Develop an external API that can respond to requests from the Host Company's General Planner for line item data. -1. Develop a method for estimating inventory forecast and availability. The Host Company may have data available. -1. Contact the Host Company to begin integration testing. - -### Obtain targeting dimensions - -The Host Company will give PG Bidders access to their Dimension Value API which will let them know what attributes and values their Prebid Servers can target at runtime for particular clients. -The values used will differ between Host Companies and publishers. For example, there may be different geographic and device info services. Publisher AdSlot and First Party Data fields will also vary. - -Once granted authenticated access to the Dimension Value endpoint, you'll use the it to query it to get attribute names and values specific to the accounts you're working with. e.g. - -- GET /dim-val/api/v2/attr/names?account=1001 -- GET /dim-val/api/v2/attr/values?account=1001 - -There are various options for filtering data. See the [Dimension Value API documentation](https://github.com/prebid/pg-dim-val-api/blob/main/docs/server_endpoints.md) for more details. - -{: .alert.alert-info :} -In order to access client-specific targeting data, you'll need to know the account ID the Host Company uses for each publisher. - -See [PG Targeting Syntax](/prebid-server/features/pg/pbs-pg-targeting.html) for a list of targeting attributes you may be able -to get from the PG Host Company and how to format them as part of the [PG Plan](/prebid-server/features/pg/pbs-pg-plan.html). - -### Getting data from the Delivery Stats Service - -There are two reasons PG Bidders need data from the Host Company's PG Delivery Stats Service: - -1. **Line Item reporting**: detailed info is available about where in the delivery funnel each Line Item is getting attention or running into problems. See the [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html#metrics) for which statistics you can expect. -1. **Inform the pacing algorithm**: in order to write a robust and responsive pacing algorithm, the PG Bidder is going to need fresh data. If the bidder's impression data stream is real-time, that may be enough. If not, the Host Company's Delivery Stats server can provide recent (5-minute) summaries of important metrics like tokens spend and bidsWon. See [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html) for more details. - -Some example Delivery Stats queries: - -- GET /del-stats-summ/api/v1/report/line-item-summary?startTime=YYYY-MM-DDT00:00:00.000Z -- this returns an hourly aggregration for all of your line items since the specified time. See the [Line Item Summary Report endpoint documentation](https://github.com/prebid/pg-del-stats/blob/main/docs/line_item_summary_endpoint.md) for more info. -- GET /del-stats-pa/api/v2/report/delivery?bidderCode=pgExample&startTime=YYYY-MM-DDT00:00:00.000Z -- this returns 5-minute aggregations for all of your line items since the specified time. See the [Delivery Report endpoint documentation](https://github.com/prebid/pg-del-stats/blob/main/docs/delivery_report_endpoints.md) - - -### Answering General Planner requests - -When the PG Bidder is ready for integration with the Host Company, they'll provide an authenticated secure endpoint that will answer requests from the Host Company's General Planner. -The path of this endpoint can be anything you'd like. It will receive these query string parameters: - -{: .table .table-bordered .table-striped } -| Parameter | Format | Required? | Description | -| --- | --- | --- | --- | -| since | string | no | Timestamp in ISO-8601 format. For example, 2019-02-01T03:00:00.000Z. Service should respond with all meta data for active or nearly-active line items and schedules that got updated since this timestamp. Absence of this parameter signals request to return all active or nearly-active line items. | -| hours | string | no | Number of hours of plans desired i.e. provide the next 3 hours worth of plans | - -Here's an [example JSON response](https://github.com/prebid/pg-general-planner/blob/main/docs/samples/pa_rsp.json) that might come from your bidder planner. - -At this point, your endpoint needs to respond quickly with the most recently calculated set of PG line item pacing plans. A `plan` is a set -of instructions to Prebid Server that tells the system how often to serve -a line item in a given period. e.g. "serve LineA 50 times from noon-12:05, 55 times from 12:05-12:10, ..." - -The General Planner will be configured to call your endpoint every 1-10 minutes depending on the Host Company. - -See [PG Plan Definition](/prebid-server/features/pg/pbs-pg-plan.html) for more details. - -### General notes on writing a pacing algorithm - -At a high level, pacing a line item seems like it might be simple: - -``` -NumberOfImpressionsEach5MinPeriod=TotalImpressionsRemaining+3percentBuffer / NumberOf5MinPeriodsRemaining -``` - -But this approach wouldn't perform well: -- When the line falls behind, it won't take advantage of higher traffic periods to catch up. It will fall behind during normal low-traffic periods, saving all impressions for the last minute. -- As covered in the description of [tokens](/prebid-server/features/pg/pbs-pg-plan.html#tokens), a PG line item cannot assume that it'll be chosen every time it's offered to the ad server. Prebid PG paces based on tokens, not impressions, so the pacing algorithm needs to estimate how many times each line item needs to be offered to the ad server in order to land a final certified impression. - -Likewise, another naive approach is to try and immediately catch up to the "even delivery" line: -``` -ImpressionDeficit=TotalImpressions+3percentBuffer - TotalImpressionsShouldHaveByNow - -NumberOfImpressionsThis5MinPeriod=ImpressionDeficit * NoiseFactor -``` - -Potential problems with this algorithm: -- If it falls far behind, it could be overly aggressive in trying to catch up, affecting the delivery of other line items. -- If it gets ahead somehow, it will stop delivering entirely until time catches up to the delivery curve. - -Here are some examples of desirable delivery patterns: - -![Desirable delivery patterns](/assets/images/prebid-server/pg/pg-good-delivery.png){: .pb-lg-img :} - -And these are examples of delivery patterns to avoid: - -![Undesirable delivery patterns](/assets/images/prebid-server/pg/pg-bad-delivery.png){: .pb-lg-img :} - -For more information, see the "Plans" section of the [Intro to PG Whitepaper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf). - -{: .alert.alert-warning :} -The PG Host Company may require periodic of testing with your pacing algorithm because undesirable -token management from on PG Bidder could affect line item delivery from other PG Bidders. - -## Related Topics - -- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html) -- [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html) -- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html) -- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html) diff --git a/prebid-server/features/pg/pbs-pg-glossary.md b/prebid-server/features/pg/pbs-pg-glossary.md deleted file mode 100644 index c4dd2df468..0000000000 --- a/prebid-server/features/pg/pbs-pg-glossary.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Programmatic Guaranteed Glossary ---- - -# Programmatic Guaranteed Glossary -{: .no_toc} - -* TOC -{:toc} - -## Basic terminology - -- **Programmatic Ad** - an ad request that flows through the multi-vendor ad tech ecosystem -- **Guaranteed** - A buyer and seller have entered into a contract: to deliver a certain amount of impressions to a particular target over a particular date range. If contract isn't met, there may be financial penalties or extra impressions. -- **PG Host Company** - the entity running the Prebid PG software: Prebid Servers, General Planner, Delivery Stats, and Dimension Value API. -- **Prebid Ad Slot** - the "hole in the page" that's requesting an ad (note: this is not currently standard Prebid.org terminology). -- **Prebid Ad Unit** - a package of bidding parameters that defines which bidders and bid parameters are to be used for a specific "hole in the page". -- **Client Requests** - OpenRTB-like network calls from a client to the Prebid Server requesting one or more auctions. -- **Auction Requests** - a single OpenRTB ad request may contain 1 or more 'imp' blocks that define different auction scenarios. Each of these blocks is an "auction". Auctions are sent to one or more bidders and are associated with auction parameters for each bidder. -- **PG Bidder** - the ad exchange, demand side platform, or other bid source that directly or indirectly connects the Auction Request to a bid. Example bidders include Magnite, Criteo, etc. -- **Bidder Parameters** - the specific parameters required by the bidder describing the auction to take place. The Rubicon account, site, and zone are example parameters. -- **PG Line Item** - the base unit of ad delivery has a goal, date range, target, creatives, deal ID, and pacing options. -- **AdServer Line Item** - corresponding to the PG Line Item, the AdServer has a similar line item which prioritizes the PG Line Item in relation to other direct-sold agreements. It may also have a goal and date range, but the targeting will be just to the deal ID, not the full PG target. The creative is the Prebid-standard creative instead of the actual creative. -- **Deal** - an agreement between a buyer and a seller. In the PG context, a Deal may be comprised of 1 or more line items for different media types, targets, date ranges, etc. Since most bidders won't understand "line items", a candidate Deal ID is likely to be what's passed to each bidder. -- **Line Item Type** - sponsorship, guaranteed, non-guaranteed, house. -- **Creative** - the actual ad that will be seen by an end user. May be an image, HTML, video, or native. -- **Target** - a description of the specific sites, user, device, and geographic characteristics a line item is aimed at. -- **Goal** - How many total impressions a campaign line needs to serve -- **Bonus** - Extra impressions assigned to a campaign line to make sure it delivers at least the total goal. This may be stated as a percentage or a number of impressions. Bonus is important to make sure that impression counting discrepancies don't cause the campaign to be perceived as missing its goal. -- **Goal Type** - which metric is used to meet the goal. (i.e. wins or views) -- **Start and End Datetime** - the date range for the campaign could include starting and ending mid-day. Each campaign may also be associated with a timezone. -- **Delivery Type** - defines the general shape of the desired delivery curve: - - even delivery - impressions are roughly equal each day of the campaign - - front-loaded delivery - there may be more impressions delivered in the early days of the campaign - - as-soon-as-possible - serve this thing whenever there's a chance -- **Historic Delivery** - Number of impressions a line delivered until the end of previous day. -- **Deficit** - The number of impressions a line is behind due to lack of overall inventory, existence of road-blocks, or other reason. -- **Late Deficit** - Number of impressions that a line is behind due to trafficking reasons, normally late creative. We may choose to catch up on a late deficit differently than other kinds of deficits because it's the fault of the advertiser, and it could affect other campaigns. -- **Priority** - a way of ranking competing line items against each other. -- **Oversold** - one or more guaranteed line items are struggling and are unlikely to reach their goals. In some cases it may be better to let some of the line items finish at the expense of others, while in other scenarios it's better to distribute what's available. -- **Underdelivery** - when a line item is not serving enough impressions to meet its goal. -- **Overdelivery** - when a line item is serving too many impressions, or has met its delivery goal too early. -- **Frequency Cap** - how often a given user is allowed to see the advertising message. -- **Discrepancy** - impressions are counted by multiple systems which often different from each other by a few percent. The buyer and seller agree on which numbers are billable. The ad system needs to deliver enough impressions that the goal is met in the system-of-record. -- **Ad Inventory** - the combined set of attributes supplied with an ad request, whether direct or indirect. e.g. page context, user info, device info, etc. Line Item 'Targets' inspect these inventory attributes for matching. -- **Forecast** - how much inventory of a particular type is expected to come in over a specified time period. e.g. "how many 300x250 ad requests from example.com will come from Windows machines next week?" -- **Commitment** - a guaranteed line item that the publisher has promised to deliver to an advertiser. -- **Availability** - starts with the Projection, but removes traffic that's already sold to other committed line items. -- **Availability Buffer** - a safety factor to recognize that projections are always an estimate, and only the most sophisticated delivery systems can properly support the juggling involved in tightly sold overlapping inventory. - -## Metrics - -The basic design of the metrics offered by the PG system is a funnel that allows us to see where a line item's chance to deliver may be struggling. Here are the metrics available: - -- **clientAuctions** - the total number of auction impression requests seen by the system across all accounts. A single HTTPS request to PBS may contain multiple auction requests – this number basically reflects all auctions taking place. -- **accountAuctions** - the number of auctions taking place for the specific Rubicon Project account ID -- **domainMatched** - the number of times the domain portion of this line item's target matched an impression request. e.g. "1000 auctions for example.com". If there is no domain targeting, this number should be the same as accountAuctions. -- **targetMatched** - the number of times the line item's entire target matched a request. -- **targetMatchedButFcapped** - the number of times the line item's entire target matched a request, but the user ad already reached their personal frequency cap limit for this line item. -- **targetMatchedButFcapLookupFailed** - the number of times the line item's entire target matched a request, but was removed from consideration because the lines item has a frequency cap and the lookup to the Frequency Capping system failed. -- **pacingDeferred** - Prebid has taken the line item out of consideration in order to make sure it's not delivering too often -- **sentToBidder** - only the top few matching line items or deals will be sent to each bidder. This metric indicates whether the line item was in the top few. -- **sentToBidderAsTopMatch** - if the line item was considered most ready to serve by Prebid Server before going to the bidder, this metric will be incremented. -- **receivedFromBidder** - this metric indicates whether the bidder chose this deal/line item from the candidates sent to it. Bidders may reject any suggested Deal ID or fail to respond. -- **receivedFromBidderInvalidated** - indicates the number of times this deal/line item was received from a bidder, but rejected by Prebid Server for any reason. Rejection reasons include: incorrect size for auction, target didn't match, ahead of pace and not ready to serve. -- **sentToClient** - indicates how many times this line item was sent as the bidder's top match to the client, and therefore the ad server. -- **sentToClientAsTopMatch** - indicates how many times this line item was sent to the client/ad server flagged by Prebid Server as the most eligible PG line item. -- **lostToLineItems** - this array provides a measure of which competing line items have been considered more eligible to serve than this line item -- **events** - how many times this line item received notification of the stated event type. For now only the only supported event type is "win", but eventually there may be other types like "click", "video 50% played", etc. - -Here's a graphical representation showing what point in the delivery funnel each of these metrics measures: - -![PG Metrics](/assets/images/prebid-server/pg/pg-metrics.png){: .pb-xlg-img :} - -## Related Topics - -- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html) -- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf) diff --git a/prebid-server/features/pg/pbs-pg-host.md b/prebid-server/features/pg/pbs-pg-host.md deleted file mode 100644 index 3abf6b3d5e..0000000000 --- a/prebid-server/features/pg/pbs-pg-host.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Becoming a PG Host Company ---- - -# Becoming a PG Host Company -{: .no_toc} - -* TOC -{:toc} - -## Overview - -Prebid PG is open source, so anyone can spin up the 4 different types of servers -needed to offer a PG service. - -1. Prebid Servers handle the real-time mix of open market and PG auctions. -1. The General Planner collects PG line items from one or more PG Bidders. -1. The Delivery Stats Service provides pacing and reporting information. -1. The Dimension Value API provides the user interface the details required to build targets. - -See [Adding a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) for the -high level view of the components. - -As a PG Host Company, you will have expenses in running and maintaining a global high-performance cluster of servers and databases. You'll need at least one PG Bidder, -which might be one you build on your own or partner with someone else. You're under -no obligation to support other PG Bidders, but your publishers may request it. - -## Installing the Servers - -For now, the only information about building and running the servers is in -the relevant GitHub repos: - -- [Prebid Server Java](https://github.com/prebid/prebid-server-java). Note that Prebid Server Go doesn't currently support Programmatic Guaranteed. -- [General Planner](https://github.com/prebid/pg-general-planner) -- [Delivery Stats Service](https://github.com/prebid/pg-del-stats) -- [Dimension Value API](https://github.com/prebid/pg-dim-val-api) - -Prebid does not offer specific guidance about fault-tolerant architectures. -It's left up to each Host Company to determine what will happen if one of the servers goes down. i.e. Will there be load-balancing, automatic failover, a warm stand-by, or no fault tolerance? - -## General notes on testing the service - -There are a fair number of moving parts in a Prebid PG installation. Prebid.org -does not run a test cluster. Changes are made by Prebid member companies, which do -have test clusters, but they may not test every possible configuration. e.g. different databases, geographic lookup vendors, - -We recommend that PG Host Companies commit to regular testing of software updates -against their specific configuration. - -The testing of PG Bidders and their pacing algorithms may be important to you, -as publishers and advertisers care about the delivery patterns of their ad campaigns -in a variety of challenging scenarios. Prebid.org may have extended recommendations -about PG Bidder testing in the future, but in the meantime, you should consider -joining Prebid.org and chatting with the development teams involved. - -## Announcing your service - -When ready to open their doors for business, Prebid.org members can ask to -have their contact info added to the list of [PG Managed Services](/prebid-server/features/pg/pbs-pg-idx.html#list-of-pg-managed-services). - -## Related Topics - -- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html) -- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf) -- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html) diff --git a/prebid-server/features/pg/pbs-pg-idx.md b/prebid-server/features/pg/pbs-pg-idx.md deleted file mode 100644 index 391b4e0b38..0000000000 --- a/prebid-server/features/pg/pbs-pg-idx.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Prebid Programmatic Guaranteed ---- - -# Prebid Programmatic Guaranteed -{: .no_toc} - -* TOC -{:toc} - -## Prebid Programmatic Guaranteed -In general, Programmatic Guaranteed (PG) has existed for several years as an ad server-based function. -While anchoring PG in the ad server is helpful from a deployment perspective, -the lack of transparency and configurability in the ad server has slowed down product momentum -and made it harder for buyers and sellers to flexibly adjust their strategy and -configurations for PG deals. The introduction of open-source, standards-based -Programmatic Guaranteed, anchored in Prebid Sever, helps both buyers and sellers in -several key ways: - -- It allows publishers to utilize preferred partners and data in the Programmatic infrastructure. -- It streamlines the traditional RFP and I/O process between buyers and sellers -- It separates the pacing, capping and forecasting functions from the ad server so publishers can more easily control and modify deals -- Enables a seamless, software-based negotiation process between buyers and sellers -- Ensures easier interoperability with a wider universe of buy-side platforms - -At a high level, the system allows any **Host Company** running Prebid Server (only PBS-Java for now) to integrate open source components into their existing UIs and data delivery systems. - -In addition, the Host Company can support other **PG Bidders** connecting into their system to make their environment richer for publishers. - -![PG High Level Framework](/assets/images/prebid-server/pg/pg-arch-1.png){: .pb-sm-img :} - -We want to encourage an ecosystem where programmatic vendors can compete on their strengths: some companies may be excellent at hosting a technical infrastructure, while others may excel at usability, reporting, or delivery algorithms. - - -## PG For Publishers - -Publishers interested in trying Programmatic Guaranteed through Prebid should -contact one of the companies hosting a PG cluster. They'll explain how it all works and walk you through the setup process. - -### List of PG Managed Services - -If you're a publisher looking to try Programmatic Guaranteed or a PG bidder that wants to integrate into an existing cluster, here's a list of Prebid.org members to consider: - -- **Magnite** - contact your account representative or globalsupport@magnite.com - -## PG for Bidders - -If you have a demand source and are ready to implement a guaranteed delivery algorithm, learn how to [become a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html). - -## Hosting your own PG Cluster - -If you're ready to host a global high-performance cluster, learn how to [become a PG Host Company](/prebid-server/features/pg/pbs-pg-host.html). - -## Questions? - -Contact prebid-server@prebid.org. - -## Related Topics - -- Intro to PG: [video](https://files.prebid.org/pg/PG_in_Prebid.mp4), [pdf](https://files.prebid.org/pg/PG_in_Prebid_Overview.pdf) -- [PG White Paper](https://files.prebid.org/pg/Prebid_Programmatic_Guaranteed_White_Paper.pdf) -- [Becoming a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) -- [Becoming a PG Host Company](/prebid-server/features/pg/pbs-pg-host.html) -- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html) -- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html) diff --git a/prebid-server/features/pg/pbs-pg-plan.md b/prebid-server/features/pg/pbs-pg-plan.md deleted file mode 100644 index 8c9c9e045e..0000000000 --- a/prebid-server/features/pg/pbs-pg-plan.md +++ /dev/null @@ -1,284 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Programmatic Guaranteed Plans ---- - -# Programmatic Guaranteed Plans -{: .no_toc} - -* TOC -{:toc} - -## What is a PG Plan? - -A `Plan` is a set of instructions to Prebid Server that tells it how often to serve a PG line item in a given period. - -1. Plans are created by each [PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) as an output of their bidder-specific pacing algorithm. -1. The 'General Planner' run by the Host Company will spread the Plan out across the cluster of Prebid Servers. -1. Each Prebid Server works to deliver its part of the Plan. - -Here's what one looks like at a high level: - -``` -[ - { - "lineItemId": "2291", - ... other line item attributes ... - deliverySchedule: [{ - "planId": "2656179", - "startTimeStamp": "2020-08-28T11:50:00.000Z", - "endTimeStamp": "2020-08-28T11:55:00.000Z", - "updatedTimeStamp": "2020-08-28T10:04:12.000Z", - "tokens": [{ - "class": 1, - "total": 50 - }] - },{ - ... next delivery schedule ... - }] - }, - ... next line item ... - } -] -``` - -The key parts of the Plan are: -- Line item details. (See [example](#annotated-plan-example) below) -- An array of Delivery Schedules broken into 5-minute periods -- Each 5-minute period defines a number of `tokens` that need to be delivered - -### Tokens - -A `token` is an ad impression scaled up to overcome delivery obstacles. - -When Prebid Server (PBS) sends a PG line item to the ad server, it might be -chosen to win, or maybe not. In either case, the act of sending a -line item to the ad server causes PBS to create a "cool down" period for that -line item. This is what pacing is all about -- making sure that delivery of the -daily impression goal doesn't complete 20 minutes after midnight. PG delivery -needs to be spread through the day, through the hour, and through each 5-minute period. - -If we could guarantee that the ad server would choose the PG line item to win every time, -we wouldn't need tokens... PG could just use impressions. But that's not the case. There are several reasons why a candidate PG line item might not end up -getting a final certified ad impression: -- competing line items in the ad server -- competing PG line items from another vendor -- user leaves the page before ad render -- the impression may be discounted as non-human traffic - -Basically, the pacing algorithms are working in a "noisy" environment. Not only are there -many things that can get in the way of delivering a certified an ad impression, -conditions can change rapidly, e.g. competing line items may start or stop, or the DSP may change its bidding pattern. - -So a "token" is Prebid PG's way of dealing with noise in the system. -Instead of being satifisfied with offering a PG line item to the ad server -and assuming that it will become a certified impression, PG operates in tokens instead, knowing that some of those opportunities won't materialize. -You can think of it in terms of this basic formula: - -``` -Tokens = ImpressionsNeeded * Noise -``` - -Where the "noise" factor is how many tokens it's currently taking to get an ad -impression through the gauntlet of challenges. Determining this noise factor -is part of what the pacing algorithm needs to do -- adjusting it in real time -as needed. e.g. if it's been taking 2 trips to the ad server to get a "bid won", the noise factor is 2, so in a plan that requires 50 impressions, there would be 100 tokens. -You might wonder "why doesn't Prebid Server just take care of this?" Because Prebid Server is stateless... useful statistics are forwarded from hundreds of front-end servers and it's the job of the backend servers to aggregate and use that data. - -Of course noise could be infinite. For example, if there's a 'roadblock' -ad in the ad server, it's possible that a PG line item will just stop delivering -entirely for a day or more, and that's ok. But even though noise can be infinite, -tokens cannot be. The Host Company will cap tokens at some reasonable level, -but the best strategy for the infinite noise scenario is to give up and use a -very small token count, waiting for when the problem has lifted. - -A good real-time way to monitor noise is to compare two fields -in the Delivery Stats reports: sentToClientAsTopMatch vs events.bidsWon. (See the [glossary.](/prebid-server/features/pg/pbs-pg-glossary.html#metrics)) These values -are indications of how many times the line item was offered to the ad server -and accepted. But this value may also be tempered with data from your -clean financial pipeline that compares certified impressions with events.bidsWon. - -### Plan Attributes - -These are the attributes that are part of a Plan. See below for an [annotated example](#annotated-plan-example). - -{: .table .table-bordered .table-striped } -| Attribute | Required? | Description | Data Type | -| --- | --- |--- |--- | -| lineItemId | yes | Bidder-specific ID for this line item | string | -| source | yes | Your PG bidder code. e.g. "pgBidderA" | string | -| status | yes | Whether this line item is currently "active" or not. The only value that matters to the General Planner is "active". Any other value will cause the line item to be ignored. | string | -| dealId | yes | Bidder-specific deal ID. Note that a Deal ID may be used by multiple line items. | string | -| accountId | yes | Host Company-specific value for the publisher. | string | -| price.cpm | yes | The CPM of the line item. | float | -| price.currency | yes | The currency for the CPM of the line item. | string | -| relativePriority | yes | Relative ranking specific to your pacing algorithm. You can put every line item at the same priority, or create 1000 different levels managed by your pacing algorithm. | integer | -| sizes | yes | An array of creative sizes associated with the line item. e.g. `[{"w": 468,"h": 60},{"w": 728,"h": 90}]` | array of objects | -| frequencyCaps.fcapId | no | Bidder-specific frequency cap ID. Needs to be uniqueo within your line items. | string | -| frequencyCaps.count | no | How many impressions can be served | integer | -| frequencyCaps.periods | no | Over how many periods | integer | -| frequencyCaps.periodType | no | Period length. E.g. "day" or "hour" | string | -| targeting | yes | Defines which ad requests are of interest to this line item. See [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html) | object | -| startTimeStamp | yes | Line start time in UTC. e.g. 2020-08-28T07:22:14.000Z | string | -| endTimeStamp | yes | Line end time in UTC. | string | -| updatedTimeStamp | no | When this plan was last modified. | string | -| deliverySchedules | yes | array of objects | -| deliverySchedules.planId | yes? | Bidder-specific ID for use in debugging. Should be unique. | string | -| deliverySchedules.startTimeStamp | yes | Start time of plan period in UTC | string | -| deliverySchedules.endTimeStamp | yes | End time of plan period in UTC | string | -| deliverySchedules.updatedTimeStamp | no | When this plan period was last modified.| string | -| deliverySchedules.tokens.class | no | For future use. Set to 1 for now. | integer | -| deliverySchedules.tokens.total | yes | Token count (Impressions * Noise) for this plan period. | integer | - -## Plans and the General Planner - -The General Planner will poll the PG Bidder endpoint frequently - e.g. every minute or every 5-minutes. The exact period will be determined between you and the Host Company, but it needs to be often because pacing line items is a dynamic business. -Even though it will be contacted frequently, they should still generate -several hours worth of the delivery schedule in case communication breaks down somehow. - -Once it receives the Plan, the General Planner will split up the tokens across -Prebid Servers. When a line item first starts, it does this in a really blunt way: just divides them evenly across the servers. But it will soon start adjusting for geographic differences -in line item delivery. e.g. if a line item only serves tokens in Europe, the Prebid Servers in Europe will get all the tokens within a few cycles. - -## Plans and Prebid Server - -Each PBS polls the General Planner once per minute, getting new and updated Plans. -Here's how it works: - -1. When an auction request comes in, check to see if the account has any active PG line items. If it doesn't, process the request normally. -2. If it is an account with active PG line items, enhance the request with geographic, device, user, and frequency capping information -3. Find out which PG line items have targets that match the current request -4. Loop through the matching line items - 1. Increment the "targetMatched" metric. - 1. If the PG line item has a frequency cap and there's no user ID or the lookup failed, increment the "targetMatchedButFcapLookupFailed" metric and take it off the list. - 1. If the PG line item has a frequency cap and it's met the cap, increment the "targetMatchedButFcapped" metric and take it off the list. - 1. If the PG line item is in "cool-down", increment the "pacingDeferred" metric and take it off the list -5. Sort the remaining line items into priority order based on the PG-bidder-provided "relative priority", with a random secondary sort. -6. Take the first 3 PG line items for each PG Bidder and send them the relevant bid adapter, incrementing the "sentToBidder" metric for each, and the "sentToBidderAsTopMatch" metric for one of them. -7. Wait for the auction delay for the results. Increment "receivedFromBidder" and "receivedFromBidderInvalidated" metrics as appropriate. -8. Take the highest priority bid from each PG Bidder and prepare ad server targeting. Increment the "sentToClient" metric. -9. If there's more than one bid from a PG Bidder, randomly choose one to be the overall winner and increment the "sentToClientAsTopMatch" metric. Only this line item is considered to have spent a token and is put into "cool-down": PBS calculates how many milliseconds it needs to wait before offering this line item to the ad server again. - -{: .alert.alert-info :} -Random numbers are used at a couple of points in the PG algorithm. This is to avoid choosing the same aggressive-but-blocked line item every time. - -## Annotated Plan Example - -Here's a complete example of a Plan with all line item and delivery schedule fields. - -``` -[ // each line item has a plan entry - { - "lineItemId": "2291", // this is specific to your internal systems - "dealId": "710216", // also specific to your internal systems - "accountId": "1001", // the Host Company's account ID for the publisher - "price": { - "cpm": 7.29, - "currency": "EUR" - }, - "relativePriority": 2, // relative stacking specific to your pacing algorithm - "sizes": [{ // creative sizes - "w": 468, - "h": 60 - }, - { - "w": 728, - "h": 90 - } - ], - "frequencyCaps": [{ // Host Company may support multiple cap levels - "fcapId": "LI-2291", // ID specific to your system - "count": 2, // show no more than 2 times per 1 day - "periods": 1, - "periodType": "day" - } - ], - "targeting": { // Line Item targeting - "$and": [{ - "adunit.size": { - "$intersects": [{ - "h": 60, - "w": 468 - }, - { - "h": 90, - "w": 728 - } - ] - } - },{ - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - },{ - "device.ext.deviceatlas.browser": { - "$in": [ - "Chrome", - "Firefox" - ] - } - },{ - "device.geo.ext.netacuity.country": { - "$in": [ - "us", - "jp" - ] - } - },{ - "adunit.adslot": { - "$in": [ - "/1111/QA_Tests" - ] - } - } - ] - }, - "startTimeStamp": "2020-08-28T07:22:14.000Z", // line start time in UTC - "endTimeStamp": "2020-08-30T17:22:14.000Z", // line end time in UTC - "updatedTimeStamp": "2020-08-28T06:22:15.000Z", - "deliverySchedules": [ // now starts the plans - { - "planId": "2656177", // ID is specific to your system - "startTimeStamp": "2020-08-28T11:40:00.000Z", // UTC 11:40 to 11:45 - "endTimeStamp": "2020-08-28T11:45:00.000Z", - "updatedTimeStamp": "2020-08-28T11:36:30.000Z", - "tokens": [ - { - "class": 1, // always 1 for now - "total": 8 // number of tokens - } - ] - }, - { - "planId": "2656178", - "startTimeStamp": "2020-08-28T11:45:00.000Z", // UTC 11:45 to 11:50 - "endTimeStamp": "2020-08-28T11:50:00.000Z", - "updatedTimeStamp": "2020-08-28T11:38:19.000Z", - "tokens": [ - { - "class": 1, - "total": 10 - } - ] - },{ - ... more plans ... - } - ], - "source": "pgBidderCode", - "status": "active" - }, - { - ... next line item ... - } -] -``` - -## Related Topics - -- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html) -- [Becoming a PG Bidder](/prebid-server/features/pg/pbs-pg-bidder.html) -- [PG Targeting](/prebid-server/features/pg/pbs-pg-targeting.html) -- [PG Glossary](/prebid-server/features/pg/pbs-pg-glossary.html) diff --git a/prebid-server/features/pg/pbs-pg-targeting.md b/prebid-server/features/pg/pbs-pg-targeting.md deleted file mode 100644 index dd8157733a..0000000000 --- a/prebid-server/features/pg/pbs-pg-targeting.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -layout: page_v2 -sidebarType: 5 -title: Programmatic Guaranteed Targeting Syntax ---- - -# Programmatic Guaranteed Targeting Syntax -{: .no_toc} - -* TOC -{:toc} - -## Overview - -Targeting is the ability for Prebid Server (PBS) to match PG line items with -incoming OpenRTB auction requests. - -Here's a simple example target that says this line item will match any request for a 300x250 banner: - -``` -{ - "$and": [ - { - "adunit.size": {"$intersects": [{"w": 300,"h": 250}]} - }, - { - "adunit.mediatype": {"$intersects": ["banner"]} - } - ] -} -``` - -In general, the syntax is: -``` -{ - "$and/$or": [ - { "ATTRIBUTE": { "OPERATOR": CONDITION } }, - "$and/$or": [ ... ], - "$not": { "ATTRIBUTE": { "OPERATOR": CONDITION } } - ] -} -``` -Here are the supported OPERATORs: - -{: .table .table-bordered .table-striped } -| Operator | Description | Attribute Datatype | Condition Datatype | Example | -| --- | --- | --- | --- | -| $matches | True if the scalar ATTRIBUTE is the same as the CONDITION, or matches with an asterisk wildcard. | string | string | "$matches": "{::nomarkdown}*sports*{:/}" | -| $in | True if the scalar ATTRIBUTE is on the CONDITION's array. | string | array of strings | "$in": ["a","b"] | -| $intersects | True if at least one value from the ATTRIBUTE's array is on the CONDITION's array | array of strings | array of strings | "$intersects": ["hockey","soccer"] | -| $within | True if user's lat/long are available and within the circle defined by the CONDITION. | from geolookup service | object with attributes: lat, lon, and radiusMiles | "$within": {"lat": 123.456,"lon": 789.123,"radiusMiles": 50} | - -## Targeting Attributes - -The full list of attributes supported by Prebid Server may differ by PG Host Company because they might use different geographic and device information services. But here's an example list: - -{: .table .table-bordered .table-striped } -| Attribute | Description | Encoding | PBS Source | OpenRTB path | Operators | -| --- | --- | --- | --- | --- | --- | -| adunit.size | Ad Sizes | [{w: 300, h: 250},...] | OpenRTB | imp[].banner.format[] | intersects | -| adunit.mediatype | Mediatype | string | OpenRTB | mediatype="banner" if imp.banner exists. mediatype="video-instream" if imp.video exists and placement is 1. mediatype="video-outstream" if imp.video exists and placement is <> 1. mediatype="native" if imp.native exists | intersects | -| adunit.adslot | The ad server slot name | string | OpenRTB | imp[].ext.context.data.pbadslot | in, matches | -| site.domain | Site domain | string | OpenRTB | site.domain | in, matches | -| site.referrer | Referring URL | string | OpenRTB | site.page | in, matches | -| app.bundle | Mobile application bundle | string | OpenRTB | app.bundle | in, matches | -| pos | Page position | 0=unknown, 1=ATF, 3=BTF | OpenRTB | imp.banner.pos | in | -| geo.distance | User's lat/lon is within a defined circle | none | Geo vendor | device.geo.lat, device.geo.lon | within | -| device.geo.ext.VENDOR.country | Country | string | Geo vendor | device.geo.ext.VENDOR.country | in| -| device.geo.ext.VENDOR.region | Region | string | Geo vendor | device.geo.ext.VENDOR.region | in| -| device.geo.ext.VENDOR.metro | Metro (DMA) | string | Geo vendor | device.geo.ext.VENDOR.metro | in| -| device.geo.ext.VENDOR.city | City | string | Geo vendor | device.geo.ext.VENDOR.city | in| -| device.geo.ext.VENDOR.zip | Postal Code | string | Geo vendor | device.geo.ext.VENDOR.zip | in| -| device.ext.VENDOR.connspeed | Connection Speed | string | Device vendor | device.ext.VENDOR.connspeed | in| -| device.ext.VENDOR.type | Device Type | string | Device vendor | device.ext.VENDOR.type | in| -| device.ext.VENDOR.make | Device Make | string | Device vendor | device.ext.VENDOR.make | in| -| device.ext.VENDOR.model | Device Model | string | Device vendor | device.ext.VENDOR.model | in| -| device.ext.VENDOR.os | Operating System | string | Device vendor | device.ext.VENDOR.os | in| -| device.ext.VENDOR.browser | Browser | string | Device vendor | device.ext.VENDOR.browser | in| -| device.ext.VENDOR.browserver | Browser Version | string | Device vendor | device.ext.VENDOR.browserver | in| -| device.ext.VENDOR.language | Device Language | string | Device vendor | device.ext.VENDOR.language | in| -| device.ext.VENDOR.osver | Operating System Version | string | Device vendor | device.ext.VENDOR.osver | in| -| device.ext.VENDOR.carrier | Internet Carrier | string | Device vendor | device.ext.VENDOR.carrier | in| -| user.ext.time.userdow | User Day of Week | 1=sun, 7=sat | Geo vendor + clock | user.ext.time.userdow | in| -| user.ext.time.userhour | User Hour | 0-23 |Geo vendor + clock | user.ext.time.userhour | in| -| ufpd.ATTR | User First Party Data | string | OpenRTB | user.ATTR or user.ext.data.ATTR | in, matches, intersects | -| sfpd.ATTR | Site First Party Data | string | OpenRTB | imp[].ext.context.data.ATTR=VAL OR site.ext.data.ATTR=VAL OR app.ext.data.ATTR=VAL | in, matches, intersects | -| segment.SOURCE | User Segment Data | string | OpenRTB | user.data[].id=SOURCE AND VALUE in user.data[].segment[].id | intersects | -| bidp.BIDDER.ATTR | Bid Parameter Data | string | OpenRTB | imp[].ext.BIDDER.ATTR | in, matches, intersects| - -## Targeting Syntax - -Here's an example of a ridiculously specific target that uses most of the -attributes and specific geographic and device info services: - -``` -{ - "$and": [ - { - "adunit.size": {"$intersects": [{"w": 300,"h": 250},{"w": 300,"h": 600}]} - }, - { - "adunit.mediatype": {"$intersects": ["banner"]} - }, - { - "$or": [ - {"site.ext.domain": {"$matches": "*.example.com"}}, - {"site.ext.domain": {"$in": ["prebid.org"]}} - ] - }, - { - "$or": [ - {"site.referrer": {"$matches": "*sports*"}}, - {"site.referrer": {"$matches": "*prebid*"}} - ] - }, - { - "$or": [ - {"adunit.adslot": {"$matches": "/home/top*"}}, - {"adunit.adslot": {"$in": ["/home/bottom"]}} - ] - }, - { - "pos": {"$in": [1,3]} - }, - { - "device.geo.ext.netacuity.country": {"$in": ["us","de"]} - }, - { - "device.geo.ext.netacuity.region": {"$in": ["de-bw","de-by"]} - }, - { - "device.geo.ext.netacuity.metro": {"$in": ["111","222"]} - }, - { - "device.geo.ext.netacuity.city": {"$in": ["444","555"]} - }, - { - "geo.distance": {"$within": {"lat": 123.456,"lon": 789.123,"radiusMiles": 50}} - }, - { - "device.ext.deviceatlas.type": {"$in": ["tablet","phone"]} - }, - { - "$or": [ - {"bidp.rubicon.siteId": {"$in": [123,321]}}, - {"bidp.appnexus.placementName": {"$matches": "*99999*"}}, - ] - }, - { - "$or": [ - {"segment.rp": {"$intersects": [123,234,345]}}, - {"segment.bluekai": {"$intersects": [123,234,345]}} - ] - }, - { - "sfpd.sport": {"$intersects": ["hockey","soccer"]} - }, - { - "user.ext.time.userdow": {"$in": [5,6]} - }, - { - "user.ext.time.userhour": {"$in": [10,11,12,13,14]} - }, - { - "$not": { - "ufpd.registered": {"$matches": ["false"]} - } - } - ] -} -``` - - -## Related Topics - -- [PG Home Page](/prebid-server/features/pg/pbs-pg-idx.html) -- [PG Plans](/prebid-server/features/pg/pbs-pg-plan.html) diff --git a/prebid-server/hosted-servers.md b/prebid-server/hosted-servers.md index f9c1618a1f..1dce66e3c9 100644 --- a/prebid-server/hosted-servers.md +++ b/prebid-server/hosted-servers.md @@ -9,4 +9,4 @@ sidebarType: 5 # Hosted Prebid Servers {:.no_toc} -See [https://prebid.org/product-suite/managed-services/](https://prebid.org/product-suite/managed-services/) +See [prebid.org/product-suite/managed-services](https://prebid.org/product-suite/managed-services/) diff --git a/prebid-server/hosting/bidder-specific-guidelines.md b/prebid-server/hosting/bidder-specific-guidelines.md new file mode 100644 index 0000000000..3ff6872d7b --- /dev/null +++ b/prebid-server/hosting/bidder-specific-guidelines.md @@ -0,0 +1,85 @@ +--- +layout: page_v2 +title: Bidder-Specific Hosting Guidelines +description: Bidder-Specific Hosting Guidelines +pid: 0 +sidebarType: 5 +--- + +# Bidder-Specific Hosting Guidelines +{:.no_toc} + +- TOC +{:toc} + +## Setting up a Bid Adapter + +In general, a PBS host company may want to run only the server-side bid adapters they require. + +PBS-Go enables most bidders by default. PBS-Java doesn't enable any bidders by default. + +### Geographic Regions + +Bidders can declare certain geographic details in their YAML that host companies should be aware of: + +1. Some bidders (e.g. rubicon) have region-specific auction endpoints. They want the host company to choose the closest matching endpoint. e.g. if the bidder says they have two endpoint "us" and "eu", you should deploy that bidders YAML with the appropriate endpoint value when you deploy to your various datacenters. Your DevOps team should be able to do this with whatever system you're using to deploy. +1. Some bidders (e.g. 33across) don't do business globally. They won't bid on requests in certain regions, so it helps everyone to avoid sending them bid requests outside of their scope of business. Please look for a `geoscope` parameter in the bidder's YAML file and consider disabling that bidder in regions where it might not make sense to call them. Again, your DevOps team should be able to manage this. + +Note that Prebid Server does not have the ability to automatically determine its datacenter region and take these actions for host companies. It must be done as part of the deploy. + +### PBS-Go + +You might want to consider disabling bid adapters that you're not +going to utilize in order to control which bidders get into the [/cookie_sync](/prebid-server/endpoints/pbs-endpoint-cookieSync.html) response when you're running the `coopSync` flag. + +To disable a bid adapter, in your main pbs.yaml file, set: + +```yaml +adapters: + BIDDERCODE: + disabled: true +``` + +As noted above, if the bidder supports different endpoints per geography, you can deploy different +config in each of your datacenters: + +```yaml +adapters: + BIDDERCODE: + endpoint: REGION_SPECIFIC_ENDPOINT +``` + +### PBS-Java + +To enable a bid adapter, in your main YAML file, set: + +```yaml +adapters: + BIDDERCODE: + enabled: true +``` + +As noted above, if the bidder supports different endpoints per geography, you can deploy different +config in each of your datacenters: + +```yaml +adapters: + BIDDERCODE: + enabled: true + endpoint: REGION_SPECIFIC_ENDPOINT +``` + +## Bidder-Specific Details + +### Rubicon + +If you'd like to run the [rubicon](/dev-docs/bidders/rubicon.html) Prebid Server adapter, here's the process: + +1. Contact explaining who you are and that you'd like to set up a Prebid Server that utilizes the rubicon adapter. +2. They will ask you a bunch of questions and hopefully approve your application. +3. If they do approve, you'll be given a login and password to place in your configuration. Please do not share this with anyone else. You'll also be provided a usersync URL. +4. The Magnite XAPI has several regional endpoints that you can utilize. Note that the default endpoint in the open source config is for US-East, which may not perform as well for you as the other regional options if your datacenters are in Europe or Asia. + +## Related Reading + +- [Hosting a Prebid Server Cluster](/prebid-server/hosting/pbs-hosting.html) diff --git a/prebid-server/hosting/hosted-servers.md b/prebid-server/hosting/hosted-servers.md index 64636b6a76..a49cf0e66d 100644 --- a/prebid-server/hosting/hosted-servers.md +++ b/prebid-server/hosting/hosted-servers.md @@ -11,4 +11,4 @@ sidebarType: 5 Several Prebid.org members host Prebid Server clusters for use by publishers. -See [https://prebid.org/product-suite/managed-services/](https://prebid.org/product-suite/managed-services/). +See [prebid.org/product-suite/managed-services/](https://prebid.org/product-suite/managed-services/). diff --git a/prebid-server/hosting/pbs-database.md b/prebid-server/hosting/pbs-database.md index 08efe50163..bed4b269fa 100644 --- a/prebid-server/hosting/pbs-database.md +++ b/prebid-server/hosting/pbs-database.md @@ -2,18 +2,36 @@ layout: page_v2 sidebarType: 5 title: Prebid Server | Developer | Database - --- # Prebid Server Database +{:.no_toc} + +* TOC +{:toc} + +## Overview + +Companies looking to spin up Prebid Server should consider setting up a database. +It could actually be file-based or no-sql based, but for the purposes of this reference, we'll assume a relational DB. +Here are the kinds of data that PBS needs from a data store: +- **account data:** defaults and settings for things like price granularities, time-to-live, privacy regulations, and modules. +- [stored requests](/prebid-server/features/pbs-storedreqs.html): blocks of JSON that define how PBS responds to mobile and AMP requests. +- **stored responses:** very useful for debugging -Companies looking to spin up Prebid Server will need to connect a database. Our design -strategy was to avoid a fixed schema, instead allowing each host company the flexibility -to define their schema any way they'd like. +**Where does this data come from?** You, the host company need to figure that out. PBS never writes this data, only reads it. The difference between a good PBS host company and an average one will be in details like the managing of this data. + +**What's the schema?** Our design +strategy is to avoid a fixed schema, instead allowing each host company the flexibility +to define their schema any way they'd like. The vision is that you already have a database +somewhere attached to a user interface that collects similar data from your users. We want +you to be able to integrate a few tables into that existing database and then replicating them to high-speed read-only copies wherever you have clusters. So instead of Prebid defining your schema, we just define the fields that need to come from the query. You can then design the SQL query and put it in PBS configuration. +That said, it's often been requested that Prebid just suggest a minimal schema, so there are examples below. + ## Database Queries Prebid Server queries the database in the following scenarios: @@ -21,10 +39,10 @@ Prebid Server queries the database in the following scenarios: {: .table .table-bordered .table-striped } | Data | SQL Config | Description | |------+---------------+-------------| -| Stored Requests | settings.database.stored-requests-query | Retrieve stored request JSON for incoming OpenRTB | -| AMP Stored Requests | settings.database.amp-stored-requests-query | Retrieve stored request JSON for incoming AMP | -| Stored Responses (PBS-Java only) | settings.database.stored-responses-query | (PBS-Java only) Retrieve stored response data | -| Account Data | (none) | Retrieve host company-specific account information | +| Auction endpoint Stored Requests | settings.database.stored-requests-query | Retrieve stored request JSON for incoming OpenRTB | +| AMP endpoint Stored Requests | settings.database.amp-stored-requests-query | Retrieve stored request JSON for incoming AMP | +| Stored Responses | settings.database.stored-responses-query | Retrieve stored response data | +| Account Data | settings.database.account-query (PBS-Java only) | Retrieve host company-specific account information | ## Expected Response Fields @@ -35,24 +53,39 @@ The Stored Request query needs to return fields in this order: {: .table .table-bordered .table-striped } | Field Num | Name | Type | Meaning | Default | |-----------+------+------+---------+---------| -| 1 | request ID | string | The Stored Request ID | n/a | -| 2 | request body | JSON | The body of the Stored Request | n/a | -| 3 | label | string | This is always just the static value 'request' | n/a | +| 1 | account ID | string | The Account ID may be used to distinguish between stored request IDs with the same name across accunts. (PBS-Java only) | n/a | +| 2 | request ID | string | The Stored Request ID | n/a | +| 3 | request body | JSON | The body of the Stored Request | n/a | +| 4 | label | string | Defines whether this item is a 'request' (top-level SR) or 'imp' (imp-level SR).| n/a | There are two parameters that can be passed into the query: -- %REQUEST_ID_LIST% : a comma-separated list of "top-level" stored request IDs -- %IMP_ID_LIST% : a comma-separated list of "impression-level" stored request IDs +- %REQUEST_ID_LIST% : a comma-separated list of "top-level" stored request IDs - these are the IDs in ext.prebid.storedrequest.id. +- %IMP_ID_LIST% : a comma-separated list of "impression-level" stored request IDs - these are the IDs in imp[].ext.prebid.storedrequest.id. This query is defined in settings.database.stored-requests-query. Example: ``` settings: database: type: mysql - stored-requests-query: SELECT uuid, config, 'request' as dataType FROM stored_requests WHERE uuid IN (%REQUEST_ID_LIST%) UNION ALL SELECT uuid, config, 'imp' as dataType FROM stored_requests WHERE uuid IN (%IMP_ID_LIST%) + stored-requests-query: SELECT accountId, reqid, storedData, 'request' as dataType FROM stored_requests WHERE reqid IN (%REQUEST_ID_LIST%) UNION ALL SELECT accountId, reqid, storedData, 'imp' as dataType FROM stored_requests WHERE reqid IN (%IMP_ID_LIST%) +``` + +This **example** assumes that one table contains both top-level and imp-level stored requests: + +``` +CREATE TABLE `stored_requests` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `accountId` int(11) NOT NULL, + `reqid` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `storedData` json NOT NULL +) ``` -Again, you can name the fields however you'd like in your database, and the query can be arbitrarily complicated as long as it returns the fields in the order and types shown here. +{: .alert.alert-info :} +This schema is for example only -- it's not a terribly smart schema for use in production. You should consider adding fields like insertDate and updateDate, and of course define indices. And again, you can name the fields however you'd like in your database, and the query can be arbitrarily complicated as long as it returns the fields in the order and types shown in the example query. + +Note: if we had to do it all over again, we'd get rid of the distinction between REQUEST_ID_LIST and IMP_ID_LIST. ### AMP Stored Requests @@ -64,12 +97,15 @@ This query is defined in settings.database.amp-stored-requests-query. Example: settings: database: type: mysql - stored-requests-query: SELECT uuid, config, 'request' as dataType FROM stored_requests WHERE uuid IN (%REQUEST_ID_LIST%) + amp-stored-requests-query: SELECT accountId, reqid, storedData, 'request' as dataType FROM stored_requests WHERE reqid IN (%REQUEST_ID_LIST%) ``` +It's expected that your AMP stored requests are stored in the same schema as yourother stored requests. The query is, however, separably configurable. + + ### Stored Responses -(PBS-Java only) The Stored Response query needs to return fields in this order: +The Stored Response query needs to return fields in this order: {: .table .table-bordered .table-striped } | Field Num | Name | Type | Meaning | Default | @@ -77,31 +113,42 @@ settings: | 1 | response ID | string | The Stored Response ID | n/a | | 2 | response body | JSON | The body of the Stored Response | n/a | -One parameter can be passed into the query: +One parameter can be passed into the query, though at this point, the parameter differs between Go and Java: -- %RESPONSE_ID_LIST% : a comma-separated list of stored response IDs +- %RESPONSE_ID_LIST% (PBS-Java): a comma-separated list of stored response IDs. These come from imp[].ext.prebid.storedbidresponse or imp[].ext.prebid.storedauctionresponse. +- %ID_LIST% (PBS-Go): a comma-separated list of stored response IDs. These come from imp[].ext.prebid.storedbidresponse or imp[].ext.prebid.storedauctionresponse. This query is defined in settings.database.stored-requests-query. Example: ``` settings: database: type: mysql - stored-responses-query: SELECT resid, responseData FROM stored_responses WHERE resid IN (%RESPONSE_ID_LIST%) + stored-responses-query: SELECT resid, responseData FROM stored_responses WHERE resid IN (%ID_LIST%) +``` + +This **example** schema assumes that the stored_responses schema includes these fields: ``` +CREATE TABLE `stored_responses` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `resid` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `responseData` json NOT NULL +) +``` + +{: .alert.alert-info :} +This schema is for example only -- it's not a terribly smart schema for use in production. You should consider adding fields like insertDate and updateDate, and of course define indices. And again, you can name the fields however you'd like in your database, and the query can be arbitrarily complicated as long as it returns the fields in the order and types shown in the example query. + +Note: there's no reason you couldn't put stored responses in the same table as stored requests as long as there's a field differentiating them for use in the query. ### Account Data {: .alert.alert-info :} -Despite what we said about Prebid not defining your schema, it's not true for account data. -Currently the account query is hard-coded in both versions of Prebid-Server. You could -create a view as desired. We'll fix this someday. +In PBS-Java, many account-configuration options come from the database. In PBS-Go, those options are available in either a YAML configuration or from an HTTP API. Account data is queried on every request to pull in important data. There is an LRU cache in the server so the database isn't actually hit on every request. -In PBS-Java, many account-configuration options come from the database. In PBS-Go, those options are available in either a YAML configuration or from an HTTP API. - -In both versions the server can optionally validate the account against this database and reject accounts from +In both versions the server can optionally validate the account and reject accounts from unknown sources. The algorithm the server uses for determining the account ID of the incoming request is: @@ -110,31 +157,32 @@ The algorithm the server uses for determining the account ID of the incoming req 2. look in app.publisher.id 3. if AMP, look for the 'account' parameter on the query string -Here are the fields the server can recognize in the database response: +One parameter can be passed into the query: + +- %ACCOUNT_ID% : selects the right row in the DB -{: .table .table-bordered .table-striped } -| Field Num | Name | Type | Meaning | Default | -|-----------+------+-----+---------+---------| -| 1 | uuid | string | Host-company specific account ID | n/a | -| 2 | price_granularity | enum | Deprecated. Granularity should be part of stored requests or the incoming OpenRTB. | n/a | -| 3 | banner_cache_ttl | integer | (PBS-Java only) How long (seconds) banner bids should be cached for this account. | Config | -| 4 | video_cache_ttl | integer | (PBS-Java only) How long (seconds) VAST should be cached for this account. | Config | -| 5 | events_enabled | 0 or 1 | (PBS-Java only) Whether to emit event URLs for this account. | 0 | -| 6 | enforce_ccpa | 0 or 1 | (PBS-Java only) Whether to enforce US-Privacy rules for this account. | Config | -| 7 | enforce_gdpr | 0 or 1 | (PBS-Java only) Whether to enforce TCF1 GDPR rules for this account. Deprecated. Use tcf_config for TCF2. | Config | -| 8 | tcf_config | JSON | (PBS-Java only) TCF2 override settings for this account. | Config | -| 9 | analytics_sampling_factor | tiny int | (PBS-Java only) Turns on analytics sampling for this account. Sampling mechanism is 1-in-N. e.g. if this value is a 2, it's a 1-in-2 (50%) sample. If 5, then 1-in-5 (20%). Max value is 100 (1%) | 1 | -| 10 | truncate_target_attr | tiny int | (PBS-Java only) Number of bytes allowed for targeting attributes for this account. 0=unlimited. | Config | - -Currently this query is hard-coded in both versions of Prebid-Server: - -PBS-Go: +The query is configurable. For example: ``` -SELECT uuid, price_granularity FROM accounts_account where uuid = ? LIMIT 1 +settings: + database: + account-query: JSON_MERGE_PATCH(JSON_OBJECT( 'id', accountId ), COALESCE(config, '{}')) as consolidated_config FROM accounts WHERE accountId = %ACCOUNT_ID% LIMIT 1 ``` -PBS-Java +This **example** schema assumes that the accounts schema includes these fields: ``` -SELECT uuid, price_granularity, banner_cache_ttl, video_cache_ttl, events_enabled, enforce_ccpa, tcf_config, analytics_sampling_factor, truncate_target_attr FROM accounts_account where uuid = ? LIMIT 1 +CREATE TABLE `accounts` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `accountId` int(11) NOT NULL, + `config` json NOT NULL +) ``` +{: .alert.alert-info :} +This schema is for example only -- it's not a terribly smart schema for use in production. You should consider adding fields like insertDate and updateDate, and of course define indices. And again, you can name the fields however you'd like in your database, and the query can be arbitrarily complicated as long as it returns the fields in the order and types shown in the example query. + +See the [PBS-Java configuration docs](https://github.com/prebid/prebid-server-java/blob/master/docs/application-settings.md#configuration-document-json) for detail on the JSON structure expected as the +result of the query. There are many account-level settings detailed there. + +## Related Reading +- [Stored Requests](/prebid-server/features/pbs-storedreqs.html) +- [Hosting a PBS cluster](/prebid-server/overview/prebid-server-overview.html) diff --git a/prebid-server/hosting/pbs-hosting.md b/prebid-server/hosting/pbs-hosting.md index 144fd0f196..e48f9e94f0 100644 --- a/prebid-server/hosting/pbs-hosting.md +++ b/prebid-server/hosting/pbs-hosting.md @@ -11,25 +11,42 @@ title: Prebid Server | Hosting * TOC {:toc} -Spinning up a self-hosted cluster of Prebid Servers requires some up-front-planning. -The components that will be needed are highlighted in this hardware +## Overview + +Prebid Server is not a turn-key solution. Whoever takes on hosting a Prebid Server is also taking on: + +* Setting up production-quality servers, networking, monitors, etc. +* Populating backend data such as stored requests and account-level configuration +* Responsibility for understanding the legal implications of ad tech in your marketplace. PBS has built-in configurable support for [several privacy regulations](/prebid-server/features/pbs-privacy.html), but you need to understand and configure them with help from your lawyers. +* Regular updates. Please don't download Prebid Server and just run the same version forever. You need to commit to checking **at least** quarterly for updates. There are new releases most every week. + +You'll need to decide which of the two implementations to utilize: + +* [Prebid Server (Go)](/prebid-server/versions/pbs-versions-go.html) - the original Prebid Server is written in the Go language. +* [Prebid Server (Java)](/prebid-server/versions/pbs-versions-java.html) - Prebid Server with a Java language port. + +To choose between them, see the [Prebid Server version overview](/prebid-server/versions/pbs-versions-overview.html) and the [FAQ](/faq/prebid-server-faq.html#why-are-there-two-versions-of-prebid-server-are-they-kept-in-sync). + +## Components + +The components required to support a PBS cluster are highlighted in this hardware layout diagram: ![Prebid Server Hardware Layout](/assets/images/prebid-server/pbs-hardware-layout.png){:class="pb-xlg-img"} -## Global Load Balancer +### Global Load Balancer Assuming you need to serve more than one geographic region, you'll need to utilize a Global Load Balaning service so your users will hit the servers in the region closest to them. -## Regional Load Balancers +### Regional Load Balancers Once the users have come into their nearest server cluster, a load balancer will direct them in one of two ways: 1. If the URI of the request contains `/cache`, they should be directed to one of the Prebid Cache servers. 2. Otherwise, all other endpoints should be forwarded to one of the Prebid Servers. -## Prebid Servers +### Prebid Servers These servers will have a mix of network and CPU work. They benefit from a fair amount of memory so they can cache stored requests @@ -37,20 +54,21 @@ and many versions of the GDPR vendors list. Other services you may want to run alongside Prebid Server are: -- Geographic lookup (for GDPR scope determination) -- Device lookup service (future: for Programmatic Guaranteed targeting) +* Geographic lookup (e.g. GDPR scope determination) + +Note that neither Prebid Server nor Prebid Cache supports configuring an SSL certificate. It's intended that they run behind a load balancer or proxy server (e.g. nginx) that provides SSL. -## Prebid Cache Servers +### Prebid Cache Servers The PBC servers consume very little CPU or memory - they just translate between Prebid protocols and the chosen No-SQL system that implements the storage cluster. -## Storage Clusters +### No-SQL Clusters -You can setup Redis, Aerospike, or Cassandra. How many you need will +This is where Prebid Cache stores its data. You can choose Redis, Aerospike, or Cassandra. How many you need will depend on the expected traffic, your traffic mix, and the average length of time that objects are cached. -## Replicated Database +### Replicated Database Account information and StoredRequests are stored in a [database](/prebid-server/hosting/pbs-database.html) queried by Prebid Server at runtime. @@ -63,13 +81,13 @@ Note that there aren't any open source tools for populating this database. Each PBS host company establishes their own methods of populating data from their internal systems. -## Metrics System +### Metrics System You'll want to hook both Prebid Server and Prebid Cache up to an operational monitoring system. -- PBS-Go currently supports Influx and Prometheus -- PBS-Java currently supports Influx and Graphite +* PBS-Go currently supports Influx and Prometheus +* PBS-Java currently supports Influx, Graphite, Prometheus, and Console ## Installing the Software @@ -81,23 +99,25 @@ as a next step. Prebid does not track who downloads Prebid Server, but sometimes we make announcements (bugs, features) and want to get feedback on proposals. You can get on -this mailing list by emailing prebid-server@prebid.org. It's low volume -Here's the information we're asking for: +this mailing list by emailing . It's low volume. Required to get on the list: -- A group email address to place on the list. No individual addresses please. + +* A group email address. No individual addresses please. Optional: -- Which version of Prebid Server are you running: PBS-Go or PBS-Java? -- A host URL so we can occasionally check what versions people are running. -- Are there any features you'd like to see in Prebid Server? + +* Which version of Prebid Server are you running: PBS-Go or PBS-Java? +* A host URL so we can occasionally check what versions people are running. +* Are there any features you'd like to see in Prebid Server? Even though this is not information about individuals, this information falls under the -[Prebid website privacy policy](/privacy.html). You can remove your company from the -email list at any time just by emailing us again at prebid-server@prebid.org. +[Prebid website privacy policy](/policies/privacy.html). You can remove your company from the +email list at any time just by emailing us again at . ## Further Reading -- [Prebid Server Database](/prebid-server/hosting/pbs-database.html) -- [PBS-Go](/prebid-server/versions/pbs-versions-go.html) -- [PBS-Java](/prebid-server/versions/pbs-versions-java.html) +* [Prebid Server Database](/prebid-server/hosting/pbs-database.html) +* [PBS-Go](/prebid-server/versions/pbs-versions-go.html) +* [PBS-Java](/prebid-server/versions/pbs-versions-java.html) +* [Bidder-specific setup guidelines](/prebid-server/hosting/bidder-specific-guidelines.html) diff --git a/prebid-server/overview/prebid-server-overview-video.md b/prebid-server/overview/prebid-server-overview-video.md new file mode 100644 index 0000000000..2f5f3220a3 --- /dev/null +++ b/prebid-server/overview/prebid-server-overview-video.md @@ -0,0 +1,67 @@ +--- +layout: page_v2 +title: Video Intro to Prebid Server +description: A video overview of Prebid Server +sidebarType: 5 +--- + +# A Video Overview of Server + +A high-level overview of Prebid Server, Prebid’s solution for header bidding in the cloud. + +{% include vimeo-iframe.html id="822889941" title="1.5_Intro-to-PBS_v6" %} + +Further Content: + +- [Intro to Prebid](/overview/intro.html) +- [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) +- [Prebid Membership](https://prebid.org/membership) +- [Prebid on Github](https://github.com/prebid) +- [All Videos](/overview/all-videos.html) + +Related Videos: + +- [Introduction to Header Bidding](/overview/intro-to-header-bidding-video.html) +- [Introduction to Prebid Mobile](/prebid-mobile/prebid-mobile-video.html) + +## Transcript + +### About Prebid Server + +Prebid Server is a solution for running real-time advertising auctions in the cloud. + +It works in conjunction with Prebid.js, Prebid SDK, and other technologies to make header bidding possible for any ad format in any type of digital media. + +Prebid Server has everything necessary to sell advertising opportunities through server-side header bidding, including bidder integrations, privacy controls, creative caching, currency conversion, price floors, and analytics. + +It supports more than 150 demand sources, including many of the world’s largest exchanges, DSPs, ad networks, and agencies. + +### Why Prebid Server? + +Prebid Server brings the revenue-maximizing power of header bidding to environments that don’t support standard JavaScript. + +Header bidding originated as a JavaScript technology for websites, and the leading solution for header bidding in standard browser-based environments is Prebid.js. Prebid.js is very popular, but it only works on normal websites. Mobile apps, AMP websites, long-form video, and digital out-of-home need their own solution for header bidding, and that’s what Prebid Server provides. + +Prebid Server can also be used to augment Prebid.js on websites. Prebid Server can be a powerful tool in yield management strategies that aim to maximize both advertising revenue and user experience. + +### How Prebid Server Works +Prebid Server is open-source code that is free to use. To use it, you’ll need to set up a server to host the solution. You can set up your own servers, or use one of the managed services offered by companies in the Prebid community. + +Let’s walk through an example of Prebid Server in use. + +A digital advertising seller sets Prebid Server up on a server. + +Prebid Server receives ad requests from a personal computer, a mobile device, or another server. + +Prebid Server is able to enrich ad requests it receives, which means that it adds additional contextual information like IP-based location. It’s also able to interpret user consent and take actions such as restricting auction functions or limiting the sharing of personal data. + +Next, Prebid Server runs the auction. It sends bid requests to bidders, who respond with bids. Prebid Server validates each of the bids, checking for things like privacy compliance and adherence to price floors. It then finalizes the auction and transmits the results to the system that sent it the initial ad request. + +The seller who uses and hosts Prebid Server configures it to work how they want it to. Settings like privacy and consent controls, price floors, auction controls, the selection of bidders, and ad request enrichment functions are all determined by configurations that the seller sets. + +### Getting Started +To learn more about Prebid Server, including information about setting up your own hosting server, visit docs.prebid.org. + +To learn more about Prebid community companies that offer hosting services, visit prebid.org. + +If you are a developer who would like to see the source code or contribute to Prebid Server, visit Prebid on Github at github.com/prebid/. diff --git a/prebid-server/overview/prebid-server-overview.md b/prebid-server/overview/prebid-server-overview.md index 493b0a9cfe..32230037b1 100644 --- a/prebid-server/overview/prebid-server-overview.md +++ b/prebid-server/overview/prebid-server-overview.md @@ -8,21 +8,21 @@ sidebarType: 5 # Prebid Server Overview {:.no_toc} -Prebid Server is an open-source solution for server-to-server header bidding. It supports a number of key use cases: [mobile app](/prebid-server/use-cases/pbs-sdk.html), [AMP](/prebid-server/use-cases/pbs-amp.html), [server-side web with Prebid.js](/prebid-server/use-cases/pbs-pbjs.html), and [long-form video](/prebid-server/use-cases/pbs-lfv.html). +Prebid Server is an open-source solution for server-to-server header bidding. It supports a number of key use cases: [mobile app](/prebid-server/use-cases/pbs-sdk.html), [AMP](/prebid-server/use-cases/pbs-amp.html), [server-side web with Prebid.js](/prebid-server/use-cases/pbs-pbjs.html), and server-side ad inclusion scenarios such as [CTV](/prebid-server/use-cases/pbs-lfv.html), [Digital Out of Home](/prebid-server/use-cases/pbs-dooh.html) and audio. ![Prebid Server Architecture](/assets/images/flowcharts/prebid-server/pbs-basic-flow.png){:class="pb-xlg-img"} Prebid Server is a header bidding server with a growing list of features. At a high level, it works like this: -1. Prebid Server completes and validates incoming requests - - Resolves dynamic stored requests - - Enforces privacy regulations +1. Prebid Server validates and enhances incoming requests + 1. Resolves dynamic 'stored requests', enriching data server-side + 1. Enforces privacy regulations 2. Next, it calls server-side bid adapters - - There are currently 100+ server-side bid adapters available + 1. There are 180+ server-side bid adapters available 3. After everyone's responded (or the timeout period has expired), it formulates an appropriate response - - Handles currency conversion - - Quantizes bids - - Caches VAST XML or creatives as needed + 1. Currency conversion + 1. Quantizes bids as needed for header bidding targeting + 1. Caches VAST XML or creatives as needed It also has optional analytics support. @@ -30,6 +30,16 @@ The Prebid Cache is an adjunct to Prebid Server that stores VAST and bids as nee Explore [Prebid Server features](/prebid-server/features/pbs-feature-idx.html) in more detail. +## Video Introduction + +A high-level overview of Prebid Server, Prebid’s solution for header bidding in the cloud. + +{% include vimeo-iframe.html id="822889941" title="1.5_Intro-to-PBS_v6" %} + +Further Reading: + +- [Transcript of this video overview](/prebid-server/overview/prebid-server-overview-video.html) + ## Where to Run Prebid Server Unlike Prebid.js, Prebid Server is a server. It needs somewhere to run, and that somewhere ought to be scaleable, distributed, and fast. @@ -40,14 +50,7 @@ The simplest route to working with Prebid Server is to sign up for a hosted solu ### DIY -But of course this is open source, so you're welcome to do this on your own. If you decide to implement your own Prebid Server solution, first check out the general [Prebid Server host company overview](/prebid-server/hosting/pbs-hosting.html). - -Then you need to decide which of the two implementations to utilize: - -- [Prebid Server (Go)](/prebid-server/versions/pbs-versions-go.html) - the original Prebid Server is written in the Go language. -- [Prebid Server (Java)](/prebid-server/versions/pbs-versions-java.html) - Prebid Server with a Java language port. - -To choose between them, see the [Prebid Server version overview](/prebid-server/versions/pbs-versions-overview.html) and the [FAQ](/faq/prebid-server-faq.html#why-are-there-two-versions-of-prebid-server-are-they-kept-in-sync). +But of course this is open source, so you're welcome to do this on your own. If you'd like to explore implementing your own Prebid Server solution, check out the [Prebid Server host company overview](/prebid-server/hosting/pbs-hosting.html). Be warned that installing PBS is not nearly as easy as Prebid.js. ## Which Server-Side Bidders to Utilize diff --git a/prebid-server/pbs-modules/confiant-ad-quality.md b/prebid-server/pbs-modules/confiant-ad-quality.md new file mode 100644 index 0000000000..adce781b7b --- /dev/null +++ b/prebid-server/pbs-modules/confiant-ad-quality.md @@ -0,0 +1,173 @@ +--- +layout: page_v2 +page_type: pbs-module +title: Prebid Server Confiant Ad Quality Module +display_name : Confiant Ad Quality Module +sidebarType : 5 +--- + +# Confiant Ad Quality Module +{:.no_toc} + +- TOC +{:toc } + +## Overview + +[Confiant](https://www.confiant.com/) is an industry leader in the field of ad tech security and quality. +This module provides a low latency pre-auction scanning for such issues. +Any suggestions or questions can be directed to [support@confiant.com](mailto:support@confiant.com) e-mail. + +## Configuration + +### Execution Plan + +This module supports running at the stage: + +- all-processed-bid-responses: this is where all bids are back and PBS-core bid validations are done. + +### Account-Level Config + +Here's a general template for the account config used in PBS-Java: + +```yaml +hooks: + confiant-ad-quality: + enabled: true + host-execution-plan: > + { + "endpoints": { + "/openrtb2/auction": { + "stages": { + "all-processed-bid-responses": { + "groups": [ + { + "timeout": 200, + "hook-sequence": [ + { + "module-code": "confiant-ad-quality", + "hook-impl-code": "confiant-ad-quality-bid-responses-scan-hook" + } + ] + } + ] + } + } + } + } + } +``` + +### List of module configuration options + +- `api-key` - Confiant's API key. +- `redis-config` + - `write-node` + - `host` - Host value of the Confiant's Write Redis Node. + - `port` - Port value of the Confiant's Write Redis Node. + - `password` - User password value of the Confiant's Write Redis Node. + - `read-node` + - `host` - Host value of the Confiant's Read Redis Node. + - `port` - Port value of the Confiant's Read Redis Node. + - `password` - User password value of the Confiant's Read Redis Node. +- `redis-retry-config` + - `short-interval-attempts` - Maximum attempts with short interval value to try to reconnect to Confiant's Redis server in case any connection error happens. + - `short-interval` - Short time interval in milliseconds after which another one attempt to connect to Redis will be executed. + - `long-interval-attempts` - Maximum attempts with long interval value to try to reconnect to Confiant's Redis server in case any connection error happens. This attempts are used when short-attempts were not successful. + - `long-interval` - Long time interval in milliseconds after which another one attempt to connect to Redis will be executed. +- `scan-state-check-interval` - Time interval in milliseconds between periodic calls to check if scan state is enabled on the side of Redis server. +- `bidders-to-exclude-from-scan` - List of bidders which won't be scanned by Confiant + +```yaml +hooks: + modules: + confiant-ad-quality: + api-key: "hgr876cerg7655" + redis-config: + write-node: + host: "127.0.0.1" + port: 8000 + password: "password-w" + read-node: + host: "127.0.0.1" + port: 8001 + password: "password-r" + redis-retry-config: + short-interval-attempts: 60 + short-interval: 1000 + long-interval-attempts: 336 + long-interval: 1800000 + scan-state-check-interval: 100000 + bidders-to-exclude-from-scan: > + adyoulike, + rtbhouse +``` + +## Analytics Tags + +There's only one analytics activity defined by this module: "ad-scan". +ATag values: + +1. for activities[].results[].status **inspected-has-issue** (response was scanned by Confiant and some issue found) + 1. No `values` block + 2. Attributes in the `appliedto` block: + 1. **bidders**: the list of bidders of the blocked response + 2. **impIds**: the list of seatbid.bid.impId of the blocked response + 3. **bidIds**: the list of seatbid.bid.id of the blocked response +2. for activities[].results[].status **inspected-no-issues** (response was scanned by Confiant and no issues found) + 1. No `values` block + 2. Attributes in the `appliedto` block: + 1. **bidders**: the list of bidders of the "clean" response + 2. **impIds**: the list of seatbid.bid.impId of the "clean" response + 3. **bidIds**: the list of seatbid.bid.id of the "clean" response +3. for activities[].results[].status **skipped** (response was skipped because of the config: `bidders-to-exclude-from-scan`) + 1. No `values` block + 2. Attributes in the `appliedto` block: + 1. **bidders**: the list of bidders of the skipped response + 2. **impIds**: the list of seatbid.bid.impId of the skipped response + 3. **bidIds**: the list of seatbid.bid.id of the skipped response + +Here's an example analytics tag that might be produced for use in an analytics adapter: + +```json +[{ + "activities": [{ + "name": "ad-scan", + "status": "success", + "results": [{ + // bidderA was scanned by Confiant and has an issue for imp=A + "status": "inspected-has-issue", + "values": null, + "appliedto": { + "bidders": ["bidderA"], + "impIds": ["A"], + "bidIds": ["bidIdA"] + } + },{ + // bidderB was scanned by Confiant and does not have any issues for imp=B + "status": "inspected-no-issues", + "values": null, + "appliedto": { + "bidders": ["bidderB"], + "impIds": ["B"], + "bidIds": ["bidIdB"] + } + },{ + // bidderC was not scanned by Confiant because of the `bidders-to-exclude-from-scan` configuration + "status": "skipped", + "values": null, + "appliedto": { + "bidders": ["bidderC"], + "impIds": ["C"], + "bidIds": ["bidIdC"] + } + }] + }] +}] +``` + +## Further Reading + +- [Prebid Server Module List](/prebid-server/pbs-modules/index.html) +- [Building a Prebid Server Module](/prebid-server/developers/add-a-module.html) +- [Confiant Real-Time Protection Module](/dev-docs/modules/confiantRtdProvider.html) diff --git a/prebid-server/pbs-modules/index.md b/prebid-server/pbs-modules/index.md index 172bf692c9..15888fdf0b 100644 --- a/prebid-server/pbs-modules/index.md +++ b/prebid-server/pbs-modules/index.md @@ -8,54 +8,66 @@ sidebarType: 5 # Prebid Server Modules {:.no_toc} -The core of Prebid Server contains the foundational code needed for header bidding. Any functionality that could be considered an add-on or that covers a special case is covered by modules. +The core of Prebid Server contains the foundational code needed for header bidding. Any functionality that could be considered an add-on or that covers a special case is covered by modules. If you're looking for bidder adapter parameters, see [Bidders' Params](/dev-docs/pbs-bidders.html). -{: .alert.alert-info :} -Only the Java version of PBS currently supports the module infrastructure. - * TOC {:toc} ## The Modules +There are two types of modules: + +1. General Modules - these plug into various stages within the main auction workflow and can affect any part of the request or response. +1. Privacy Modules - these are more limited, plugging into the [Activity Controls](/prebid-server/features/pbs-activitycontrols.html) system to delegate decisions about potentially privacy-sensitive scenarios. + +The full list of modules: + {: .table .table-bordered .table-striped } -| Module | Description | PBS-Go | PBS-Java | -|---------------------+--------------+--------+----------| -| [**ORTB2 Blocking**](/prebid-server/pbs-modules/ortb2-blocking.html) | Support bidders that aren't full-service SSPs. | | | +| Module | Description | Type | PBS-Go | PBS-Java | +|---------------------+--------------+------+--------+----------| +| [**ORTB2 Blocking**](/prebid-server/pbs-modules/ortb2-blocking.html) | Support bidders that aren't full-service SSPs. | general | check | check | +| [**Confiant Ad Quality**](/prebid-server/pbs-modules/confiant-ad-quality.html) | Scans bid responses for security and quality issues. | general | | check | +| [**US Gen Privacy**](/prebid-server/features/pbs-usgen.html) | Links with the [Activity Controls](/prebid-server/pbs-activitycontrols.html) to process GPP strings to determine whether an activity should be allowed. | privacy | | check | +| [**US Custom Logic Privacy**](/prebid-server/features/pbs-uscustomlogic.html) | Similar to the `US Gen Privacy` module, but publishers define their own interpretation of the GPP string. | privacy | | check | +| [**Richmedia Filter**](/prebid-server/pbs-modules/richmedia.html) | Can filter MRAID creatives from the bid stream. | validation | | check | -## Installing a PBS Module +## Installing a PBS General Module Once a Prebid Server host company decides which modules they want to support, here's how installation works: -### 1. Build PBS with modules. +### 1. Build PBS with modules Note that modules are currently an all-or-nothing nothing from a code perspective. -``` + +```bash mvn clean package --file extra/pom.xml ``` ### 2. Define an 'execution plan' The execution plan details: -- which modules are used in your server -- what order they're invoked in -- how long modules have to run before timeout -- whether any modules depend on each other + +* which modules are used in your server +* what order they're invoked in +* how long modules have to run before timeout +* whether any modules depend on each other If you want the module to run on every request regardless of account, this is a host-level config you should place in `application.yaml`. If the module should be active only for certain accounts, you'll need to place the plan in the account-specific config. To define a plan, you'll need to know the following module details, which should be available in the module documentation: -- urls: which PBS 'entry points' are relevant. e.g. /openrtb2/auction, /openrtb2/amp -- stages: one or more of the 7 workflow stages where the module should be called: entrypoint, raw-auction-request, processed-auction-request, bidder-request, raw-bidder-response, processed-bidder-response, and/or auction-response. -- hooks: for each stage where a module runs, its documentation will provide the hook function name. + +* urls: which PBS 'entry points' are relevant. e.g. /openrtb2/auction, /openrtb2/amp +* stages: one or more of the 7 workflow stages where the module should be called: entrypoint, raw-auction-request, processed-auction-request, bidder-request, raw-bidder-response, processed-bidder-response, and/or auction-response. +* hooks: for each stage where a module runs, its documentation will provide the hook function name. Here's an example application.yaml entry: -``` + +```yaml hooks: host-execution-plan: > # these hooks are always run for all accounts { @@ -77,13 +89,13 @@ hooks: } ] },{ // this group depends on the results of the first group - "timeout": 5, # in milliseconds - "hook-sequence": [ + "timeout": 5, # in milliseconds + "hook-sequence": [ { "modulecode": "modulecode3", "hookimplcode": "hook3-depends-on-hook1" } - ] + ] } ] } @@ -120,12 +132,17 @@ hooks: Modules may require configuration at startup or during the request: -- If the module requires config at initialization, its documentation will +* If the module requires config at initialization, its documentation will describe where the config file lives and what format it should take. -- If the module requires runtime config, it should be passed via the account-conig mechanism. +* If the module requires runtime config, it should be passed via the account-conig mechanism. + +## Installing a PBS Privacy Module +Privacy modules are already built into the code base. They just need to be linked to the +relevant 'Activity' using the `privacyreg` directive as described in the [Activity Control reference](/prebid-server/features/pbs-activitycontrols.html). ## Further Reading -+ [Developing a Prebid Server Module](/prebid-server/developers/add-a-module.html) -+ [Prebid Server Features](/prebid-server/features/pbs-feature-idx.html) +* [Developing a Prebid Server General Module](/prebid-server/developers/add-a-module.html) +* [Developing a Prebid Server Privacy Module](/prebid-server/developers/add-a-privacy-module.html) +* [Prebid Server Features](/prebid-server/features/pbs-feature-idx.html) diff --git a/prebid-server/pbs-modules/ortb2-blocking.md b/prebid-server/pbs-modules/ortb2-blocking.md index 74cfb12388..1a7648a61a 100644 --- a/prebid-server/pbs-modules/ortb2-blocking.md +++ b/prebid-server/pbs-modules/ortb2-blocking.md @@ -12,9 +12,6 @@ sidebarType : 5 * TOC {:toc } -{: .alert.alert-warning :} -Currently only available for the Java version of Prebid Server - ## Overview This module helps support bidders that aren't full-service SSPs by allowing @@ -71,7 +68,7 @@ There is no host-company level config for this module. ### Account-Level Config -Here's a general template for the account config: +Here's a general template for the account config used in PBS-Java: ``` { "hooks": { @@ -80,13 +77,13 @@ Here's a general template for the account config: "attributes": { "ATTRIBUTE": { // badv, bcat, bapp, btype, battr DEFAULT_SETTINGS, - "action-overrides": [{ + "action-overrides": { OVERRIDE_SETTING: [{ "conditions": { ... }, - // the value below will be the datatype of the SETTING + // the value below will be the datatype of the SETTING "override": VALUE }] - }] + } } } } @@ -98,10 +95,39 @@ Here's a general template for the account config: } ``` +PBS-Go version of the same config: +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "ATTRIBUTE": { // badv, bcat, bapp, btype, battr + DEFAULT_SETTINGS, + "action_overrides": { + OVERRIDE_SETTING: [{ + "conditions": { ... }, + // the value below will be the datatype of the SETTING + "override": VALUE + }] + } + } + } + } + } + }, + "execution_plan": { + ... + } + } +} +``` + The 'ATTRIBUTE' above is one of the 5 blockable entities defined in OpenRTB. A 'SETTING' is a feature this module supports. The following sections detail each of the 5 blockable entities. -Here's a detailed example: +Here's a detailed example for PBS-Java: ``` { "hooks": { @@ -197,6 +223,102 @@ Here's a detailed example: } ``` +For PBS-Go: +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { + "attributes": { + "badv": { + "enforce_blocks": false, + "blocked_adomain": [], + "action_overrides": { + "blocked_adomain": [ + { + "override": [ "example.com" ], + "conditions": { + "bidders": [ "bidderA" ] + } + } + ] + } + }, + "bcat": { + "enforce_blocks": false, + "blocked_adv_cat": [], + "action_overrides": { + "blocked_adv_cat": [ + { + "override": [ "IAB7" ], + "conditions": { + "bidders": [ "bidderA" ] + } + } + ] + } + }, + "battr": { + "enforce_blocks": false, + "action_overrides": { + "blocked_banner_attr": [ + { + "override": [1,3,8,9,10,13,14,17], + "conditions": { + "bidders": [ "bidderA" ] + } + } + ] + }, + "blocked_banner_attr": [] + } + } + } + } + }, + "execution_plan": { + "endpoints": { + "/openrtb2/amp": { + "stages": { + "bidder_request": { + "groups": [ + { + "timeout": 5, + "hook_sequence": [ + { + "module_code": "prebid.ortb2blocking", + "hook_impl_code": "ortb2-blocking-bidder-request" + } + ] + } + ] + } + } + }, + "/openrtb2/auction": { + "stages": { + "bidder_request": { + "groups": [ + { + "timeout": 5, + "hook_sequence": [ + { + "module_code": "prebid.ortb2blocking", + "hook_impl_code": "ortb2-blocking-bidder-request" + } + ] + } + ] + } + } + } + } + } + } +} +``` + ### Configuration Details The module supports flexibile definition of behavior surrounding the 5 blocked attributes. Here are the details. @@ -210,10 +332,10 @@ This attribute is related to the 'badv' of the request, and the 'adomain' of the |---+---+---+---| | blocked-adomain | List of adomains not allowed to display on this inventory | array of strings | bidders (array of strings), media-types (array of strings). | | enforce-blocks | Whether to enforce adomains in responses | boolean | bidders (array of strings), media-types (array of strings) | -| block-unknown-adomain | Whether to block responses not specifying adomain. Only active if enforce-blocks is true. | bidders (array of strings), media-types (array of strings) | +| block-unknown-adomain | Whether to block responses not specifying adomain. Only active if enforce-blocks is true. | boolean | bidders (array of strings), media-types (array of strings) | | allowed-adomain-for-deals | List of adomains allowed for deals in general or a specific dealid. | array of strings | deal-ids (array of strings). This isn't a true override - values are added to the global. | -Here's an example account config with several scenarios: +Here's an example account config for PBS-Java with several scenarios: ``` { "hooks": { @@ -228,7 +350,7 @@ Here's an example account config with several scenarios: "blocked-adomain": [ "a.com", "b.com", "c.com" ], // but deals can return this one "allowed-adomain-for-deals": [ "a.com" ], - "action-overrides": [{ + "action-overrides": { "blocked-adomain": [{ // c.com allowed on these bidders for video "conditions": { @@ -264,8 +386,7 @@ Here's an example account config with several scenarios: "override": [ "b.com" ] } ] - } - ] + } } } } @@ -274,6 +395,68 @@ Here's an example account config with several scenarios: } ``` +For PBS-Go: +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "badv": { + // enforce domain blocks by default + "enforce_blocks": true, + "block_unknown_adomain": true, + // these are the default undesirable domains + "blocked_adomain": [ "a.com", "b.com", "c.com" ], + // but deals can return this one + "allowed_adomain_for_deals": [ "a.com" ], + "action_overrides": { + "blocked_adomain": [{ + // c.com allowed on these bidders for video + "conditions": { + "bidders": [ "bidderA", "bidderB" ], + "media_types": [ "video" ] + }, + "override": [ "a.com", "b.com" ] + }, + { + // more domains blocked for this bidder + "conditions": { + "bidders": [ "bidderc" ] + }, + "override": [ "a.com", "b.com", "c.com", "d.com", "e.com" ] + } + ], + "block_unknown_adomain": [ + { + // don't block unnknown for video bids from this bidder + "conditions": { + "bidders": [ "bidderA" ], + "media_types": [ "video" ] + }, + "override": false + } + ], + "allowed_adomain_for_deals": [ + { + // this deal is for normally blocked domain b.com + "conditions": { + "deal_ids": [ "12345678" ] + }, + "override": [ "b.com" ] + } + ] + } + } + } + } + } + } + } +} +``` + #### Blocked Advertiser Category This attribute is related to the 'bcat' of the request and 'cat' of the response. @@ -283,10 +466,10 @@ This attribute is related to the 'bcat' of the request and 'cat' of the response |---+---+---+---| | blocked-adv-cat | List of IAB categories not allowed to display on this inventory | array of strings | bidders (array of strings), media-types (array of strings) | | enforce-blocks | Whether to enforce cat in responses | boolean | bidders (array of strings), media-types (array of strings) | -| block-unknown-adv-cat | Whether to block responses not specifying cat. Only active if enforce-blocks is true. | bidders (array of strings), media-types (array of strings) | +| block-unknown-adv-cat | Whether to block responses not specifying cat. Only active if enforce-blocks is true. | boolean | bidders (array of strings), media-types (array of strings) | | allowed-adv-cat-for-deals | List of adomains allowed for deals in general or a specific dealid. | array of strings | deal-ids (array of strings). This isn't a true override - values are added to the global.| -Here's an example account config with several scenarios: +Here's an example account config for PBS-Java with several scenarios: ``` { "hooks": { @@ -300,7 +483,7 @@ Here's an example account config with several scenarios: "blocked-adv-cat": [ "IAB-1", "IAB-2" ], // deals can return this cat "allowed-adv-cat-for-deals": [ "IAB-1" ], - "action-overrides": [ { + "action-overrides": { "blocked-adv-cat": [ { // block additional categories for video @@ -337,8 +520,7 @@ Here's an example account config with several scenarios: "override": [ "IAB-2" ] } ] - } - ] + } } } } @@ -347,6 +529,68 @@ Here's an example account config with several scenarios: } ``` +For PBS-Go +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "bcat": { + // don't enforce blocks + "enforce_blocks": false, + // block these categories by default + "blocked_adv_cat": [ "IAB-1", "IAB-2" ], + // deals can return this cat + "allowed_adv_cat_for_deals": [ "IAB-1" ], + "action_overrides": { + "blocked_adv_cat": [ + { + // block additional categories for video + "conditions": { + "media_types": [ "video" ] + }, + "override": [ "IAB-1", "IAB-2", "IAB-3", "IAB-4" ] + } + ], + "enforce_blocks": [ + { + // enforce bcat blocks for this bidder + "conditions": { + "bidders": [ "bidderA" ] + }, + "override": true + } + ], + "block_unknown_adv_cat": [ + { + // enforce unknown cat for this bidder + "conditions": { + "bidders": [ "bidderA" ] + }, + "override": true + } + ], + "allowed_adv_cat_for_deals": [ + { + // this deal ID allowed to be this category + "conditions": { + "deal_ids": [ "1111111" ] + }, + "override": [ "IAB-2" ] + } + ] + } + } + } + } + } + } + } +} +``` + #### Blocked App This attribute is related to the 'bapp' of the request and 'bundle' of the response. @@ -358,7 +602,7 @@ This attribute is related to the 'bapp' of the request and 'bundle' of the respo | enforce-blocks | Whether to enforce bundles in responses | boolean | bidders (array of strings), media-types (array of strings) | | allowed-bapp-for-deals | List of bundles allowed for deals in general or a specific dealid. | array of strings | deal-ids (array of strings). This isn't a true override - values are added to the global. | -Here's an example account config: +Here's an example account config for PBS-Java: ``` { "hooks": { @@ -370,8 +614,7 @@ Here's an example account config: "enforce-blocks": false, // these bundles blocked by default "blocked-app": [ "app1", "app2" ], - "action-overrides": [ - { + "action-overrides": { "blocked-app": [ { // this bidder also blocked for an additional app @@ -381,8 +624,7 @@ Here's an example account config: "override": [ "app1", "app2", "app3" ] } ] - } - ] + } } } } @@ -391,6 +633,39 @@ Here's an example account config: } ``` +For PBS-Go +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "bapp": { + // don't enforce + "enforce_blocks": false, + // these bundles blocked by default + "blocked_app": [ "app1", "app2" ], + "action_overrides": { + "blocked_app": [ + { + // this bidder also blocked for an additional app + "conditions": { + "bidders": [ "bidderA" ] + }, + "override": [ "app1", "app2", "app3" ] + } + ] + } + } + } + } + } + } + } +} +``` + #### Blocked Banner Type This attribute is related to the 'btype' of the request. @@ -406,7 +681,7 @@ Note: no enforcement is possible because the creative type is not explictly part of the response and Prebid Server does not currently contain logic to parse creatives to derive the type. -Here's an example account config: +Here's an example account config for PBS-Java: ``` { "hooks": { @@ -416,8 +691,7 @@ Here's an example account config: "btype": { // block these types for all bidders "blocked-banner-type": [ 3, 4 ], - "action-overrides": [ - { + "action-overrides": { "blocked-banner-type": [ { // block an additional type for this bidder @@ -427,8 +701,7 @@ Here's an example account config: "override": [ 3, 4, 5 ] } ] - } - ] + } } } } @@ -437,6 +710,37 @@ Here's an example account config: } ``` +For PBS-Go +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "btype": { + // block these types for all bidders + "blocked_banner_type": [ 3, 4 ], + "action_overrides": { + "blocked_banner_type": [ + { + // block an additional type for this bidder + "conditions": { + "bidders": [ "bidderA" ] + }, + "override": [ 3, 4, 5 ] + } + ] + } + } + } + } + } + } + } +} +``` + #### Blocked Banner Attributes This attribute is related to the 'battr' of the request and 'attr' of the response. @@ -450,7 +754,7 @@ This attribute is related to the 'battr' of the request and 'attr' of the respon See Table 5.3 in the [OpenRTB 2.5 spec](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf) for the possible values. -Here's an example account config: +Here's an example account config for PBS-Java: ``` { "hooks": { @@ -462,8 +766,7 @@ Here's an example account config: "enforce-blocks": false, // block these attributes for all bidders "blocked-banner-attr": [ 1, 8, 9, 10 ], - "action-overrides": [ - { + "action-overrides": { "enforce-blocks": [ { // enforce the attr block for this bidder @@ -473,8 +776,7 @@ Here's an example account config: "override": true } ] - } - ] + } } } } @@ -482,6 +784,50 @@ Here's an example account config: } } ``` + +For PBS-Go +``` +{ + "hooks": { + "modules": { + "prebid": { + "ortb2blocking": { // start of this module's config + "attributes": { + "battr": { + // don't enforce + "enforce_blocks": false, + // block these attributes for all bidders + "blocked_banner_attr": [ 1, 8, 9, 10 ], + "action_overrides": { + "enforce_blocks": [ + { + // enforce the attr block for this bidder + "conditions": { + "bidders": [ "bidderA" ] + }, + "override": true + } + ] + } + } + } + } + } + } + } +} +``` + +### Enable for Spring Boot +In order to allow the module to be picked up by Prebid Server, a Spring Boot configuration property `hooks.ortb2-blocking.enabled` must be set to `true`. + +Here's an example of how your PBS configuration YAML should look like: +```YAML +hooks: + ortb2-blocking: + enabled: true +``` + ## Analytics Tags There's only one analytics activity defined by this module: "enforce-blocking". diff --git a/prebid-server/pbs-modules/richmedia.md b/prebid-server/pbs-modules/richmedia.md new file mode 100644 index 0000000000..017ab25e3a --- /dev/null +++ b/prebid-server/pbs-modules/richmedia.md @@ -0,0 +1,92 @@ +--- +layout: page_v2 +page_type: pbs-module +title: Prebid Server Richmedia Filter Module +display_name : Richmedia Filter Module +sidebarType : 5 +--- + +# Richmedia Filter Module +{:.no_toc} + +- TOC +{:toc } + +## Overview + +This module lets Prebid Server accounts define filtering rules for certain types +of richmedia bid responses. + +Currently, it can be configured to block MRAID responses for publishers that +do not want MRAID creatives to run. + +## Configuration + +The parameters to the module are: + +{: .table .table-bordered .table-striped } +| Parameter | Type | Scope | Description | Notes | +| --------- | ---- | ----- | ----------- | ----- | +| enabled | boolean | optional | Enable the module for this account | Defaults to false | +| filter-mraid | boolean | optional | Enable the MRAID filter for this account | Defaults to false | +| mraid-script-pattern | string | optional | Required if filter-mraid is true, defines what pattern is used to identity MRAID creatives. | No default | + +Here's an example of the account config used in PBS-Java: + +```json +{ + "hooks": { + "modules": { + "pb-richmedia-filter": { + "enabled": true, + "filter-mraid": true, + "mraid-script-pattern": "mraid.js" + // future richmedia filtering options go here + } + }, + "execution-plan": { + "endpoints": { + "/openrtb2/amp": { + "stages": { + "all-processed-bid-responses": { + "groups": [ + { + "timeout": 5, + "hook-sequence": [ + { + "module-code": "pb-richmedia-filter", + "hook-impl-code": "pb-richmedia-filter-all-processed-bid-responses-hook" + } + ] + } + ] + } + } + }, + "/openrtb2/auction": { + "stages": { + "all-processed-bid-responses": { + "groups": [ + { + "timeout": 5, + "hook-sequence": [ + { + "module-code": "pb-richmedia-filter", + "hook-impl-code": "pb-richmedia-filter-all-processed-bid-responses-hook" + } + ] + } + ] + } + } + } + } + } + } +} +``` + +## Further Reading + +- [Prebid Server Module List](/prebid-server/pbs-modules/index.html) +- [Building a Prebid Server Module](/prebid-server/developers/add-a-module.html) diff --git a/prebid-server/use-cases/pbs-amp.md b/prebid-server/use-cases/pbs-amp.md index d5ec56c52e..bf2b03b61c 100644 --- a/prebid-server/use-cases/pbs-amp.md +++ b/prebid-server/use-cases/pbs-amp.md @@ -25,7 +25,7 @@ Here's a workflow diagramming how this works. 1. The auction takes place and bid responses are placed in a cache. 1. Prebid Server responds to the AMP page with results and ad server targeting variables. 1. The ad server targeting variables are sent along to the ad server with the ad request. -1. When header bidding wins in the ad server, the ad server responds with a call to the [Prebid Universal Creative](overview/prebid-universal-creative.html). +1. When header bidding wins in the ad server, the ad server responds with a call to the [Prebid Universal Creative](/overview/prebid-universal-creative.html). 1. The Prebid Universal Creative pulls the winning bid from the cache. 1. The Prebid Universal Creative displays the winning bid creative from the cache. @@ -52,7 +52,7 @@ There are two basic ways of invoking AMP RTC: ``` {: .alert.alert-info :} -**Note:** the `prebidrubicon` and `prebidappnexus` AMP vendor strings define slightly different parameters; AppNexus uses "PLACEMENT_ID" as the argument to rtc-config while Rubicon uses "REQUEST_ID". They both translate to `tag_id` when passed to Prebid Server. +**Note:** the `prebidrubicon` and `prebidappnexuspsp` AMP vendor strings define slightly different parameters; AppNexus uses "PLACEMENT_ID" as the argument to rtc-config while Rubicon uses "REQUEST_ID". They both translate to `tag_id` when passed to Prebid Server. - The other option is to construct a direct URL from component pieces: w, h, slot, targeting, gdpr_consent, account, page url (purl), etc. diff --git a/prebid-server/use-cases/pbs-dooh.md b/prebid-server/use-cases/pbs-dooh.md new file mode 100644 index 0000000000..6eaf1f1fde --- /dev/null +++ b/prebid-server/use-cases/pbs-dooh.md @@ -0,0 +1,38 @@ +--- +layout: page_v2 +sidebarType: 5 +title: Prebid Server | Use Cases | Digital Out Of Home + +--- + +# Use Case: Prebid Server | Digital Out Of Home + +Prebid Server (PBS) supports Digital Out Of Home (DOOH) advertising with this architecture: + +## Workflow + +Here's a workflow diagramming how this works. + +![Prebid Server DOOH](/assets/images/flowcharts/prebid-server/pbs-dooh-flow.png){:class="pb-xlg-img"} + +1. DOOH screen makes request for an ad either directly (1a) or through a Content Management System (1b) +2. The DOOH ad server sends an OpenRTB request to PBS, specifying the screen requirements. +3. PBS sends a request for bids to selected demand partners by relaying OpenRTB requests to them. +4. Demand partners return a bid response to PBS. Bid creative assets may be stored in Prebid Cache. +5. PBS returns the resulting bids to the DOOH ad server. +6. The ad server retrieves the cached DOOH bid assets as necessary. +7. The ad server returns the bid to the CMS or device. + +## OpenRTB and DOOH + +These are the fields in OpenRTB 2.6 that support the Digital Out Of Home use case: + +- `dooh` - an object containing many values such as the venue type, publisher, etc. +- imp.qty - impression quantity +- imp.dt - estimated impression timestamp + +Bidders generally expect these values to be present in the original Prebid Server request. + +## Further Reading + +- [DOOH in OpenRTB 2.6](https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md#objectdooh) diff --git a/prebid-server/use-cases/pbs-sdk.md b/prebid-server/use-cases/pbs-sdk.md index f1500f8b2e..dd14f5de6c 100644 --- a/prebid-server/use-cases/pbs-sdk.md +++ b/prebid-server/use-cases/pbs-sdk.md @@ -24,7 +24,7 @@ Here's a workflow diagramming how this works. 1. The auction takes place and bid responses are placed in a cache. 1. Prebid Server responds to the Prebid SDK with results and ad server targeting variables. 1. The ad server targeting variables are sent along with the ad request to the publisher ad server. -1. When header bidding wins in the ad server, the ad server responds with a call to the [Prebid Universal Creative](overview/prebid-universal-creative.html). +1. When header bidding wins in the ad server, the ad server responds with a call to the [Prebid Universal Creative](/overview/prebid-universal-creative.html). 1. The Prebid Universal Creative pulls the winning bid from the Prebid Cache. 1. The Prebid Universal Creative displays the winning bid creative from the cache. @@ -97,9 +97,9 @@ The resulting OpenRTB generated by the SDK and sent to Prebid Server would be: ], "ext": { "prebid": { - "storedrequest": { // this maps to the "top-level" stored request + "storedrequest": { // this maps to the "top-level" stored request "id": "1234" // from setPrebidServerAccountId(). Pulls in global behavior (cache, targeting) - } + } } } } @@ -247,9 +247,9 @@ The behavior of the keys is: * `includewinners`: If set to true, Prebid Server will emit the top winning bid as `hb_pb` format. If set to false, Prebid Server will not supply the top bid. * `includebidderkeys`: If set to true, Prebid Server will emit all bidder keys as `hb_pb_BIDDERNAME` along with all other bidder specific keys. If false, Prebid Server will not supply any bidder specific keys. -### The SDK Recieves Prebid Server's Response +### The SDK Receives Prebid Server's Response -Prebid SDK will set the publisher ad server targeting with all keys recieved from Prebid Server's response, unadultered, contained in the `ext.prebid.targeting` object. +Prebid SDK will set the publisher ad server targeting with all keys received from Prebid Server's response, unadultered, contained in the `ext.prebid.targeting` object. #### Application Code Calls the Ad Server @@ -265,7 +265,7 @@ Prebid Universal Creative loads in the webiview, which sees the `hb_env=mobile-a ### Load Ad -The Prebid Universal Crative will parse the response, looking for the `adm` object, loading the full markup into the webview. +The Prebid Universal Creative will parse the response, looking for the `adm` object, loading the full markup into the webview. ## Further Reading diff --git a/prebid-server/versions/pbs-versions-java.md b/prebid-server/versions/pbs-versions-java.md index 7f68600244..9b4f044875 100644 --- a/prebid-server/versions/pbs-versions-java.md +++ b/prebid-server/versions/pbs-versions-java.md @@ -10,11 +10,7 @@ title: Prebid Server | Versions | Java
        -The Java version of Prebid Server is for those who: -
          -
        • Want to host Programmatic Guaranteed
        • -
        • Prefer the Java language
        • -
        +The Java version of Prebid Server is for those who prefer the Java language.
        @@ -24,16 +20,12 @@ The Java version of Prebid Server is for those who:
        - ## Features We recommend you review the [feature comparison list](/prebid-server/features/pbs-feature-idx.html) to familiarize yourself with the differences between this and PBS-Go in deciding which version is right for you. ## Code Repositories -The repositories are currently in the Rubicon-Project GitHub organization, but -will soon move to the Prebid org. - - [Prebid Server - Java](https://github.com/prebid/prebid-server-java) - [Prebid Cache Server - Java](https://github.com/prebid/prebid-cache-java) @@ -42,6 +34,31 @@ will soon move to the Prebid org. See [Hosting your own Prebid Server](/prebid-server/hosting/pbs-hosting.html) for important architectural considerations, then follow the instructions for [Installing PBS-Java](/prebid-server/developers/installing-java.html). +## Quick Start + +There are a few test requests in sample/requests that work with prebid-config-file-bidders.yaml and the files in the samples/stored directory. + +1. Follow the instructions in the root-level README.txt file to build the server + +2. Start the server pointing to a config in the sample directory. e.g. + + ```bash + java -jar target/prebid-server.jar --spring.config.additional-location=sample/prebid-config.yaml + ``` + +3. Use one of the stored requests in the sample directory with curl: + + ```bash + cd sample + curl --header "X-Forwarded-For: 151.101.194.216" -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' -H 'Referer: https://example.com/demo/' -H "Content-Type: application/json" http://localhost:8080/openrtb2/auction --data @FILENAME + ``` + + Where FILENAME is one of: + + - rubicon-storedresponse.json - this is a request that calls for a stored-auction-response. + - appnexus-disabled-gdpr.json - this is a request that actually calls the appnexus endpoint after disabling GDPR by setting regs.ext.gdpr:0 + - pbs-stored-req-test-video.json - this is a stored-request/response chain returning a VAST document + ## References - [Building an Analytics Adapter](/prebid-server/developers/pbs-build-an-analytics-adapter.html#adding-an-analytics-adapter-in-pbs-java) diff --git a/prebid-video/video-getting-started.md b/prebid-video/video-getting-started.md index fbc05431c3..b7bed07f67 100644 --- a/prebid-video/video-getting-started.md +++ b/prebid-video/video-getting-started.md @@ -9,23 +9,24 @@ sidebarType: 4 # Getting Started with Video for Prebid.js + {: .no_toc } If you’re new to header bidding and Prebid, your implementation of Prebid for video demand will likely go much smoother if you first read the following: -- [What Is Prebid?]({{site.github.url}}/overview/intro.html) -- [Getting Started with Prebid]({{site.github.url}}/overview/getting-started.html) +- [What Is Prebid?](/overview/intro.html) +- [Getting Started with Prebid for Developers](/dev-docs/getting-started.html) -See [Prebid.js Video Overview]({{site.github.url}}/prebid-video/video-overview.html) for a general description and high-level overview of working with video demand in Prebid.js. +See [Prebid.js Video Overview](/prebid-video/video-overview.html) for a general description and high-level overview of working with video demand in Prebid.js. -* TOC +- TOC {:toc} ## Ad Ops ### Ad Server Setup -Start by reading [AdOps Getting Started]({{site.github.url}}/overview/getting-started.html). This will give you a general overview of setting up your price buckets and line items on your ad server. +Start by reading [Ad Ops Getting Started](/adops/before-you-start.html). This will give you a general overview of setting up your price buckets and line items on your ad server. One thing to keep in mind as you set up your line items is price granularity. Be sure to communicate your price granularity requirements to your developers, as they might need to define custom configuration settings, depending on your granularity. @@ -34,144 +35,52 @@ One thing to keep in mind as you set up your line items is price granularity. Be If you already have a Prebid integration for banner, you must create a separate set of ad server line items to enable Prebid to monetize instream video. If you’re using Google Ad Manager as your ad server: -Once you understand the general setup requirements, follow the instructions for video-specific line item setup in [Setting Up Prebid Video in Google Ad Manager]({{site.github.url}}/adops/setting-up-prebid-video-in-dfp.html). +Once you understand the general setup requirements, follow the instructions for video-specific line item setup in [Setting Up Prebid Video in Google Ad Manager](/adops/setting-up-prebid-video-in-dfp.html). If you’re using another ad server: Follow the instructions for your ad server to create line items for instream video content. The primary points to keep in mind as you set up your line items include: -• Line items must target Prebid key-values. -• The VAST creative URL must be in the format `https://prebid.adnxs.com/pbc/v1/cache?uuid={hb_cache_id}`, where `{hb_cache_id}` is the value passed to the ad server from Prebid.js. +- Line items must target Prebid key-values. +- The VAST creative URL must be in the format `https://prebid.adnxs.com/pbc/v1/cache?uuid={hb_cache_id}`, where `{hb_cache_id}` is the value passed to the ad server from Prebid.js. #### Outstream -If you already have a Prebid integration for banner, you don’t need to do anything differently for outstream video. Outstream units use the same creative and line item targeting setup as banner creatives. See the [Step by Step Guide to Google Ad Manager Setup]({{site.github.url}}/adops/step-by-step.html) for instructions. (If you’re not using Google Ad Manager as your ad server, follow your ad server’s guidelines for setting up your line items.) +If you already have a Prebid integration for banner, you don’t need to do anything differently for outstream video. Outstream units use the same creative and line item targeting setup as banner creatives. See the [Step by Step Guide to Google Ad Manager Setup](/adops/step-by-step.html) for instructions. (If you’re not using Google Ad Manager as your ad server, follow your ad server’s guidelines for setting up your line items.) {: .alert.alert-info :} **Prebid Server** If you’ve decided to conduct your header bidding auctions server-side rather than on the client, you need to have a Prebid Server account or set up your own. See the [Prebid Server Overview](/prebid-server/overview/prebid-server-overview.html) to begin your integration. - - ## Developers ### Download Prebid.js -Your first step to implementing header bidding for video is to [download Prebid.js]({{site.github.url}}/download.html). Before downloading, select the adapters you want to include. (You can add more adapters later.) - -- Include at least one video adapter. Find a list of available video adapters [here]({{site.github.url}}/dev-docs/bidders.html#bidder-video-native). -- If Google Ad Manager is your ad server, you must include the [Google Ad Manager Video module](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html). -- If you’ll be integrating with Prebid Server, be sure to include “Prebid Server” in the list of adapters. - -### Define Prebid Ad Units - -Setting up Prebid ad units is almost the same whether you’re working with instream video ads or outstream. The primary difference is specifying the type of video ad (instream or outstream), which you do in the mediaTypes.video.context field: - -``` - var adUnit1 = { - code: 'videoAdUnit', - mediaTypes: { - video: { - context: 'instream', //or 'outstream' - playerSize: [640, 480], - mimes: ['video/mp4'], // required for Prebid Server - protocols: [1, 2, 3, 4, 5, 6, 7, 8], - playbackmethod: [2], - skip: 1 - } -``` - -The mediaTypes.video.playerSize field is where you define the player size that will be passed to demand partners. - -
        - Prebid Server -

        If you’re using Prebid Server, you must also include the mediaTypes.video.mimes field, as this is required by OpenRTB.

        -
        - -In your ad unit you also need to define your list of bidders. For example, including AppNexus as a bidder would look something like this: - -``` - var adUnit1 = { - ... - bids: [{ - bidder: 'appnexus', - params: { - placementId: '123456789', - } - }] -``` - -The parameters differ depending on which bidder you’re including. For a list of parameters for each bidder, see [Bidders’ Params]({{site.github.url}}/dev-docs/bidders.html). - -For full details on creating instream video ad units, see [Show Video Ads with Google Ad Manager – Create Ad Unit]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html#create-a-video-ad-unit). - -For full details on creating outstream video ad units, see [Show Outstream Video Ads – Create Ad Unit]({{site.github.url}}/dev-docs/show-outstream-video-ads.html#step-1-set-up-ad-units-with-the-video-media-type-and-outstream-context). +Your first step to implementing header bidding for video is to [download Prebid.js](/download.html). Before downloading, select the adapters you want to include. (You can add more adapters later.) -### Configuration +- Include at least one bid adapter that supports video. Find a list of eligible adapters [here](/dev-docs/bidders.html#bidder-video-native). +- If Google Ad Manager is your ad server, you must include the [Google Ad Manager Video module](/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html). +- If you’ll be integrating with Prebid Server, be sure to include “Prebid Server” in the list of adapters. -After you’ve defined your ad units, you can continue with the rest of your configuration. In -most cases for video, the first step will be to define where the VAST XML coming back in the bids -will be stored. Some bidders have you covered here -- the VAST is stored on their servers. But -many bidders don't have their own server-side cache. +### How to integrate -{: .alert.alert-success :} -Video players expect that the response from the ad server will be a URL that points to somewhere -on the internet that stores the video ad creative. This URL can't point to the browser, -so Prebid.js will send bid VAST XML out to a cache so it can be displayed if it wins in the ad server. +#### Prebid Video Module -Configuring the video cache is done with [`setConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-vast-cache): +{: .alert.alert-warning :} +The Video Module is a new way of handling Video in Prebid. -``` - pbjs.setConfig({ - cache: { - url: 'https://prebid.adnxs.com/pbc/v1/cache' - /* Or whatever your preferred video cache URL is */ - } - }); -``` - - -And this is where setups for instream and outstream diverge. Please follow one of these links: - -- Instream: [Show Video Ads with Google Ad Manager]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html) -- Outstream: [Show Outstream Video Ads]({{site.github.url}}/dev-docs/show-outstream-video-ads.html) - -Be sure to note the setting for price granularity. You might need to set up a custom price granularity. (See “Custom CPM Bucket Sizing” under [Price Granularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity). Or, if you’re monetizing both banner and video inventory with Prebid, you might need to define format-specific price granularity settings through [mediaTypePriceGranularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-MediaType-Price-Granularity). - -{: .alert.alert-info :} -**Prebid Server** If you’re using Prebid Server, you also need to configure your server-to-server bidder adapters. See [Getting Started with Prebid Server](/overview/prebid-server-overview.html). - -### Examples - -This section contains working examples of instream and outstream video ads for various players. - -### Using client-side adapters - -#### Instream -+ [Akamai AMP]({{site.github.url}}/examples/video/instream/akamai/pb-ve-amp.html) -+ [Brid]({{site.github.url}}/examples/video/instream/brid/pb-ve-brid.html) -+ [Brightcove]({{site.github.url}}/examples/video/instream/brightcove/pb-ve-brightcove.html) -+ [Flowplayer]({{site.github.url}}/examples/video/instream/flowplayer/pb-ve-flowplayer.html) -+ [JWPlayer - Platform]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) -+ [JWPlayer - Hosted]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) -+ [Kaltura]({{site.github.url}}/examples/video/instream/kaltura/pb-ve-kaltura.html) -+ [Ooyala]({{site.github.url}}/examples/video/instream/ooyala/pb-ve-ooyala.html) -+ [VideoJS]({{site.github.url}}/examples/video/instream/videojs/pb-ve-videojs.html) - -#### Outstream +To integrate Prebid with a video player, we recommend using the Video Module. The Video Module will allow Prebid.js to automatically: -+ [Outstream with Google Ad Manager]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html) -+ [Outstream without an Ad Server]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-no-server.html) +- render bids in your desired video player +- mark used bids as won +- trigger player and media events +- fill the oRTB Video Impression and Content params in the bid request -### Using Prebid Server +For details on how to configure follow these [instructions](/prebid-video/video-module.html). -+ [Brid]({{site.baseurl}}/examples/video/server/brid/pbs-ve-brid.html) -+ [JW Player - Platform]({{site.baseurl}}/examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html) -+ [JW Player - Hosted]({{site.baseurl}}/examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html) -+ [Kaltura]({{site.baseurl}}/examples/video/server/kaltura/pbs-ve-kaltura.html) -+ [Ooyala]({{site.baseurl}}/examples/video/server/ooyala/pbs-ve-ooyala.html) -+ [VideoJS]({{site.baseurl}}/examples/video/server/videojs/pbs-ve-videojs.html) +#### Integrating on your own +If you prefer to fully own the integration between Prebid and Video, you can follow these [instructions]({{site.github.url}}/prebid-video/video-integrating-solo.html). ## Further Reading -- [Prebid.js for Video Overview]({{site.github.url}}/prebid-video/video-overview.html) -- [What is Prebid?]({{site.github.url}}/overview/intro.html) +- [Prebid.js for Video Overview](/prebid-video/video-overview.html) +- [What is Prebid?](/overview/intro.html) diff --git a/prebid-video/video-integrating-solo.md b/prebid-video/video-integrating-solo.md new file mode 100644 index 0000000000..0f63b5c5fa --- /dev/null +++ b/prebid-video/video-integrating-solo.md @@ -0,0 +1,114 @@ +--- +layout: page_v2 +title: Integrating Prebid.js with video on your own +description: How to support video in Prebid with your own code +pid: 1 +sidebarType: 4 +--- + +# Integrating Prebid.js with video on your own + +## Define Prebid Ad Units + +Setting up Prebid ad units is almost the same whether you’re working with instream video ads or outstream. The primary difference is specifying the type of video ad (instream or outstream), which you do in the mediaTypes.video.context field: + +```javascript +var adUnit1 = { + code: 'videoAdUnit', + mediaTypes: { + video: { + context: 'instream', // or 'outstream' + plcmt: 2, // 1 = Instream Sound On, 2 = Accompanying Content, 3 = Interstitial 4 = No Content/Standalone + playerSize: [640, 480], + mimes: ['video/mp4'], // required for Prebid Server + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + playbackmethod: [2], + skip: 1 + } + } +} +``` + +The mediaTypes.video.playerSize field is where you define the player size that will be passed to demand partners. + +
        + Prebid Server +

        If you’re using Prebid Server, you must also include the mediaTypes.video.mimes field, as this is required by OpenRTB.

        +
        + +For full details on video ad unit parameters, see [Ad Unit Reference for Video]({{site.baseurl}}/dev-docs/adunit-reference.html#adunitmediatypesvideo) + +In your ad unit you also need to define your list of bidders. For example, including AppNexus as a bidder would look something like this: + +```javascript +var adUnit1 = { + // ... + bids: [{ + bidder: 'appnexus', + params: { + placementId: '123456789', + } + }] +} +``` + +The parameters differ depending on which bidder you’re including. For a list of parameters for each bidder, see [Bidders’ Params]({{site.github.url}}/dev-docs/bidders.html). + +For full details on creating instream video ad units, see [Show Video Ads with Google Ad Manager – Create Ad Unit]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html#create-a-video-ad-unit). + +For full details on creating outstream video ad units, see [Show Outstream Video Ads – Create Ad Unit]({{site.github.url}}/dev-docs/show-outstream-video-ads.html#step-1-set-up-ad-units-with-the-video-media-type-and-outstream-context). + +## Configuration + +After you’ve defined your ad units, you can continue with the rest of your configuration. In +most cases for video, the first step will be to define where the VAST XML coming back in the bids +will be stored. Some bidders have you covered here -- the VAST is stored on their servers. But +many bidders don't have their own server-side cache. + +{: .alert.alert-success :} +Video players expect that the response from the ad server will be a URL that points to somewhere +on the internet that stores the video ad creative. This URL can't point to the browser, +so Prebid.js will send bid VAST XML out to a cache so it can be displayed if it wins in the ad server. + +Configuring the video cache is done with [`setConfig`](/dev-docs/publisher-api-reference/setConfig.html#setConfig-vast-cache): + +```javascript +pbjs.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + /* Or whatever your preferred video cache URL is */ + } +}); +``` + +And this is where setups for instream and outstream diverge. Please follow one of these links: + +- Instream: [Show Video Ads with Google Ad Manager]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html) +- Outstream: [Show Outstream Video Ads]({{site.github.url}}/dev-docs/show-outstream-video-ads.html) + +Be sure to note the setting for price granularity. You might need to set up a custom price granularity. (See “Custom CPM Bucket Sizing” under [Price Granularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-Price-Granularity). Or, if you’re monetizing both banner and video inventory with Prebid, you might need to define format-specific price granularity settings through [mediaTypePriceGranularity](/dev-docs/publisher-api-reference/setConfig.html#setConfig-MediaType-Price-Granularity). + +{: .alert.alert-info :} +**Prebid Server** If you’re using Prebid Server, you also need to configure your server-to-server bidder adapters. See [Getting Started with Prebid Server](/prebid-server/overview/prebid-server-overview.html). + +## Examples + +This section contains working examples of instream and outstream video ads for various players. + +## Using client-side adapters + +### Instream + +- [JWPlayer - Platform]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html) +- [JWPlayer - Hosted]({{site.github.url}}/examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html) +- [VideoJS]({{site.github.url}}/examples/video/instream/videojs/pb-ve-videojs.html) + +### Outstream + +- [Outstream with Google Ad Manager]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-dfp.html) +- [Outstream without an Ad Server]({{site.github.url}}/examples/video/outstream/pb-ve-outstream-no-server.html) + +# Further Reading + +- [Prebid.js for Video Overview]({{site.github.url}}/prebid-video/video-overview.html) +- [What is Prebid?]({{site.github.url}}/overview/intro.html) diff --git a/prebid-video/video-long-form.md b/prebid-video/video-long-form.md index 4eb1a61b2d..2e4db9d4a8 100644 --- a/prebid-video/video-long-form.md +++ b/prebid-video/video-long-form.md @@ -10,39 +10,41 @@ sidebarType: 4 --- # Getting Started with Long-Form Video + {: .no_toc } If you’re new to header bidding and Prebid review the following to get a general understanding of Prebid.js. -- [What Is Prebid?]({{site.github.url}}/overview/intro.html) -- [Getting Started with Prebid]({{site.github.url}}/overview/getting-started.html) +- [What Is Prebid?](/overview/intro.html) +- [Getting Started with Prebid](/adops/before-you-start.html) -See [Prebid.js Video Overview]({{site.github.url}}/prebid-video/video-overview.html) for a general description and high-level overview of working with video demand in Prebid.js. +See [Prebid.js Video Overview](/prebid-video/video-overview.html) for a general description and high-level overview of working with video demand in Prebid.js. -* TOC +- TOC {:toc} ## Ad Server Setup -Prebid uses FreeWheel for the distrubtion of `Creatives`. Refer to [Setting Up Prebid video in FreeWheel]({{site.github.url}}/adops/setting-up-prebid-video-in-freewheel.html) for an Ad Ops getting started guide. +Prebid uses FreeWheel for the distrubtion of `Creatives`. Refer to [Setting Up Prebid video in FreeWheel](/adops/setting-up-prebid-video-in-freewheel.html) for an Ad Ops getting started guide. ## Developers ### Download Prebid.js -To implement header bidding for long-form video start by [downloading Prebid.js]({{site.github.url}}/download.html). +To implement header bidding for long-form video start by [downloading Prebid.js](/download.html). Before downloading, select the adapters you want to include. (You can add more adapters later.) -- Include at least one video adapter. Find a list of available video adapters [here]({{site.github.url}}/dev-docs/bidders.html#bidder-video-native). +- Include at least one video adapter. Find a list of available video adapters [here](/dev-docs/bidders.html#bidder-video-native). - Include the [FreeWheel](/dev-docs/modules/freewheel.html) Ad Server module. - Include the [Category Translation](/dev-docs/modules/categoryTranslation.html) module. - If you’ll be integrating with Prebid Server, be sure to include “Prebid Server” in the list of adapters. ### Ensuring Competitve Separation + You will need to configure Prebid to ensure competitive separation, the process of preventing two ads from the same industry appearing within an ad pod. After you have instantiated a Prebid instance call the setConfig method and add the following key-values. -``` +```javascript pbjs.setConfig({ 'adpod': { 'brandCategoryExclusion': true @@ -56,7 +58,7 @@ As with instream and outstream videos, you must set the video context for long-f As with all ad unit types you must include a list of bidders. The parameters differ depending on which bidder you’re including. For a list of parameters for each bidder, see [Bidders’ Params](/dev-docs/bidders.html). -``` +```javascript var longFormatAdUnit = { video: { // required params @@ -93,7 +95,7 @@ A string indicating the ad unit type. An array of numbers indicating the height and width of the video player size that will be passed to the demand partners. `video.adPodDurationSec` -A number indicating how long the ad pod should run. +A number indicating how long the ad pod should run. `video.durationRangeSec` A number indicating how long the creatives of an ad pod should run. @@ -118,7 +120,7 @@ A number representing the episode number of the television series the adpod will `video.contentLengthSec` A number representing the length of the content the adpod will appear in. -`video.contentMode` +`video.contentMode` A string indicating the type of content being displayed in the video player. There are two options, `live` and `on-demand`.
        @@ -126,11 +128,13 @@ A string indicating the type of content being displayed in the video player. The

        If you’re using Prebid Server, you must also include the mediaTypes.video.mimes field, as this is required by OpenRTB.

        -        mediaTypes: {
        -            video: {
        -                context: 'apod', // or 'instream', 'outstream'
        -                playerSize: [640, 480],
        -                mimes: ['video/mp4'],
        +  mediaTypes: {
        +      video: {
        +          context: 'apod', // or 'instream', 'outstream'
        +          playerSize: [640, 480],
        +          mimes: ['video/mp4'],
        +      }
        +  }
           

        For more on Prebid Server ad unit requirements, see Getting Started with Prebid Server – Video.

        @@ -148,9 +152,9 @@ To prioritize certain video deals and ensure delivery and performance within the `prioritizeDeals` A boolean that indicates if deals should be given a higher preference. If true, Prebid will set the value of `hb_pb_cat_dur` with `bid.video.tier` replacing the cpm value. For example: -
        -    hb_pb_cat_dur=dealId_395_15s
        -  
        +```text +hb_pb_cat_dur=dealId_395_15s +``` `dealTier` An object that enables publishers to set a prefix and minimum deal tier for each bidder. The `dealTier` object enables publishers to have different line item setups with varying priorities. @@ -161,57 +165,57 @@ An optional string that enables bidders to target deal line items. `dealTier.minDealTier` An integer that will give higher preference to deal bids which return tier greater than minDealTier. Bids with `minDealTier` values less than five will not be ignored, however their cache key will contain `dealId` in place of `cpm`. These bids will be auctioned as non-deal bids. -
        -    // This will replace the cpm with dealId in cache key as well as targeting kv pair when prioritizeDeals flag is set to true.
        -        pbjs.setConfig({
        -        adpod: {
        -          prioritizeDeals: true,
        -          dealTier: {
        -            'appnexus': {
        -              prefix: 'tier',
        -              minDealTier: 5
        -            },
        -            'some-other-bidder': {
        -              prefix: 'deals',
        -              minDealTier: 20
        -            }
        -          }
        -        }
        -        })
        -    
        +```javascript +// This will replace the cpm with dealId in cache key as well as targeting kv pair when prioritizeDeals flag is set to true. +pbjs.setConfig({ + adpod: { + prioritizeDeals: true, + dealTier: { + 'appnexus': { + prefix: 'tier', + minDealTier: 5 + }, + 'some-other-bidder': { + prefix: 'deals', + minDealTier: 20 + } + } + } +}) +``` For adpods, the bidder will return multiple bids. Each bid can have a different priority/deal tier setting. To enable publishers to have control over the deal tier a `filterBids` setting has been added to `pbjs.adServers.freewheel.getTargeting` to select certain deal bids. -
        -    pbjs.adServers.freewheel.getTargeting({
        -      codes: [adUnitCode1],
        -      callback: function(err, targeting) {
        -          //pass targeting to player api
        -      }
        -    });
        -  
        +```javascript +pbjs.adServers.freewheel.getTargeting({ + codes: [adUnitCode1], + callback: function(err, targeting) { + //pass targeting to player api + } +}); +``` Below is an example of a bid response for deals. -
        -  // Sample return targeting key value pairs
        +```javascript
        +// Sample return targeting key value pairs
        +{
        +  'adUnitCode-1': [
             {
        -    'adUnitCode-1': [
        -      {
        -        'hb_pb_cat_dur': 'tier9_400_15s', // Bid with deal id
        -      },
        -      {
        -        'hb_pb_cat_dur': 'tier7_401_15s', // Bid with deal id
        -      },
        -      {
        -        'hb_pb_cat_dur': '15.00_402_15s',
        -      },
        -      {
        -        'hb_cache_id': '123'
        -      }
        -    ]
        +      'hb_pb_cat_dur': 'tier9_400_15s', // Bid with deal id
        +    },
        +    {
        +      'hb_pb_cat_dur': 'tier7_401_15s', // Bid with deal id
        +    },
        +    {
        +      'hb_pb_cat_dur': '15.00_402_15s',
        +    },
        +    {
        +      'hb_cache_id': '123'
             }
        -  
        + ] +} +``` ### Examples @@ -219,6 +223,6 @@ See [Prebid Video Examples](/examples/video/long-form/pb-ve-lf-freewheel.html) f ## Further Reading -- [Prebid.js for Video Overview]({{site.github.url}}/prebid-video/video-overview.html) -- [Getting Started with Video for Prebid.js]({{site.github.url}}/prebid-video/video-getting-started.html) -- [What is Prebid?]({{site.github.url}}/overview/intro.html) +- [Prebid.js for Video Overview](/prebid-video/video-overview.html) +- [Getting Started with Video for Prebid.js](/prebid-video/video-getting-started.html) +- [What is Prebid?](/overview/intro.html) diff --git a/prebid-video/video-module.md b/prebid-video/video-module.md new file mode 100644 index 0000000000..4c580e5dfd --- /dev/null +++ b/prebid-video/video-module.md @@ -0,0 +1,592 @@ +--- +layout: page_v2 +title: Prebid Video Module +description: How to use the Video Module to integrate Prebid with Video +pid: 1 +sidebarType: 4 +--- + +# The Video Module + +The Prebid Video Module allows Prebid to directly integrate with a Video Player. Currently the Video Module only supports instream implementations. + +The Video Module will allow Prebid.js to automatically: + +- render bids in the desired video player +- mark used bids as won +- trigger player and media events +- fill the oRTB Video Impression and Content params in the bid request + +## Publishers + +Publishers benefit the most from the Video Module since it allows integrating with a Video Player by simply configuring Prebid. + +### Setting up + +{: .alert.alert-warning :} +The Video Module does not load the Video Player source files on the page. The publisher must have the Video Player's build on the page. + +#### Include submodule in build + +The first step is to include the submodules for the Video Players that you will be integrating with in your build. + +```bash +gulp build --modules=jwplayerVideoProvider,bidAdapter1,bidAdapter2 +``` + +The following Video Players are currently supported: + +{: .table .table-bordered .table-striped } +| Video Player | Submodule Name | Vendor Code | +|--------------|----------------|-------------| +| [JW Player](https://info.jwplayer.com/sign-up/?utm_source=developer&utm_medium=CTA) | jwplayerVideoProvider | 1 | +| [video.js](https://videojs.com/) | videojsVideoProvider | 2 | + +Not seeing your desired video player ? Learn how to add support by reading our [contribution guide](#Video-Module-Contributing) + +Optionally, if you are using an Ad Server, you can configure the Video Module to integrate with it. The following Ad Servers are currently supported: + +{: .table .table-bordered .table-striped } +| Ad Server | Module Name | Vendor Code | +|--------------|----------------|-------------| +| [Google Ad Manager](https://admanager.google.com/) | dfpAdServerVideo | 'gam' | + +{: .alert.alert-warning :} +**Note:** You must include the Ad Server's module in your build. + +#### Configure Prebid + +To register a video player with Prebid, you must use `setConfig` to set a `video` config compliant with the structure described in the [setConfig reference]({{site.baseurl}}/dev-docs/publisher-api-reference/setConfig.html#video-module). + +#### Configure Ad Units + +In order for Prebid to know which Ad Unit relates to which Video Player, you must include a `video` configuration in your Ad Unit. This allows Prebid to render the ad in the proper Video Player and obtain the Ortb data from the Video Player that will render the ad. +For the list of properties in the `video` object of the ad unit please visit the [adUnit.video reference]({{site.baseurl}}/dev-docs/adunit-reference.html#adUnit.video). + +#### Implementation Examples + +[Video.js]({{site.baseurl}}/prebid-video/video-module/integration-examples/videojs.html) + +[JW Player]({{site.baseurl}}/prebid-video/video-module/integration-examples/jwplayer.html) + +### Features for Publishers + +Integrating with the Video Module gives publishers access to the following features + +#### Render ads + +Prebid can load the ad directly into the player when the auction is complete. +This feature happens automatically as long as you do **not** define a `bidsBackHandler` when calling `requestBids`. + + + +#### Events + +Media, ad and Player events are added when using the Video Module. +The event payload includes metadata which can be used for analytics, error handling, and customizing your integration. + +{: .table .table-bordered .table-striped } +| Event Constant | Event String | Description | +|----------------|--------------|-------------| +| SETUP_COMPLETE | 'videoSetupComplete' | Fired when the player is instantiated and the integration is complete. At this point the API is ready to be used. | +| SETUP_FAILED | 'videoSetupFailed' | Fired when the integration was unsuccessful. | +| DESTROYED | 'videoDestroyed' | Fired when the player instance has been destroyed. | +| AD_REQUEST | 'videoAdRequest' | Fired when the player is asked to load an ad. | +| AD_BREAK_START | 'videoAdBreakStart' | Fired when an ad break begins. An ad break consists of an ad, or a sequence of subsequent ads. | +| AD_LOADED | 'videoAdLoaded' | Fired when the player has finished loading the ad's VAST response. | +| AD_STARTED | 'videoAdStarted' | Fired when the ad playback has started. | +| AD_IMPRESSION | 'videoAdImpression' | Fired when an ad has been played for 2 consecutive seconds while the player is at least 50% viewable, as defined by the IAB standards for video ad impressions. | +| AD_PLAY | 'videoAdPlay' | Fired when ad playback starts and is resumed after a pause. | +| AD_TIME | 'videoAdTime' | Fired as the ad playback progresses. Frequency depends on the player. | +| AD_PAUSE | 'videoAdPause' | Fired when the ad is paused. | +| AD_CLICK | 'videoAdClick' | Fired when the ad is clicked or tapped. | +| AD_SKIPPED | 'videoAdSkipped' | Fired when the ad is skipped. | +| AD_ERROR | 'videoAdError' | Fired when an error occurred while attempting to load or render the ad. | +| AD_COMPLETE | 'videoAdComplete' | Fired when the ad has reached its end. | +| AD_BREAK_END | 'videoAdBreakEnd' | Fired when the sequence of ads in the break has ended. | +| PLAYLIST | 'videoPlaylist' | Fired when a media playlist has been loaded into the player. | +| PLAYBACK_REQUEST | 'videoPlaybackRequest' | Fired when an attempt to start the media playback has been made i.e. the viewer has tapped the play icon. | +| AUTOSTART_BLOCKED | 'videoAutostartBlocked' | Fired when autostart has been prevented. Generally, autostart is prevented by the browser. | +| PLAY_ATTEMPT_FAILED | 'videoPlayAttemptFailed' | Fired when the user's attempt to begin playback is unsuccessful. | +| CONTENT_LOADED | 'videoContentLoaded' | Fired when the content media is loaded into the player. | +| PLAY | 'videoPlay' | Fired when the content playback begins or is resumed. | +| PAUSE | 'videoPause' | Fired when the content playback is paused. | +| BUFFER | 'videoBuffer' | Fired when the player enters a buffer state. Usually caused by a delay in loading video segments to continue playback. | +| TIME | 'videoTime' | Fired as the content playback progresses. Frequency depends on the player. | +| SEEK_START | 'videoSeekStart' | Fired when the viewer begins seeking in content. | +| SEEK_END | 'videoSeekEnd' | Fired when the viewer has finished seeking in the content. | +| MUTE | 'videoMute' | Fired when the player is muted. | +| VOLUME | 'videoVolume' | Fired when the player's volume has changed. | +| RENDITION_UPDATE | 'videoRenditionUpdate' | Fired when a change occurred in the video's encoded width, encoded height, reported video bitrate, reported audio bitrate or video framerate. | +| ERROR | 'videoError' | Fired when a player experiences an unrecoverable playback error while playing or attempting to play content. | +| COMPLETE | 'videoComplete' | Fired when a media content has reached its end. | +| PLAYLIST_COMPLETE | 'videoPlaylistComplete' | Fired when the last piece of content in a media playlist has ended. | +| FULLSCREEN | 'videoFullscreen' | Fired when the player enters or exits fullscreen mode. | +| PLAYER_RESIZE | 'videoPlayerResize' | Fired when the player's size is modified. | +| VIEWABLE | 'videoViewable' | Fired when the player's viewability is changed. Viewability is a percentage of the player's size currently in view. The granularity at which this event is triggered depends on the player. | +| CAST | 'videoCast' | Fired when casting to an external device begins or ends. | +| AUCTION_AD_LOAD_ATTEMPT | 'videoAuctionAdLoadAttempt' | Fired when Prebid attempts to load the winning ad from a Prebid auction into the player. | +| AUCTION_AD_LOAD_QUEUED | 'videoAuctionAdLoadQueued' | Fired when Prebid queues the winning ad from a Prebid auction. This occurs when the Video Provider is not yet instantiated. The ad will be loaded into the player once the Video Provider is instantiated. | +| AUCTION_AD_LOAD_ABORT | 'videoAuctionAdLoadAbort' | Fired when the attempt to load the winning ad from a Prebid auction into the player is prevented. | +| BID_IMPRESSION | 'videoBidImpression' | Fired when the ad from a bid resulted in an impression. | +| BID_ERROR | 'videoBidError' | Fired when the ad from a bid resulted in an error. | + +##### Event params + +All Video Module events include a `divId` and `type` param in the payload by default. +The `divId` is the div id string of the player emitting the event; it can be used as an identifier. The `type` is the string name of the event. +The remaining Payload params are listed in the following: + +###### SETUP_COMPLETE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playerVersion | string | The version of the player on the page | +| viewable | boolean | Is the player currently viewable? | +| viewabilityPercentage | number | The percentage of the video that is currently viewable on the user's screen. | +| mute | boolean | Whether or not the player is currently muted. | +| volumePercentage | number | The volume of the player, as a percentage | + +###### SETUP_FAILED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playerVersion | string | The version of the player on the page | +| errorCode | number | The identifier of the error preventing the media from rendering | +| errorMessage | string | Developer friendly description of the reason the error occurred. | +| sourceError | object | The underlying root Error which prevented the playback. | + +###### DESTROYED + +No additional params. + +###### AD_REQUEST + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | + +###### AD_BREAK_START + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | + +###### AD_LOADED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | +| loadTime | number | Time the ad took to load in milliseconds | +| vastAdId | string | The ID given to the ad within the ad tag's XML. Nullable when absent from the VAST xml. | +| adDescription | string | Description of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| adServer | string | Ad server used (e.g. dart or mediamind) from the vast tag. Nullable when absent from the VAST xml. | +| adTitle | string | Title of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| advertiserId | string | Optional identifier for the advertiser, provided by the ad server. Nullable when absent from the VAST xml. | +| advertiserName | string | Name of the advertiser as defined by the ad serving party, from the vast XML. Nullable when absent from the VAST xml. | +| dealId | string | The ID of the Ads deal. Generally relates to Direct Sold Ad Campaigns. Nullable when absent from the VAST xml. | +| linear | boolean | Is the ad linear or not? | +| vastVersion | string | Version of VAST being reported from the tag | +| creativeUrl | string | The URL representing the VPAID or MP4 ad that is run | +| adId | string | Unique Ad ID - refers to the 'attribute' of the node within the VAST. Nullable when absent from the VAST xml. | +| universalAdId | string | Unique identifier for an ad in VAST4. Nullable when absent from the VAST xml. | +| creativeId | string | Ad server's unique ID for the creative pulled from the ad tag's XML. Should be used to specify the ad server’s unique identifier as opposed to the Universal Ad Id which is used for maintaining a creative id for the ad across multiple systems. Nullable when absent from the VAST xml. | +| creativeType | string | The MIME type of the ad creative currently being displayed | +| redirectUrl | string | the url to which the viewer is being redirected after clicking the ad. Nullable when absent from the VAST xml. | +| adPlacementType | number | The video placements per IAB guidelines. Enum list: In-Stream: 1, In-Banner: 2, In-Article: 3, In-Feed: 4, Interstitial/Slider/Floating: 5 | +| waterfallIndex | number | Index of the current item in the ad waterfall | +| waterfallCount | number | The count of items in a given ad waterfall | +| adPodCount | number | the total number of ads in the pod | +| adPodIndex | number | The index of the currently playing ad within an ad pod | +| wrapperAdIds | array[string] | Ad IDs of the VAST Wrappers that were loaded while loading the Ad tag. The list returned starts at the inline ad (innermost) and traverses to the outermost wrapper ad. An empty array is returned if there are no wrapper ads. | + +###### AD_STARTED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | +| loadTime | number | Time the ad took to load in milliseconds | +| vastAdId | string | The ID given to the ad within the ad tag's XML. Nullable when absent from the VAST xml. | +| adDescription | string | Description of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| adServer | string | Ad server used (e.g. dart or mediamind) from the vast tag. Nullable when absent from the VAST xml. | +| adTitle | string | Title of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| advertiserId | string | Optional identifier for the advertiser, provided by the ad server. Nullable when absent from the VAST xml. | +| advertiserName | string | Name of the advertiser as defined by the ad serving party, from the vast XML. Nullable when absent from the VAST xml. | +| dealId | string | The ID of the Ads deal. Generally relates to Direct Sold Ad Campaigns. Nullable when absent from the VAST xml. | +| linear | boolean | Is the ad linear or not? | +| vastVersion | string | Version of VAST being reported from the tag | +| creativeUrl | string | The URL representing the VPAID or MP4 ad that is run | +| adId | string | Unique Ad ID - refers to the 'attribute' of the node within the VAST. Nullable when absent from the VAST xml. | +| universalAdId | string | Unique identifier for an ad in VAST4. Nullable when absent from the VAST xml. | +| creativeId | string | Ad server's unique ID for the creative pulled from the ad tag's XML. Should be used to specify the ad server’s unique identifier as opposed to the Universal Ad Id which is used for maintaining a creative id for the ad across multiple systems. Nullable when absent from the VAST xml. | +| creativeType | string | The MIME type of the ad creative currently being displayed | +| redirectUrl | string | the url to which the viewer is being redirected after clicking the ad. Nullable when absent from the VAST xml. | +| adPlacementType | number | The video placements per IAB guidelines. Enum list: In-Stream: 1, In-Banner: 2, In-Article: 3, In-Feed: 4, Interstitial/Slider/Floating: 5 | +| waterfallIndex | number | Index of the current item in the ad waterfall | +| waterfallCount | number | The count of items in a given ad waterfall | +| adPodCount | number | the total number of ads in the pod | +| adPodIndex | number | The index of the currently playing ad within an ad pod | +| wrapperAdIds | array[string] | Ad IDs of the VAST Wrappers that were loaded while loading the Ad tag. The list returned starts at the inline ad (innermost) and traverses to the outermost wrapper ad. An empty array is returned if there are no wrapper ads. | + + + +###### AD_IMPRESSION + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | +| loadTime | number | Time the ad took to load in milliseconds | +| vastAdId | string | The ID given to the ad within the ad tag's XML. Nullable when absent from the VAST xml. | +| adDescription | string | Description of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| adServer | string | Ad server used (e.g. dart or mediamind) from the vast tag. Nullable when absent from the VAST xml. | +| adTitle | string | Title of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| advertiserId | string | Optional identifier for the advertiser, provided by the ad server. Nullable when absent from the VAST xml. | +| advertiserName | string | Name of the advertiser as defined by the ad serving party, from the vast XML. Nullable when absent from the VAST xml. | +| dealId | string | The ID of the Ads deal. Generally relates to Direct Sold Ad Campaigns. Nullable when absent from the VAST xml. | +| linear | boolean | Is the ad linear or not? | +| vastVersion | string | Version of VAST being reported from the tag | +| creativeUrl | string | The URL representing the VPAID or MP4 ad that is run | +| adId | string | Unique Ad ID - refers to the 'attribute' of the node within the VAST. Nullable when absent from the VAST xml. | +| universalAdId | string | Unique identifier for an ad in VAST4. Nullable when absent from the VAST xml. | +| creativeId | string | Ad server's unique ID for the creative pulled from the ad tag's XML. Should be used to specify the ad server’s unique identifier as opposed to the Universal Ad Id which is used for maintaining a creative id for the ad across multiple systems. Nullable when absent from the VAST xml. | +| creativeType | string | The MIME type of the ad creative currently being displayed | +| redirectUrl | string | the url to which the viewer is being redirected after clicking the ad. Nullable when absent from the VAST xml. | +| adPlacementType | number | The video placements per IAB guidelines. Enum list: In-Stream: 1, In-Banner: 2, In-Article: 3, In-Feed: 4, Interstitial/Slider/Floating: 5 | +| waterfallIndex | number | Index of the current item in the ad waterfall | +| waterfallCount | number | The count of items in a given ad waterfall | +| adPodCount | number | the total number of ads in the pod | +| adPodIndex | number | The index of the currently playing ad within an ad pod | +| wrapperAdIds | array[string] | Ad IDs of the VAST Wrappers that were loaded while loading the Ad tag. The list returned starts at the inline ad (innermost) and traverses to the outermost wrapper ad. An empty array is returned if there are no wrapper ads. | +| time | number | The playback time in the ad when the event occurs, in seconds. | +| duration | number | Total duration of an ad in seconds | + +###### AD_PLAY + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | + +###### AD_TIME + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| time | number | The current poisition in the ad timeline | +| duration | number | Total duration of an ad in seconds | + +###### AD_PAUSE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | + +###### AD_CLICK + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | +| loadTime | number | Time the ad took to load in milliseconds | +| vastAdId | string | The ID given to the ad within the ad tag's XML. Nullable when absent from the VAST xml. | +| adDescription | string | Description of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| adServer | string | Ad server used (e.g. dart or mediamind) from the vast tag. Nullable when absent from the VAST xml. | +| adTitle | string | Title of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| advertiserId | string | Optional identifier for the advertiser, provided by the ad server. Nullable when absent from the VAST xml. | +| advertiserName | string | Name of the advertiser as defined by the ad serving party, from the vast XML. Nullable when absent from the VAST xml. | +| dealId | string | The ID of the Ads deal. Generally relates to Direct Sold Ad Campaigns. Nullable when absent from the VAST xml. | +| linear | boolean | Is the ad linear or not? | +| vastVersion | string | Version of VAST being reported from the tag | +| creativeUrl | string | The URL representing the VPAID or MP4 ad that is run | +| adId | string | Unique Ad ID - refers to the 'attribute' of the node within the VAST. Nullable when absent from the VAST xml. | +| universalAdId | string | Unique identifier for an ad in VAST4. Nullable when absent from the VAST xml. | +| creativeId | string | Ad server's unique ID for the creative pulled from the ad tag's XML. Should be used to specify the ad server’s unique identifier as opposed to the Universal Ad Id which is used for maintaining a creative id for the ad across multiple systems. Nullable when absent from the VAST xml. | +| creativeType | string | The MIME type of the ad creative currently being displayed | +| redirectUrl | string | the url to which the viewer is being redirected after clicking the ad. Nullable when absent from the VAST xml. | +| adPlacementType | number | The video placements per IAB guidelines. Enum list: In-Stream: 1, In-Banner: 2, In-Article: 3, In-Feed: 4, Interstitial/Slider/Floating: 5 | +| waterfallIndex | number | Index of the current item in the ad waterfall | +| waterfallCount | number | The count of items in a given ad waterfall | +| adPodCount | number | the total number of ads in the pod | +| adPodIndex | number | The index of the currently playing ad within an ad pod | +| wrapperAdIds | array[string] | Ad IDs of the VAST Wrappers that were loaded while loading the Ad tag. The list returned starts at the inline ad (innermost) and traverses to the outermost wrapper ad. An empty array is returned if there are no wrapper ads. | +| time | number | The playback time in the ad when the event occurs, in seconds. | +| duration | number | Total duration of an ad in seconds | + +###### AD_SKIPPED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| time | number | The playback time in the ad when the event occurs, in seconds. | +| duration | number | Total duration of an ad in seconds | + + + +###### AD_ERROR + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playerErrorCode | number | The ad error code from the Player’s internal spec. | +| vastErrorCode | number | The error code for the VAST response that is returned from the request, as defined in the VAST spec. | +| errorMessage | string | Developer friendly description of the reason the error occurred. | +| sourceError | object | The underlying root Error which prevented the playback. | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | +| loadTime | number | Time the ad took to load in milliseconds | +| vastAdId | string | The ID given to the ad within the ad tag's XML. Nullable when absent from the VAST xml. | +| adDescription | string | Description of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| adServer | string | Ad server used (e.g. dart or mediamind) from the vast tag. Nullable when absent from the VAST xml. | +| adTitle | string | Title of the ad pulled from the ad tag's XML. Nullable when absent from the VAST xml. | +| advertiserId | string | Optional identifier for the advertiser, provided by the ad server. Nullable when absent from the VAST xml. | +| advertiserName | string | Name of the advertiser as defined by the ad serving party, from the vast XML. Nullable when absent from the VAST xml. | +| dealId | string | The ID of the Ads deal. Generally relates to Direct Sold Ad Campaigns. Nullable when absent from the VAST xml. | +| linear | boolean | Is the ad linear or not? | +| vastVersion | string | Version of VAST being reported from the tag | +| creativeUrl | string | The URL representing the VPAID or MP4 ad that is run | +| adId | string | Unique Ad ID - refers to the 'attribute' of the node within the VAST. Nullable when absent from the VAST xml. | +| universalAdId | string | Unique identifier for an ad in VAST4. Nullable when absent from the VAST xml. | +| creativeId | string | Ad server's unique ID for the creative pulled from the ad tag's XML. Should be used to specify the ad server’s unique identifier as opposed to the Universal Ad Id which is used for maintaining a creative id for the ad across multiple systems. Nullable when absent from the VAST xml. | +| creativeType | string | The MIME type of the ad creative currently being displayed | +| redirectUrl | string | the url to which the viewer is being redirected after clicking the ad. Nullable when absent from the VAST xml. | +| adPlacementType | number | The video placements per IAB guidelines. Enum list: In-Stream: 1, In-Banner: 2, In-Article: 3, In-Feed: 4, Interstitial/Slider/Floating: 5 | +| waterfallIndex | number | Index of the current item in the ad waterfall | +| waterfallCount | number | The count of items in a given ad waterfall | +| adPodCount | number | the total number of ads in the pod | +| adPodIndex | number | The index of the currently playing ad within an ad pod | +| wrapperAdIds | array[string] | Ad IDs of the VAST Wrappers that were loaded while loading the Ad tag. The list returned starts at the inline ad (innermost) and traverses to the outermost wrapper ad. An empty array is returned if there are no wrapper ads. | +| time | number | The playback time in the ad when the event occurs, in seconds. | +| duration | number | Total duration of an ad in seconds | + +###### AD_COMPLETE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | + +###### AD_BREAK_END + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| offset | string | Scheduled position in the video for the ad to play. For mid-rolls, will be the position in seconds as string. Other options: 'pre' (pre-roll), 'post' (post-roll), 'api' (ad was not scheduled) | + +###### PLAYLIST + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playlistItemCount | number | The number of items in the current playlist | +| autostart | boolean | Whether or not the player is set to begin playing automatically. | + +###### PLAYBACK_REQUEST + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playReason | string | wWy the play attempt originated. Options: ‘Unknown’ (Unknown reason:we cannot tell), ‘Interaction’ (A viewer interacts with the UI), ‘Auto’ (Autoplay based on the configuration of the player - autoStart), ‘autoOnViewable’ (autoStart when viewable), ‘autoRepeat’ (media automatically restarted after completion, without any user interaction), ‘Api’ (caused by a call on the player’s API), ‘Internal’ (started because of an internal mechanism i.e. playlist progressed to a recommended item) | + +###### AUTOSTART_BLOCKED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| errorCode | number | The identifier of error preventing the media from rendering | +| errorMessage | string | Developer friendly description of the reason the error occurred. | +| sourceError | object | The underlying root Error which prevented the playback. | + +###### PLAY_ATTEMPT_FAILED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| playReason | string | Why the play attempt originated. Options: ‘Unknown’ (Unknown reason:we cannot tell), ‘Interaction’ (A viewer interacts with the UI), ‘Auto’ (Autoplay based on the configuration of the player - autoStart), ‘autoOnViewable’ (autoStart when viewable), ‘autoRepeat’ (media automatically restarted after completion, without any user interaction), ‘Api’ (caused by a call on the player’s API), ‘Internal’ (started because of an internal mechanism i.e. playlist progressed to a recommended item) | +| errorCode | number | The identifier of error preventing the media from rendering | +| errorMessage | string | Developer friendly description of the reason the error occurred. | +| sourceError | object | The underlying root Error which prevented the playback. | + +###### CONTENT_LOADED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| contentId | string | The unique identifier of the media item being rendered by the video player. Nullable when not provided by Publisher, or unknown. | +| contentUrl | string | The URL of the media source of the playlist item | +| title | string | The title of the content; not meant to be used as a unique identifier. Nullable when not provided by Publisher, or unknown. | +| description | string | The description of the content. Nullable when not provided by Publisher, or unknown. | +| playlistIndex | number | The currently playing media item's index in the playlist. | +| contentTags | array[string] | Customer media level tags describing the content. Nullable when not provided by Publisher, or unknown. | + +###### PLAY + +No additional params. + +###### PAUSE + +No additional params. + +###### BUFFER + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| time | number | Playback position of the media in seconds | +| duration | number | Current media’s length in seconds | +| playbackMode | number | The current playback mode used by a given player. Enum list: vod: 0, live: 1, dvr: 2 | + +###### TIME + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| position | number | Playback position of the media in seconds | +| duration | number | Current media’s length in seconds | + +###### SEEK_START + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| position | number | Playback position of the media in seconds, when the seek begins | +| destination | number | Desired playback position of a seek action, in seconds | +| duration | number | Current media’s length in seconds | + +###### SEEK_END + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| position | number | Playback position of the media in seconds, when the seek has ended | +| duration | number | Current media’s length in seconds | + +###### MUTE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| mute | boolean | Whether or not the player is currently muted. | + +###### VOLUME + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| volumePercentage | number | The volume of the player, as a percentage | + +###### RENDITION_UPDATE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| videoReportedBitrate | number | The bitrate of the currently playing video in kbps as reported by the Adaptive Manifest. | +| audioReportedBitrate | number | The bitrate of the currently playing audio in kbps as reported by the Adaptive Manifest. | +| encodedVideoWidth | number | The encoded width in pixels of the currently playing video rendition. | +| encodedVideoHeight | number | The encoded height in pixels of the currently playing video rendition. | +| videoFramerate | number | The current rate of playback. For a video that is playing twice as fast as the default playback, the playbackRate value should be 2.00 | + +###### ERROR + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| errorCode | number | The identifier of the error preventing the media from rendering | +| errorMessage | string | Developer friendly description of the reason the error occurred. | +| sourceError | object | The underlying root Error which prevented the playback. | + +###### COMPLETE + +No additional params. + +###### PLAYLIST_COMPLETE + +No additional params. + +###### FULLSCREEN + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| fullscreen | boolean | Whether or not the player is currently in fullscreen | + +###### PLAYER_RESIZE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| height | number | The height of the player in pixels | +| width | number | The width of the player in pixels | + +###### VIEWABLE + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| viewable | boolean | Is the player currently viewable? | +| viewabilityPercentage | number | The percentage of the video that is currently viewable on the user's screen. | + +###### CAST + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| casting | boolean | Whether or not the current user is casting to a device | + +###### AUCTION_AD_LOAD_ATTEMPT + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| adUnitCode | string | Unique identifier that was used when creating the ad unit. | + +###### AUCTION_AD_LOAD_QUEUED + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adTagUrl | string | The URL for the ad tag associated with the given ad event | +| adUnitCode | string | Unique identifier that was used when creating the ad unit. | + +###### AUCTION_AD_LOAD_ABORT + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| adUnitCode | string | Unique identifier that was used when creating the ad unit. | + +###### BID_IMPRESSION + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| bid | object | Information about the Bid which resulted in the Ad Impression | +| adEvent | object | Event payload from the [Ad Impression](#ad-impression-params) | + +###### BID_ERROR + +{: .table .table-bordered .table-striped } +| argument name | type | description | +| bid | object | Information about the Bid which resulted in the Ad Error | +| adEvent | object | Event payload from the [Ad Error](#ad-error-params) | + +#### Bids marked as won + +When an impression or error from an ad originating from a winning bid occurs, the bid will be automatically marked as used. + +{: .alert.alert-warning :} +Limitations: the mechanism used to determine when an error occurred for an ad originating from a winning might fail at times when the ad server is GAM because of a limitation in GAM. + +#### Bid request Enrichment + +For your convenience, when an auction begins, the Video Module will update oRTB params in the auction for SSPs to consume and include in their bid requests. + +##### adUnit.mediaTypes.video + +The params in `adUnit.mediaTypes.video` are populated with information extracted from the player. Any param already filled by the publisher will remain unchanged. +Some params such as `battr`, `minduration`, `maxduration` are specific to a publisher's preferences and should therefore be populated by the Publisher. + +##### bidderRequest.ortb2.site.content + +The params in `bidderRequest.ortb2.site.content` are populated with information extracted from the video player. Any params already filled by the publisher will remain unchanged. +This feature can be disabled by setting `video.contentEnrichmentEnabled` to `false` in the Prebid config. +In the case where multiple video players are registered with the Video Module, the `bidderRequest.ortb2.site.content` params will be updated by the video player registered to the ad unit in the auction. If one of the Video Players is responsible for rendering the main content on the page, it may be appropriate for the `site.content` params to be populated with metadata from that player; in such case, you should populate `video.mainContentDivId` in the Prebid config with the video player's div id. | + +## SSPs + +Before bids are requested, the Video Module automatically enriches the auction. SSPs can benefit from this by reading from the proper params. +Given that the video player is the source of truth for most video params, SSPs and DSPs can rely on the accuracy of the information. + +### mediaTypes.video + +Before bids are requested, all ad units configured to be handled by the Video Module will be enriched. The adUnit's `mediaTypes.video` param will be populated automatically. +SSPs wishing to benefit from this enrichment should read from `mediaTypes.video`. + +### bidderRequest.ortb2.site.content + +Similarly, before bids are requested, the `bidderRequest.ortb2.site.content` param is populated in the `bidderRequest` argument of the `buildRequests` function with content metadata from the video player and its media. +SSPs wishing to benefit from this enrichment should read from `bidderRequest.ortb2.site.content`. + + + +## Contributing + +The Prebid Video Module acts as a simple Video interface which Prebid can connect to. In order for the Video Module to plug into a Video Player, a video submodule must be implemented. The Video Submodule acts as a bridge between the Video Module and the Video Player. +To add a submodule please follow the instructions in [How to add a video submodule]({{site.github.url}}/dev-docs/add-video-submodule.html). diff --git a/prebid-video/video-module/integration-examples/jwplayer.html b/prebid-video/video-module/integration-examples/jwplayer.html new file mode 100644 index 0000000000..b96d150912 --- /dev/null +++ b/prebid-video/video-module/integration-examples/jwplayer.html @@ -0,0 +1,123 @@ + + + + + + + JW Player with Playlist + + + + + + + + +

        JW Player with Playlist

        + +
        Div-1: Player placeholder div
        +
        + + + diff --git a/prebid-video/video-module/integration-examples/videojs.html b/prebid-video/video-module/integration-examples/videojs.html new file mode 100644 index 0000000000..74d180ea82 --- /dev/null +++ b/prebid-video/video-module/integration-examples/videojs.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + VideoJS with Playlist + + + + + + + + +

        VideoJS with Playlist

        + +
        Div-1: Player placeholder div
        + + + + + diff --git a/prebid-video/video-overview-video.md b/prebid-video/video-overview-video.md new file mode 100644 index 0000000000..a47afb2d05 --- /dev/null +++ b/prebid-video/video-overview-video.md @@ -0,0 +1,130 @@ +--- +layout: page_v2 +title: Video Intro to Prebid Video +description: A video overview of Prebid Video +sidebarType: 5 +--- + +# Prebid.js and the Video Ad Format + +An introduction to how video works with Prebid.js. + +{% include vimeo-iframe.html id="871606980" title="3.2 Video in Prebid 2023-12-20" %} + +

        +Further Content: + +- [Getting Started with Video for Prebid.js](/prebid-video/video-getting-started.html) +- [Intro to Header Bidding](/overview/intro-to-header-bidding.html) +- [Header Bidding with Prebid](/overview/intro.html#header-bidding-with-prebid) + +Related Videos: + +- [Introduction to Prebid.js](/prebid/prebidjs-video.html) +- [Prebid.js Impression Flow](/prebid/prebidjs-flow-video.html) +- [Components of Prebid.js](/prebid/prebidjs-components-video.html) +- [All Videos](/overview/all-videos.html) + +## Transcript + +### Introduction + +This video explains how video ads work in Prebid.js. + +We’ll discuss the two main ways that video ads can be integrated with page content, how to run Prebid.js auctions for video ads, and how to integrate Prebid.js with your primary ad server for video. + +Let’s start with page integration. There are many ways for video ads to be shown on a website. + +In some cases, the video ads run before, during, or after video content within a video player that is the focus of the user’s attention on the page. + +We call these player-initiated video placements. + +In others, the video ads are positioned alongside static content like a banner ad. Sometimes, publishers even set up multi-format placements that can display banners, video, or native ads. + +We call these page-initiated video placements. + +How you choose to design your video advertising experiences depends on your content and monetization strategies. Your Prebid.js setup will follow the decisions you’ve made about how to integrate video ads into your pages. + +As you start to think about integrating video ad placements with Prebid.js, it’s important to keep one distinction in mind: what communicates with the ad server? Is it the player, or a JavaScript tag on the page? You can certainly run successful Prebid.js auctions in either scenario, but the distinction does impact how Prebid.js is set up. Let’s take a moment to explore each type. + +With player-initiated video ads, the ad opportunity occurs within a video player. In these cases, the video player will be responsible for making the ad request to the primary ad server. Usually, these ads run before, during, or after video content. This type of ad is sometimes called “instream”. To serve ads in this scenario, Prebid.js will work closely with the player in a process that differs in a few key ways from a traditional Prebid.js banner auction. + +Conversely, page-initiated video auctions are quite similar to ordinary banner auctions. For page-initiated video, a video player does not load with the page source code. The ad slot is defined much like a banner or native slot, and JavaScript tags are responsible for making the request to the primary ad server. + +This video will focus mainly on the player-initiated scenario. We’ll touch on the page-initiated case at the end. + +Next, we’ll explain how in-player video works. To get the most of out of this video, you’ll need a basic understanding about how a Prebid.js auction works. For a refresher, check out our other videos, particularly the Introduction to Prebid.js and the Prebid.js Impression Flow. The links to these videos can be found in the notes below. + +### How Prebid.js Video Works + +Next, we’ll explain how in-player video works. To get the most of out of this video, you’ll need a basic understanding about how a Prebid.js auction works. For a refresher, check out our other videos, particularly the Introduction to Prebid.js and the Prebid.js Impression Flow. The links to these videos can be found in the notes below. + +Like in any Prebid.js auction, the process can be broken down into three stages: Pre-Auction, Auction, and Post-Auction + +#### Pre-Auction + +The Pre-Auction phase for pages containing player-initiated video placements is the same as the process we describe in the Prebid.js Impression Flow video. + +In the Pre-Auction phase, the user requests the page, the publishers’ CMS is called and returns the page source, which includes instructions to load Prebid.js and begin an auction for one or more Ad Units. An ad unit defines a unique impression opportunity. + +The ad unit’s media type configuration includes slot attributes like the player size and playback methods. + +Video ads require several more parameters than banner ads. Many of these parameters describe the characteristics of the video player that affect user interaction. These include the size of the video player, whether or not the video plays automatically, whether or not the video has sound automatically enabled, and more. You can set these details manually in the Ad Unit Configuration, or use the Prebid Video Module, which is able to gather them automatically from the video player + +You can set these details manually in the Ad Unit Configuration, or use the Prebid Video Module, which is able to gather them automatically from the video player. + +For more information about the Prebid Video Module, including a list of supported video players, visit docs. Prebid.org. + +#### Auction + +Next comes the auction stage. During this stage, Prebid.js will collect bids. + +Prebid.js makes bid requests to bidders who are enabled for the video ad units. + +The bid request signals that that ad unit is a video player using the `placement` parameter. + +Bidders consider the impression opportunity and decide whether or not to submit a bid. + +When a bidder chooses to bid, they make a response to Prebid.js that contains a price, a VAST Document, and other optional information such as deal IDs. + +VAST is an XML file whose format is standardized by the Interactive Advertising Bureau, or IAB. It contains information that the player will need to display the ad correctly. It also contains information that the player will use to send notifications for tracking events. + +#### Post-Auction + +Next, the Post Auction stage begins. + +Prebid.js evaluates the bid responses using the steps described in the Prebid.js impression flow video. + +In addition, Prebid.js extracts the VAST XML from video bid responses and may be configured to store it in a server-side cache. For most bidders, the cache is a shared location, but some bidders prefer to use their own caching servers. When it’s time for the player to display the ad, the stored VAST document will be retrieved. + +Prebid.js evaluates the bids and generates an ad server request URL for the player. This URL will contain the bid key-value pairs and is passed on to the video player. + +The video player loads the ad server request URL to make a request for ads to the primary ad server. + +The ad server receives the request and chooses a line item to serve, using information about the ad slot and bids to make its decision. + +The creative associated with Prebid line items is a URL that points to the cache where the VAST XML has been stored. When the ad server selects a Prebid line item, it responds to the video player with this URL. + +The video player begins the process of displaying the ad by requesting the VAST XML from the caching server. + +The video ad interprets the VAST document and displays the video ad. + +If the Prebid Video Module is installed, it will generate Prebid.js analytics tracking events from the player as the ad plays. + +### Page-Initiated Video Ads + +We’ll end this video with a brief discussion of page-initiated video ads. + +Page-initiated and player-initiated differ substantially in how Prebid.js identifies the ad slots and communicates with the ad server. + +From Prebid’s perspective, page-initiated video behaves much like the banner and native media types. It is able to coexist with banner and native in multi ad format ad slots, and auction information for page-initiated ad units are sent to the ad server using the targeting key-value pairs used for banner. + +It also uses a JavaScript component like the Prebid Universal Creative to trigger the process of displaying the ad. + +This process usually involves Prebid.js retrieving a renderer which is a JavaScript component that is able to play the video ad. Many renderers integrate seamlessly with the page layout by collapsing and expanding or adhering to a position within the browser window. + +Many bidders provide the renderer for the ads they deliver, but you can use your own instead if you prefer + +### Conclusion + +That’s it for this explanation of Video in Prebid.js. To learn more, check out the reference documentation at docs.prebid.org diff --git a/prebid-video/video-overview.md b/prebid-video/video-overview.md index bb5370d960..6aa791fc03 100644 --- a/prebid-video/video-overview.md +++ b/prebid-video/video-overview.md @@ -8,26 +8,33 @@ nav_section: pbjs-video-get-started sidebarType: 4 --- - - # Prebid.js for Video Overview +{:.no_toc} -Prebid.js provides tools that allow header bidding video demand to compete with your ad server video demand. Prebid video demand can be incorporated for both instream, outstream, and long-form video slots. - -- Instream - Instream video ads serve in-line with existing video content on your page. The ads can serve before, during, or after a piece of video content. As the publisher, you must provide your own video player that can be used to render the ads. +- TOC +{:toc} -- Outstream – Outstream video ads serve separately from any existing video content. Often, outstream video ad units are used to create video inventory on pages that do not include any video content. The outstream video ad is displayed through an associated outstream video renderer, which usually ingests configuration options that control the user experience. (For example, the outstream video player can be configured to expand within a text body on-page when in view, and collapse when the video is finished). +Prebid.js provides tools that allow header bidding video demand to compete with your ad server video demand. Prebid video demand can be incorporated for both instream, outstream, and long-form video slots. -- Long-form - Long-form video content always has a content arc with a beginning, middle and end. Ads display in an ad pod, a grouping of individual ads that appear either in the beginning, end or during the video content. As the publisher you must provide your own video player that can be used to render the ads. +Prebid.js supports all the latest [OpenRTB Video types and subtypes](https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/develop/AdCOM%20v1.0%20FINAL.md#list--placement-subtypes---video-). ## Implementation Here’s a high-level overview of the steps required to start using Prebid.js for video demand. +![Video Overview](/assets/images/prebid-video/video-overview.png){:class="pb-lg-img"} + +For implementation details, see [Getting Started with Video for Prebid.js](/prebid-video/video-getting-started.html). + +The [Prebid Video Module](/prebid-video/video-getting-started.html#prebid-video-module) is the recommended way to implement video. -![Video Overview]({{site.baseurl}}/assets/images/prebid-video/video-overview.png){:class="pb-lg-img"} +## Video Introduction -For implementation details, see [Getting Started with Video for Prebid.js]({{site.github.url}}/prebid-video/video-getting-started.html). +An introduction to how the video ad format works with Prebid.js. + +{% include vimeo-iframe.html id="871606980" title="3.2 Video in Prebid 2023-12-20" %} + +- [Transcript of this video overview](/prebid-video/video-overview-video.html) ## How It Works @@ -35,88 +42,88 @@ For implementation details, see [Getting Started with Video for Prebid.js]({{sit Here’s a high-level diagram showing how video header bidding works for instream video (with more details outlined in the steps below): - ![Instream Video Diagram]({{site.baseurl}}/assets/images/prebid-video/instream-video.png){: .pb-img.pb-lg-img :} - -1. **Prebid sends bid requests.** +1. **Prebid sends bid requests.** Prebid.js code loads within the page header and sends a bid request to each video demand partner included on a given Prebid video ad unit. -2. **Demand partners respond.** +2. **Demand partners respond.** Each response includes the bid price and the video creative in the form of a VAST tag URL which returns a VAST XML wrapper. This video creative will be rendered by the video player if the bid is selected in the ad server. -3. **Prebid.js caches video bids.** +3. **Prebid.js caches video bids.** Each video bid is cached server-side and mapped to a unique cache ID which will be passed to the ad server via key-value targeting. The [Prebid.js video creative]({{site.github.url}}/adops/setting-up-prebid-video-in-dfp.html#creative-setup) configured in the ad server contains a macro that references this cache ID. (Note: Some bidders will cache before responding to Prebid.js. In those cases, the bidder will provide a `bidResponse.videoCacheKey` and this step will be skipped. See [Notes on Prebid Cache]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html#notes-on-prebid-cache) for details.) -4. **Prebid creates new master video ad server tag URL.** +4. **Prebid creates new master video ad server tag URL.** Prebid combines an existing video ad server tag with Prebid key-value targeting pairs to create a new master video ad server tag URL. This URL will be passed into the video player. -5. **Video player calls ad server.** +5. **Video player calls ad server.** The video player loads the master video ad server tag URL, which makes a call to the ad server. -6. **Ad server matches Prebid.js key-value pairs to a pre-configured line item.** +6. **Ad server matches Prebid.js key-value pairs to a pre-configured line item.** -7. **Video player renders the video from the winning bidder.** - a. The master video ad server tag URL returns a VAST XML wrapper containing the Prebid.js video creative. - b. The Prebid.js video creative returns a VAST XML document containing the cached video bid, which was returned by the Prebid demand partner in its bid response. - c. The demand partner’s VAST tag URL is rendered in the video player. +7. **Video player renders the video from the winning bidder.** + a. The master video ad server tag URL returns a VAST XML wrapper containing the Prebid.js video creative. + b. The Prebid.js video creative returns a VAST XML document containing the cached video bid, which was returned by the Prebid demand partner in its bid response. + c. The demand partner’s VAST tag URL is rendered in the video player. ### Outstream Video Outstream video is displayed in banner ad slots using video renderers that are provided either by the demand partner with the bid response or by a renderer that the publisher has associated with the ad unit. This is a high-level diagram showing how header bidding works with outstream video: - ![Outstream Video Diagram]({{site.baseurl}}/assets/images/prebid-video/outstream-video.png){: .pb-img.pb-lg-img :} -1. **Prebid sends request to demand partners.** +1. **Prebid sends request to demand partners.** Prebid.js code loads within the page header and sends a bid request to each video demand partner included on a given Prebid video ad unit. -2. **Demand partners respond.** +2. **Demand partners respond.** Demand partners respond with their respective bids, which may contain a video renderer. (Publishers are encouraged to associate their own video renderer with each outstream video ad unit to include video demand that was not returned with its own renderer.) -3. **Prebid passes key-value targeting to ad server.** +3. **Prebid.js may cache video bids.** +If the configuration is set up, video bids are cached server-side and mapped to a unique cache ID. This may be used at render time. See [Notes on Prebid Cache](/dev-docs/show-video-with-a-dfp-video-tag.html#notes-on-prebid-cache) for details. + +4. **Prebid passes key-value targeting to ad server.** Prebid assigns a unique hb_adid to each video bid/renderer combination, and passes this ID to the ad server via key-value targeting (along with other standard Prebid key-value pairs). This ad ID serves the same role for outstream video ad units as it does for banner ad units. -4. **Ad server chooses winning line item.** +5. **Ad server chooses winning line item.** The ad server chooses the winning line item. If a Prebid line item is selected, the Prebid creative is returned. The creative can be the standard call to `renderAd` or the Universal Creative. -5. **Prebid renders the outstream video.** -Prebid retrieves the winning outstream video bid and renderer from the ad ID (hb_adid). Prebid renders the outstream video into the banner slot. +6. **Prebid renders the outstream video.** +Prebid retrieves the winning outstream video bid and renderer from the ad ID (hb_adid). Prebid renders the outstream video into the banner slot. It is up to the rendering code to retrieve the VAST, which may have been returned fully-formed to the browser, or it may be just a URL where the VAST is cached that the renderer has to load. -### Long-form Video +### Long-form Video Here’s a high-level diagram showing how long-form video header bidding works for adpod video (with more details outlined in the steps below): ![Instream Video Diagram]({{site.baseurl}}/assets/images/prebid-video/instream-video.png){: .pb-img.pb-lg-img :} -1. **Prebid sends request to demand partners.** +1. **Prebid sends request to demand partners.** Prebid.js code loads within the page header and sends a bid request to each video demand partner included on a given Prebid video ad unit. -2. **Demand partners respond.** +2. **Demand partners respond.** As with instream videos, each response includes the bid price and the video creative in the form of a VAST tag URL which returns a VAST XML wrapper. This video creative will be rendered by the video player if the bid is selected in the ad server. - + Additionally each response is required to return an IAB subcategory. A module is provided that converts adserver categories to IAB sub categories. If a publisher prefers to use their own mapping file they will need to set the URL location of that file. -3. **Prebid.js caches video bids.** -Each video bid is cached server-side and mapped to a unique cache ID which will be passed to the FreeWheel ad server via key-value targeting. The [Prebid.js video creative]({{site.github.url}}/adops/setting-up-prebid-video-in-dfp.html#creative-setup) configured in the ad server contains a macro that references this cache ID. (Note: Some bidders will cache before responding to Prebid.js. In those cases, the bidder will provide a `bidResponse.videoCacheKey` and this step will be skipped. See [Notes on Prebid Cache]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html#notes-on-prebid-cache) for details.) +3. **Prebid.js caches video bids.** +Each video bid is cached server-side and mapped to a unique cache ID which will be passed to the FreeWheel ad server via key-value targeting. The [Prebid.js video creative]({{site.github.url}}/adops/setting-up-prebid-video-in-dfp.html#creative-setup) configured in the ad server contains a macro that references this cache ID. (Note: Some bidders will cache before responding to Prebid.js. In those cases, the bidder will provide a `bidResponse.videoCacheKey` and this step will be skipped. See [Notes on Prebid Cache]({{site.github.url}}/dev-docs/show-video-with-a-dfp-video-tag.html#notes-on-prebid-cache) for details.) -4. **Prebid creates new master video ad server tag URL.** +4. **Prebid creates new master video ad server tag URL.** Prebid combines an existing video ad server tag with Prebid key-value targeting pairs to create a new master video ad server tag URL. This URL will be passed into the video player. -5. **Video player calls ad server.** +5. **Video player calls ad server.** The video player loads the master video ad server tag URL, which makes a call to the ad server. -6. **Ad server matches Prebid.js key-value pairs to a pre-configured line item.** +6. **Ad server matches Prebid.js key-value pairs to a pre-configured line item.** -7. **Video player renders the video from the winning bidder.** - a. The master video ad server tag URL returns a VAST XML wrapper containing the Prebid.js video creative. - b. The Prebid.js video creative returns a VAST XML document containing the cached video bid, which was returned by the Prebid demand partner in its bid response. - c. The demand partner’s VAST tag URL is rendered in the video player. +7. **Video player renders the video from the winning bidder.** + a. The master video ad server tag URL returns a VAST XML wrapper containing the Prebid.js video creative. + b. The Prebid.js video creative returns a VAST XML document containing the cached video bid, which was returned by the Prebid demand partner in its bid response. + c. The demand partner’s VAST tag URL is rendered in the video player. ## Further Reading -- [Getting Started with Video for Prebid.js]({{site.github.url}}/prebid-video/video-getting-started.html) -- [Getting Started with Long-Form Video for Prebid.js]({{site.github.url}}/prebid-video/video-long-form.html) -- [What is Prebid?]({{site.github.url}}/overview/intro.html) -- [AdOps - Before You Start]({{site.github.url}}/overview/getting-started.html) -- [Getting Started for Developers]({{site.github.url}}/dev-docs/getting-started.html) +- [Getting Started with Video for Prebid.js](/prebid-video/video-getting-started.html) +- [Getting Started with Long-Form Video for Prebid.js](/prebid-video/video-long-form.html) +- [What is Prebid?](/overview/intro.html) +- [AdOps - Before You Start](/adops/before-you-start.html) +- [Getting Started for Developers](/dev-docs/getting-started.html) diff --git a/prebid/deviceStorageDisclosure.json b/prebid/deviceStorageDisclosure.json new file mode 100644 index 0000000000..47257e171f --- /dev/null +++ b/prebid/deviceStorageDisclosure.json @@ -0,0 +1,22 @@ +{ + "disclosures": [ + { + "identifier": "_sharedid", + "type": "cookie", + "maxAgeSeconds": 2419200, + "cookieRefresh": true, + "domains": [ + "*.sharedid.org" + ], + "purposes": [ + 1 + ] + } + ], + "domains": [ + { + "domain": "*.sharedid.org", + "use": "Cross-domain ID, deprecated in Prebid 5.x. Aside: this is the only purpose Prebid obtained a GVL id for; other device storage set by publisher web or app software maintained by prebid.org are publisher set values. Prebid.org is not a vendor, tracker, or processor of personal information on independent sites or apps running prebid software. There is no reason to seek consent for Prebid's vendor id unless a publisher is using long-deprecated functionality. Values such as _pbjs_userid_consent_data are written by the publisher themselves and should be declared as such. Publishers seeking to understand all values should consider setting strictStorageEnforcement or reference relevant prebid documentation discussing each value." + } + ] +} diff --git a/prebid/events.md b/prebid/events.md index 19d95b126e..15bbb53e51 100644 --- a/prebid/events.md +++ b/prebid/events.md @@ -6,18 +6,17 @@ sidebarType: 0 --- # Prebid.org Events + {:.no_toc} -## Upcoming Event: +## Upcoming Event {: .table .table-bordered .table-striped } | Title: | How to Make Prebid the Supply Path Buyers Choose | | Date: | Aug 27, 2020 | | Registration: | [link](https://event.on24.com/eventRegistration/EventLobbyServlet?target=reg20.jsp&referrer=&eventid=2543494&sessionid=1&key=A724FF00CF11F4BF9C611B265C62DAEE®Tag=&sourcepage=register) | - - -## Past Events: +## Past Events {: .table .table-bordered .table-striped } | Date | Description | Location | diff --git a/prebid/native-implementation-legacy.md b/prebid/native-implementation-legacy.md new file mode 100644 index 0000000000..457457330c --- /dev/null +++ b/prebid/native-implementation-legacy.md @@ -0,0 +1,484 @@ +--- + +layout: page_v2 +title: Prebid.js Legacy Native Implementation Guide +description: Prebid.js Legacy Native Implementation Guide +sidebarType: 1 + +--- + +# Prebid.js Legacy Native Implementation Guide + +{: .no_toc} + +{% capture version2 %} +Prebid recommends new native implementations use the [OpenRTB method of defining native ads](/prebid/native-implementation.html). +{% endcapture %} +{% include alerts/alert_important.html content=version2 %} + +- TOC +{:toc} + +## Overview + +A native ad is made up of assets such as a title, description, and image URL that are plugged into a publisher-defined HTML template. The template includes placeholder macros for those assets, and may be styled to match the form of the surrounding page. + +At a high level, Prebid.js’ support for native ads works like this: + +- The publisher establishes one or more native rendering templates and sets up the ad server. +- The publisher defines which AdUnits are eligible for native ads and the bidders participating in the auction. +- Prebid.js requests native demand from bidder adapters that support the “native” mediatype. +- Native bids are stored in the Prebid.js memory space. +- The call to the ad server is made as usual. +- If the native ad wins, it’s displayed and any trackers are fired. + +{: .alert.alert-info :} +To determine whether a bidder can supply native demand, check the [bidder parameter page](/dev-docs/bidders.html). + +## 1. Set up your ad server ad slot and HTML div + +Create your ad server in-page implementation as usual. See [Setting Up Prebid Native in GAM](/adops/gam-native.html) for instructions for how to do this with Google Ad Manager. + +## 2. Determine where the native template will be defined + +There are three options for defining the native template: + +- If you want to manage your creative within the ad server (e.g. Google Ad Manager), follow the instructions for [AdServer-Defined Template](#41-implementing-adserver-defined-template). +- If you’d prefer to manage your creative within the Prebid.js AdUnit, follow the instructions for [AdUnit-Defined Template](#42-implementing-adunit-defined-template). +- If you’d prefer to manage your creative from a separate piece of JavaScript, follow the instructions for the [Custom Renderer](#43-implementing-the-custom-renderer-scenario). + +This table summarizes how the 3 approaches work: + +**Table 1: Native Implementation Approaches** + +{: .table .table-bordered .table-striped } +| Component | AdServer-Defined Creative Scenario | AdUnit-Defined Creative Scenario | Custom Renderer Scenario | +| --- | --- |--- | --- | +| Prebid.js | mediaTypes. native.sendTargetingKeys: false | sendTargetingKeys:false and mediaTypes.native.adTemplate contains ##macros## | sendTargetingKeys:false and mediaTypes.native.rendererUrl | +| Ad Server Key Value Pairs | hb_adid | hb_adid | hb_adid | +| Ad Server | Native template loads native-render.js and calls renderNativeAd(). Uses Prebid ##macro## format. | Native creative loads native-render.js and calls renderNativeAd() with requestAllAssets: true | Native creative loads native-render.js and calls renderNativeAd(), with requestAllAssets:true | +| Prebid Universal Creative | renderNativeAd resolves macros in the creative body and CSS. | renderNativeAd resolves ##macros## in adTemplate and CSS, appending the adTemplate to the creative body | renderNativeAd loads javascript from renderUrl, calls the renderAd function, appending the results to the creative body. | +| Javascript rendering function | n/a | n/a | Receives hash of attributes, responsible for resolving any macro format and returning an HTML block. | + +## 3. Prebid.js Native AdUnit Overview + +The Prebid.js AdUnit needs to defines a native mediatype object to tell bidders which assets are required. This table defines all attributes that could be included in AdUnit.mediatypes.native. Specific examples of the three different scenarios follow. + +**Table 2: Prebid.js AdUnit Native MediaType Options** + +{: .table .table-bordered .table-striped } +| Attribute | Scope | Description | Example | Type | +| --- | --- | --- | --- | --- | +| sendTargetingKeys | optional | Defines whether or not to send the hb_native_ASSET targeting keys to the ad server. Defaults to `true` for now, though we recommend setting this to `false` and utilizing one of the ways to define a native template. | `false` | boolean | +| adTemplate | optional | Used in the ‘AdUnit-Defined Creative Scenario’, this value controls the Native template right in the page. | See [example](#42-implementing-adunit-defined-template) below. | escaped ES5 string | +| rendererUrl | optional | Used in the ‘Custom Renderer Scenario’, this points to javascript code that will produce the Native template. | `'https://host/path.js'` | string | +| type | optional | A “type” is like a macro that defines a group of assets. The only value currently supported is ‘image’, which implies the following assets: image, title, sponsoredBy, clickUrl, body, icon, and cta. The first 4 are required attributes. | `image` | string | +| ASSETCODE. required | optional | Defines whether native bids must include this asset. Defaults to `false`. | `true` | boolean | +| ASSETCODE. len | optional | For text assets, bidders should pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. | 40 | integer | +| ASSETCODE. sizes | optional | For image assets, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. Format is an array with two elements: [WIDTH, HEIGHT] | `[50, 50]` | array of integers | +| ASSETCODE. aspect_ratios | optional | For image assets, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. Format is an object with the attributes in the rows below. | | object | +| ASSETCODE. aspect_ratios.min_width | optional | Part of the aspect_ratios object, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. | 50 | integer | +| ASSETCODE. aspect_ratios.min_height | optional | Part of the aspect_ratios object, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. | 75 | integer | +| ASSETCODE. aspect_ratios.ratio_width | optional | Part of the aspect_ratios object, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. | 2 | integer | +| ASSETCODE. aspect_ratios.ratio_height | optional | Part of the aspect_ratios object, bidders may pass this value through to the endpoint. Prebid.js does not enforce the responses and there’s no default. | 3 | integer | +| ext.CUSTOMASSET | optional | Non-standard or bidder-specific assets can be supplied on the `ext` here. Attributes on custom assets are documented by the vendor. | | | + +**Table 3: Native Assets Recognized by Prebid.js** + +{% include dev-docs/native-assets.md %} + +{: .alert.alert-warning :} +Specific bidders may not support all of the fields listed below or may return differing responses for the assets that are requested. + +### 3.1. Two ways to define image sizes + +{% include dev-docs/native-image-asset-sizes.md %} + +### 3.2 Custom native assets + +In order to fit special bidder requirements, Prebid.js supports defining assets beyond the standard set. Simply define custom attributes in mediaTypes.native.ext, and they can be retrieved at render time. Other than being under the `ext` object, custom assets are declared in the same way as the standard ones. + +{: .alert.alert-success :} +Note: The `native-render.js::renderNativeAd()` function must be called with `requestAllAssets: true`. + +Bid adapters will declare which custom assets they support in their documentation. It is recommended to prefix the asset name with the bidderCode to avoid collision issues. + +```javascript +mediaTypes { + native: { + body: { + required: true + }, + ext: { + bidderA_specialtracking: { // custom asset + required: false + } + } +} +``` + +In the native template, simply access the custom value with the normal Prebid ##macro## format assuming `hb_native_` as the prefix. For example: + +```html +

        +... render a lovely creative ... +... refer to ##hb_native_bidderA_specialtracking## when appropriate ... +
        +``` + +## 4. Implementing the Native Template + +- If you want to manage your creative within the ad server (e.g. Google Ad Manager), follow the instructions for [AdServer-Defined Creative](#41-implementing-adserver-defined-template). +- If you’d prefer to manage your creative within the Prebid.js AdUnit, follow the instructions for [AdUnit-Defined Creative](#42-implementing-adunit-defined-template) +- If you’d prefer to manage your creative from a separate piece of JavaScript, follow the instructions for the [Custom Renderer](#43-implementing-the-custom-renderer-scenario). + +### 4.1. Implementing AdServer-Defined Template + +In this scenario, the body of the native creative template is managed within the ad server and includes special Prebid.js macros. + +#### Turn Targeting Keys off in Prebid.js + +When the native AdUnit is defined in the page, declare `sendTargetingKeys: false` in the native Object. This will prevent Prebid.js from sending all the native-related ad server targeting variables. + +Example Native AdUnit: + +```javascript +pbjs.addAdUnits({ + code: slot.code, + mediaTypes: { + native: { + sendTargetingKeys: false, + image: { + required: true, + sizes: [150, 50] + }, + title: { + required: true, + len: 80 + }, + sponsoredBy: { + required: true + }, + clickUrl: { + required: true + }, + privacyLink: { + required: false + }, + body: { + required: true + }, + icon: { + required: true, + sizes: [50, 50] + } + } + }, + bids: [{ + ... + }] +}); +``` + +Here’s an example native AdUnit using the ‘type’ feature, which implies a number of required and optional attributes. + +```javascript +const adUnits = [{ + code: 'adUnit-code', + mediaTypes: { + sendTargetingKeys: false, + native: { + type: 'image' + } + } + bids: [{ + ... + }] +}]; +``` + +#### Native Template in AdServer + +There are three key aspects of the native template: + +1. Build the creative with special Prebid.js macros, e.g. ##hb_native_assetname##. (See the Native Assets table above for an exhaustive list of assets and macros.) Note that macros can be placed in the body (HTML) and/or head (CSS) of the native creative. +2. Load the Prebid.js native rendering code. You may utilize the jsdelivr version of native-render.js or host your own copy. If you use the version hosted on jsdelivr, make sure any necessary ad server permissions are established. +3. Invoke the Prebid.js native rendering function with an object containing the following attributes: + 1. adid - used to identify which Prebid.js creative holds the appropriate native assets + 2. pubUrl - the URL of the page, which is needed for the HTML postmessage call + 3. requestAllAssets - tells the renderer to get all the native assets from Prebid.js rather than having to scan the template to find which specific assets are needed. + +Example creative HTML: + +```html + + + +``` + +{: .alert.alert-warning :} +When using 'Send All Bids' mode you should update `pbNativeTagData.adId = "%%PATTERN:hb_adid_BIDDERCODE%%";` for each bidder’s creative + +Example CSS: + +```css +.sponsored-post { + background-color: #fffdeb; + font-family: sans-serif; + padding: 10px 20px 10px 20px; +} + +.content { + overflow: hidden; +} + +.thumbnail { + width: 120px; + height: 100px; + float: left; + margin: 0 20px 10px 0; + background-image: url(##native_image##); + background-size: cover; +} + +h1 { + font-size: 18px; + margin: 0; +} + +a { + color: #0086b3; + text-decoration: none; +} + +p { + font-size: 16px; + color: #444; + margin: 10px 0 10px 0; +} + +.attribution { + color: #fff; + font-size: 9px; + font-weight: bold; + display: inline-block; + letter-spacing: 2px; + background-color: #ffd724; + border-radius: 2px; + padding: 4px; +} +``` + +### 4.2 Implementing AdUnit-Defined Template + +In this scenario, the body of the native creative template is managed within the Prebid.js AdUnit and includes special Prebid.js macros. + +#### Prebid.js AdUnit Setup + +When the Native AdUnit is defined in the page: + +- Declare `sendTargetingKeys: false` in the native Object. This will prevent Prebid.js from sending all the native-related ad server targeting variables. +- Define the adTemplate as an escaped ES5 string using Prebid.js ##macros##. (See the appendix for an exhaustive list of assets and macros.) Note that this approach only affects the HTML body. Any CSS definitions need to be defined in the body of the template or in the AdServer. + +Example AdUnit: + +```javascript +var adUnits = [{ + code: 'native-div', + mediaTypes: { + native: { + sendTargetingKeys: false, + adTemplate: "
        \r\n
        <\/div>\r\n
        \r\n

        \r\n \r\n ##hb_native_title##\r\n <\/a>\r\n <\/h1>\r\n

        ##hb_native_body##<\/p>\r\n \t

        \r\n \t##hb_native_brand##\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>", + title: { + required: true, + len: 800 + }, + image: { + required: true, + sizes: [989, 742], + }, + sponsoredBy: { + required: true + } + } + } + } +}]; +``` + +#### Native Template in the AdServer + +Even though the body of the native creative is defined in the AdUnit, an AdServer creative is still needed. There are two key aspects of the native creative in this scenario: + +1. Load the Prebid.js native rendering code. You may utilize the jsdelivr version of native-render.js or host your own copy. If you use the version hosted on jsdelivr, make sure any necessary ad server permissions are established. +2. Invoke the Prebid.js native rendering function with an object containing the following attributes: + 1. adid - used to identify which Prebid.js creative holds the appropriate native assets + 2. pubUrl - the URL of the page, which is needed for the HTML postmessage call + 3. requestAllAssets - tells the renderer to get all the native assets from Prebid.js. The rendering function cannot currently scan a template defined in the AdUnit. + +Example Creative HTML + +```html + + +``` + +{: .alert.alert-warning :} +When using 'Send All Bids' mode you should update `pbNativeTagData.adId = "%%PATTERN:hb_adid_BIDDERCODE%%";` for each bidder’s creative + +### 4.3 Implementing the Custom Renderer Scenario + +In this scenario, the body of the native creative is managed from an external JavaScript file. + +#### Prebid.js AdUnit Setup + +When the Native AdUnit is defined in the page: + +- Declare`sendTargetingKeys: false` in the Native Object. This will prevent Prebid.js from sending all the native-related ad server targeting variables. +- Define the `rendererUrl` as a URL that defines a `window.renderAd` function in the creative iframe. Any CSS definitions need to be defined in the body (e.g. `