Repository: prebid/prebid-server
Pull request #2871 (2023-06-27 20:09:42)

Update Go version to 1.20.5


Patch:
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f4ea099d..ebf6f614 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -6,7 +6,7 @@
 		"dockerfile": "Dockerfile",
 		"args": {
 			// Update the VARIANT arg to pick a version of Go
-			"VARIANT": "1.19",
+			"VARIANT": "1.20",
 			// Options
 			"INSTALL_NODE": "false",
 			"NODE_VERSION": "lts/*"
diff --git a/.github/workflows/helpers/pull-request-utils.js b/.github/workflows/helpers/pull-request-utils.js
new file mode 100644
index 00000000..64ea5382
--- /dev/null
+++ b/.github/workflows/helpers/pull-request-utils.js
@@ -0,0 +1,337 @@
+const synchronizeEvent = "synchronize",
+  openedEvent = "opened",
+  completedStatus = "completed",
+  resultSize = 100
+
+class diffHelper {
+  constructor(input) {
+    this.owner = input.context.repo.owner
+    this.repo = input.context.repo.repo
+    this.github = input.github
+    this.pullRequestNumber = input.context.payload.pull_request.number
+    this.pullRequestEvent = input.event
+    this.testName = input.testName
+    this.fileNameFilter = !input.fileNameFilter ? () => true : input.fileNameFilter
+    this.fileLineFilter = !input.fileLineFilter ? () => true : input.fileLineFilter
+  }
+
+  /*
+    Checks whether the test defined by this.testName has been executed on the given commit
+    @param {string} commit - commit SHA to check for test execution
+    @returns {boolean} - returns true if the test has been executed on the commit, otherwise false
+  */
+  async #isTestExecutedOnCommit(commit) {
+    const response = await this.github.rest.checks.listForRef({
+      owner: this.owner,
+      repo: this.repo,
+      ref: commit,
+    })
+
+    return response.data.check_runs.some(
+      ({ status, name }) => status === completedStatus && name === this.testName
+    )
+  }
+
+  /*
+    Retrieves the line numbers of added or updated lines in the provided files
+    @param {Array} files - array of files containing their filename and patch
+    @returns {Object} - object mapping filenames to arrays of line numbers indicating the added or updated lines
+  */
+  async #getDiffForFiles(files = []) {
+    let diff = {}
+    for (const { filename, patch } of files) {
+      if (this.fileNameFilter(filename)) {
+        const lines = patch.split("\n")
+        if (lines.length === 1) {
+          continue
+        }
+
+        let lineNumber
+        for (const line of lines) {
+          // Check if line is diff header
+          //  example:
+          //    @@ -1,3 +1,3 @@
+          //    1    var a
+          //    2
+          //    3   - //test
+          //    3   +var b
+          // Here @@ -1,3 +1,3 @@ is diff header
+          if (line.match(/@@\s.*?@@/) != null) {
+            lineNumber = parseInt(line.match(/\+(\d+)/)[0])
+            continue
+          }
+
+          // "-" prefix indicates line was deleted. So do not consider deleted line
+          if (line.startsWith("-")) {
+            continue
+          }
+
+          // "+"" prefix indicates line was added or updated. Include line number in diff details
+          if (line.startsWith("+") && this.fileLineFilter(line)) {
+            diff[filename] = diff[filename] || []
+            diff[filename].push(lineNumber)
+          }
+          lineNumber++
+        }
+      }
+    }
+    return diff
+  }
+
+  /*
+    Retrieves a list of commits that have not been checked by the test defined by this.testName
+    @returns {Array} - array of commit SHAs that have not been checked by the test
+  */
+  async #getNonScannedCommits() {
+    const { data } = await this.github.rest.pulls.listCommits({
+      owner: this.owner,
+      repo: this.repo,
+      pull_number: this.pullRequestNumber,
+      per_page: resultSize,
+    })
+    let nonScannedCommits = []
+
+    // API returns commits in ascending order. Loop in reverse to quickly retrieve unchecked commits
+    for (let i = data.length - 1; i >= 0; i--) {
+      const { sha, parents } = data[i]
+
+      // Commit can be merged master commit. Such commit have multiple parents
+      // Do not consider such commit for building file diff
+      if (parents.length > 1) {
+        continue
+      }
+
+      const isTestExecuted = await this.#isTestExecutedOnCommit(sha)
+      if (isTestExecuted) {
+        // Remaining commits have been tested in previous scans. Therefore, do not need to be considered again
+        break
+      } else {
+        nonScannedCommits.push(sha)
+      }
+    }
+
+    // Reverse to return commits in ascending order. This is needed to build diff for commits in chronological order
+    return nonScannedCommits.reverse()
+  }
+
+  /*
+    Filters the commit diff to include only the files that are part of the PR diff
+    @param {Array} commitDiff - array of line numbers representing lines added or updated in the commit
+    @param {Array} prDiff - array of line numbers representing lines added or updated in the pull request
+    @returns {Array} - filtered commit diff, including only the files that are part of the PR diff
+  */
+  async #filterCommitDiff(commitDiff = [], prDiff = []) {
+    return commitDiff.filter((file) => prDiff.includes(file))
+  }
+
+  /*
+    Builds the diff for the pull request, including both the changes in the pull request and the changes in non-scanned commits
+    @returns {string} - json string representation of the pull request diff and the diff for non-scanned commits
+  */
+  async buildDiff() {
+    const { data } = await this.github.rest.pulls.listFiles({
+      owner: this.owner,
+      repo: this.repo,
+      pull_number: this.pullRequestNumber,
+      per_page: resultSize,
+    })
+
+    const pullRequestDiff = await this.#getDiffForFiles(data)
+
+    const nonScannedCommitsDiff =
+      Object.keys(pullRequestDiff).length != 0 && this.pullRequestEvent === synchronizeEvent // The "synchronize" event implies that new commit are pushed after the pull request was opened
+        ? await this.getNonScannedCommitDiff(pullRequestDiff)
+        : {}
+
+    const prDiffFiles = Object.keys(pullRequestDiff)
+    const pullRequest = {
+      hasChanges: prDiffFiles.length > 0,
+      files: prDiffFiles.join(" "),
+      diff: pullRequestDiff,
+    }
+    const uncheckedCommits = { diff: nonScannedCommitsDiff }
+    return JSON.stringify({ pullRequest, uncheckedCommits })
+  }
+
+  /*
+    Retrieves the diff for non-scanned commits by comparing their changes with the pull request diff
+    @param {Object} pullRequestDiff - The diff of files in the pull request
+    @returns {Object} - The diff of files in the non-scanned commits that are part of the pull request diff
+   */
+  async getNonScannedCommitDiff(pullRequestDiff) {
+    let nonScannedCommitsDiff = {}
+    // Retrieves list of commits that have not been scanned by the PR check
+    const nonScannedCommits = await this.#getNonScannedCommits()
+    for (const commit of nonScannedCommits) {
+      const { data } = await this.github.rest.repos.getCommit({
+        owner: this.owner,
+        repo: this.repo,
+        ref: commit,
+      })
+
+      const commitDiff = await this.#getDiffForFiles(data.files)
+      const files = Object.keys(commitDiff)
+      for (const file of files) {
+        // Consider scenario where the changes made to a file in the initial commit are completely undone by subsequent commits
+        // In such cases, the modifications from the initial commit should not be taken into account
+        // If the changes were entirely removed, there should be no entry for the file in the pullRequestStats
+        const filePRDiff = pullRequestDiff[file]
+        if (!filePRDiff) {
+          continue
+        }
+
+        // Consider scenario where changes made in the commit were partially removed or modified by subsequent commits
+        // In such cases, include only those commit changes that are part of the pullRequestStats object
+        // This ensures that only the changes that are reflected in the pull request are considered
+        const changes = await this.#filterCommitDiff(commitDiff[file], filePRDiff)
+
+        if (changes.length !== 0) {
+          // Check if nonScannedCommitsDiff[file] exists, if not assign an empty array to it
+          nonScannedCommitsDiff[file] = nonScannedCommitsDiff[file] || []
+          // Combine the existing nonScannedCommitsDiff[file] array with the commit changes
+          // Remove any duplicate elements using the Set data structure
+          nonScannedCommitsDiff[file] = [
+            ...new Set([...nonScannedCommitsDiff[file], ...changes]),
+          ]
+        }
+      }
+    }
+    return nonScannedCommitsDiff
+  }
+}
+
+class semgrepHelper {
+  constructor(input) {
+    this.owner = input.context.repo.owner
+    this.repo = input.context.repo.repo
+    this.github = input.github
+
+    this.pullRequestNumber = input.context.payload.pull_request.number
+    this.pullRequestEvent = input.event
+
+    this.pullRequestDiff = input.diff.pullRequest.diff
+    this.newCommitsDiff = input.diff.uncheckedCommits.diff
+
+    this.semgrepErrors = []
+    this.semgrepWarnings = []
+    input.semgrepResult.forEach((res) => {
+      res.severity === "High" ? this.semgrepErrors.push(res) : this.semgrepWarnings.push(res)
+    })
+
+    this.headSha = input.headSha
+  }
+
+  /*
+    Retrieves the matching line number from the provided diff for a given file and range of lines
+    @param {Object} range - object containing the file, start line, and end line to find a match
+    @param {Object} diff - object containing file changes and corresponding line numbers
+    @returns {number|null} - line number that matches the range within the diff, or null if no match is found
+  */
+  async #getMatchingLineFromDiff({ file, start, end }, diff) {
+    const fileDiff = diff[file]
+    if (!fileDiff) {
+      return null
+    }
+    if (fileDiff.includes(start)) {
+      return start
+    }
+    if (fileDiff.includes(end)) {
+      return end
+    }
+    return null
+  }
+
+  /*
+    Splits the semgrep results into different categories based on the scan
+    @param {Array} semgrepResults - array of results reported by semgrep
+    @returns {Object} - object containing the categorized semgrep results i.e results reported in previous scans and new results found in the current scan
+  */
+  async #splitSemgrepResultsByScan(semgrepResults = []) {
+    const result = {
+      nonDiff: [], // Errors or warnings found in files updated in pull request, but not part of sections that were modified in the pull request
+      previous: [], // Errors or warnings found in previous semgrep scans
+      current: [], // Errors or warnings found in current semgrep scan
+    }
+
+    for (const se of semgrepResults) {
+      const prDiffLine = await this.#getMatchingLineFromDiff(se, this.pullRequestDiff)
+      if (!prDiffLine) {
+        result.nonDiff.push({ ...se })
+        continue
+      }
+
+      switch (this.pullRequestEvent) {
+        case openedEvent:
+          // "Opened" event implies that this is the first check
+          // Therefore, the error should be appended to the result.current
+          result.current.push({ ...se, line: prDiffLine })
+        case synchronizeEvent:
+          const commitDiffLine = await this.#getMatchingLineFromDiff(se, this.newCommitsDiff)
+          // Check if error or warning is part of current commit diff
+          // If not then error or warning was reported in previous scans
+          commitDiffLine != null
+            ? result.current.push({ ...se, line: commitDiffLine })
+            : result.previous.push({
+                ...se,
+                line: prDiffLine,
+              })
+      }
+    }
+    return result
+  }
+
+  /*
+    Adds review comments based on the semgrep results to the current pull request
+    @returns {Object} - object containing the count of unaddressed comments from the previous scan and the count of new comments from the current scan
+  */
+  async addReviewComments() {
+    let result = {
+      previousScan: { unAddressedComments: 0 },
+      currentScan: { newComments: 0 },
+    }
+
+    if (this.semgrepErrors.length == 0 && this.semgrepWarnings.length == 0) {
+      return result
+    }
+
+    const errors = await this.#splitSemgrepResultsByScan(this.semgrepErrors)
+    if (errors.previous.length == 0 && errors.current.length == 0) {
+      console.log("Semgrep did not find any errors in the current pull request changes")
+    } else {
+      for (const { message, file, line } of errors.current) {
+        await this.github.rest.pulls.createReviewComment({
+          owner: this.owner,
+          repo: this.repo,
+          pull_number: this.pullRequestNumber,
+          commit_id: this.headSha,
+          body: message,
+          path: file,
+          line: line,
+        })
+      }
+      result.currentScan.newComments = errors.current.length
+      if (this.pullRequestEvent == synchronizeEvent) {
+        result.previousScan.unAddressedComments = errors.previous.length
+      }
+    }
+
+    const warnings = await this.#splitSemgrepResultsByScan(this.semgrepWarnings)
+    for (const { message, file, line } of warnings.current) {
+      await this.github.rest.pulls.createReviewComment({
+        owner: this.owner,
+        repo: this.repo,
+        pull_number: this.pullRequestNumber,
+        commit_id: this.headSha,
+        body: "Consider this as a suggestion. " + message,
+        path: file,
+        line: line,
+      })
+    }
+    return result
+  }
+}
+
+module.exports = {
+  diffHelper: (input) => new diffHelper(input),
+  semgrepHelper: (input) => new semgrepHelper(input),
+}
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
new file mode 100644
index 00000000..87c5573e
--- /dev/null
+++ b/.github/workflows/semgrep.yml
@@ -0,0 +1,74 @@
+name: Adapter semgrep checks
+on:
+  pull_request:
+    paths: ["adapters/*/*.go"]
+permissions: write-all
+jobs:
+  semgrep-check:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repo
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Calculate diff
+        id: calculate_diff
+        uses: actions/github-script@v6
+        with:
+          result-encoding: string
+          script: |
+            const utils = require('./.github/workflows/helpers/pull-request-utils.js')
+            // consider only non-test Go files that are part of the adapter code
+            function fileNameFilter(filename) {
+              return filename.startsWith("adapters/") && filename.split("/").length > 2 && filename.endsWith(".go") && !filename.endsWith("_test.go")
+            }
+            const helper = utils.diffHelper({github, context, fileNameFilter, event: "${{github.event.action}}", testName: "${{github.job}}"})
+            return await helper.buildDiff()
+
+      - name: Should run semgrep
+        id: should_run_semgrep
+        run: |
+          hasChanges=$(echo '${{ steps.calculate_diff.outputs.result }}' | jq .pullRequest.hasChanges)
+          echo "hasChanges=${hasChanges}" >> $GITHUB_OUTPUT
+
+      - name: Install semgrep
+        if: contains(steps.should_run_semgrep.outputs.hasChanges, 'true')
+        run: |
+          pip3 install semgrep==1.22.0
+          semgrep --version
+
+      - name: Run semgrep tests
+        id: run_semgrep_tests
+        if: contains(steps.should_run_semgrep.outputs.hasChanges, 'true')
+        run: |
+          unqouted_string=$(echo '${{ steps.calculate_diff.outputs.result }}' | jq .pullRequest.files | tr -d '"')
+          outputs=$(semgrep --gitlab-sast --config=.semgrep/adapter $unqouted_string  | jq '[.vulnerabilities[] | {"file": .location.file, "severity": .severity, "start": .location.start_line, "end": .location.end_line, "message": (.message | gsub("\\n"; "\n"))}]' | jq -c | jq -R)
+          echo "semgrep_result=${outputs}" >> "$GITHUB_OUTPUT"
+
+      - name: Add pull request comment
+        id: add_pull_request_comment
+        if: contains(steps.should_run_semgrep.outputs.hasChanges, 'true')
+        uses: actions/github-script@v6.4.1
+        with:
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+          result-encoding: string
+          script: |
+            const utils = require('./.github/workflows/helpers/pull-request-utils.js')
+            const helper = utils.semgrepHelper({
+                github, context, event: "${{github.event.action}}", 
+                semgrepResult: JSON.parse(${{ steps.run_semgrep_tests.outputs.semgrep_result }}), 
+                diff: ${{ steps.calculate_diff.outputs.result }}, headSha: "${{github.event.pull_request.head.sha}}"
+            })
+            const { previousScan, currentScan } = await helper.addReviewComments()
+            return previousScan.unAddressedComments + currentScan.newComments
+
+      - name: Adapter semgrep checks result
+        if: contains(steps.should_run_semgrep.outputs.hasChanges, 'true')
+        run: |
+          if [ "${{steps.add_pull_request_comment.outputs.result}}" -ne "0" ]; then
+              echo 'Semgrep has found "${{steps.add_pull_request_comment.outputs.result}}" errors'
+              exit 1
+          else
+              echo 'Semgrep did not find any errors in the pull request changes'
+          fi
diff --git a/.github/workflows/validate-merge.yml b/.github/workflows/validate-merge.yml
index e85dc3de..07f1baca 100644
--- a/.github/workflows/validate-merge.yml
+++ b/.github/workflows/validate-merge.yml
@@ -12,7 +12,7 @@ jobs:
     - name: Install Go
       uses: actions/setup-go@v4
       with:
-        go-version: 1.19.2
+        go-version: 1.20.5
 
     - name: Checkout Merged Branch
       uses: actions/checkout@v3
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index 83b29709..9047e1f4 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -10,7 +10,7 @@ jobs:
   validate:
     strategy:
       matrix:
-        go-version: [1.18.x, 1.19.x]
+        go-version: [1.19.x, 1.20.x]
         os: [ubuntu-20.04]
     runs-on: ${{ matrix.os }}
     
diff --git a/.semgrep/adapter/builder-struct-name.go b/.semgrep/adapter/builder-struct-name.go
new file mode 100644
index 00000000..37a938ca
--- /dev/null
+++ b/.semgrep/adapter/builder-struct-name.go
@@ -0,0 +1,124 @@
+/*
+	builder-struct-name tests
+	https://semgrep.dev/docs/writing-rules/testing-rules
+	"ruleid" prefix in comment indicates patterns that should be flagged by semgrep
+	"ok" prefix in comment indidcates  patterns that should not be flagged by the semgrep
+*/
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	foo1 := foo{}
+	// ruleid: builder-struct-name-check
+	return &fooadapter{foo: foo1}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &adapterbar{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &fooadapterbar{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &FooAdapter{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &AdapterBar{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &AdapterBar{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	// ruleid: builder-struct-name-check
+	return &FooAdapterBar{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	foo2 := foo{}
+	//ruleid: builder-struct-name-check
+	adpt1 := Adapter{foo: foo2}
+	return &adpt1, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	//ruleid: builder-struct-name-check
+	builder := &Adapter{foo{}}
+	return builder, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	foo3 := foo{}
+	if foo3.bar == "" {
+		foo3.bar = "bar"
+	}
+	//ruleid: builder-struct-name-check
+	adpt2 := Adapter{}
+	adpt2.foo = foo3
+	return &adpt2, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	//ruleid: builder-struct-name-check
+	return &foo{}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	//ruleid: builder-struct-name-check
+	var obj Adapter
+	obj.Foo = "foo"
+	if obj.Bar == "" {
+		obj.Bar = "bar"
+	}
+	return &obj, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	//ruleid: builder-struct-name-check
+	var obj *FooAdapterBar
+	obj.Foo = "foo"
+	if obj.Bar == "" {
+		obj.Bar = "bar"
+	}
+	return obj, nil
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	// ok: builder-struct-name-check
+	return &adapter{endpoint: "www.foo.com"}, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	builder := &adapter{}
+	builder.endpoint = "www.foo.com"
+	// ok: builder-struct-name-check
+	return builder, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	builder := adapter{}
+	builder.endpoint = "www.foo.com"
+	// ok: builder-struct-name-check
+	return &builder, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	var builder adapter
+	builder.endpoint = "www.foo.com"
+	// ok: builder-struct-name-check
+	return &builder, nil
+}
+
+func Builder(_ openrtb_ext.BidderName, config config.Adapter, _ config.Server) (adapters.Bidder, error) {
+	var builder *adapter
+	builder.endpoint = "www.foo.com"
+	// ok: builder-struct-name-check
+	return builder, nil
+}
\ No newline at end of file
diff --git a/.semgrep/adapter/builder-struct-name.yml b/.semgrep/adapter/builder-struct-name.yml
new file mode 100644
index 00000000..bc876ae1
--- /dev/null
+++ b/.semgrep/adapter/builder-struct-name.yml
@@ -0,0 +1,58 @@
+rules:
+  - id: builder-struct-name-check
+    languages:
+      - go
+    message: | 
+      You can call this simply "adapter", the `$BUILDER` identification is already supplied by the package name. As you have it, referencing your adapter from outside the package would be `$BUILDER.$BUILDER` which looks a little redundant. See example below:
+      
+      ```
+        package foo
+
+        type adapter struct {
+          endpoint string
+        }
+        
+        func  Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+          return &adapter{endpoint: "https://www.foo.com"}, nil
+        }
+      ```
+    severity: ERROR
+    patterns:
+      - pattern-either:
+          - pattern-inside: >
+              func Builder($BIDDER_NAME openrtb_ext.BidderName, $CONFIG config.Adapter, $SERVER config.Server) (adapters.Bidder, error) {
+                ...
+                $BUILDER_OBJ := &$BUILDER{...}
+                ...
+                return $BUILDER_OBJ, nil
+              }
+          - pattern-inside: >
+              func Builder($BIDDER_NAME openrtb_ext.BidderName, $CONFIG config.Adapter, $SERVER config.Server) (adapters.Bidder, error) {
+                ...
+                $BUILDER_OBJ := $BUILDER{...}
+                ...
+                return &$BUILDER_OBJ, nil
+              }
+          - pattern-inside: >
+              func Builder($BIDDER_NAME openrtb_ext.BidderName, $CONFIG config.Adapter, $SERVER config.Server) (adapters.Bidder, error) {
+                ...
+                return &$BUILDER{...}, ...
+              }
+          - pattern-inside: >
+              func Builder($BIDDER_NAME openrtb_ext.BidderName, $CONFIG config.Adapter, $SERVER config.Server) (adapters.Bidder, error) {
+                ...
+                var $BUILDER_OBJ $BUILDER
+                ...
+                return &$BUILDER_OBJ, ...
+              }            
+          - pattern-inside: >
+              func Builder($BIDDER_NAME openrtb_ext.BidderName, $CONFIG config.Adapter, $SERVER config.Server) (adapters.Bidder, error) {
+                ...
+                var $BUILDER_OBJ *$BUILDER
+                ...
+                return $BUILDER_OBJ, ...
+              }        
+      - focus-metavariable: $BUILDER
+      - metavariable-regex:
+          metavariable: $BUILDER
+          regex: (?!adapter$)
diff --git a/.semgrep/adapter/package-import.go b/.semgrep/adapter/package-import.go
new file mode 100644
index 00000000..a34ce878
--- /dev/null
+++ b/.semgrep/adapter/package-import.go
@@ -0,0 +1,47 @@
+import (
+	// ok: package-import-check
+	"fmt"
+	// ok: package-import-check
+	"os"
+	// ruleid: package-import-check
+	"github.com/mitchellh/copystructure"
+	// ruleid: package-import-check
+	"github.com/golang/glog"
+)
+
+import (
+	// ok: package-import-check
+	"fmt"
+	// ruleid: package-import-check
+	cs "github.com/mitchellh/copystructure"
+	// ok: package-import-check
+	"os"
+	// ruleid: package-import-check
+	log "github.com/golang/glog"
+)
+
+import (
+	// ok: package-import-check
+	"fmt"
+	// ruleid: package-import-check
+	cs "github.com/mitchellh/copystructure/subpackage"
+	// ok: package-import-check
+	"os"
+	// ruleid: package-import-check
+	log "github.com/golang/glog/subpackage"
+)
+
+// ruleid: package-import-check
+import "github.com/golang/glog"
+
+// ruleid: package-import-check
+import "github.com/mitchellh/copystructure"
+
+// ruleid: package-import-check
+import log "github.com/golang/glog"
+
+// ruleid: package-import-check
+import copy "github.com/mitchellh/copystructure"
+
+// ok: package-import-check
+import "fmt"  
diff --git a/.semgrep/adapter/package-import.yml b/.semgrep/adapter/package-import.yml
new file mode 100644
index 00000000..20de2d10
--- /dev/null
+++ b/.semgrep/adapter/package-import.yml
@@ -0,0 +1,13 @@
+rules:
+  - id: package-import-check
+    message: Usage of "$PKG" package is prohibited in adapter code
+    languages:
+      - go
+    severity: ERROR
+    pattern-either:
+      - patterns:
+          - pattern: import "$PKG"
+          - focus-metavariable: $PKG
+          - metavariable-regex:
+              metavariable: $PKG
+              regex: (^github\.com/mitchellh/copystructure(/.*)?$|^github\.com/golang/glog(/.*)?$)
\ No newline at end of file
diff --git a/.semgrep/adapter/type-bid-assignment.go b/.semgrep/adapter/type-bid-assignment.go
new file mode 100644
index 00000000..fb29a491
--- /dev/null
+++ b/.semgrep/adapter/type-bid-assignment.go
@@ -0,0 +1,181 @@
+/*
+	type-bid-assignment tests
+	https://semgrep.dev/docs/writing-rules/testing-rules
+	"ruleid" prefix in comment indicates patterns that should be flagged by semgrep
+	"ok" prefix in comment indidcates  patterns that should not be flagged by the semgrep
+*/
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for _, sb := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					// ruleid: type-bid-assignment-check
+					Bid:     &sb,
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for _, sb := range seatBid.Bid {
+			sbcopy := sb
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					// ok: type-bid-assignment-check
+					Bid:     &sbcopy,
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for _, sb := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				return nil, err
+			}
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				// ruleid: type-bid-assignment-check
+				Bid:     &sb,
+				BidType: bidType,
+			})
+
+		}
+	}
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for _, sb := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				return nil, err
+			}
+			// ruleid: type-bid-assignment-check
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{Bid: &sb, BidType: bidType})
+		}
+	}
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	var errors []error
+	for _, seatBid := range bidResp.SeatBid {
+		for _, bid := range seatBid.Bid {
+			var t adapters.TypedBid
+			// ruleid: type-bid-assignment-check
+			t.Bid = &bid
+			bidResponse.Bids = append(bidResponse.Bids, &t)
+		}
+	}
+	return bidResponse, errors
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	var errors []error
+	for _, seatBid := range bidResp.SeatBid {
+		for _, bid := range seatBid.Bid {
+			var t adapters.TypedBid
+			t = adapters.TypedBid{
+				// ruleid: type-bid-assignment-check
+				Bid: &bid,
+			}
+
+			bidResponse.Bids = append(bidResponse.Bids, &t)
+		}
+	}
+	return bidResponse, errors
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for idx, _ := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					// ok: type-bid-assignment-check
+					Bid:     &seatBid.Bid[idx],
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var bidResp openrtb2.BidResponse
+
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{err}
+	}
+
+	for _, seatBid := range bidResp.SeatBid {
+		for idx := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp)
+			if err != nil {
+				return nil, err
+			}
+			// ok: type-bid-assignment-check
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{Bid: &seatBid.Bid[idx], BidType: bidType})
+		}
+	}
+}
diff --git a/.semgrep/adapter/type-bid-assignment.yml b/.semgrep/adapter/type-bid-assignment.yml
new file mode 100644
index 00000000..95fb6811
--- /dev/null
+++ b/.semgrep/adapter/type-bid-assignment.yml
@@ -0,0 +1,64 @@
+rules:
+  - id: type-bid-assignment-check
+    languages:
+      - go
+    message: >      
+      Found incorrect assignment made to $KEY. $BID variable receives a new value in each iteration of range loop. Assigning the address of $BID `(&$BID)` to $KEY will result in a pointer that always points to the same memory address with the value of the last iteration. 
+      This can lead to unexpected behavior or incorrect results. Refer https://go.dev/play/p/9ZS1f-5h4qS
+
+      Consider using an index variable in the seatBids.Bid loop as shown below
+
+      ```
+        for _, seatBid := range response.SeatBid {
+          for i := range seatBids.Bid {
+            ...
+            responseBid := &adapters.TypedBid{
+              Bid: &seatBids.Bid[i],
+              ...
+            }
+            ...
+            ...
+          }
+        }
+      ```
+    severity: ERROR
+    patterns:
+      - pattern-either:
+          - pattern: >
+              for _, $BID := range ... {
+                ...
+                ... := &adapters.TypedBid{
+                  $KEY: &$BID,
+                  ...
+                }
+                ...
+              }
+          - pattern: >
+              for _, $BID := range ... {
+                ...
+                ... = adapters.TypedBid{
+                  $KEY: &$BID,
+                  ...
+                }
+                ...
+              } 
+          - pattern: >
+              for _, $BID := range ... {
+                ...
+                ... = append(...,  &adapters.TypedBid{
+                  $KEY: &$BID,
+                  ...
+                })
+                ...
+              }
+          - pattern: >
+              for _, $BID := range ... {
+                var $TYPEBID_OBJ adapters.TypedBid
+                ...
+                $TYPEBID_OBJ.$KEY = &$BID
+                ...
+              }                              
+      - focus-metavariable: $KEY
+      - metavariable-regex:
+          metavariable: $KEY
+          regex: Bid
diff --git a/Dockerfile b/Dockerfile
index 80269c90..090d9a79 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,8 +3,8 @@ RUN apt-get update && \
     apt-get -y upgrade && \
     apt-get install -y wget
 WORKDIR /tmp
-RUN wget https://dl.google.com/go/go1.19.2.linux-amd64.tar.gz && \
-    tar -xf go1.19.2.linux-amd64.tar.gz && \
+RUN wget https://dl.google.com/go/go1.20.5.linux-amd64.tar.gz && \
+    tar -xf go1.20.5.linux-amd64.tar.gz && \
     mv go /usr/local
 RUN mkdir -p /app/prebid-server/
 WORKDIR /app/prebid-server/
diff --git a/README.md b/README.md
index 4ec6792c..9b657f35 100644
--- a/README.md
+++ b/README.md
@@ -5,23 +5,23 @@
 # Prebid Server
 
 Prebid Server is an open source implementation of Server-Side Header Bidding.
-It is managed by [Prebid.org](http://prebid.org/overview/what-is-prebid-org.html),
-and upholds the principles from the [Prebid Code of Conduct](http://prebid.org/wrapper_code_of_conduct.html).
+It is managed by [Prebid.org](https://prebid.org/about/),
+and upholds the principles from the [Prebid Code of Conduct](https://prebid.org/code-of-conduct/).
 
 This project does not support the same set of Bidders as Prebid.js, although there is overlap.
 The current set can be found in the [adapters](./adapters) package. If you don't see the one you want, feel free to [contribute it](https://docs.prebid.org/prebid-server/developers/add-new-bidder-go.html).
 
 For more information, see:
 
-- [What is Prebid?](https://prebid.org/overview/intro.html)
+- [What is Prebid?](https://docs.prebid.org/overview/intro.html)
 - [Prebid Server Overview](https://docs.prebid.org/prebid-server/overview/prebid-server-overview.html)
-- [Current Bidders](http://prebid.org/dev-docs/pbs-bidders.html)
+- [Current Bidders](https://docs.prebid.org/dev-docs/pbs-bidders.html)
 
 Please consider [registering your Prebid Server](https://docs.prebid.org/prebid-server/hosting/pbs-hosting.html#optional-registration) to get on the mailing list for updates, etc.
 
 ## Installation
 
-First install [Go](https://golang.org/doc/install) version 1.18 or newer.
+First install [Go](https://golang.org/doc/install) version 1.19 or newer.
 
 Note that prebid-server is using [Go modules](https://blog.golang.org/using-go-modules).
 We officially support the most recent two major versions of the Go runtime. However, if you'd like to use a version <1.13 and are inside GOPATH `GO111MODULE` needs to be set to `GO111MODULE=on`.
diff --git a/adapters/aidem/aidem.go b/adapters/aidem/aidem.go
new file mode 100644
index 00000000..9748f32c
--- /dev/null
+++ b/adapters/aidem/aidem.go
@@ -0,0 +1,102 @@
+package aidem
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/prebid/openrtb/v19/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+type adapter struct {
+	endpoint string
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+
+	reqJson, err := json.Marshal(request)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+
+	return []*adapters.RequestData{{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    reqJson,
+		Headers: headers,
+	}}, nil
+}
+
+func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	var errs []error
+
+	if adapters.IsResponseStatusCodeNoContent(response) {
+		return nil, nil
+	}
+
+	if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil {
+		return nil, []error{&errortypes.BadInput{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
+		}}
+	}
+
+	var bidResp openrtb2.BidResponse
+	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: fmt.Sprintf("JSON parsing error: %v", err),
+		}}
+	}
+
+	if len(bidResp.SeatBid) == 0 {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: "Empty SeatBid array",
+		}}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(bidResp.SeatBid[0].Bid))
+
+	for _, seatBid := range bidResp.SeatBid {
+		for i := range seatBid.Bid {
+			bidType, err := getMediaTypeForBid(seatBid.Bid[i])
+			if err != nil {
+				errs = append(errs, err)
+			} else {
+				b := &adapters.TypedBid{
+					Bid:     &seatBid.Bid[i],
+					BidType: bidType,
+				}
+				bidResponse.Bids = append(bidResponse.Bids, b)
+			}
+		}
+	}
+	return bidResponse, errs
+}
+
+// Builder builds a new instance of the AIDEM adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
+	return &adapter{
+		endpoint: config.Endpoint,
+	}, nil
+}
+
+func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+	switch bid.MType {
+	case openrtb2.MarkupBanner:
+		return openrtb_ext.BidTypeBanner, nil
+	case openrtb2.MarkupVideo:
+		return openrtb_ext.BidTypeVideo, nil
+	case openrtb2.MarkupAudio:
+		return openrtb_ext.BidTypeAudio, nil
+	case openrtb2.MarkupNative:
+		return openrtb_ext.BidTypeNative, nil
+	default:
+		return "", fmt.Errorf("Unable to fetch mediaType in multi-format: %s", bid.ImpID)
+	}
+}
diff --git a/adapters/consumable/consumable.go b/adapters/consumable/consumable.go
index 9969ea37..0e164977 100644
--- a/adapters/consumable/consumable.go
+++ b/adapters/consumable/consumable.go
@@ -40,6 +40,8 @@ type bidRequest struct {
 	Coppa              bool                 `json:"coppa,omitempty"`
 	SChain             openrtb2.SupplyChain `json:"schain"`
 	Content            *openrtb2.Content    `json:"content,omitempty"`
+	GPP                string               `json:"gpp,omitempty"`
+	GPPSID             []int8               `json:"gpp_sid,omitempty"`
 }
 
 type placement struct {
@@ -192,6 +194,14 @@ func (a *ConsumableAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *
 
 	body.Coppa = request.Regs != nil && request.Regs.COPPA > 0
 
+	if request.Regs != nil && request.Regs.GPP != "" {
+		body.GPP = request.Regs.GPP
+	}
+
+	if request.Regs != nil && request.Regs.GPPSID != nil {
+		body.GPPSID = request.Regs.GPPSID
+	}
+
 	if request.Site != nil && request.Site.Content != nil {
 		body.Content = request.Site.Content
 	} else if request.App != nil && request.App.Content != nil {
diff --git a/adapters/consumable/consumable/supplemental/simple-banner-gpp.json b/adapters/consumable/consumable/supplemental/simple-banner-gpp.json
new file mode 100644
index 00000000..9b2e3d75
--- /dev/null
+++ b/adapters/consumable/consumable/supplemental/simple-banner-gpp.json
@@ -0,0 +1,130 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id",
+        "banner": {
+          "format": [{"w": 728, "h": 250}]
+        },
+        "ext": {
+          "bidder": {
+            "networkId": 11,
+            "siteId": 32,
+            "unitId": 42
+          }
+        }
+      }
+    ],
+    "device": {
+      "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36",
+      "ip": "123.123.123.123"
+    },
+    "site": {
+      "domain": "www.some.com",
+      "page": "http://www.some.com/page-where-ad-will-be-shown"
+    },
+    "regs": {
+      "gpp": "gppString",
+      "gpp_sid": [7]
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "https://e.serverbid.com/api/v2",
+        "headers": {
+          "Accept": [
+            "application/json"
+          ],
+          "Content-Type": [
+            "application/json"
+          ],
+          "User-Agent": [
+            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36"
+          ],
+          "X-Forwarded-For": [
+            "123.123.123.123"
+          ],
+          "Forwarded": [
+            "for=123.123.123.123"
+          ],
+          "Origin": [
+            "http://www.some.com"
+          ],
+          "Referer": [
+            "http://www.some.com/page-where-ad-will-be-shown"
+          ]
+        },
+        "body": {
+          "placements": [
+            {
+              "adTypes": [2730],
+              "divName": "test-imp-id",
+              "networkId": 11,
+              "siteId": 32,
+              "unitId": 42
+            }
+          ],
+          "schain": {
+            "complete": 0,
+            "nodes": null,
+            "ver": ""
+          },
+          "networkId": 11,
+          "siteId": 32,
+          "unitId": 42,
+          "time": 1451651415,
+          "url": "http://www.some.com/page-where-ad-will-be-shown",
+          "includePricingData": true,
+          "user":{},
+          "enableBotFiltering": true,
+          "parallel": true,
+          "gpp": "gppString",
+          "gpp_sid": [7]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "decisions": {
+            "test-imp-id": {
+              "adId": 1234567890,
+              "pricing": {
+                "clearPrice": 0.5
+              },
+              "width": 728,
+              "height": 250,
+              "impressionUrl": "http://localhost:8080/shown",
+              "contents" : [
+                {
+                  "body": "<blink>Remember this: https://www.google.com/search?q=blink+tag ?</blink>"
+                }
+              ]
+            }
+          }
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "test-request-id",
+            "impid": "test-imp-id",
+            "price": 0.5,
+            "adm": "<blink>Remember this: https://www.google.com/search?q=blink+tag ?</blink>",
+            "crid": "1234567890",
+            "exp": 30,
+            "w": 728,
+            "h": 250
+          },
+          "type": "banner"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/improvedigital/improvedigital.go b/adapters/improvedigital/improvedigital.go
index 4c64451f..b934ac75 100644
--- a/adapters/improvedigital/improvedigital.go
+++ b/adapters/improvedigital/improvedigital.go
@@ -140,6 +140,7 @@ func (a *ImprovedigitalAdapter) MakeBids(internalRequest *openrtb2.BidRequest, e
 	}
 
 	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(seatBid.Bid))
+	bidResponse.Currency = bidResp.Cur
 
 	for i := range seatBid.Bid {
 		bid := seatBid.Bid[i]
diff --git a/adapters/ix/ix.go b/adapters/ix/ix.go
index b17d913f..796fefbb 100644
--- a/adapters/ix/ix.go
+++ b/adapters/ix/ix.go
@@ -19,8 +19,7 @@ import (
 )
 
 type IxAdapter struct {
-	URI         string
-	maxRequests int
+	URI string
 }
 
 type ExtRequest struct {
@@ -30,108 +29,127 @@ type ExtRequest struct {
 }
 
 type IxDiag struct {
-	PbsV  string `json:"pbsv,omitempty"`
-	PbjsV string `json:"pbjsv,omitempty"`
+	PbsV            string `json:"pbsv,omitempty"`
+	PbjsV           string `json:"pbjsv,omitempty"`
+	MultipleSiteIds string `json:"multipleSiteIds,omitempty"`
 }
 
 func (a *IxAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
-	nImp := len(request.Imp)
-	if nImp > a.maxRequests {
-		request.Imp = request.Imp[:a.maxRequests]
-		nImp = a.maxRequests
-	}
-
+	requests := make([]*adapters.RequestData, 0, len(request.Imp))
 	errs := make([]error, 0)
 
-	if err := BuildIxDiag(request); err != nil {
-		errs = append(errs, err)
-	}
-
-	// Multi-size banner imps are split into single-size requests.
-	// The first size imp requests are added to the first slice.
-	// Additional size requests are added to the second slice and are merged with the first at the end.
-	// Preallocate the max possible size to avoid reallocating arrays.
-	requests := make([]*adapters.RequestData, 0, a.maxRequests)
-	multiSizeRequests := make([]*adapters.RequestData, 0, a.maxRequests-nImp)
-
 	headers := http.Header{
 		"Content-Type": {"application/json;charset=utf-8"},
 		"Accept":       {"application/json"}}
 
-	imps := request.Imp
-	for iImp := range imps {
-		request.Imp = imps[iImp : iImp+1]
-		if request.Site != nil {
-			if err := setSitePublisherId(request, iImp); err != nil {
-				errs = append(errs, err)
-				continue
-			}
+	uniqueSiteIDs := make(map[string]struct{})
+	filteredImps := make([]openrtb2.Imp, 0, len(request.Imp))
+	requestCopy := *request
+
+	ixDiag := &IxDiag{}
+
+	for _, imp := range requestCopy.Imp {
+		var err error
+		ixExt, err := unmarshalToIxExt(&imp)
+
+		if err != nil {
+			errs = append(errs, err)
+			continue
 		}
 
-		if request.Imp[0].Banner != nil {
-			banner := *request.Imp[0].Banner
-			request.Imp[0].Banner = &banner
-			formats := getBannerFormats(&banner)
-			for iFmt := range formats {
-				banner.Format = formats[iFmt : iFmt+1]
-				banner.W = openrtb2.Int64Ptr(banner.Format[0].W)
-				banner.H = openrtb2.Int64Ptr(banner.Format[0].H)
-				if requestData, err := createRequestData(a, request, &headers); err == nil {
-					if iFmt == 0 {
-						requests = append(requests, requestData)
-					} else {
-						multiSizeRequests = append(multiSizeRequests, requestData)
-					}
-				} else {
-					errs = append(errs, err)
-				}
-				if len(multiSizeRequests) == cap(multiSizeRequests) {
-					break
-				}
+		if err = parseSiteId(ixExt, uniqueSiteIDs); err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		if err := moveSid(&imp, ixExt); err != nil {
+			errs = append(errs, err)
+		}
+
+		if imp.Banner != nil {
+			bannerCopy := *imp.Banner
+
+			if len(bannerCopy.Format) == 0 && bannerCopy.W != nil && bannerCopy.H != nil {
+				bannerCopy.Format = []openrtb2.Format{{W: *bannerCopy.W, H: *bannerCopy.H}}
 			}
-		} else if requestData, err := createRequestData(a, request, &headers); err == nil {
+
+			if len(bannerCopy.Format) == 1 {
+				bannerCopy.W = openrtb2.Int64Ptr(bannerCopy.Format[0].W)
+				bannerCopy.H = openrtb2.Int64Ptr(bannerCopy.Format[0].H)
+			}
+			imp.Banner = &bannerCopy
+		}
+		filteredImps = append(filteredImps, imp)
+	}
+	requestCopy.Imp = filteredImps
+
+	setSitePublisherId(&requestCopy, uniqueSiteIDs, ixDiag)
+
+	err := setIxDiagIntoExtRequest(&requestCopy, ixDiag)
+	if err != nil {
+		errs = append(errs, err)
+	}
+
+	if len(requestCopy.Imp) != 0 {
+		if requestData, err := createRequestData(a, &requestCopy, &headers); err == nil {
 			requests = append(requests, requestData)
 		} else {
 			errs = append(errs, err)
 		}
 	}
-	request.Imp = imps
 
-	return append(requests, multiSizeRequests...), errs
+	return requests, errs
 }
 
-func setSitePublisherId(request *openrtb2.BidRequest, iImp int) error {
-	if iImp == 0 {
-		// first impression - create a site and pub copy
-		site := *request.Site
+func setSitePublisherId(requestCopy *openrtb2.BidRequest, uniqueSiteIDs map[string]struct{}, ixDiag *IxDiag) {
+	if requestCopy.Site != nil {
+		site := *requestCopy.Site
 		if site.Publisher == nil {
 			site.Publisher = &openrtb2.Publisher{}
 		} else {
 			publisher := *site.Publisher
 			site.Publisher = &publisher
 		}
-		request.Site = &site
+
+		siteIDs := make([]string, 0, len(uniqueSiteIDs))
+		for key := range uniqueSiteIDs {
+			siteIDs = append(siteIDs, key)
+		}
+		if len(siteIDs) == 1 {
+			site.Publisher.ID = siteIDs[0]
+		}
+		if len(siteIDs) > 1 {
+			// Sorting siteIDs for predictable output as Go maps don't guarantee order
+			sort.Strings(siteIDs)
+			multipleSiteIDs := strings.Join(siteIDs, ", ")
+			ixDiag.MultipleSiteIds = multipleSiteIDs
+		}
+		requestCopy.Site = &site
 	}
+}
 
+func unmarshalToIxExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpIx, error) {
 	var bidderExt adapters.ExtImpBidder
-	if err := json.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil {
-		return err
+	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+		return nil, err
 	}
 
 	var ixExt openrtb_ext.ExtImpIx
 	if err := json.Unmarshal(bidderExt.Bidder, &ixExt); err != nil {
-		return err
+		return nil, err
 	}
 
-	request.Site.Publisher.ID = ixExt.SiteId
-	return nil
+	return &ixExt, nil
 }
 
-func getBannerFormats(banner *openrtb2.Banner) []openrtb2.Format {
-	if len(banner.Format) == 0 && banner.W != nil && banner.H != nil {
-		banner.Format = []openrtb2.Format{{W: *banner.W, H: *banner.H}}
+func parseSiteId(ixExt *openrtb_ext.ExtImpIx, uniqueSiteIDs map[string]struct{}) error {
+	if ixExt == nil {
+		return fmt.Errorf("Nil Ix Ext")
+	}
+	if ixExt.SiteId != "" {
+		uniqueSiteIDs[ixExt.SiteId] = struct{}{}
 	}
-	return banner.Format
+	return nil
 }
 
 func createRequestData(a *IxAdapter, request *openrtb2.BidRequest, headers *http.Header) (*adapters.RequestData, error) {
@@ -180,7 +198,8 @@ func (a *IxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalReque
 		}
 	}
 
-	bidderResponse := adapters.NewBidderResponseWithBidsCapacity(5)
+	// capacity 0 will make channel unbuffered
+	bidderResponse := adapters.NewBidderResponseWithBidsCapacity(0)
 	bidderResponse.Currency = bidResponse.Cur
 
 	var errs []error
@@ -275,8 +294,7 @@ func getMediaTypeForBid(bid openrtb2.Bid, impMediaTypeReq map[string]openrtb_ext
 // Builder builds a new instance of the Ix 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 := &IxAdapter{
-		URI:         config.Endpoint,
-		maxRequests: 20,
+		URI: config.Endpoint,
 	}
 	return bidder, nil
 }
@@ -328,29 +346,33 @@ func marshalJsonWithoutUnicode(v interface{}) (string, error) {
 	return strings.TrimSuffix(sb.String(), "\n"), nil
 }
 
-func BuildIxDiag(request *openrtb2.BidRequest) error {
+func setIxDiagIntoExtRequest(request *openrtb2.BidRequest, ixDiag *IxDiag) error {
 	extRequest := &ExtRequest{}
 	if request.Ext != nil {
 		if err := json.Unmarshal(request.Ext, &extRequest); err != nil {
 			return err
 		}
 	}
-	ixdiag := &IxDiag{}
 
 	if extRequest.Prebid != nil && extRequest.Prebid.Channel != nil {
-		ixdiag.PbjsV = extRequest.Prebid.Channel.Version
+		ixDiag.PbjsV = extRequest.Prebid.Channel.Version
 	}
-
 	// Slice commit hash out of version
 	if strings.Contains(version.Ver, "-") {
-		ixdiag.PbsV = version.Ver[:strings.Index(version.Ver, "-")]
+		ixDiag.PbsV = version.Ver[:strings.Index(version.Ver, "-")]
 	} else if version.Ver != "" {
-		ixdiag.PbsV = version.Ver
+		ixDiag.PbsV = version.Ver
 	}
 
 	// Only set request.ext if ixDiag is not empty
-	if *ixdiag != (IxDiag{}) {
-		extRequest.IxDiag = ixdiag
+	if *ixDiag != (IxDiag{}) {
+		extRequest := &ExtRequest{}
+		if request.Ext != nil {
+			if err := json.Unmarshal(request.Ext, &extRequest); err != nil {
+				return err
+			}
+		}
+		extRequest.IxDiag = ixDiag
 		extRequestJson, err := json.Marshal(extRequest)
 		if err != nil {
 			return err
@@ -359,3 +381,24 @@ func BuildIxDiag(request *openrtb2.BidRequest) error {
 	}
 	return nil
 }
+
+// moves sid from imp[].ext.bidder.sid to imp[].ext.sid
+func moveSid(imp *openrtb2.Imp, ixExt *openrtb_ext.ExtImpIx) error {
+	if ixExt == nil {
+		return fmt.Errorf("Nil Ix Ext")
+	}
+
+	if ixExt.Sid != "" {
+		var m map[string]interface{}
+		if err := json.Unmarshal(imp.Ext, &m); err != nil {
+			return err
+		}
+		m["sid"] = ixExt.Sid
+		ext, err := json.Marshal(m)
+		if err != nil {
+			return err
+		}
+		imp.Ext = ext
+	}
+	return nil
+}
diff --git a/adapters/sharethrough/sharethrough.go b/adapters/sharethrough/sharethrough.go
index f797bfe4..009ce0aa 100644
--- a/adapters/sharethrough/sharethrough.go
+++ b/adapters/sharethrough/sharethrough.go
@@ -83,21 +83,29 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 		requestCopy.BCat = append(requestCopy.BCat, strImpParams.BCat...)
 		requestCopy.BAdv = append(requestCopy.BAdv, strImpParams.BAdv...)
 
-		requestCopy.Imp = []openrtb2.Imp{imp}
-
-		requestJSON, err := json.Marshal(requestCopy)
+		impressionsByMediaType, err := splitImpressionsByMediaType(&imp)
 		if err != nil {
 			errors = append(errors, err)
 			continue
 		}
 
-		requestData := &adapters.RequestData{
-			Method:  "POST",
-			Uri:     a.endpoint,
-			Body:    requestJSON,
-			Headers: headers,
+		for _, impression := range impressionsByMediaType {
+			requestCopy.Imp = []openrtb2.Imp{impression}
+
+			requestJSON, err := json.Marshal(requestCopy)
+			if err != nil {
+				errors = append(errors, err)
+				continue
+			}
+
+			requestData := &adapters.RequestData{
+				Method:  "POST",
+				Uri:     a.endpoint,
+				Body:    requestJSON,
+				Headers: headers,
+			}
+			requests = append(requests, requestData)
 		}
-		requests = append(requests, requestData)
 	}
 
 	return requests, errors
@@ -150,6 +158,40 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.R
 	return bidderResponse, errors
 }
 
+func splitImpressionsByMediaType(impression *openrtb2.Imp) ([]openrtb2.Imp, error) {
+	if impression.Banner == nil && impression.Video == nil && impression.Native == nil {
+		return nil, &errortypes.BadInput{Message: "Invalid MediaType. Sharethrough only supports Banner, Video and Native."}
+	}
+
+	if impression.Audio != nil {
+		impression.Audio = nil
+	}
+
+	impressions := make([]openrtb2.Imp, 0, 3)
+
+	if impression.Banner != nil {
+		impCopy := *impression
+		impCopy.Video = nil
+		impCopy.Native = nil
+		impressions = append(impressions, impCopy)
+	}
+
+	if impression.Video != nil {
+		impCopy := *impression
+		impCopy.Banner = nil
+		impCopy.Native = nil
+		impressions = append(impressions, impCopy)
+	}
+
+	if impression.Native != nil {
+		impression.Banner = nil
+		impression.Video = nil
+		impressions = append(impressions, *impression)
+	}
+
+	return impressions, nil
+}
+
 func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
 
 	if bid.Ext != nil {
diff --git a/adapters/yahooAdvertising/yahooAdvertising.go b/adapters/yahooAds/yahooAds.go
similarity index 93%
rename from adapters/yahooAdvertising/yahooAdvertising.go
rename to adapters/yahooAds/yahooAds.go
index d476adb4..3597d0e3 100644
--- a/adapters/yahooAdvertising/yahooAdvertising.go
+++ b/adapters/yahooAds/yahooAds.go
@@ -1,4 +1,4 @@
-package yahooAdvertising
+package yahooAds
 
 import (
 	"encoding/json"
@@ -41,8 +41,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 			continue
 		}
 
-		var yahooAdvertisingExt openrtb_ext.ExtImpYahooAdvertising
-		err = json.Unmarshal(bidderExt.Bidder, &yahooAdvertisingExt)
+		var yahooAdsExt openrtb_ext.ExtImpYahooAds
+		err = json.Unmarshal(bidderExt.Bidder, &yahooAdsExt)
 		if err != nil {
 			err = &errortypes.BadInput{
 				Message: fmt.Sprintf("imp #%d: %s", idx, err.Error()),
@@ -64,7 +64,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 			reqCopy.App = &appCopy
 		}
 
-		if err := changeRequestForBidService(&reqCopy, &yahooAdvertisingExt); err != nil {
+		if err := changeRequestForBidService(&reqCopy, &yahooAdsExt); err != nil {
 			errors = append(errors, err)
 			continue
 		}
@@ -150,7 +150,7 @@ func getImpInfo(impId string, imps []openrtb2.Imp) (bool, openrtb_ext.BidType) {
 	return exists, mediaType
 }
 
-func changeRequestForBidService(request *openrtb2.BidRequest, extension *openrtb_ext.ExtImpYahooAdvertising) error {
+func changeRequestForBidService(request *openrtb2.BidRequest, extension *openrtb_ext.ExtImpYahooAds) error {
 	/* Always override the tag ID and (site ID or app ID) of the request */
 	request.Imp[0].TagID = extension.Pos
 	if request.Site != nil {
@@ -218,7 +218,7 @@ func validateBanner(banner *openrtb2.Banner) error {
 	return nil
 }
 
-// Builder builds a new instance of the YahooAdvertising adapter for the given bidder with the given config.
+// Builder builds a new instance of the YahooAds 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{
 		URI: config.Endpoint,
diff --git a/config/account.go b/config/account.go
index 8beff9b6..02040211 100644
--- a/config/account.go
+++ b/config/account.go
@@ -40,7 +40,7 @@ type Account struct {
 	Validations             Validations                                 `mapstructure:"validations" json:"validations"`
 	DefaultBidLimit         int                                         `mapstructure:"default_bid_limit" json:"default_bid_limit"`
 	BidAdjustments          *openrtb_ext.ExtRequestPrebidBidAdjustments `mapstructure:"bidadjustments" json:"bidadjustments"`
-	Privacy                 AccountPrivacy                              `mapstructure:"privacy" json:"privacy"`
+	Privacy                 *AccountPrivacy                             `mapstructure:"privacy" json:"privacy"`
 }
 
 // CookieSync represents the account-level defaults for the cookie sync endpoint.
diff --git a/config/activity.go b/config/activity.go
index 987cbe84..5bddc7c6 100644
--- a/config/activity.go
+++ b/config/activity.go
@@ -8,16 +8,17 @@ type AllowActivities struct {
 	TransmitUserFPD          Activity `mapstructure:"transmitUfpd" json:"transmitUfpd"`
 	TransmitPreciseGeo       Activity `mapstructure:"transmitPreciseGeo" json:"transmitPreciseGeo"`
 	TransmitUniqueRequestIds Activity `mapstructure:"transmitUniqueRequestIds" json:"transmitUniqueRequestIds"`
+	TransmitTids             Activity `mapstructure:"transmitTid" json:"transmitTid"`
 }
 
 type Activity struct {
 	Default *bool          `mapstructure:"default" json:"default"`
 	Rules   []ActivityRule `mapstructure:"rules" json:"rules"`
-	Allow   bool           `mapstructure:"allow" json:"allow"`
 }
 
 type ActivityRule struct {
 	Condition ActivityCondition `mapstructure:"condition" json:"condition"`
+	Allow     bool              `mapstructure:"allow" json:"allow"`
 }
 
 type ActivityCondition struct {
diff --git a/config/config.go b/config/config.go
index ee18c746..543d1afd 100644
--- a/config/config.go
+++ b/config/config.go
@@ -155,6 +155,10 @@ func (cfg *Configuration) validate(v *viper.Viper) []error {
 		cfg.TmaxAdjustments.Enabled = false
 	}
 
+	if cfg.AccountDefaults.Privacy != nil {
+		glog.Warning("account_defaults.Privacy has no effect as the feature is under development.")
+	}
+
 	errs = cfg.Experiment.validate(errs)
 	errs = cfg.BidderInfos.validate(errs)
 	return errs
diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go
index 73f4842a..8d328b7c 100644
--- a/endpoints/openrtb2/amp_auction.go
+++ b/endpoints/openrtb2/amp_auction.go
@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"github.com/prebid/prebid-server/privacy"
 	"net/http"
 	"net/url"
 	"strings"
@@ -222,6 +223,13 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
 
 	tcf2Config := gdpr.NewTCF2Config(deps.cfg.GDPR.TCF2, account.GDPR)
 
+	activities, activitiesErr := privacy.NewActivityControl(account.Privacy)
+	if activitiesErr != nil {
+		errL = append(errL, activitiesErr)
+		writeError(errL, w, &labels)
+		return
+	}
+
 	secGPC := r.Header.Get("Sec-GPC")
 
 	auctionRequest := &exchange.AuctionRequest{
@@ -239,6 +247,7 @@ func (deps *endpointDeps) AmpAuction(w http.ResponseWriter, r *http.Request, _ h
 		HookExecutor:               hookExecutor,
 		QueryParams:                r.URL.Query(),
 		TCF2Config:                 tcf2Config,
+		Activities:                 activities,
 	}
 
 	auctionResponse, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 216bff6e..3f01967a 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"github.com/prebid/prebid-server/privacy"
 	"io"
 	"io/ioutil"
 	"net/http"
@@ -191,6 +192,15 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 
 	tcf2Config := gdpr.NewTCF2Config(deps.cfg.GDPR.TCF2, account.GDPR)
 
+	activities, activitiesErr := privacy.NewActivityControl(account.Privacy)
+	if activitiesErr != nil {
+		errL = append(errL, activitiesErr)
+		if errortypes.ContainsFatalError(errL) {
+			writeError(errL, w, &labels)
+			return
+		}
+	}
+
 	ctx := context.Background()
 
 	timeout := deps.cfg.AuctionTimeouts.LimitAuctionTimeout(time.Duration(req.TMax) * time.Millisecond)
@@ -236,6 +246,7 @@ func (deps *endpointDeps) Auction(w http.ResponseWriter, r *http.Request, _ http
 		PubID:                      labels.PubID,
 		HookExecutor:               hookExecutor,
 		TCF2Config:                 tcf2Config,
+		Activities:                 activities,
 	}
 	auctionResponse, err := deps.ex.HoldAuction(ctx, auctionRequest, nil)
 	ao.RequestWrapper = req
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 171600c0..3818a16a 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -28,6 +28,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/adview"
 	"github.com/prebid/prebid-server/adapters/adxcg"
 	"github.com/prebid/prebid-server/adapters/adyoulike"
+	"github.com/prebid/prebid-server/adapters/aidem"
 	"github.com/prebid/prebid-server/adapters/aja"
 	"github.com/prebid/prebid-server/adapters/algorix"
 	"github.com/prebid/prebid-server/adapters/amx"
@@ -169,7 +170,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
 	"github.com/prebid/prebid-server/adapters/xeworks"
-	"github.com/prebid/prebid-server/adapters/yahooAdvertising"
+	"github.com/prebid/prebid-server/adapters/yahooAds"
 	"github.com/prebid/prebid-server/adapters/yeahmobi"
 	"github.com/prebid/prebid-server/adapters/yieldlab"
 	"github.com/prebid/prebid-server/adapters/yieldmo"
@@ -212,6 +213,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderAdView:            adview.Builder,
 		openrtb_ext.BidderAdxcg:             adxcg.Builder,
 		openrtb_ext.BidderAdyoulike:         adyoulike.Builder,
+		openrtb_ext.BidderAidem:             aidem.Builder,
 		openrtb_ext.BidderAJA:               aja.Builder,
 		openrtb_ext.BidderAlgorix:           algorix.Builder,
 		openrtb_ext.BidderAMX:               amx.Builder,
@@ -367,8 +369,9 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderVisx:              visx.Builder,
 		openrtb_ext.BidderVrtcal:            vrtcal.Builder,
 		openrtb_ext.BidderXeworks:           xeworks.Builder,
-		openrtb_ext.BidderYahooAdvertising:  yahooAdvertising.Builder,
-		openrtb_ext.BidderYahooSSP:          yahooAdvertising.Builder,
+		openrtb_ext.BidderYahooAds:          yahooAds.Builder,
+		openrtb_ext.BidderYahooAdvertising:  yahooAds.Builder,
+		openrtb_ext.BidderYahooSSP:          yahooAds.Builder,
 		openrtb_ext.BidderYeahmobi:          yeahmobi.Builder,
 		openrtb_ext.BidderYieldlab:          yieldlab.Builder,
 		openrtb_ext.BidderYieldmo:           yieldmo.Builder,
diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go
index d8f683b3..ad1866a6 100644
--- a/exchange/adapter_util.go
+++ b/exchange/adapter_util.go
@@ -88,7 +88,7 @@ func GetDisabledBiddersErrorMessages(infos config.BidderInfos) map[string]string
 		"lifestreet":     `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
 		"adagio":         `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 		"somoaudience":   `Bidder "somoaudience" is no longer available in Prebid Server. Please update your configuration.`,
-		"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAdvertising" in your configuration.`,
+		"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAds" in your configuration.`,
 		"andbeyondmedia": `Bidder "andbeyondmedia" is no longer available in Prebid Server. If you're looking to use the AndBeyond.Media SSP adapter, please rename it to "beyondmedia" in your configuration.`,
 		"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 		"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
diff --git a/exchange/exchange.go b/exchange/exchange.go
index 24ca193f..07dce45a 100644
--- a/exchange/exchange.go
+++ b/exchange/exchange.go
@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"github.com/prebid/prebid-server/privacy"
 	"math/rand"
 	"net/url"
 	"runtime/debug"
@@ -195,6 +196,7 @@ type AuctionRequest struct {
 	GlobalPrivacyControlHeader string
 	ImpExtInfoMap              map[string]ImpExtInfo
 	TCF2Config                 gdpr.TCF2ConfigReader
+	Activities                 privacy.ActivityControl
 
 	// LegacyLabels is included here for temporary compatibility with cleanOpenRTBRequests
 	// in HoldAuction until we get to factoring it away. Do not use for anything new.
diff --git a/exchange/utils.go b/exchange/utils.go
index d43a4182..5b29fd62 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -150,6 +150,15 @@ func (rs *requestSplitter) cleanOpenRTBRequests(ctx context.Context,
 	for _, bidderRequest := range allBidderRequests {
 		bidRequestAllowed := true
 
+		// fetchBids activity
+		fetchBidsActivityAllowed := auctionReq.Activities.Allow(privacy.ActivityFetchBids,
+			privacy.ScopedName{Scope: privacy.ScopeTypeBidder, Name: bidderRequest.BidderName.String()})
+		if fetchBidsActivityAllowed == privacy.ActivityDeny {
+			// skip the call to a bidder if fetchBids activity is not allowed
+			// do not add this bidder to allowedBidderRequests
+			continue
+		}
+
 		// CCPA
 		privacyEnforcement.CCPA = ccpaEnforcer.ShouldEnforce(bidderRequest.BidderName.String())
 
diff --git a/go.mod b/go.mod
index 3833ef3d..6731c177 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/prebid/prebid-server
 
-go 1.19
+go 1.20
 
 require (
 	github.com/DATA-DOG/go-sqlmock v1.5.0
@@ -33,14 +33,14 @@ require (
 	github.com/yudai/gojsondiff v1.0.0
 	golang.org/x/net v0.7.0
 	golang.org/x/text v0.7.0
-	google.golang.org/grpc v1.46.2
+	google.golang.org/grpc v1.53.0
 	gopkg.in/evanphx/json-patch.v4 v4.12.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
-	github.com/cespare/xxhash/v2 v2.1.2 // indirect
+	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/fsnotify/fsnotify v1.5.4 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
@@ -68,8 +68,8 @@ require (
 	github.com/yudai/pp v2.0.1+incompatible // indirect
 	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
 	golang.org/x/sys v0.5.0 // indirect
-	google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
-	google.golang.org/protobuf v1.28.0 // indirect
+	google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
+	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/ini.v1 v1.66.4 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 )
diff --git a/go.sum b/go.sum
index e1226ab1..1f76be7a 100644
--- a/go.sum
+++ b/go.sum
@@ -86,8 +86,9 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
 github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chasex/glog v0.0.0-20160217080310-c62392af379c h1:eXqCBUHfmjbeDqcuvzjsd+bM6A+bnwo5N9FVbV6m5/s=
 github.com/chasex/glog v0.0.0-20160217080310-c62392af379c/go.mod h1:omJZNg0Qu76bxJd+ExohVo8uXzNcGOk2bv7vel460xk=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -125,7 +126,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
 github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
-github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -210,7 +210,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -392,8 +392,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
 github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
-github.com/prebid/go-gdpr v1.11.0 h1:QbMjscuw3Ul0mDVWeMy5tP0Kii6lmTSSVhV6fm8rY9s=
-github.com/prebid/go-gdpr v1.11.0/go.mod h1:mPZAdkRxn+iuSjaUuJAi9+0SppBOdM1PCzv/55UH3pY=
 github.com/prebid/go-gdpr v1.12.0 h1:OrjQ7Uc+lCRYaOirQ48jjG/PBMvZsKNAaRTgzxN6iZ0=
 github.com/prebid/go-gdpr v1.12.0/go.mod h1:mPZAdkRxn+iuSjaUuJAi9+0SppBOdM1PCzv/55UH3pY=
 github.com/prebid/go-gpp v0.1.1 h1:uTMJ+eHmKWL9WvDuxFT4LDoOeJW1yOsfWITqi49ZuY0=
@@ -910,8 +908,8 @@ google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ6
 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
-google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
+google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -942,9 +940,8 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K
 google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
-google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
+google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -959,8 +956,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index 03056123..9906d12e 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -114,6 +114,7 @@ const (
 	BidderAdView            BidderName = "adview"
 	BidderAdxcg             BidderName = "adxcg"
 	BidderAdyoulike         BidderName = "adyoulike"
+	BidderAidem             BidderName = "aidem"
 	BidderAJA               BidderName = "aja"
 	BidderAlgorix           BidderName = "algorix"
 	BidderAMX               BidderName = "amx"
@@ -269,6 +270,7 @@ const (
 	BidderVisx              BidderName = "visx"
 	BidderVrtcal            BidderName = "vrtcal"
 	BidderXeworks           BidderName = "xeworks"
+	BidderYahooAds          BidderName = "yahooAds"
 	BidderYahooAdvertising  BidderName = "yahooAdvertising"
 	BidderYahooSSP          BidderName = "yahoossp"
 	BidderYeahmobi          BidderName = "yeahmobi"
@@ -310,6 +312,7 @@ func CoreBidderNames() []BidderName {
 		BidderAdView,
 		BidderAdxcg,
 		BidderAdyoulike,
+		BidderAidem,
 		BidderAJA,
 		BidderAlgorix,
 		BidderAMX,
@@ -465,6 +468,7 @@ func CoreBidderNames() []BidderName {
 		BidderVisx,
 		BidderVrtcal,
 		BidderXeworks,
+		BidderYahooAds,
 		BidderYahooAdvertising,
 		BidderYahooSSP,
 		BidderYeahmobi,
diff --git a/openrtb_ext/deal_tier.go b/openrtb_ext/deal_tier.go
index ef85b9b1..45285d21 100644
--- a/openrtb_ext/deal_tier.go
+++ b/openrtb_ext/deal_tier.go
@@ -27,20 +27,6 @@ func ReadDealTiersFromImp(imp openrtb2.Imp) (DealTierBidderMap, error) {
 		return dealTiers, nil
 	}
 
-	// imp.ext.{bidder}
-	var impExt map[string]struct {
-		DealTier *DealTier `json:"dealTier"`
-	}
-	if err := json.Unmarshal(imp.Ext, &impExt); err != nil {
-		return nil, err
-	}
-	for bidder, param := range impExt {
-		if param.DealTier != nil {
-			dealTiers[BidderName(bidder)] = *param.DealTier
-		}
-	}
-
-	// imp.ext.prebid.{bidder}
 	var impPrebidExt struct {
 		Prebid struct {
 			Bidders map[string]struct {
diff --git a/openrtb_ext/imp_aidem.go b/openrtb_ext/imp_aidem.go
new file mode 100644
index 00000000..59457f1e
--- /dev/null
+++ b/openrtb_ext/imp_aidem.go
@@ -0,0 +1,8 @@
+package openrtb_ext
+
+type ImpExtFoo struct {
+	SiteID      string `json:"siteId"`
+	PublisherID string `json:"publisherId"`
+	PlacementID string `json:"placementId"`
+	RateLimit   string `json:"rateLimit"`
+}
diff --git a/openrtb_ext/imp_ix.go b/openrtb_ext/imp_ix.go
index 9f977fb0..40c3f518 100644
--- a/openrtb_ext/imp_ix.go
+++ b/openrtb_ext/imp_ix.go
@@ -4,4 +4,5 @@ package openrtb_ext
 type ExtImpIx struct {
 	SiteId string `json:"siteId"`
 	Size   []int  `json:"size"`
+	Sid    string `json:"sid"`
 }
diff --git a/openrtb_ext/imp_yahooAds.go b/openrtb_ext/imp_yahooAds.go
new file mode 100644
index 00000000..36a4a0f6
--- /dev/null
+++ b/openrtb_ext/imp_yahooAds.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+// ExtImpYahooAds defines the contract for bidrequest.imp[i].ext.prebid.bidder.yahooAds
+type ExtImpYahooAds struct {
+	Dcn string `json:"dcn"`
+	Pos string `json:"pos"`
+}
diff --git a/privacy/activity.go b/privacy/activity.go
index 7cdef175..6ca48ae0 100644
--- a/privacy/activity.go
+++ b/privacy/activity.go
@@ -11,6 +11,7 @@ const (
 	ActivityTransmitUserFPD
 	ActivityTransmitPreciseGeo
 	ActivityTransmitUniqueRequestIds
+	ActivityTransmitTids
 )
 
 func (a Activity) String() string {
@@ -29,6 +30,8 @@ func (a Activity) String() string {
 		return "transmitPreciseGeo"
 	case ActivityTransmitUniqueRequestIds:
 		return "transmitUniqueRequestIds"
+	case ActivityTransmitTids:
+		return "transmitTid"
 	}
 
 	return ""
diff --git a/privacy/enforcer.go b/privacy/enforcer.go
index 0d5ecad5..d63cd8de 100644
--- a/privacy/enforcer.go
+++ b/privacy/enforcer.go
@@ -1,43 +1,236 @@
 package privacy
 
-// PolicyEnforcer determines if personally identifiable information (PII) should be removed or anonymized per the policy.
-type PolicyEnforcer interface {
-	// CanEnforce returns true when policy information is specifically provided by the publisher.
-	CanEnforce() bool
+import (
+	"fmt"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/errortypes"
+	"strings"
+)
 
-	// ShouldEnforce returns true when the OpenRTB request should have personally identifiable
-	// information (PII) removed or anonymized per the policy.
-	ShouldEnforce(bidder string) bool
+type ActivityResult int
+
+const (
+	ActivityAbstain ActivityResult = iota
+	ActivityAllow
+	ActivityDeny
+)
+
+const (
+	ScopeTypeBidder    = "bidder"
+	ScopeTypeAnalytics = "analytics"
+	ScopeTypeRTD       = "rtd" // real time data
+	ScopeTypeUserID    = "userid"
+	ScopeTypeGeneral   = "general"
+)
+
+type ActivityControl struct {
+	plans map[Activity]ActivityPlan
 }
 
-// NilPolicyEnforcer implements the PolicyEnforcer interface but will always return false.
-type NilPolicyEnforcer struct{}
+func NewActivityControl(privacyConf *config.AccountPrivacy) (ActivityControl, error) {
+	ac := ActivityControl{}
+	var err error
 
-// CanEnforce is hardcoded to always return false.
-func (NilPolicyEnforcer) CanEnforce() bool {
-	return false
+	if privacyConf == nil {
+		return ac, err
+	} else {
+		//temporarily disable Activities if they are specified at the account level
+		return ac, &errortypes.Warning{Message: "account.Privacy has no effect as the feature is under development."}
+	}
+
+	plans := make(map[Activity]ActivityPlan)
+
+	plans[ActivitySyncUser], err = buildEnforcementPlan(privacyConf.AllowActivities.SyncUser)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityFetchBids], err = buildEnforcementPlan(privacyConf.AllowActivities.FetchBids)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityEnrichUserFPD], err = buildEnforcementPlan(privacyConf.AllowActivities.EnrichUserFPD)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityReportAnalytics], err = buildEnforcementPlan(privacyConf.AllowActivities.ReportAnalytics)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityTransmitUserFPD], err = buildEnforcementPlan(privacyConf.AllowActivities.TransmitUserFPD)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityTransmitPreciseGeo], err = buildEnforcementPlan(privacyConf.AllowActivities.TransmitPreciseGeo)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityTransmitUniqueRequestIds], err = buildEnforcementPlan(privacyConf.AllowActivities.TransmitUniqueRequestIds)
+	if err != nil {
+		return ac, err
+	}
+	plans[ActivityTransmitTids], err = buildEnforcementPlan(privacyConf.AllowActivities.TransmitTids)
+	if err != nil {
+		return ac, err
+	}
+
+	ac.plans = plans
+
+	return ac, nil
+}
+
+func buildEnforcementPlan(activity config.Activity) (ActivityPlan, error) {
+	ef := ActivityPlan{}
+	rules, err := activityRulesToEnforcementRules(activity.Rules)
+	if err != nil {
+		return ef, err
+	}
+	ef.defaultResult = activityDefaultToDefaultResult(activity.Default)
+	ef.rules = rules
+	return ef, nil
 }
 
-// ShouldEnforce is hardcoded to always return false.
-func (NilPolicyEnforcer) ShouldEnforce(bidder string) bool {
-	return false
+func activityRulesToEnforcementRules(rules []config.ActivityRule) ([]ActivityRule, error) {
+	enfRules := make([]ActivityRule, 0)
+	for _, r := range rules {
+		cmpName, err := conditionToRuleComponentName(r.Condition.ComponentName)
+		if err != nil {
+			return nil, err
+		}
+		er := ComponentEnforcementRule{
+			allowed:       r.Allow,
+			componentName: cmpName,
+			componentType: r.Condition.ComponentType,
+		}
+		enfRules = append(enfRules, er)
+	}
+	return enfRules, nil
 }
 
-// EnabledPolicyEnforcer decorates a PolicyEnforcer with an enabled flag.
-type EnabledPolicyEnforcer struct {
-	Enabled        bool
-	PolicyEnforcer PolicyEnforcer
+func conditionToRuleComponentName(conditions []string) ([]ScopedName, error) {
+	sn := make([]ScopedName, 0)
+	for _, condition := range conditions {
+		scope, err := NewScopedName(condition)
+		if err != nil {
+			return sn, err
+		}
+		sn = append(sn, scope)
+	}
+	return sn, nil
 }
 
-// CanEnforce returns true when the PolicyEnforcer can enforce.
-func (p EnabledPolicyEnforcer) CanEnforce() bool {
-	return p.PolicyEnforcer.CanEnforce()
+func activityDefaultToDefaultResult(activityDefault *bool) ActivityResult {
+	if activityDefault == nil {
+		// if default is unspecified, the hardcoded default-default is true.
+		return ActivityAllow
+	} else if *activityDefault {
+		return ActivityAllow
+	}
+	return ActivityDeny
 }
 
-// ShouldEnforce returns true when the enforcer is enabled the PolicyEnforcer allows enforcement.
-func (p EnabledPolicyEnforcer) ShouldEnforce(bidder string) bool {
-	if p.Enabled {
-		return p.PolicyEnforcer.ShouldEnforce(bidder)
+func (e ActivityControl) Allow(activity Activity, target ScopedName) ActivityResult {
+	plan, planDefined := e.plans[activity]
+
+	if !planDefined {
+		return ActivityAbstain
 	}
-	return false
+
+	return plan.Allow(target)
+}
+
+type ActivityPlan struct {
+	defaultResult ActivityResult
+	rules         []ActivityRule
+}
+
+func (p ActivityPlan) Allow(target ScopedName) ActivityResult {
+	for _, rule := range p.rules {
+		result := rule.Allow(target)
+		if result == ActivityDeny || result == ActivityAllow {
+			return result
+		}
+	}
+	return p.defaultResult
+}
+
+type ActivityRule interface {
+	Allow(target ScopedName) ActivityResult
+}
+
+type ComponentEnforcementRule struct {
+	componentName []ScopedName
+	componentType []string
+	// include gppSectionId from 3.5
+	// include geo from 3.5
+	allowed bool
+}
+
+func (r ComponentEnforcementRule) Allow(target ScopedName) ActivityResult {
+	if len(r.componentName) == 0 && len(r.componentType) == 0 {
+		return ActivityAbstain
+	}
+
+	nameClauseExists := len(r.componentName) > 0
+	typeClauseExists := len(r.componentType) > 0
+
+	componentNameFound := false
+	for _, scope := range r.componentName {
+		if strings.EqualFold(scope.Scope, target.Scope) &&
+			(scope.Name == "*" || strings.EqualFold(scope.Name, target.Name)) {
+			componentNameFound = true
+			break
+		}
+	}
+
+	componentTypeFound := false
+	for _, componentType := range r.componentType {
+		if strings.EqualFold(componentType, target.Scope) {
+			componentTypeFound = true
+			break
+		}
+	}
+	// behavior if rule matches: can be either true=allow or false=deny. result is abstain if the rule doesn't match
+	matchFound := (componentNameFound || !nameClauseExists) && (componentTypeFound || !typeClauseExists)
+	if matchFound {
+		if r.allowed {
+			return ActivityAllow
+		} else {
+			return ActivityDeny
+		}
+	}
+	return ActivityAbstain
+}
+
+type ScopedName struct {
+	Scope string
+	Name  string
+}
+
+func NewScopedName(condition string) (ScopedName, error) {
+	if condition == "" {
+		return ScopedName{}, fmt.Errorf("unable to parse empty condition")
+	}
+	var scope, name string
+	split := strings.Split(condition, ".")
+	if len(split) == 2 {
+		s := strings.ToLower(split[0])
+		if s == ScopeTypeBidder || s == ScopeTypeAnalytics || s == ScopeTypeUserID {
+			scope = s
+		} else if strings.Contains(s, ScopeTypeRTD) {
+			scope = ScopeTypeRTD
+		} else {
+			scope = ScopeTypeGeneral
+		}
+		name = split[1]
+	} else if len(split) == 1 {
+		scope = ScopeTypeBidder
+		name = split[0]
+	} else {
+		return ScopedName{}, fmt.Errorf("unable to parse condition: %s", condition)
+	}
+
+	return ScopedName{
+		Scope: scope,
+		Name:  name,
+	}, nil
 }
diff --git a/privacy/policyenforcer.go b/privacy/policyenforcer.go
new file mode 100644
index 00000000..e70c0d3d
--- /dev/null
+++ b/privacy/policyenforcer.go
@@ -0,0 +1,45 @@
+package privacy
+
+// NOTE: Reanme this package. Will eventually replace in its entirety with Activites.
+
+// PolicyEnforcer determines if personally identifiable information (PII) should be removed or anonymized per the policy.
+type PolicyEnforcer interface {
+	// CanEnforce returns true when policy information is specifically provided by the publisher.
+	CanEnforce() bool
+
+	// ShouldEnforce returns true when the OpenRTB request should have personally identifiable
+	// information (PII) removed or anonymized per the policy.
+	ShouldEnforce(bidder string) bool
+}
+
+// NilPolicyEnforcer implements the PolicyEnforcer interface but will always return false.
+type NilPolicyEnforcer struct{}
+
+// CanEnforce is hardcoded to always return false.
+func (NilPolicyEnforcer) CanEnforce() bool {
+	return false
+}
+
+// ShouldEnforce is hardcoded to always return false.
+func (NilPolicyEnforcer) ShouldEnforce(bidder string) bool {
+	return false
+}
+
+// EnabledPolicyEnforcer decorates a PolicyEnforcer with an enabled flag.
+type EnabledPolicyEnforcer struct {
+	Enabled        bool
+	PolicyEnforcer PolicyEnforcer
+}
+
+// CanEnforce returns true when the PolicyEnforcer can enforce.
+func (p EnabledPolicyEnforcer) CanEnforce() bool {
+	return p.PolicyEnforcer.CanEnforce()
+}
+
+// ShouldEnforce returns true when the enforcer is enabled the PolicyEnforcer allows enforcement.
+func (p EnabledPolicyEnforcer) ShouldEnforce(bidder string) bool {
+	if p.Enabled {
+		return p.PolicyEnforcer.ShouldEnforce(bidder)
+	}
+	return false
+}
diff --git a/static/bidder-info/adsinteractive.yaml b/static/bidder-info/adsinteractive.yaml
index ae60ec88..d430e63b 100644
--- a/static/bidder-info/adsinteractive.yaml
+++ b/static/bidder-info/adsinteractive.yaml
@@ -12,6 +12,6 @@ capabilities:
       - banner
 userSync:
   redirect:
-    url: "http://bid.adsinteractive.com/getuid?{{.RedirectURL}}"
+    url: "https://bid.adsinteractive.com/getuid?{{.RedirectURL}}"
     userMacro: "$AUID"
  
diff --git a/static/bidder-info/aidem.yaml b/static/bidder-info/aidem.yaml
new file mode 100644
index 00000000..35ea898a
--- /dev/null
+++ b/static/bidder-info/aidem.yaml
@@ -0,0 +1,19 @@
+endpoint: "https://zero.aidemsrv.com/ortb/v2.6/bid/request"
+maintainer:
+  email: prebid@aidem.com
+modifyingVastXmlAllowed: true
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+      - native
+  site:
+    mediaTypes:
+      - banner
+      - video
+      - native
+userSync:
+  redirect:
+    url: https://gum.aidemsrv.com/prebid_sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}
+    userMacro: "$UID"
diff --git a/static/bidder-info/consumable.yaml b/static/bidder-info/consumable.yaml
index e1c4fc9b..cc290149 100644
--- a/static/bidder-info/consumable.yaml
+++ b/static/bidder-info/consumable.yaml
@@ -11,6 +11,8 @@ capabilities:
     - banner
 userSync:
   redirect:
-    url: "https://e.serverbid.com/udb/9969/match?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+    url: "https://e.serverbid.com/udb/9969/match?gdpr={{.GDPR}}&euconsent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}"
     userMacro: ""
     # consumable appends the user id to end of the redirect url and does not utilize a macro
+openrtb:
+  gpp-supported: true   
diff --git a/static/bidder-info/imds.yaml b/static/bidder-info/imds.yaml
index e608a6c6..491a5bd0 100644
--- a/static/bidder-info/imds.yaml
+++ b/static/bidder-info/imds.yaml
@@ -13,8 +13,10 @@ capabilities:
 userSync:
   supportCors: true
   iframe:
-    url: "https://ad-cdn.technoratimedia.com/html/usersync.html?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
+    url: "https://ad-cdn.technoratimedia.com/html/usersync.html?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gppsid={{.GPPSID}}&cb={{.RedirectURL}}"
     userMacro: "[USER_ID]"
   redirect:
-    url: "https://sync.technoratimedia.com/services?srv=cs&gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
+    url: "https://sync.technoratimedia.com/services?srv=cs&gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gppsid={{.GPPSID}}&cb={{.RedirectURL}}"
     userMacro: "[USER_ID]"
+openrtb:
+  gpp-supported: true
diff --git a/static/bidder-info/ix.yaml b/static/bidder-info/ix.yaml
index 9ac7dba3..4ab520ad 100644
--- a/static/bidder-info/ix.yaml
+++ b/static/bidder-info/ix.yaml
@@ -17,8 +17,10 @@ capabilities:
       - audio
 userSync:
   redirect:
-    url: "https://ssum.casalemedia.com/usermatchredir?s=194962&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
+    url: "https://ssum.casalemedia.com/usermatchredir?s=194962&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gppsid={{.GPPSID}}&cb={{.RedirectURL}}"
     userMacro: ""
   iframe:
-    url: "https://ssum-sec.casalemedia.com/usermatch?s=184674&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&cb={{.RedirectURL}}"
+    url: "https://ssum-sec.casalemedia.com/usermatch?s=184674&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gppsid={{.GPPSID}}&cb={{.RedirectURL}}"
     # ix appends the user id to end of the redirect url and does not utilize a macro
+openrtb:
+  gpp-supported: true
diff --git a/static/bidder-info/mediafuse.yaml b/static/bidder-info/mediafuse.yaml
index b78b21e1..be19cc6c 100644
--- a/static/bidder-info/mediafuse.yaml
+++ b/static/bidder-info/mediafuse.yaml
@@ -12,5 +12,5 @@ capabilities:
       - banner
       - video
       - native
-userSync:
-  key: "adnxs"
+# userSync:
+#   key: "adnxs"
diff --git a/static/bidder-info/pwbid.yaml b/static/bidder-info/pwbid.yaml
index ac687273..a172ff39 100644
--- a/static/bidder-info/pwbid.yaml
+++ b/static/bidder-info/pwbid.yaml
@@ -1,4 +1,4 @@
-endpoint: "https://bid.pubwise.io/prebid"
+endpoint: "https://bidder.east2.pubwise.io/bid/pubwisedirect"
 maintainer:
   email: info@pubwise.io
 gvlVendorID: 842
@@ -17,4 +17,4 @@ userSync:
   # PubWise supports user syncing, but requires configuration by the host. contact this
   # bidder directly at the email address in this file to ask about enabling user sync.
   supports:
-    - redirect
\ No newline at end of file
+    - redirect
diff --git a/static/bidder-info/triplelift.yaml b/static/bidder-info/triplelift.yaml
index 45811c0c..605bcc71 100644
--- a/static/bidder-info/triplelift.yaml
+++ b/static/bidder-info/triplelift.yaml
@@ -16,9 +16,11 @@ userSync:
   # Contact this bidder directly at the email address above to ask about enabling user sync.
   # 
   iframe:
-    url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+    url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}"
     userMacro: $UID
   redirect:
-    url: "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+    url: "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}"
     userMacro: "$UID"
-endpointCompression: "GZIP"
\ No newline at end of file
+endpointCompression: "GZIP"
+openrtb:
+  gpp-supported: true
\ No newline at end of file
diff --git a/static/bidder-info/triplelift_native.yaml b/static/bidder-info/triplelift_native.yaml
index 85ebd1a5..ff93b544 100644
--- a/static/bidder-info/triplelift_native.yaml
+++ b/static/bidder-info/triplelift_native.yaml
@@ -16,8 +16,10 @@ userSync:
   # Contact this bidder directly at the email address above to ask about enabling user sync.
   # 
   iframe:
-    url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+    url: "https://eb2.3lift.com/sync?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}"
     userMacro: $UID
   redirect:
-    url: "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
-    userMacro: "$UID"
\ No newline at end of file
+    url: "https://eb2.3lift.com/getuid?gdpr={{.GDPR}}&cmp_cs={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redir={{.RedirectURL}}"
+    userMacro: "$UID"
+openrtb:
+  gpp-supported: true
\ No newline at end of file
diff --git a/static/bidder-info/ucfunnel.yaml b/static/bidder-info/ucfunnel.yaml
index 0034b9d4..99af7313 100644
--- a/static/bidder-info/ucfunnel.yaml
+++ b/static/bidder-info/ucfunnel.yaml
@@ -13,5 +13,6 @@ capabilities:
       - video
 userSync:
   redirect:
+  # for syncing to work, please register your Prebid Server domain with the contact email above
     url: "https://sync.aralego.com/idsync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&usprivacy={{.USPrivacy}}&redirect={{.RedirectURL}}"
     userMacro: "SspCookieUserId"
diff --git a/static/bidder-info/yahooAds.yaml b/static/bidder-info/yahooAds.yaml
new file mode 100644
index 00000000..a2581387
--- /dev/null
+++ b/static/bidder-info/yahooAds.yaml
@@ -0,0 +1,18 @@
+endpoint: "https://s2shb.ssp.yahoo.com/admax/bid/partners/PBS"
+maintainer:
+  email: "hb-fe-tech@yahooinc.com"
+gvlVendorID: 25
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
+userSync:
+  # yahooAds supports user syncing, but requires configuration by the host. contact this
+  # bidder directly at the email address in this file to ask about enabling user sync.
+  supports:
+    - redirect
\ No newline at end of file
diff --git a/static/bidder-params/aidem.json b/static/bidder-params/aidem.json
new file mode 100644
index 00000000..221e5ff7
--- /dev/null
+++ b/static/bidder-params/aidem.json
@@ -0,0 +1,29 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "AIDEM Adapter Params",
+    "description": "A schema which validates params accepted by the AIDEM adapter",
+    "type": "object",
+    "properties": {
+        "siteId": {
+            "type": "string",
+            "minLength": 1,
+            "description": "Unique site ID"
+        },
+        "publisherId": {
+            "type": "string",
+            "minLength": 1,
+            "description": "Unique publisher ID"
+        },
+        "placementId": {
+            "type": "string",
+            "minLength": 1,
+            "description": "Unique publisher ttag ID"
+        },
+        "rateLimit": {
+            "type": "number",
+            "minimum": 0,
+            "maximum": 1
+        }
+    },
+    "required": ["siteId", "publisherId"]
+}
\ No newline at end of file
diff --git a/static/bidder-params/ix.json b/static/bidder-params/ix.json
index a7a5cb73..172690cc 100644
--- a/static/bidder-params/ix.json
+++ b/static/bidder-params/ix.json
@@ -27,6 +27,11 @@
       "minItems": 2,
       "maxItems": 2,
       "description": "An array of two integer containing the dimension"
+    },
+    "sid": {
+      "type": "string",
+      "minLength": 1,
+      "description": "Slot ID"
     }
   },
   "oneOf": [
diff --git a/static/bidder-params/yahooAds.json b/static/bidder-params/yahooAds.json
new file mode 100644
index 00000000..77e71073
--- /dev/null
+++ b/static/bidder-params/yahooAds.json
@@ -0,0 +1,19 @@
+{
+	"$schema": "http://json-schema.org/draft-04/schema#",
+	"title": "YahooAds Adapter Params",
+	"description": "A schema which validates params accepted by the YahooAds adapter",
+	"type": "object",
+	"properties": {
+		"dcn": {
+			"type": "string",
+			"minLength": 1,
+			"description": "Site ID provided by One Mobile"
+		},
+		"pos": {
+			"type": "string",
+			"minLength": 1,
+			"description": "Placement ID"
+		}
+	},
+	"required": ["dcn", "pos"]
+}


Test patch:
diff --git a/adapters/aidem/aidem_test.go b/adapters/aidem/aidem_test.go
new file mode 100644
index 00000000..03bcc7e0
--- /dev/null
+++ b/adapters/aidem/aidem_test.go
@@ -0,0 +1,30 @@
+package aidem
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/prebid/prebid-server/adapters/adapterstest"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestJsonSamples(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderAidem, config.Adapter{
+		Endpoint: "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "aidemtest", bidder)
+}
+
+func TestEndpointTemplateMalformed(t *testing.T) {
+	_, buildErr := Builder(openrtb_ext.BidderAidem, config.Adapter{
+		Endpoint: "{{Malformed}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+
+	assert.Nil(t, buildErr)
+}
diff --git a/adapters/aidem/aidemtest/exemplary/multi-format.json b/adapters/aidem/aidemtest/exemplary/multi-format.json
new file mode 100644
index 00000000..0c940d4b
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/multi-format.json
@@ -0,0 +1,119 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 320,
+                            "h": 50
+                        }
+                    ]
+                },
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "protocols": [
+                        2,
+                        5
+                    ],
+                    "w": 320,
+                    "h": 480
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 320,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "protocols": [
+                                    2,
+                                    5
+                                ],
+                                "w": 320,
+                                "h": 480
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 1.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "h": 50,
+                                    "w": 320,
+                                    "mtype": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 1.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 50,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/aidem/aidemtest/exemplary/multi-imps-multi-bid.json b/adapters/aidem/aidemtest/exemplary/multi-imps-multi-bid.json
new file mode 100644
index 00000000..5c2b3694
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/multi-imps-multi-bid.json
@@ -0,0 +1,154 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 320,
+                            "h": 50
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            },
+            {
+                "id": "2",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 50
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 320,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        },
+                        {
+                            "id": "2",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 1.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "h": 50,
+                                    "w": 320,
+                                    "mtype": 1
+                                },
+                                {
+                                    "id": "test-bid-id-2",
+                                    "impid": "2",
+                                    "price": 1.10,
+                                    "adm": "some-test-ad-2",
+                                    "crid": "test-crid-2",
+                                    "h": 50,
+                                    "w": 300,
+                                    "mtype": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 1.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 50,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                },
+                {
+                    "bid": {
+                        "id": "test-bid-id-2",
+                        "impid": "2",
+                        "price": 1.10,
+                        "adm": "some-test-ad-2",
+                        "crid": "test-crid-2",
+                        "w": 300,
+                        "h": 50,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/aidem/aidemtest/exemplary/multi-imps-single-bid.json b/adapters/aidem/aidemtest/exemplary/multi-imps-single-bid.json
new file mode 100644
index 00000000..9eae7101
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/multi-imps-single-bid.json
@@ -0,0 +1,131 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 320,
+                            "h": 50
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            },
+            {
+                "id": "2",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 50
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 320,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        },
+                        {
+                            "id": "2",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 1.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "h": 50,
+                                    "w": 320,
+                                    "mtype": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 1.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 50,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/aidem/aidemtest/exemplary/no-bid.json b/adapters/aidem/aidemtest/exemplary/no-bid.json
new file mode 100644
index 00000000..7418425f
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/no-bid.json
@@ -0,0 +1,58 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
diff --git a/adapters/aidem/aidemtest/exemplary/optional-params.json b/adapters/aidem/aidemtest/exemplary/optional-params.json
new file mode 100644
index 00000000..69511fb5
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/optional-params.json
@@ -0,0 +1,60 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234",
+                        "placementId": "ext"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234",
+                                    "placementId": "ext"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
diff --git a/adapters/aidem/aidemtest/exemplary/simple-banner.json b/adapters/aidem/aidemtest/exemplary/simple-banner.json
new file mode 100644
index 00000000..73db297e
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/simple-banner.json
@@ -0,0 +1,97 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 320,
+                            "h": 50
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 320,
+                                        "h": 50
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 1.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "h": 50,
+                                    "w": 320,
+                                    "mtype": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 1.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 50,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/aidem/aidemtest/exemplary/simple-video.json b/adapters/aidem/aidemtest/exemplary/simple-video.json
new file mode 100644
index 00000000..0daaffaa
--- /dev/null
+++ b/adapters/aidem/aidemtest/exemplary/simple-video.json
@@ -0,0 +1,103 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "1",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "protocols": [
+                        2,
+                        5
+                    ],
+                    "w": 320,
+                    "h": 480
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "1",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "protocols": [
+                                    2,
+                                    5
+                                ],
+                                "w": 320,
+                                "h": 480
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "cur": "USD",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "test-bid-id",
+                                    "impid": "1",
+                                    "price": 2.50,
+                                    "adm": "some-test-ad",
+                                    "crid": "test-crid",
+                                    "w": 320,
+                                    "h": 480,
+                                    "mtype": 2
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test-bid-id",
+                        "impid": "1",
+                        "price": 2.50,
+                        "adm": "some-test-ad",
+                        "crid": "test-crid",
+                        "w": 320,
+                        "h": 480,
+                        "mtype": 2
+                    },
+                    "type": "video"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/aidem/aidemtest/supplemental/invalid-req-400-status-code-bad-request.json b/adapters/aidem/aidemtest/supplemental/invalid-req-400-status-code-bad-request.json
new file mode 100644
index 00000000..3dea13ef
--- /dev/null
+++ b/adapters/aidem/aidemtest/supplemental/invalid-req-400-status-code-bad-request.json
@@ -0,0 +1,97 @@
+{
+    "mockBidRequest": {
+        "id": "some-request-id",
+        "tmax": 1000,
+        "user": {
+            "buyeruid": "0000-000-000-0000"
+        },
+        "app": {
+            "publisher": {
+                "id": "123456789"
+            },
+            "cat": [
+                "IAB22-1"
+            ],
+            "bundle": "com.app.awesome",
+            "name": "Awesome App",
+            "domain": "awesomeapp.com",
+            "id": "123456789"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "w": 640,
+                    "h": 480,
+                    "minduration": 120,
+                    "maxduration": 150
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "some-request-id",
+                    "imp": [
+                        {
+                            "id": "some-impression-id",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "w": 640,
+                                "h": 480,
+                                "minduration": 120,
+                                "maxduration": 150
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ],
+                    "app": {
+                        "publisher": {
+                            "id": "123456789"
+                        },
+                        "cat": [
+                            "IAB22-1"
+                        ],
+                        "bundle": "com.app.awesome",
+                        "name": "Awesome App",
+                        "domain": "awesomeapp.com",
+                        "id": "123456789"
+                    },
+                    "user": {
+                        "buyeruid": "0000-000-000-0000"
+                    },
+                    "tmax": 1000
+                }
+            },
+            "mockResponse": {
+                "status": 400
+            }
+        }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unexpected status code: 400. Run with request.debug = 1 for more info",
+            "comparison": "literal"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/aidem/aidemtest/supplemental/invalid-res-200-status-code-empty-bids.json b/adapters/aidem/aidemtest/supplemental/invalid-res-200-status-code-empty-bids.json
new file mode 100644
index 00000000..dd64125f
--- /dev/null
+++ b/adapters/aidem/aidemtest/supplemental/invalid-res-200-status-code-empty-bids.json
@@ -0,0 +1,102 @@
+{
+    "mockBidRequest": {
+        "id": "some-request-id",
+        "tmax": 1000,
+        "user": {
+            "buyeruid": "0000-000-000-0000"
+        },
+        "app": {
+            "publisher": {
+                "id": "123456789"
+            },
+            "cat": [
+                "IAB22-1"
+            ],
+            "bundle": "com.app.awesome",
+            "name": "Awesome App",
+            "domain": "awesomeapp.com",
+            "id": "123456789"
+        },
+        "imp": [
+            {
+                "id": "some-impression-id",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "w": 640,
+                    "h": 480,
+                    "minduration": 120,
+                    "maxduration": 150
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "some-request-id",
+                    "imp": [
+                        {
+                            "id": "some-impression-id",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "w": 640,
+                                "h": 480,
+                                "minduration": 120,
+                                "maxduration": 150
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ],
+                    "app": {
+                        "publisher": {
+                            "id": "123456789"
+                        },
+                        "cat": [
+                            "IAB22-1"
+                        ],
+                        "bundle": "com.app.awesome",
+                        "name": "Awesome App",
+                        "domain": "awesomeapp.com",
+                        "id": "123456789"
+                    },
+                    "user": {
+                        "buyeruid": "0000-000-000-0000"
+                    },
+                    "tmax": 1000
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "tid",
+                    "seatbid": [],
+                    "bidid": "bid01"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Empty SeatBid array",
+            "comparison": "literal"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/aidem/aidemtest/supplemental/invalid-resp-multi-imp-type.json b/adapters/aidem/aidemtest/supplemental/invalid-resp-multi-imp-type.json
new file mode 100644
index 00000000..95f97d31
--- /dev/null
+++ b/adapters/aidem/aidemtest/supplemental/invalid-resp-multi-imp-type.json
@@ -0,0 +1,151 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "w": 300,
+                    "h": 250
+                },
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "w": 640,
+                    "h": 480,
+                    "minduration": 120,
+                    "maxduration": 150
+                },
+                "native": {
+                    "ver": "1.1",
+                    "request": "{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "domain": "www.example.com",
+            "page": "http://www.example.com",
+            "publisher": {
+                "domain": "example.com"
+            },
+            "ext": {
+                "amp": 0
+            }
+        },
+        "device": {
+            "ua": "userAgent",
+            "ip": "193.168.244.1"
+        },
+        "at": 1,
+        "tmax": 5000,
+        "cur": [
+            "USD"
+        ],
+        "regs": {
+            "ext": {
+                "gdpr": 0
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "w": 300,
+                                "h": 250
+                            },
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "w": 640,
+                                "h": 480,
+                                "minduration": 120,
+                                "maxduration": 150
+                            },
+                            "native": {
+                                "ver": "1.1",
+                                "request": "{\"adunit\":2,\"assets\":[{\"id\":3,\"img\":{\"h\":120,\"hmin\":0,\"type\":3,\"w\":180,\"wmin\":0},\"required\":1},{\"id\":0,\"required\":1,\"title\":{\"len\":25}},{\"data\":{\"len\":25,\"type\":1},\"id\":4,\"required\":1},{\"data\":{\"len\":140,\"type\":2},\"id\":6,\"required\":1}],\"context\":1,\"layout\":1,\"contextsubtype\":11,\"plcmtcnt\":1,\"plcmttype\":2,\"ver\":\"1.1\",\"ext\":{\"banner\":{\"w\":320,\"h\":50}}}"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ],
+                    "site": {
+                        "domain": "www.example.com",
+                        "page": "http://www.example.com",
+                        "publisher": {
+                            "domain": "example.com"
+                        },
+                        "ext": {
+                            "amp": 0
+                        }
+                    },
+                    "device": {
+                        "ua": "userAgent",
+                        "ip": "193.168.244.1"
+                    },
+                    "at": 1,
+                    "tmax": 5000,
+                    "cur": [
+                        "USD"
+                    ],
+                    "regs": {
+                        "ext": {
+                            "gdpr": 0
+                        }
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "tid",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "randomid",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "12345678",
+                                    "adm": "some-test-ad",
+                                    "cid": "987",
+                                    "crid": "12345678",
+                                    "h": 250,
+                                    "w": 300
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "bid01"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [{"currency":"USD","bids":[]}],
+    "expectedMakeBidsErrors": [
+        {
+            "value": "Unable to fetch mediaType in multi-format: test-imp-id",
+            "comparison": "literal"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/aidem/aidemtest/supplemental/valid-req-200-bid-response-from-aidem.json b/adapters/aidem/aidemtest/supplemental/valid-req-200-bid-response-from-aidem.json
new file mode 100644
index 00000000..cbd534cd
--- /dev/null
+++ b/adapters/aidem/aidemtest/supplemental/valid-req-200-bid-response-from-aidem.json
@@ -0,0 +1,141 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "w": 300,
+                    "h": 250
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "domain": "www.example.com",
+            "page": "http://www.example.com",
+            "publisher": {
+                "domain": "example.com"
+            },
+            "ext": {
+                "amp": 0
+            }
+        },
+        "device": {
+            "ua": "userAgent",
+            "ip": "193.168.244.1"
+        },
+        "at": 1,
+        "tmax": 5000,
+        "cur": [
+            "USD"
+        ],
+        "regs": {
+            "ext": {
+                "gdpr": 0
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "banner": {
+                                "w": 300,
+                                "h": 250
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            }
+                        }
+                    ],
+                    "site": {
+                        "domain": "www.example.com",
+                        "page": "http://www.example.com",
+                        "publisher": {
+                            "domain": "example.com"
+                        },
+                        "ext": {
+                            "amp": 0
+                        }
+                    },
+                    "device": {
+                        "ua": "userAgent",
+                        "ip": "193.168.244.1"
+                    },
+                    "at": 1,
+                    "tmax": 5000,
+                    "cur": [
+                        "USD"
+                    ],
+                    "regs": {
+                        "ext": {
+                            "gdpr": 0
+                        }
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "tid",
+                    "seatbid": [
+                        {
+                            "seat": "aax",
+                            "bid": [
+                                {
+                                    "id": "randomid",
+                                    "impid": "test-imp-id",
+                                    "price": 0.500000,
+                                    "adid": "12345678",
+                                    "adm": "some-test-ad",
+                                    "cid": "987",
+                                    "crid": "12345678",
+                                    "h": 250,
+                                    "w": 300,
+                                    "mtype": 1
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "bid01"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "h": 250,
+                        "w": 300,
+                        "mtype": 1
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/aidem/aidemtest/supplemental/valid-req-204-response-from-aidem.json b/adapters/aidem/aidemtest/supplemental/valid-req-204-response-from-aidem.json
new file mode 100644
index 00000000..ddd4e5a7
--- /dev/null
+++ b/adapters/aidem/aidemtest/supplemental/valid-req-204-response-from-aidem.json
@@ -0,0 +1,66 @@
+{
+    "mockBidRequest": {
+        "app": {
+            "bundle": "com.example.app"
+        },
+        "id": "req-id",
+        "device": {
+            "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d",
+            "ip": "1.1.1.1",
+            "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36"
+        },
+        "imp": [
+            {
+                "ext": {
+                    "bidder": {
+                        "siteId": "TCID",
+                        "publisherId": "1234"
+                    }
+                },
+                "banner": {
+                    "w": 320,
+                    "h": 50
+                },
+                "id": "imp-id"
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "https://fakezero.aidemsrv.com/ortb/v2.6/bid/request",
+                "body": {
+                    "app": {
+                        "bundle": "com.example.app"
+                    },
+                    "id": "req-id",
+                    "device": {
+                        "ifa": "9d8fe0a9-c0dd-4482-b16b-5709b00c608d",
+                        "ip": "1.1.1.1",
+                        "ua": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36"
+                    },
+                    "imp": [
+                        {
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "TCID",
+                                    "publisherId": "1234"
+                                }
+                            },
+                            "banner": {
+                                "w": 320,
+                                "h": 50
+                            },
+                            "id": "imp-id"
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 204,
+                "body": {}
+            }
+        }
+    ],
+    "expectedBidResponses": []
+}
\ No newline at end of file
diff --git a/adapters/aidem/params_test.go b/adapters/aidem/params_test.go
new file mode 100644
index 00000000..36190c0b
--- /dev/null
+++ b/adapters/aidem/params_test.go
@@ -0,0 +1,57 @@
+package aidem
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+// This file actually intends to test static/bidder-params/aidem.json TODO: MUST BE CREATED
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, validParam := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderAidem, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected aidem params: %s", validParam)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json-schemas. %v", err)
+	}
+
+	for _, invalidParam := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderAidem, json.RawMessage(invalidParam)); err == nil {
+			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"siteId":"123", "publisherId":"1234"}`,
+	`{"siteId":"123", "publisherId":"1234", "placementId":"12345"}`,
+	`{"siteId":"123", "publisherId":"1234", "rateLimit":1}`,
+	`{"siteId":"123", "publisherId":"1234", "placementId":"12345", "rateLimit":1}`,
+}
+
+var invalidParams = []string{
+	``,
+	`null`,
+	`true`,
+	`5`,
+	`4.2`,
+	`[]`,
+	`{}`,
+	`{"siteId":"", "publisherId":""}`,
+	`{"siteId":"only siteId is present"}`,
+	`{"publisherId":"only publisherId is present"}`,
+	`{"ssiteId":"123","ppublisherId":"123"}`,
+	`{"aid":123, "placementId":"123", "siteId":"321"}`,
+}
diff --git a/adapters/improvedigital/improvedigitaltest/supplemental/foreign-currency.json b/adapters/improvedigital/improvedigitaltest/supplemental/foreign-currency.json
new file mode 100644
index 00000000..633e8b6b
--- /dev/null
+++ b/adapters/improvedigital/improvedigitaltest/supplemental/foreign-currency.json
@@ -0,0 +1,89 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "cur": ["EUR"],
+        "site": {
+            "page": "https://good.site/url"
+        },
+        "imp": [{
+            "id": "test-imp-id",
+            "banner": {
+                "format": [{
+                    "w": 300,
+                    "h": 250
+                }]
+            },
+            "ext": {
+                "bidder": {
+                    "placementId": 13245
+                }
+            }
+        }]
+    },
+
+    "httpCalls": [{
+        "expectedRequest": {
+            "uri": "http://localhost/pbs",
+            "body": {
+                "id": "test-request-id",
+                "cur": ["EUR"],
+                "site": {
+                    "page": "https://good.site/url"
+                },
+                "imp": [{
+                    "id": "test-imp-id",
+                    "banner": {
+                        "format": [{
+                            "w": 300,
+                            "h": 250
+                        }]
+                    },
+                    "ext": {
+                        "bidder": {
+                            "placementId": 13245
+                        }
+                    }
+                }]
+            }
+        },
+        "mockResponse": {
+            "status": 200,
+            "body": {
+                "id": "test-request-id",
+                "cur": "EUR",
+                "seatbid": [{
+                    "seat": "improvedigital",
+                    "bid": [{
+                        "id": "randomid",
+                        "impid": "test-imp-id",
+                        "price": 0.500000,
+                        "adid": "12345678",
+                        "adm": "some-test-ad",
+                        "cid": "987",
+                        "crid": "12345678",
+                        "h": 250,
+                        "w": 300
+                    }]
+                }]
+            }
+        }
+    }],
+
+    "expectedBidResponses": [{
+        "currency": "EUR",
+        "bids": [{
+            "bid": {
+                "id": "randomid",
+                "impid": "test-imp-id",
+                "price": 0.5,
+                "adm": "some-test-ad",
+                "adid": "12345678",
+                "cid": "987",
+                "crid": "12345678",
+                "w": 300,
+                "h": 250
+            },
+            "type": "banner"
+        }]
+    }]
+}
diff --git a/adapters/ix/ix_test.go b/adapters/ix/ix_test.go
index 0f6b856d..a64e3d0c 100644
--- a/adapters/ix/ix_test.go
+++ b/adapters/ix/ix_test.go
@@ -19,8 +19,6 @@ const endpoint string = "http://host/endpoint"
 
 func TestJsonSamples(t *testing.T) {
 	if bidder, err := Builder(openrtb_ext.BidderIx, config.Adapter{Endpoint: endpoint}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}); err == nil {
-		ixBidder := bidder.(*IxAdapter)
-		ixBidder.maxRequests = 2
 		adapterstest.RunJSONBidderTest(t, "ixtest", bidder)
 	} else {
 		t.Fatalf("Builder returned unexpected error %v", err)
@@ -44,7 +42,7 @@ func TestIxMakeBidsWithCategoryDuration(t *testing.T) {
 				`{
 					"prebid": {},
 					"bidder": {
-						"siteID": 123456
+						"siteID": "123456"
 					}
 				}`,
 			)},
@@ -106,7 +104,6 @@ func TestIxMakeBidsWithCategoryDuration(t *testing.T) {
 
 func TestIxMakeRequestWithGppString(t *testing.T) {
 	bidder := &IxAdapter{}
-	bidder.maxRequests = 2
 
 	testGppString := "DBACNYA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA~1YNN"
 
@@ -124,7 +121,7 @@ func TestIxMakeRequestWithGppString(t *testing.T) {
 				`{
 					"prebid": {},
 					"bidder": {
-						"siteID": 123456
+						"siteId": "123456"
 					}
 				}`,
 			)},
@@ -256,7 +253,8 @@ func TestBuildIxDiag(t *testing.T) {
 	for _, test := range testCases {
 		t.Run(test.description, func(t *testing.T) {
 			version.Ver = test.pbsVersion
-			err := BuildIxDiag(test.request)
+			ixDiag := &IxDiag{}
+			err := setIxDiagIntoExtRequest(test.request, ixDiag)
 			if test.expectError {
 				assert.NotNil(t, err)
 			} else {
diff --git a/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json b/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json
new file mode 100644
index 00000000..4decdaf9
--- /dev/null
+++ b/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json
@@ -0,0 +1,211 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id-1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-2",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-3",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "page": "https://www.example.com/"
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id-1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-2",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-3",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "h": 600
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ],
+                    "site": {
+                        "page": "https://www.example.com/",
+                        "publisher": {
+                            "id": "569749"
+                        }
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id-1",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 600,
+                                    "w": 300,
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id-1",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 600,
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/exemplary/max-requests.json b/adapters/ix/ixtest/exemplary/multi-imp-requests.json
similarity index 69%
rename from adapters/ix/ixtest/exemplary/max-requests.json
rename to adapters/ix/ixtest/exemplary/multi-imp-requests.json
index 46d9ec5d..d8d00aee 100644
--- a/adapters/ix/ixtest/exemplary/max-requests.json
+++ b/adapters/ix/ixtest/exemplary/multi-imp-requests.json
@@ -9,10 +9,6 @@
                         {
                             "w": 300,
                             "h": 250
-                        },
-                        {
-                            "w": 300,
-                            "h": 600
                         }
                     ]
                 },
@@ -62,6 +58,38 @@
                         "siteId": "569749"
                     }
                 }
+            },
+            {
+                "id": "test-imp-id-4",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-5",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
             }
         ]
     },
@@ -89,49 +117,7 @@
                                     "siteId": "569749"
                                 }
                             }
-                        }
-                    ]
-                }
-            },
-            "mockResponse": {
-                "status": 200,
-                "body": {
-                    "id": "test-request-id",
-                    "seatbid": [
-                        {
-                            "seat": "958",
-                            "bid": [
-                                {
-                                    "id": "7706636740145184841",
-                                    "impid": "test-imp-id-1",
-                                    "price": 0.5,
-                                    "adid": "29681110",
-                                    "adm": "some-test-ad",
-                                    "adomain": [
-                                        "https://advertiser.example.com"
-                                    ],
-                                    "cid": "958",
-                                    "crid": "29681110",
-                                    "h": 250,
-                                    "w": 300,
-                                    "ext": {
-                                        "ix": {}
-                                    }
-                                }
-                            ]
-                        }
-                    ],
-                    "bidid": "5778926625248726496",
-                    "cur": "USD"
-                }
-            }
-        },
-        {
-            "expectedRequest": {
-                "uri": "http://host/endpoint",
-                "body": {
-                    "id": "test-request-id",
-                    "imp": [
+                        },
                         {
                             "id": "test-imp-id-2",
                             "video": {
@@ -156,6 +142,60 @@
                                     "siteId": "569749"
                                 }
                             }
+                        },
+                        {
+                            "banner": {
+                              "format": [
+                                {
+                                  "h": 600,
+                                  "w": 300
+                                }
+                              ],
+                              "h": 600,
+                              "w": 300
+                            },
+                            "ext": {
+                              "bidder": {
+                                "siteId": "569749"
+                              }
+                            },
+                            "id": "test-imp-id-3"
+                        },
+                        {
+                            "id": "test-imp-id-4",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    }
+                                ],
+                                "w": 300,
+                                "h": 250
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-5",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    }
+                                ],
+                                "w": 300,
+                                "h": 250
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
                         }
                     ]
                 }
@@ -170,7 +210,7 @@
                             "bid": [
                                 {
                                     "id": "7706636740145184841",
-                                    "impid": "test-imp-id-2",
+                                    "impid": "test-imp-id-1",
                                     "price": 0.5,
                                     "adid": "29681110",
                                     "adm": "some-test-ad",
@@ -181,9 +221,6 @@
                                     "crid": "29681110",
                                     "h": 250,
                                     "w": 300,
-                                    "cat": [
-                                        "IAB9-1"
-                                    ],
                                     "ext": {
                                         "ix": {}
                                     }
@@ -222,34 +259,6 @@
                     "type": "banner"
                 }
             ]
-        },
-        {
-            "currency": "USD",
-            "bids": [
-                {
-                    "bid": {
-                        "id": "7706636740145184841",
-                        "impid": "test-imp-id-2",
-                        "price": 0.5,
-                        "adm": "some-test-ad",
-                        "adid": "29681110",
-                        "adomain": [
-                            "https://advertiser.example.com"
-                        ],
-                        "cid": "958",
-                        "crid": "29681110",
-                        "w": 300,
-                        "h": 250,
-                        "cat": [
-                            "IAB9-1"
-                        ],
-                        "ext": {
-                            "ix": {}
-                        }
-                    },
-                    "type": "video"
-                }
-            ]
         }
     ]
 }
diff --git a/adapters/ix/ixtest/exemplary/multiple-siteIds.json b/adapters/ix/ixtest/exemplary/multiple-siteIds.json
new file mode 100644
index 00000000..7f4227ac
--- /dev/null
+++ b/adapters/ix/ixtest/exemplary/multiple-siteIds.json
@@ -0,0 +1,224 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id-1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-2",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569750"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-3",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569751"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "page": "https://www.example.com/"
+        },
+        "ext": {
+            "prebid": {
+                "channel": {
+                    "name": "web",
+                    "version": "7.0.0"
+                }
+            }
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id-1",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    }
+                                ],
+                                "w": 300,
+                                "h": 250
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-2",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569750"
+                                }
+                            }
+                        },
+                        {
+                            "banner": {
+                              "format": [
+                                {
+                                  "h": 600,
+                                  "w": 300
+                                }
+                              ],
+                              "h": 600,
+                              "w": 300
+                            },
+                            "ext": {
+                              "bidder": {
+                                "siteId": "569751"
+                              }
+                            },
+                            "id": "test-imp-id-3"
+                        }
+                    ],
+                    "site": {
+                        "page": "https://www.example.com/",
+                        "publisher": {
+                        }
+                    },
+                    "ext": {
+                        "ixdiag": {
+                          "multipleSiteIds": "569749, 569750, 569751",
+                          "pbjsv": "7.0.0"
+                        },
+                        "prebid": {
+                          "channel": {
+                            "name": "web",
+                            "version": "7.0.0"
+                          }
+                        }
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id-1",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 250,
+                                    "w": 300,
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id-1",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 250,
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json b/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json
index 5e0a311a..15dc3ecb 100644
--- a/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json
+++ b/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json
@@ -13,6 +13,10 @@
                         {
                             "w": 300,
                             "h": 600
+                        },
+                        {
+                            "w": 600,
+                            "h": 800
                         }
                     ]
                 },
@@ -22,7 +26,10 @@
                     }
                 }
             }
-        ]
+        ],
+        "site": {
+            "page": "https://www.example.com/"
+        }
     },
     "httpCalls": [
         {
@@ -38,70 +45,16 @@
                                     {
                                         "w": 300,
                                         "h": 250
-                                    }
-                                ],
-                                "w": 300,
-                                "h": 250
-                            },
-                            "ext": {
-                                "bidder": {
-                                    "siteId": "569749"
-                                }
-                            }
-                        }
-                    ]
-                }
-            },
-            "mockResponse": {
-                "status": 200,
-                "body": {
-                    "id": "test-request-id",
-                    "seatbid": [
-                        {
-                            "seat": "958",
-                            "bid": [
-                                {
-                                    "id": "7706636740145184841",
-                                    "impid": "test-imp-id",
-                                    "price": 0.5,
-                                    "adid": "29681110",
-                                    "adm": "some-test-ad",
-                                    "adomain": [
-                                        "https://advertiser.example.com"
-                                    ],
-                                    "cid": "958",
-                                    "crid": "29681110",
-                                    "h": 250,
-                                    "w": 300,
-                                    "ext": {
-                                        "ix": {}
-                                    }
-                                }
-                            ]
-                        }
-                    ],
-                    "bidid": "5778926625248726496",
-                    "cur": "USD"
-                }
-            }
-        },
-        {
-            "expectedRequest": {
-                "uri": "http://host/endpoint",
-                "body": {
-                    "id": "test-request-id",
-                    "imp": [
-                        {
-                            "id": "test-imp-id",
-                            "banner": {
-                                "format": [
+                                    },
                                     {
                                         "w": 300,
                                         "h": 600
+                                    },
+                                    {
+                                        "w": 600,
+                                        "h": 800
                                     }
-                                ],
-                                "w": 300,
-                                "h": 600
+                                ]
                             },
                             "ext": {
                                 "bidder": {
@@ -109,7 +62,13 @@
                                 }
                             }
                         }
-                    ]
+                    ],
+                    "site": {
+                        "page": "https://www.example.com/",
+                        "publisher": {
+                            "id": "569749"
+                        }
+                    }
                 }
             },
             "mockResponse": {
@@ -131,7 +90,7 @@
                                     ],
                                     "cid": "958",
                                     "crid": "29681110",
-                                    "h": 600,
+                                    "h": 250,
                                     "w": 300,
                                     "ext": {
                                         "ix": {}
@@ -171,31 +130,6 @@
                     "type": "banner"
                 }
             ]
-        },
-        {
-            "currency": "USD",
-            "bids": [
-                {
-                    "bid": {
-                        "id": "7706636740145184841",
-                        "impid": "test-imp-id",
-                        "price": 0.5,
-                        "adm": "some-test-ad",
-                        "adid": "29681110",
-                        "adomain": [
-                            "https://advertiser.example.com"
-                        ],
-                        "cid": "958",
-                        "crid": "29681110",
-                        "w": 300,
-                        "h": 600,
-                        "ext": {
-                            "ix": {}
-                        }
-                    },
-                    "type": "banner"
-                }
-            ]
         }
     ]
 }
diff --git a/adapters/ix/ixtest/exemplary/structured-pod.json b/adapters/ix/ixtest/exemplary/structured-pod.json
new file mode 100644
index 00000000..a5ca9895
--- /dev/null
+++ b/adapters/ix/ixtest/exemplary/structured-pod.json
@@ -0,0 +1,236 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id-1",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560,
+                    "podid": "1",
+                    "slotinpod": 1,
+                    "podseq": 1
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-2",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560,
+                    "podid": "1",
+                    "slotinpod": -1,
+                    "podseq": 1
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                  "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id-1",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560,
+                                "podid": "1",
+                                "slotinpod": 1,
+                                "podseq": 1
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-2",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560,
+                                "podid": "1",
+                                "slotinpod": -1,
+                                "podseq": 1
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id-1",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 560,
+                                    "w": 940,
+                                    "dur": 30,
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        },
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id-2",
+                                    "price": 0.75,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 560,
+                                    "w": 940,
+                                    "dur": 30,
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id-1",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "h": 560,
+                        "w": 940,
+                        "dur": 30,
+                    "ext": {
+                        "ix": {}
+                    }
+                },
+                "type": "video"
+            },
+            {
+                "bid": {
+                    "id": "7706636740145184841",
+                    "impid": "test-imp-id-2",
+                    "price": 0.75,
+                    "adm": "some-test-ad",
+                    "adid": "29681110",
+                    "adomain": [
+                        "https://advertiser.example.com"
+                    ],
+                    "cid": "958",
+                    "crid": "29681110",
+                    "h": 560,
+                    "w": 940,
+                    "dur": 30,
+                "ext": {
+                    "ix": {}
+                }
+            },
+                "type": "video"
+            }
+        ]
+    }
+    ]
+}
diff --git a/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json b/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json
new file mode 100644
index 00000000..223e8632
--- /dev/null
+++ b/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json
@@ -0,0 +1,189 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id-1",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749",
+                        "sid": 12345
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-2",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "minduration": 15,
+                    "maxduration": 30,
+                    "protocols": [
+                        2,
+                        3,
+                        5,
+                        6,
+                        7,
+                        8
+                    ],
+                    "w": 940,
+                    "h": 560
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            },
+            {
+                "id": "test-imp-id-3",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "siteId": "569749"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://host/endpoint",
+                "body": {
+                  "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id-2",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "minduration": 15,
+                                "maxduration": 30,
+                                "protocols": [
+                                    2,
+                                    3,
+                                    5,
+                                    6,
+                                    7,
+                                    8
+                                ],
+                                "w": 940,
+                                "h": 560
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        },
+                        {
+                            "id": "test-imp-id-3",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ],
+                                "w": 300,
+                                "h": 600
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "siteId": "569749"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "seat": "958",
+                            "bid": [
+                                {
+                                    "id": "7706636740145184841",
+                                    "impid": "test-imp-id-1",
+                                    "price": 0.5,
+                                    "adid": "29681110",
+                                    "adm": "some-test-ad",
+                                    "adomain": [
+                                        "https://advertiser.example.com"
+                                    ],
+                                    "cid": "958",
+                                    "crid": "29681110",
+                                    "h": 600,
+                                    "w": 300,
+                                    "ext": {
+                                        "ix": {}
+                                    }
+                                }
+                            ]
+                        }
+                    ],
+                    "bidid": "5778926625248726496",
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "7706636740145184841",
+                        "impid": "test-imp-id-1",
+                        "price": 0.5,
+                        "adm": "some-test-ad",
+                        "adid": "29681110",
+                        "adomain": [
+                            "https://advertiser.example.com"
+                        ],
+                        "cid": "958",
+                        "crid": "29681110",
+                        "w": 300,
+                        "h": 600,
+                        "ext": {
+                            "ix": {}
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ],
+    "expectedMakeRequestsErrors": [
+        {
+            "value": "json: cannot unmarshal number into Go struct field ExtImpIx.sid of type string",
+            "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/ix/ixtest/supplemental/sid.json b/adapters/ix/ixtest/supplemental/sid.json
new file mode 100644
index 00000000..c2156b6b
--- /dev/null
+++ b/adapters/ix/ixtest/supplemental/sid.json
@@ -0,0 +1,184 @@
+{
+  "mockBidRequest": {
+    "id": "test-request-id",
+    "imp": [
+      {
+        "id": "test-imp-id-1",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "minduration": 15,
+          "maxduration": 30,
+          "protocols": [
+            2,
+            3,
+            5,
+            6,
+            7,
+            8
+          ],
+          "w": 940,
+          "h": 560
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "569749",
+            "sid": "1234"
+          }
+        }
+      },
+      {
+        "id": "test-imp-id-2",
+        "video": {
+          "mimes": [
+            "video/mp4"
+          ],
+          "minduration": 15,
+          "maxduration": 30,
+          "protocols": [
+            2,
+            3,
+            5,
+            6,
+            7,
+            8
+          ],
+          "w": 940,
+          "h": 560
+        },
+        "ext": {
+          "bidder": {
+            "siteId": "569750",
+            "sid": "5678"
+          }
+        }
+      }
+    ]
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://host/endpoint",
+        "body": {
+          "id": "test-request-id",
+          "imp": [
+            {
+              "id": "test-imp-id-1",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 15,
+                "maxduration": 30,
+                "protocols": [
+                  2,
+                  3,
+                  5,
+                  6,
+                  7,
+                  8
+                ],
+                "w": 940,
+                "h": 560
+              },
+              "ext": {
+                "bidder": {
+                  "siteId": "569749",
+                  "sid": "1234"
+                },
+                "sid": "1234"
+              }
+            },
+            {
+              "id": "test-imp-id-2",
+              "video": {
+                "mimes": [
+                  "video/mp4"
+                ],
+                "minduration": 15,
+                "maxduration": 30,
+                "protocols": [
+                  2,
+                  3,
+                  5,
+                  6,
+                  7,
+                  8
+                ],
+                "w": 940,
+                "h": 560
+              },
+              "ext": {
+                "bidder": {
+                  "siteId": "569750",
+                  "sid": "5678"
+                },
+                "sid": "5678"
+              }
+            }
+          ]
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "test-request-id",
+          "seatbid": [
+            {
+              "seat": "958",
+              "bid": [
+                {
+                  "id": "7706636740145184841",
+                  "impid": "test-imp-id-1",
+                  "price": 0.5,
+                  "adid": "29681110",
+                  "adm": "some-test-ad",
+                  "adomain": [
+                    "https://advertiser.example.com"
+                  ],
+                  "cid": "958",
+                  "crid": "29681110",
+                  "h": 250,
+                  "w": 300,
+                  "ext": {
+                    "ix": {}
+                  }
+                }
+              ]
+            }
+          ],
+          "bidid": "5778926625248726496",
+          "cur": "USD"
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "7706636740145184841",
+            "impid": "test-imp-id-1",
+            "price": 0.5,
+            "adm": "some-test-ad",
+            "adid": "29681110",
+            "adomain": [
+              "https://advertiser.example.com"
+            ],
+            "cid": "958",
+            "crid": "29681110",
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "ix": {}
+            }
+          },
+          "type": "video"
+        }
+      ]
+    }
+  ]
+}
diff --git a/adapters/ix/params_test.go b/adapters/ix/params_test.go
index 9246a43a..8ba937c1 100644
--- a/adapters/ix/params_test.go
+++ b/adapters/ix/params_test.go
@@ -38,6 +38,7 @@ var validParams = []string{
 	`{"siteID":"12345"}`,
 	`{"siteId":"123456"}`,
 	`{"siteid":"1234567", "size": [640,480]}`,
+	`{"siteId":"123456", "sid":"12345"}`,
 }
 
 var invalidParams = []string{
diff --git a/adapters/pwbid/pwbid_test.go b/adapters/pwbid/pwbid_test.go
index 21a41942..194e4bde 100644
--- a/adapters/pwbid/pwbid_test.go
+++ b/adapters/pwbid/pwbid_test.go
@@ -10,7 +10,7 @@ import (
 
 func TestJsonSamples(t *testing.T) {
 	bidder, buildErr := Builder(openrtb_ext.BidderPWBid, config.Adapter{
-		Endpoint: "https://bid.pubwise.io/prebid"},
+		Endpoint: "https://bidder.east2.pubwise.io/bid/pubwisedirect"},
 		config.Server{ExternalUrl: "http://hosturl.com", GvlID: 842, DataCenter: "2"})
 
 	if buildErr != nil {
diff --git a/adapters/pwbid/pwbidtest/exemplary/banner.json b/adapters/pwbid/pwbidtest/exemplary/banner.json
index ba618cb8..4cf93e1a 100644
--- a/adapters/pwbid/pwbidtest/exemplary/banner.json
+++ b/adapters/pwbid/pwbidtest/exemplary/banner.json
@@ -23,7 +23,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id-banner",
           "imp": [
@@ -90,4 +90,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/adapters/pwbid/pwbidtest/exemplary/native.json b/adapters/pwbid/pwbidtest/exemplary/native.json
index 907c16d4..ff57752c 100644
--- a/adapters/pwbid/pwbidtest/exemplary/native.json
+++ b/adapters/pwbid/pwbidtest/exemplary/native.json
@@ -18,7 +18,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id-native",
           "imp": [
@@ -78,4 +78,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/adapters/pwbid/pwbidtest/exemplary/optional-params.json b/adapters/pwbid/pwbidtest/exemplary/optional-params.json
index a080be90..5ababb24 100644
--- a/adapters/pwbid/pwbidtest/exemplary/optional-params.json
+++ b/adapters/pwbid/pwbidtest/exemplary/optional-params.json
@@ -25,7 +25,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id-banner",
           "imp": [
@@ -94,4 +94,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/adapters/pwbid/pwbidtest/exemplary/video.json b/adapters/pwbid/pwbidtest/exemplary/video.json
index b74c780d..6257de63 100644
--- a/adapters/pwbid/pwbidtest/exemplary/video.json
+++ b/adapters/pwbid/pwbidtest/exemplary/video.json
@@ -20,7 +20,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json
index 146ba93a..0d469893 100644
--- a/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json
+++ b/adapters/pwbid/pwbidtest/supplemental/response-200-without-body.json
@@ -19,7 +19,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/pwbid/pwbidtest/supplemental/response-204.json b/adapters/pwbid/pwbidtest/supplemental/response-204.json
index 5fff7ee3..4fc8961e 100644
--- a/adapters/pwbid/pwbidtest/supplemental/response-204.json
+++ b/adapters/pwbid/pwbidtest/supplemental/response-204.json
@@ -19,7 +19,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/pwbid/pwbidtest/supplemental/response-400.json b/adapters/pwbid/pwbidtest/supplemental/response-400.json
index d594e571..a1517883 100644
--- a/adapters/pwbid/pwbidtest/supplemental/response-400.json
+++ b/adapters/pwbid/pwbidtest/supplemental/response-400.json
@@ -19,7 +19,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/pwbid/pwbidtest/supplemental/response-500.json b/adapters/pwbid/pwbidtest/supplemental/response-500.json
index fa3d4d06..c2b56494 100644
--- a/adapters/pwbid/pwbidtest/supplemental/response-500.json
+++ b/adapters/pwbid/pwbidtest/supplemental/response-500.json
@@ -19,7 +19,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://bid.pubwise.io/prebid",
+        "uri": "https://bidder.east2.pubwise.io/bid/pubwisedirect",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/sharethrough/sharethroughtest/supplemental/multiformat-impression.json b/adapters/sharethrough/sharethroughtest/supplemental/multiformat-impression.json
new file mode 100644
index 00000000..fcebf79a
--- /dev/null
+++ b/adapters/sharethrough/sharethroughtest/supplemental/multiformat-impression.json
@@ -0,0 +1,362 @@
+{
+  "mockBidRequest": {
+    "id": "parent-id",
+    "tmax": 3000,
+    "imp": [
+      {
+        "id": "impression-id",
+        "ext": {
+          "bidder": {
+            "pkey": "pkey1"
+          }
+        },
+        "banner": {
+          "format": [
+            {
+              "w": 300,
+              "h": 250
+            }
+          ]
+        },
+        "video": {
+          "w": 640,
+          "h": 480,
+          "mimes": [
+            "video/mp4"
+          ],
+          "placement": 1
+        },
+        "native": {
+          "ver": "1.2",
+          "request": "placeholder request"
+        },
+        "audio": {
+          "mimes": [
+            "audio/mp4"
+          ],
+          "protocols": [
+            1,
+            2
+          ]
+        }
+      }
+    ],
+    "site": {
+      "publisher": {
+        "id": "1"
+      },
+      "page": "https://some-site.com",
+      "ref": "https://some-site.com"
+    },
+    "device": {
+      "w": 1200,
+      "h": 900
+    }
+  },
+  "httpCalls": [
+    {
+      "expectedRequest": {
+        "uri": "http://whatever.url",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "body": {
+          "id": "parent-id",
+          "tmax": 3000,
+          "imp": [
+            {
+              "id": "impression-id",
+              "tagid": "pkey1",
+              "ext": {
+                "bidder": {
+                  "pkey": "pkey1"
+                }
+              },
+              "banner": {
+                "format": [
+                  {
+                    "w": 300,
+                    "h": 250
+                  }
+                ]
+              }
+            }
+          ],
+          "site": {
+            "publisher": {
+              "id": "1"
+            },
+            "page": "https://some-site.com",
+            "ref": "https://some-site.com"
+          },
+          "device": {
+            "w": 1200,
+            "h": 900
+          },
+          "source": {
+            "ext": {
+              "version": "",
+              "str": "10.0"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "parent-id",
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "parent-id",
+                  "impid": "impression-id",
+                  "crid": "some-creative-id",
+                  "adm": "<div>Ad</div>",
+                  "price": 20,
+                  "w": 300,
+                  "h": 250,
+                  "ext": {
+                    "prebid": {
+                      "type": "banner"
+                    }
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      }
+    },
+    {
+      "expectedRequest": {
+        "uri": "http://whatever.url",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "body": {
+          "id": "parent-id",
+          "tmax": 3000,
+          "imp": [
+            {
+              "id": "impression-id",
+              "tagid": "pkey1",
+              "ext": {
+                "bidder": {
+                  "pkey": "pkey1"
+                }
+              },
+              "video": {
+                "w": 640,
+                "h": 480,
+                "mimes": [
+                  "video/mp4"
+                ],
+                "placement": 1
+              }
+            }
+          ],
+          "site": {
+            "publisher": {
+              "id": "1"
+            },
+            "page": "https://some-site.com",
+            "ref": "https://some-site.com"
+          },
+          "device": {
+            "w": 1200,
+            "h": 900
+          },
+          "source": {
+            "ext": {
+              "version": "",
+              "str": "10.0"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "parent-id",
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "parent-id",
+                  "impid": "impression-id",
+                  "crid": "some-creative-id",
+                  "adm": "<VAST>TAG</VAST>",
+                  "price": 20,
+                  "w": 640,
+                  "h": 480,
+                  "ext": {
+                    "prebid": {
+                      "type": "video"
+                    }
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      }
+    },
+    {
+      "expectedRequest": {
+        "uri": "http://whatever.url",
+        "headers": {
+          "Content-Type": [
+            "application/json;charset=utf-8"
+          ],
+          "Accept": [
+            "application/json"
+          ]
+        },
+        "body": {
+          "id": "parent-id",
+          "tmax": 3000,
+          "imp": [
+            {
+              "id": "impression-id",
+              "tagid": "pkey1",
+              "ext": {
+                "bidder": {
+                  "pkey": "pkey1"
+                }
+              },
+              "native": {
+                "ver": "1.2",
+                "request": "placeholder request"
+              }
+            }
+          ],
+          "site": {
+            "publisher": {
+              "id": "1"
+            },
+            "page": "https://some-site.com",
+            "ref": "https://some-site.com"
+          },
+          "device": {
+            "w": 1200,
+            "h": 900
+          },
+          "source": {
+            "ext": {
+              "version": "",
+              "str": "10.0"
+            }
+          }
+        }
+      },
+      "mockResponse": {
+        "status": 200,
+        "body": {
+          "id": "parent-id",
+          "cur": "USD",
+          "seatbid": [
+            {
+              "bid": [
+                {
+                  "id": "parent-id",
+                  "impid": "impression-id",
+                  "crid": "some-creative-id",
+                  "adm": "<div>Ad</div>",
+                  "price": 20,
+                  "w": 640,
+                  "h": 480,
+                  "ext": {
+                    "prebid": {
+                      "type": "native"
+                    }
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      }
+    }
+  ],
+  "expectedBidResponses": [
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "parent-id",
+            "impid": "impression-id",
+            "crid": "some-creative-id",
+            "adm": "<div>Ad</div>",
+            "price": 20,
+            "w": 300,
+            "h": 250,
+            "ext": {
+              "prebid": {
+                "type": "banner"
+              }
+            }
+          },
+          "type": "banner"
+        }
+      ]
+    },
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "parent-id",
+            "impid": "impression-id",
+            "crid": "some-creative-id",
+            "adm": "<VAST>TAG</VAST>",
+            "price": 20,
+            "w": 640,
+            "h": 480,
+            "ext": {
+              "prebid": {
+                "type": "video"
+              }
+            }
+          },
+          "type": "video"
+        }
+      ]
+    },
+    {
+      "currency": "USD",
+      "bids": [
+        {
+          "bid": {
+            "id": "parent-id",
+            "impid": "impression-id",
+            "crid": "some-creative-id",
+            "adm": "<div>Ad</div>",
+            "price": 20,
+            "w": 640,
+            "h": 480,
+            "ext": {
+              "prebid": {
+                "type": "native"
+              }
+            }
+          },
+          "type": "native"
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/adapters/yahooAdvertising/params_test.go b/adapters/yahooAds/params_test.go
similarity index 63%
rename from adapters/yahooAdvertising/params_test.go
rename to adapters/yahooAds/params_test.go
index 10d504cb..c0deaaa3 100644
--- a/adapters/yahooAdvertising/params_test.go
+++ b/adapters/yahooAds/params_test.go
@@ -1,4 +1,4 @@
-package yahooAdvertising
+package yahooAds
 
 import (
 	"encoding/json"
@@ -7,11 +7,11 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-// This file actually intends to test static/bidder-params/yahooAdvertising.json
+// This file actually intends to test static/bidder-params/yahooAds.json
 //
-// These also validate the format of the external API: request.imp[i].ext.yahooAdvertising
+// These also validate the format of the external API: request.imp[i].ext.yahooAds
 
-// TestValidParams makes sure that the yahooAdvertising schema accepts all imp.ext fields which we intend to support.
+// TestValidParams makes sure that the yahooAds schema accepts all imp.ext fields which we intend to support.
 func TestValidParams(t *testing.T) {
 	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
 	if err != nil {
@@ -19,13 +19,13 @@ func TestValidParams(t *testing.T) {
 	}
 
 	for _, validParam := range validParams {
-		if err := validator.Validate(openrtb_ext.BidderYahooAdvertising, json.RawMessage(validParam)); err != nil {
-			t.Errorf("Schema rejected yahooAdvertising params: %s", validParam)
+		if err := validator.Validate(openrtb_ext.BidderYahooAds, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected yahooAds params: %s", validParam)
 		}
 	}
 }
 
-// TestInvalidParams makes sure that the yahooAdvertising schema rejects all the imp.ext fields we don't support.
+// TestInvalidParams makes sure that the yahooAds schema rejects all the imp.ext fields we don't support.
 func TestInvalidParams(t *testing.T) {
 	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
 	if err != nil {
@@ -33,7 +33,7 @@ func TestInvalidParams(t *testing.T) {
 	}
 
 	for _, invalidParam := range invalidParams {
-		if err := validator.Validate(openrtb_ext.BidderYahooAdvertising, json.RawMessage(invalidParam)); err == nil {
+		if err := validator.Validate(openrtb_ext.BidderYahooAds, json.RawMessage(invalidParam)); err == nil {
 			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
 		}
 	}
diff --git a/adapters/yahooAdvertising/yahooAdvertising_test.go b/adapters/yahooAds/yahooAds_test.go
similarity index 51%
rename from adapters/yahooAdvertising/yahooAdvertising_test.go
rename to adapters/yahooAds/yahooAds_test.go
index e701c333..924eabd5 100644
--- a/adapters/yahooAdvertising/yahooAdvertising_test.go
+++ b/adapters/yahooAds/yahooAds_test.go
@@ -1,4 +1,4 @@
-package yahooAdvertising
+package yahooAds
 
 import (
 	"testing"
@@ -10,8 +10,8 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-func TestYahooAdvertisingBidderEndpointConfig(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderYahooAdvertising, config.Adapter{
+func TestYahooAdsBidderEndpointConfig(t *testing.T) {
+	bidder, buildErr := Builder(openrtb_ext.BidderYahooAds, config.Adapter{
 		Endpoint: "http://localhost/bid",
 	}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
 
@@ -19,17 +19,17 @@ func TestYahooAdvertisingBidderEndpointConfig(t *testing.T) {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 
-	bidderYahooAdvertising := bidder.(*adapter)
+	bidderYahooAds := bidder.(*adapter)
 
-	assert.Equal(t, "http://localhost/bid", bidderYahooAdvertising.URI)
+	assert.Equal(t, "http://localhost/bid", bidderYahooAds.URI)
 }
 
 func TestJsonSamples(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderYahooAdvertising, config.Adapter{}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
+	bidder, buildErr := Builder(openrtb_ext.BidderYahooAds, config.Adapter{}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 
-	adapterstest.RunJSONBidderTest(t, "yahooAdvertisingtest", bidder)
+	adapterstest.RunJSONBidderTest(t, "yahooAdstest", bidder)
 }
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-app-banner.json b/adapters/yahooAds/yahooAdstest/exemplary/simple-app-banner.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-app-banner.json
rename to adapters/yahooAds/yahooAdstest/exemplary/simple-app-banner.json
index d5e77c71..7ad41161 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-app-banner.json
+++ b/adapters/yahooAds/yahooAdstest/exemplary/simple-app-banner.json
@@ -77,7 +77,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-banner.json b/adapters/yahooAds/yahooAdstest/exemplary/simple-banner.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-banner.json
rename to adapters/yahooAds/yahooAdstest/exemplary/simple-banner.json
index d08bdf06..7036664d 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-banner.json
+++ b/adapters/yahooAds/yahooAdstest/exemplary/simple-banner.json
@@ -77,7 +77,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-video.json b/adapters/yahooAds/yahooAdstest/exemplary/simple-video.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-video.json
rename to adapters/yahooAds/yahooAdstest/exemplary/simple-video.json
index ea95ec40..ebf7af93 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/exemplary/simple-video.json
+++ b/adapters/yahooAds/yahooAdstest/exemplary/simple-video.json
@@ -92,7 +92,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/empty-banner-format.json b/adapters/yahooAds/yahooAdstest/supplemental/empty-banner-format.json
similarity index 100%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/empty-banner-format.json
rename to adapters/yahooAds/yahooAdstest/supplemental/empty-banner-format.json
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/invalid-banner-height.json b/adapters/yahooAds/yahooAdstest/supplemental/invalid-banner-height.json
similarity index 100%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/invalid-banner-height.json
rename to adapters/yahooAds/yahooAdstest/supplemental/invalid-banner-height.json
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/invalid-banner-width.json b/adapters/yahooAds/yahooAdstest/supplemental/invalid-banner-width.json
similarity index 100%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/invalid-banner-width.json
rename to adapters/yahooAds/yahooAdstest/supplemental/invalid-banner-width.json
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/non-supported-requests-bids-ignored.json b/adapters/yahooAds/yahooAdstest/supplemental/non-supported-requests-bids-ignored.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/non-supported-requests-bids-ignored.json
rename to adapters/yahooAds/yahooAdstest/supplemental/non-supported-requests-bids-ignored.json
index a44020da..c0d77fa4 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/non-supported-requests-bids-ignored.json
+++ b/adapters/yahooAds/yahooAdstest/supplemental/non-supported-requests-bids-ignored.json
@@ -74,7 +74,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/required-nobidder-info.json b/adapters/yahooAds/yahooAdstest/supplemental/required-nobidder-info.json
similarity index 100%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/required-nobidder-info.json
rename to adapters/yahooAds/yahooAdstest/supplemental/required-nobidder-info.json
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/server-error.json b/adapters/yahooAds/yahooAdstest/supplemental/server-error.json
similarity index 100%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/server-error.json
rename to adapters/yahooAds/yahooAdstest/supplemental/server-error.json
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/server-response-wrong-impid.json b/adapters/yahooAds/yahooAdstest/supplemental/server-response-wrong-impid.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/server-response-wrong-impid.json
rename to adapters/yahooAds/yahooAdstest/supplemental/server-response-wrong-impid.json
index 1fcf61e1..f4081949 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/server-response-wrong-impid.json
+++ b/adapters/yahooAds/yahooAdstest/supplemental/server-response-wrong-impid.json
@@ -76,7 +76,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "wrong",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp-overwrite.json b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp-overwrite.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp-overwrite.json
rename to adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp-overwrite.json
index 190f96bf..94c895b9 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp-overwrite.json
+++ b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp-overwrite.json
@@ -92,7 +92,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp.json b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp.json
rename to adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp.json
index 81c89f55..3d5aff6c 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-gpp.json
+++ b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-gpp.json
@@ -87,7 +87,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-ignore-width-when-height-missing.json b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-ignore-width-when-height-missing.json
similarity index 98%
rename from adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-ignore-width-when-height-missing.json
rename to adapters/yahooAds/yahooAdstest/supplemental/simple-banner-ignore-width-when-height-missing.json
index 353d5e29..12060059 100644
--- a/adapters/yahooAdvertising/yahooAdvertisingtest/supplemental/simple-banner-ignore-width-when-height-missing.json
+++ b/adapters/yahooAds/yahooAdstest/supplemental/simple-banner-ignore-width-when-height-missing.json
@@ -78,7 +78,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "yahooAdvertising",
+              "seat": "yahooAds",
               "bid": [{
                 "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
                 "impid": "test-imp-id",
diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go
index 9d2a5c3c..2dd0fd04 100644
--- a/exchange/adapter_util_test.go
+++ b/exchange/adapter_util_test.go
@@ -210,7 +210,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"lifestreet":     `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
 				"adagio":         `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"somoaudience":   `Bidder "somoaudience" is no longer available in Prebid Server. Please update your configuration.`,
-				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAdvertising" in your configuration.`,
+				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAds" in your configuration.`,
 				"andbeyondmedia": `Bidder "andbeyondmedia" is no longer available in Prebid Server. If you're looking to use the AndBeyond.Media SSP adapter, please rename it to "beyondmedia" in your configuration.`,
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
@@ -224,7 +224,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"lifestreet":     `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
 				"adagio":         `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"somoaudience":   `Bidder "somoaudience" is no longer available in Prebid Server. Please update your configuration.`,
-				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAdvertising" in your configuration.`,
+				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAds" in your configuration.`,
 				"andbeyondmedia": `Bidder "andbeyondmedia" is no longer available in Prebid Server. If you're looking to use the AndBeyond.Media SSP adapter, please rename it to "beyondmedia" in your configuration.`,
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
 				"groupm":         `Bidder "groupm" is no longer available in Prebid Server. Please update your configuration.`,
@@ -238,7 +238,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"lifestreet":     `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
 				"adagio":         `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"somoaudience":   `Bidder "somoaudience" is no longer available in Prebid Server. Please update your configuration.`,
-				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAdvertising" in your configuration.`,
+				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAds" in your configuration.`,
 				"appnexus":       `Bidder "appnexus" has been disabled on this instance of Prebid Server. Please work with the PBS host to enable this bidder again.`,
 				"andbeyondmedia": `Bidder "andbeyondmedia" is no longer available in Prebid Server. If you're looking to use the AndBeyond.Media SSP adapter, please rename it to "beyondmedia" in your configuration.`,
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
@@ -253,7 +253,7 @@ func TestGetDisabledBiddersErrorMessages(t *testing.T) {
 				"lifestreet":     `Bidder "lifestreet" is no longer available in Prebid Server. Please update your configuration.`,
 				"adagio":         `Bidder "adagio" is no longer available in Prebid Server. Please update your configuration.`,
 				"somoaudience":   `Bidder "somoaudience" is no longer available in Prebid Server. Please update your configuration.`,
-				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAdvertising" in your configuration.`,
+				"yssp":           `Bidder "yssp" is no longer available in Prebid Server. If you're looking to use the Yahoo SSP adapter, please rename it to "yahooAds" in your configuration.`,
 				"appnexus":       `Bidder "appnexus" has been disabled on this instance of Prebid Server. Please work with the PBS host to enable this bidder again.`,
 				"andbeyondmedia": `Bidder "andbeyondmedia" is no longer available in Prebid Server. If you're looking to use the AndBeyond.Media SSP adapter, please rename it to "beyondmedia" in your configuration.`,
 				"oftmedia":       `Bidder "oftmedia" is no longer available in Prebid Server. Please update your configuration.`,
diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go
index 511fd84b..8306849a 100644
--- a/exchange/exchange_test.go
+++ b/exchange/exchange_test.go
@@ -2085,7 +2085,7 @@ func getTestBuildRequest(t *testing.T) *openrtb2.BidRequest {
 					H: 600,
 				}},
 			},
-			Ext: json.RawMessage(`{"ext_field":"value}"}`),
+			Ext: json.RawMessage(`{"prebid":{"bidder":{"appnexus": {"placementId": 1}}}}`),
 		}, {
 			Video: &openrtb2.Video{
 				MIMEs:       []string{"video/mp4"},
@@ -2094,7 +2094,7 @@ func getTestBuildRequest(t *testing.T) *openrtb2.BidRequest {
 				W:           300,
 				H:           600,
 			},
-			Ext: json.RawMessage(`{"ext_field":"value}"}`),
+			Ext: json.RawMessage(`{"prebid":{"bidder":{"appnexus": {"placementId": 1}}}}`),
 		}},
 	}
 }
@@ -3592,7 +3592,7 @@ func TestApplyDealSupport(t *testing.T) {
 		{
 			description:  "hb_pb_cat_dur should be modified",
 			dealPriority: 5,
-			impExt:       json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+			impExt:       json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_movies_30s",
 			},
@@ -3603,7 +3603,7 @@ func TestApplyDealSupport(t *testing.T) {
 		{
 			description:  "hb_pb_cat_dur should not be modified due to priority not exceeding min",
 			dealPriority: 9,
-			impExt:       json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 10, "prefix": "tier"}, "placementId": 10433394}}`),
+			impExt:       json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 10, "prefix": "tier"}, "placementId": 10433394}}}}`),
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_medicine_30s",
 			},
@@ -3614,7 +3614,7 @@ func TestApplyDealSupport(t *testing.T) {
 		{
 			description:  "hb_pb_cat_dur should not be modified due to invalid config",
 			dealPriority: 5,
-			impExt:       json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": ""}, "placementId": 10433394}}`),
+			impExt:       json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": ""}, "placementId": 10433394}}}}`),
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_games_30s",
 			},
@@ -3625,7 +3625,7 @@ func TestApplyDealSupport(t *testing.T) {
 		{
 			description:  "hb_pb_cat_dur should not be modified due to deal priority of 0",
 			dealPriority: 0,
-			impExt:       json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+			impExt:       json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 			targ: map[string]string{
 				"hb_pb_cat_dur": "12.00_auto_30s",
 			},
@@ -3695,11 +3695,11 @@ func TestApplyDealSupportMultiBid(t *testing.T) {
 					Imp: []openrtb2.Imp{
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 					},
 				},
@@ -3741,11 +3741,11 @@ func TestApplyDealSupportMultiBid(t *testing.T) {
 					Imp: []openrtb2.Imp{
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 					},
 				},
@@ -3792,11 +3792,11 @@ func TestApplyDealSupportMultiBid(t *testing.T) {
 					Imp: []openrtb2.Imp{
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 						{
 							ID:  "imp_id1",
-							Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}`),
+							Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}, "placementId": 10433394}}}}`),
 						},
 					},
 				},
@@ -3869,7 +3869,7 @@ func TestGetDealTiers(t *testing.T) {
 			description: "One",
 			request: openrtb2.BidRequest{
 				Imp: []openrtb2.Imp{
-					{ID: "imp1", Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}}}`)},
+					{ID: "imp1", Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier"}}}}}`)},
 				},
 			},
 			expected: map[string]openrtb_ext.DealTierBidderMap{
@@ -3880,8 +3880,8 @@ func TestGetDealTiers(t *testing.T) {
 			description: "Many",
 			request: openrtb2.BidRequest{
 				Imp: []openrtb2.Imp{
-					{ID: "imp1", Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier1"}}}`)},
-					{ID: "imp2", Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 8, "prefix": "tier2"}}}`)},
+					{ID: "imp1", Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier1"}}}}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 8, "prefix": "tier2"}}}}}`)},
 				},
 			},
 			expected: map[string]openrtb_ext.DealTierBidderMap{
@@ -3893,8 +3893,8 @@ func TestGetDealTiers(t *testing.T) {
 			description: "Many - Skips Malformed",
 			request: openrtb2.BidRequest{
 				Imp: []openrtb2.Imp{
-					{ID: "imp1", Ext: json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier1"}}}`)},
-					{ID: "imp2", Ext: json.RawMessage(`{"appnexus": {"dealTier": "wrong type"}}`)},
+					{ID: "imp1", Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "tier1"}}}}}`)},
+					{ID: "imp2", Ext: json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": "wrong type"}}}}`)},
 				},
 			},
 			expected: map[string]openrtb_ext.DealTierBidderMap{
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 8bb82fe4..973edc53 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -17,6 +17,7 @@ import (
 	"github.com/prebid/prebid-server/gdpr"
 	"github.com/prebid/prebid-server/metrics"
 	"github.com/prebid/prebid-server/openrtb_ext"
+	"github.com/prebid/prebid-server/privacy"
 	"github.com/prebid/prebid-server/util/ptrutil"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/mock"
@@ -505,7 +506,7 @@ func TestCleanOpenRTBRequestsWithFPD(t *testing.T) {
 		App:  &openrtb2.App{Name: "fpdApnApp"},
 		User: &openrtb2.User{Keywords: "fpdApnUser"},
 	}
-	fpd[openrtb_ext.BidderName("appnexus")] = &apnFpd
+	fpd[openrtb_ext.BidderName("rubicon")] = &apnFpd
 
 	brightrollFpd := firstpartydata.ResolvedFirstPartyData{
 		Site: &openrtb2.Site{Name: "fpdBrightrollSite"},
@@ -4273,3 +4274,72 @@ func TestGetMediaTypeForBid(t *testing.T) {
 		})
 	}
 }
+
+func TemporarilyDisabledTestCleanOpenRTBRequestsActivitiesFetchBids(t *testing.T) {
+	testCases := []struct {
+		name              string
+		req               *openrtb2.BidRequest
+		componentName     string
+		allow             bool
+		expectedReqNumber int
+	}{
+		{
+			name:              "request_with_one_bidder_allowed",
+			req:               newBidRequest(t),
+			componentName:     "appnexus",
+			allow:             true,
+			expectedReqNumber: 1,
+		},
+		{
+			name:              "request_with_one_bidder_not_allowed",
+			req:               newBidRequest(t),
+			componentName:     "appnexus",
+			allow:             false,
+			expectedReqNumber: 0,
+		},
+	}
+
+	for _, test := range testCases {
+		privacyConfig := getDefaultActivityConfig(test.componentName, test.allow)
+		activities, err := privacy.NewActivityControl(privacyConfig)
+		assert.NoError(t, err, "")
+		auctionReq := AuctionRequest{
+			BidRequestWrapper: &openrtb_ext.RequestWrapper{BidRequest: test.req},
+			UserSyncs:         &emptyUsersync{},
+			Activities:        activities,
+		}
+
+		bidderToSyncerKey := map[string]string{}
+		reqSplitter := &requestSplitter{
+			bidderToSyncerKey: bidderToSyncerKey,
+			me:                &metrics.MetricsEngineMock{},
+			hostSChainNode:    nil,
+			bidderInfo:        config.BidderInfos{},
+		}
+
+		t.Run(test.name, func(t *testing.T) {
+			bidderRequests, _, errs := reqSplitter.cleanOpenRTBRequests(context.Background(), auctionReq, nil, gdpr.SignalNo)
+			assert.Empty(t, errs)
+			assert.Len(t, bidderRequests, test.expectedReqNumber)
+		})
+	}
+}
+
+func getDefaultActivityConfig(componentName string, allow bool) *config.AccountPrivacy {
+	return &config.AccountPrivacy{
+		AllowActivities: config.AllowActivities{
+			FetchBids: config.Activity{
+				Default: ptrutil.ToPtr(true),
+				Rules: []config.ActivityRule{
+					{
+						Allow: allow,
+						Condition: config.ActivityCondition{
+							ComponentName: []string{componentName},
+							ComponentType: []string{"bidder"},
+						},
+					},
+				},
+			},
+		},
+	}
+}
diff --git a/openrtb_ext/bidders_validate_test.go b/openrtb_ext/bidders_validate_test.go
index 530f260c..87a8c96d 100644
--- a/openrtb_ext/bidders_validate_test.go
+++ b/openrtb_ext/bidders_validate_test.go
@@ -50,7 +50,7 @@ func TestBidderUniquenessGatekeeping(t *testing.T) {
 	// - Exclude duplicates of adapters for the same bidder, as it's unlikely a publisher will use both.
 	var bidders []string
 	for _, bidder := range CoreBidderNames() {
-		if bidder != BidderTripleliftNative && bidder != BidderAdkernelAdn && bidder != BidderFreewheelSSPOld {
+		if bidder != BidderTripleliftNative && bidder != BidderAdkernelAdn && bidder != BidderFreewheelSSPOld && bidder != BidderYahooAdvertising {
 			bidders = append(bidders, string(bidder))
 		}
 	}
diff --git a/openrtb_ext/deal_tier_test.go b/openrtb_ext/deal_tier_test.go
index 6aaebbab..0046b788 100644
--- a/openrtb_ext/deal_tier_test.go
+++ b/openrtb_ext/deal_tier_test.go
@@ -31,55 +31,50 @@ func TestReadDealTiersFromImp(t *testing.T) {
 			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:    "imp.ext - with other params",
-			impExt:         json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "anyPrefix"}, "placementId": 12345}}`),
-			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "anyPrefix", MinDealTier: 5}},
+			description:    "imp.ext - no prebid but with other params",
+			impExt:         json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "anyPrefix"}, "placementId": 12345}, "tid": "1234"}`),
+			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:    "imp.ext - multiple",
-			impExt:         json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "appnexusPrefix"}, "placementId": 12345}, "rubicon": {"dealTier": {"minDealTier": 8, "prefix": "rubiconPrefix"}, "placementId": 12345}}`),
-			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "appnexusPrefix", MinDealTier: 5}, BidderRubicon: {Prefix: "rubiconPrefix", MinDealTier: 8}},
+			description:    "imp.ext.prebid - nil",
+			impExt:         json.RawMessage(`{"prebid": null}`),
+			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:    "imp.ext - no deal tier",
-			impExt:         json.RawMessage(`{"appnexus": {"placementId": 12345}}`),
+			description:    "imp.ext.prebid - empty",
+			impExt:         json.RawMessage(`{"prebid": {}}`),
 			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:   "imp.ext - error",
-			impExt:        json.RawMessage(`{"appnexus": {"dealTier": "wrong type", "placementId": 12345}}`),
-			expectedError: "json: cannot unmarshal string into Go struct field .dealTier of type openrtb_ext.DealTier",
+			description:    "imp.ext.prebid - no bidder but with other params",
+			impExt:         json.RawMessage(`{"prebid": {"supportdeals": true}}`),
+			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:    "imp.ext.prebid",
+			description:    "imp.ext.prebid.bidder - one",
 			impExt:         json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "anyPrefix"}, "placementId": 12345}}}}`),
 			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "anyPrefix", MinDealTier: 5}},
 		},
 		{
-			description:    "imp.ext.prebid- multiple",
+			description:    "imp.ext.prebid.bidder - one with other params",
+			impExt:         json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "anyPrefix"}, "placementId": 12345}}, "supportdeals": true}, "tid": "1234"}`),
+			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "anyPrefix", MinDealTier: 5}},
+		},
+		{
+			description:    "imp.ext.prebid.bidder - multiple",
 			impExt:         json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "appnexusPrefix"}, "placementId": 12345}, "rubicon": {"dealTier": {"minDealTier": 8, "prefix": "rubiconPrefix"}, "placementId": 12345}}}}`),
 			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "appnexusPrefix", MinDealTier: 5}, BidderRubicon: {Prefix: "rubiconPrefix", MinDealTier: 8}},
 		},
 		{
-			description:    "imp.ext.prebid - no deal tier",
+			description:    "imp.ext.prebid.bidder - one without deal tier",
 			impExt:         json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"placementId": 12345}}}}`),
 			expectedResult: DealTierBidderMap{},
 		},
 		{
-			description:   "imp.ext.prebid - error",
+			description:   "imp.ext.prebid.bidder - error",
 			impExt:        json.RawMessage(`{"prebid": {"bidder": {"appnexus": {"dealTier": "wrong type", "placementId": 12345}}}}`),
 			expectedError: "json: cannot unmarshal string into Go struct field .prebid.bidder.dealTier of type openrtb_ext.DealTier",
 		},
-		{
-			description:    "imp.ext.prebid wins over imp.ext",
-			impExt:         json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "impExt"}, "placementId": 12345}, "prebid": {"bidder": {"appnexus": {"dealTier": {"minDealTier": 8, "prefix": "impExtPrebid"}, "placementId": 12345}}}}`),
-			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "impExtPrebid", MinDealTier: 8}},
-		},
-		{
-			description:    "imp.ext.prebid coexists with imp.ext",
-			impExt:         json.RawMessage(`{"appnexus": {"dealTier": {"minDealTier": 5, "prefix": "impExt"}, "placementId": 12345}, "prebid": {"bidder": {"rubicon": {"dealTier": {"minDealTier": 8, "prefix": "impExtPrebid"}, "placementId": 12345}}}}`),
-			expectedResult: DealTierBidderMap{BidderAppnexus: {Prefix: "impExt", MinDealTier: 5}, BidderRubicon: {Prefix: "impExtPrebid", MinDealTier: 8}},
-		},
 	}
 
 	for _, test := range testCases {
diff --git a/privacy/enforcer_test.go b/privacy/enforcer_test.go
index b0c4032c..e87a9eb2 100644
--- a/privacy/enforcer_test.go
+++ b/privacy/enforcer_test.go
@@ -1,18 +1,427 @@
 package privacy
 
 import (
-	"testing"
-
+	"errors"
+	"github.com/prebid/prebid-server/config"
+	"github.com/prebid/prebid-server/util/ptrutil"
 	"github.com/stretchr/testify/assert"
+	"testing"
 )
 
-func TestNilEnforcerCanEnforce(t *testing.T) {
-	nilEnforcer := &NilPolicyEnforcer{}
-	assert.False(t, nilEnforcer.CanEnforce())
+func TemporarilyDisabledTestNewActivityControl(t *testing.T) {
+
+	testCases := []struct {
+		name            string
+		privacyConf     *config.AccountPrivacy
+		activityControl ActivityControl
+		err             error
+	}{
+		{
+			name:            "privacy_config_is_nil",
+			privacyConf:     nil,
+			activityControl: ActivityControl{plans: nil},
+			err:             nil,
+		},
+		{
+			name: "privacy_config_is_specified_and_correct",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					SyncUser:                 getDefaultActivityConfig(),
+					FetchBids:                getDefaultActivityConfig(),
+					EnrichUserFPD:            getDefaultActivityConfig(),
+					ReportAnalytics:          getDefaultActivityConfig(),
+					TransmitUserFPD:          getDefaultActivityConfig(),
+					TransmitPreciseGeo:       getDefaultActivityConfig(),
+					TransmitUniqueRequestIds: getDefaultActivityConfig(),
+					TransmitTids:             getDefaultActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: map[Activity]ActivityPlan{
+				ActivitySyncUser:                 getDefaultActivityPlan(),
+				ActivityFetchBids:                getDefaultActivityPlan(),
+				ActivityEnrichUserFPD:            getDefaultActivityPlan(),
+				ActivityReportAnalytics:          getDefaultActivityPlan(),
+				ActivityTransmitUserFPD:          getDefaultActivityPlan(),
+				ActivityTransmitPreciseGeo:       getDefaultActivityPlan(),
+				ActivityTransmitUniqueRequestIds: getDefaultActivityPlan(),
+				ActivityTransmitTids:             getDefaultActivityPlan(),
+			}},
+			err: nil,
+		},
+		{
+			name: "privacy_config_is_specified_and_SyncUser_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					SyncUser: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_FetchBids_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					FetchBids: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_EnrichUserFPD_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					EnrichUserFPD: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_ReportAnalytics_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					ReportAnalytics: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_TransmitUserFPD_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					TransmitUserFPD: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_TransmitPreciseGeo_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					TransmitPreciseGeo: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_TransmitUniqueRequestIds_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					TransmitUniqueRequestIds: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name: "privacy_config_is_specified_and_TransmitTids_is_incorrect",
+			privacyConf: &config.AccountPrivacy{
+				AllowActivities: config.AllowActivities{
+					TransmitTids: getIncorrectActivityConfig(),
+				},
+			},
+			activityControl: ActivityControl{plans: nil},
+			err:             errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			actualAC, actualErr := NewActivityControl(test.privacyConf)
+			if test.err == nil {
+				assert.Equal(t, test.activityControl, actualAC)
+				assert.NoError(t, actualErr)
+			} else {
+				assert.EqualError(t, actualErr, test.err.Error())
+			}
+		})
+	}
+}
+
+func TestActivityDefaultToDefaultResult(t *testing.T) {
+
+	testCases := []struct {
+		name            string
+		activityDefault *bool
+		expectedResult  ActivityResult
+	}{
+		{
+			name:            "activityDefault_is_nil",
+			activityDefault: nil,
+			expectedResult:  ActivityAllow,
+		},
+		{
+			name:            "activityDefault_is_true",
+			activityDefault: ptrutil.ToPtr(true),
+			expectedResult:  ActivityAllow,
+		},
+		{
+			name:            "activityDefault_is_false",
+			activityDefault: ptrutil.ToPtr(false),
+			expectedResult:  ActivityDeny,
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			actualResult := activityDefaultToDefaultResult(test.activityDefault)
+			assert.Equal(t, test.expectedResult, actualResult)
+		})
+	}
+}
+
+func TestAllowActivityControl(t *testing.T) {
+
+	testCases := []struct {
+		name            string
+		activityControl ActivityControl
+		activity        Activity
+		target          ScopedName
+		activityResult  ActivityResult
+	}{
+		{
+			name:            "plans_is_nil",
+			activityControl: ActivityControl{plans: nil},
+			activity:        ActivityFetchBids,
+			target:          ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult:  ActivityAbstain,
+		},
+		{
+			name: "activity_not_defined",
+			activityControl: ActivityControl{plans: map[Activity]ActivityPlan{
+				ActivitySyncUser: getDefaultActivityPlan()}},
+			activity:       ActivityFetchBids,
+			target:         ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult: ActivityAbstain,
+		},
+		{
+			name: "activity_defined_but_not_found_default_returned",
+			activityControl: ActivityControl{plans: map[Activity]ActivityPlan{
+				ActivityFetchBids: getDefaultActivityPlan()}},
+			activity:       ActivityFetchBids,
+			target:         ScopedName{Scope: "bidder", Name: "bidderB"},
+			activityResult: ActivityAllow,
+		},
+		{
+			name: "activity_defined_and_allowed",
+			activityControl: ActivityControl{plans: map[Activity]ActivityPlan{
+				ActivityFetchBids: getDefaultActivityPlan()}},
+			activity:       ActivityFetchBids,
+			target:         ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult: ActivityAllow,
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			actualResult := test.activityControl.Allow(test.activity, test.target)
+			assert.Equal(t, test.activityResult, actualResult)
+
+		})
+	}
+}
+
+func TestAllowComponentEnforcementRule(t *testing.T) {
+
+	testCases := []struct {
+		name           string
+		componentRule  ComponentEnforcementRule
+		target         ScopedName
+		activityResult ActivityResult
+	}{
+		{
+			name: "activity_is_allowed",
+			componentRule: ComponentEnforcementRule{
+				allowed: true,
+				componentName: []ScopedName{
+					{Scope: "bidder", Name: "bidderA"},
+				},
+				componentType: []string{"bidder"},
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult: ActivityAllow,
+		},
+		{
+			name: "activity_is_not_allowed",
+			componentRule: ComponentEnforcementRule{
+				allowed: false,
+				componentName: []ScopedName{
+					{Scope: "bidder", Name: "bidderA"},
+				},
+				componentType: []string{"bidder"},
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult: ActivityDeny,
+		},
+		{
+			name: "abstain_both_clauses_do_not_match",
+			componentRule: ComponentEnforcementRule{
+				allowed: true,
+				componentName: []ScopedName{
+					{Scope: "bidder", Name: "bidderA"},
+				},
+				componentType: []string{"bidder"},
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderB"},
+			activityResult: ActivityAbstain,
+		},
+		{
+			name: "activity_is_not_allowed_componentName_only",
+			componentRule: ComponentEnforcementRule{
+				allowed: true,
+				componentName: []ScopedName{
+					{Scope: "bidder", Name: "bidderA"},
+				},
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderA"},
+			activityResult: ActivityAllow,
+		},
+		{
+			name: "activity_is_allowed_componentType_only",
+			componentRule: ComponentEnforcementRule{
+				allowed:       true,
+				componentType: []string{"bidder"},
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderB"},
+			activityResult: ActivityAllow,
+		},
+		{
+			name: "abstain_activity_no_componentType_and_no_componentName",
+			componentRule: ComponentEnforcementRule{
+				allowed: true,
+			},
+			target:         ScopedName{Scope: "bidder", Name: "bidderB"},
+			activityResult: ActivityAbstain,
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			actualResult := test.componentRule.Allow(test.target)
+			assert.Equal(t, test.activityResult, actualResult)
+
+		})
+	}
+}
+
+func TestNewScopedName(t *testing.T) {
+
+	testCases := []struct {
+		name              string
+		condition         string
+		expectedScopeName ScopedName
+		err               error
+	}{
+		{
+			name:              "condition_is_empty",
+			condition:         "",
+			expectedScopeName: ScopedName{},
+			err:               errors.New("unable to parse empty condition"),
+		},
+		{
+			name:              "condition_is_incorrect",
+			condition:         "bidder.bidderA.bidderB",
+			expectedScopeName: ScopedName{},
+			err:               errors.New("unable to parse condition: bidder.bidderA.bidderB"),
+		},
+		{
+			name:              "condition_is_scoped_to_bidder",
+			condition:         "bidder.bidderA",
+			expectedScopeName: ScopedName{Scope: "bidder", Name: "bidderA"},
+			err:               nil,
+		},
+		{
+			name:              "condition_is_scoped_to_analytics",
+			condition:         "analytics.bidderA",
+			expectedScopeName: ScopedName{Scope: "analytics", Name: "bidderA"},
+			err:               nil,
+		},
+		{
+			name:              "condition_is_scoped_to_userid",
+			condition:         "userid.bidderA",
+			expectedScopeName: ScopedName{Scope: "userid", Name: "bidderA"},
+			err:               nil,
+		},
+		{
+			name:              "condition_is_bidder_name",
+			condition:         "bidderA",
+			expectedScopeName: ScopedName{Scope: "bidder", Name: "bidderA"},
+			err:               nil,
+		},
+		{
+			name:              "condition_is_module_tag_rtd",
+			condition:         "rtd.test",
+			expectedScopeName: ScopedName{Scope: "rtd", Name: "test"},
+			err:               nil,
+		},
+		{
+			name:              "condition_scope_defaults_to_genera",
+			condition:         "test.test",
+			expectedScopeName: ScopedName{Scope: "general", Name: "test"},
+			err:               nil,
+		},
+	}
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			actualSN, actualErr := NewScopedName(test.condition)
+			if test.err == nil {
+				assert.Equal(t, test.expectedScopeName, actualSN)
+				assert.NoError(t, actualErr)
+			} else {
+				assert.EqualError(t, actualErr, test.err.Error())
+			}
+		})
+	}
+}
+
+// constants
+func getDefaultActivityConfig() config.Activity {
+	return config.Activity{
+		Default: ptrutil.ToPtr(true),
+		Rules: []config.ActivityRule{
+			{
+				Allow: true,
+				Condition: config.ActivityCondition{
+					ComponentName: []string{"bidderA"},
+					ComponentType: []string{"bidder"},
+				},
+			},
+		},
+	}
+}
+
+func getDefaultActivityPlan() ActivityPlan {
+	return ActivityPlan{
+		defaultResult: ActivityAllow,
+		rules: []ActivityRule{
+			ComponentEnforcementRule{
+				allowed: true,
+				componentName: []ScopedName{
+					{Scope: "bidder", Name: "bidderA"},
+				},
+				componentType: []string{"bidder"},
+			},
+		},
+	}
 }
 
-func TestNilEnforcerShouldEnforce(t *testing.T) {
-	nilEnforcer := &NilPolicyEnforcer{}
-	assert.False(t, nilEnforcer.ShouldEnforce(""))
-	assert.False(t, nilEnforcer.ShouldEnforce("anyBidder"))
+func getIncorrectActivityConfig() config.Activity {
+	return config.Activity{
+		Default: ptrutil.ToPtr(true),
+		Rules: []config.ActivityRule{
+			{
+				Allow: true,
+				Condition: config.ActivityCondition{
+					ComponentName: []string{"bidder.bidderA.bidderB"},
+					ComponentType: []string{"bidder"},
+				},
+			},
+		},
+	}
 }
diff --git a/privacy/policyenforcer_test.go b/privacy/policyenforcer_test.go
new file mode 100644
index 00000000..b0c4032c
--- /dev/null
+++ b/privacy/policyenforcer_test.go
@@ -0,0 +1,18 @@
+package privacy
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNilEnforcerCanEnforce(t *testing.T) {
+	nilEnforcer := &NilPolicyEnforcer{}
+	assert.False(t, nilEnforcer.CanEnforce())
+}
+
+func TestNilEnforcerShouldEnforce(t *testing.T) {
+	nilEnforcer := &NilPolicyEnforcer{}
+	assert.False(t, nilEnforcer.ShouldEnforce(""))
+	assert.False(t, nilEnforcer.ShouldEnforce("anyBidder"))
+}