Repository: prebid/prebid-server
Pull request #2112 (2021-12-15 14:14:20)

Adnuntius: Read device information from ortb Request
This PR would make it possible for the requesting source to send device information to our adserver that would be used for geo-targeting and device targeting.


Patch:
diff --git a/adapters/adnuntius/adnuntius.go b/adapters/adnuntius/adnuntius.go
index f556081a..da66e443 100644
--- a/adapters/adnuntius/adnuntius.go
+++ b/adapters/adnuntius/adnuntius.go
@@ -74,10 +74,19 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E
 	return a.generateRequests(*request)
 }
 
-func setHeaders() http.Header {
+func setHeaders(ortbRequest openrtb2.BidRequest) http.Header {
+
 	headers := http.Header{}
 	headers.Add("Content-Type", "application/json;charset=utf-8")
 	headers.Add("Accept", "application/json")
+	if ortbRequest.Device != nil {
+		if ortbRequest.Device.IP != "" {
+			headers.Add("X-Forwarded-For", ortbRequest.Device.IP)
+		}
+		if ortbRequest.Device.UA != "" {
+			headers.Add("user-agent", ortbRequest.Device.UA)
+		}
+	}
 	return headers
 }
 
@@ -113,7 +122,7 @@ func makeEndpointUrl(ortbRequest openrtb2.BidRequest, a *adapter) (string, []err
 func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters.RequestData, []error) {
 	var requestData []*adapters.RequestData
 	networkAdunitMap := make(map[string][]adnAdunit)
-	headers := setHeaders()
+	headers := setHeaders(ortbRequest)
 
 	endpoint, err := makeEndpointUrl(ortbRequest, a)
 	if err != nil {
diff --git a/adapters/algorix/algorix.go b/adapters/algorix/algorix.go
index 31d01349..628207d6 100644
--- a/adapters/algorix/algorix.go
+++ b/adapters/algorix/algorix.go
@@ -90,10 +90,22 @@ func getImpAlgoriXExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpAlgorix, error) {
 	return &extImpAlgoriX, nil
 }
 
+func getRegionInfo(region string) string {
+	switch region {
+	case "APAC":
+		return "apac.xyz"
+	case "USE":
+		return "use.xyz"
+	default:
+		return "xyz"
+	}
+}
+
 func (a *adapter) getEndPoint(ext *openrtb_ext.ExtImpAlgorix) (string, error) {
 	endPointParams := macros.EndpointTemplateParams{
 		SourceId:  url.PathEscape(ext.Sid),
 		AccountID: url.PathEscape(ext.Token),
+		Host:      url.PathEscape(getRegionInfo(ext.Region)),
 	}
 	return macros.ResolveMacros(a.EndpointTemplate, endPointParams)
 }
diff --git a/adapters/apacdex/apacdex.go b/adapters/apacdex/apacdex.go
new file mode 100644
index 00000000..294b7188
--- /dev/null
+++ b/adapters/apacdex/apacdex.go
@@ -0,0 +1,161 @@
+package apacdex
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb/v15/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
+}
+
+// Builder builds a new instance of the Apacdex adapter for the given bidder with the given config.
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var errs []error
+	var adapterRequests []*adapters.RequestData
+
+	if err := preprocess(request); err != nil {
+		errs = append(errs, err)
+		return nil, errs
+	}
+
+	adapterReq, err := a.makeRequest(request)
+	if err != nil {
+		errs = append(errs, err)
+		return nil, errs
+	}
+
+	adapterRequests = append(adapterRequests, adapterReq)
+
+	return adapterRequests, errs
+}
+
+func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) {
+	var err error
+
+	jsonBody, err := json.Marshal(request)
+	if err != nil {
+		return nil, err
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	headers.Add("x-openrtb-version", "2.5")
+
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    jsonBody,
+		Headers: headers,
+	}, nil
+}
+
+func preprocess(request *openrtb2.BidRequest) error {
+	if len(request.Imp) == 0 {
+		return &errortypes.BadInput{
+			Message: "No Imps in Bid Request",
+		}
+	}
+	for i := 0; i < len(request.Imp); i++ {
+		var imp = &request.Imp[i]
+		var bidderExt adapters.ExtImpBidder
+
+		if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
+			return &errortypes.BadInput{
+				Message: err.Error(),
+			}
+		}
+
+		var extImp openrtb_ext.ExtImpApacdex
+		if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil {
+			return &errortypes.BadInput{
+				Message: err.Error(),
+			}
+		}
+
+		imp.Ext = bidderExt.Bidder
+	}
+
+	return nil
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if responseData.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if responseData.StatusCode == http.StatusBadRequest {
+		err := &errortypes.BadInput{
+			Message: "Unexpected status code: 400. Bad request from publisher. Run with request.debug = 1 for more info.",
+		}
+		return nil, []error{err}
+	}
+
+	if responseData.StatusCode != http.StatusOK {
+		err := &errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
+		}
+		return nil, []error{err}
+	}
+
+	var response openrtb2.BidResponse
+
+	if err := json.Unmarshal(responseData.Body, &response); err != nil {
+		return nil, []error{&errortypes.BadServerResponse{
+			Message: err.Error(),
+		}}
+	}
+
+	if len(response.SeatBid) == 0 {
+		return nil, nil
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+	bidResponse.Currency = response.Cur
+	var errors []error
+
+	for _, seatbid := range response.SeatBid {
+		for _, bid := range seatbid.Bid {
+			bidType, err := getMediaTypeForBid(bid)
+			if err != nil {
+				errors = append(errors, err)
+				continue
+			}
+			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
+				Bid:     &bid,
+				BidType: bidType,
+			})
+		}
+	}
+	return bidResponse, errors
+}
+
+// getMediaTypeForBid determines which type of bid.
+func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
+	if bid.Ext != nil {
+		var bidExt openrtb_ext.ExtBid
+		err := json.Unmarshal(bid.Ext, &bidExt)
+		if err == nil && bidExt.Prebid != nil {
+			return openrtb_ext.ParseBidType(string(bidExt.Prebid.Type))
+		}
+	}
+
+	return "", &errortypes.BadServerResponse{
+		Message: fmt.Sprintf("Failed to parse bid mediatype for impression \"%s\"", bid.ImpID),
+	}
+}
diff --git a/adapters/compass/compass.go b/adapters/compass/compass.go
new file mode 100644
index 00000000..eed84657
--- /dev/null
+++ b/adapters/compass/compass.go
@@ -0,0 +1,154 @@
+package compass
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"github.com/mxmCherry/openrtb/v15/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
+}
+
+type reqBodyExt struct {
+	CompassBidderExt reqBodyExtBidder `json:"bidder"`
+}
+
+type reqBodyExtBidder struct {
+	Type        string `json:"type"`
+	PlacementID string `json:"placementId,omitempty"`
+	EndpointID  string `json:"endpointId,omitempty"`
+}
+
+func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+	bidder := &adapter{
+		endpoint: config.Endpoint,
+	}
+	return bidder, nil
+}
+
+func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
+	var err error
+	var adapterRequests []*adapters.RequestData
+
+	reqCopy := *request
+	for _, imp := range request.Imp {
+		reqCopy.Imp = []openrtb2.Imp{imp}
+
+		var bidderExt adapters.ExtImpBidder
+		var compassExt openrtb_ext.ImpExtCompass
+
+		if err = json.Unmarshal(reqCopy.Imp[0].Ext, &bidderExt); err != nil {
+			return nil, []error{err}
+		}
+		if err = json.Unmarshal(bidderExt.Bidder, &compassExt); err != nil {
+			return nil, []error{err}
+		}
+
+		temp := reqBodyExt{CompassBidderExt: reqBodyExtBidder{}}
+
+		if compassExt.PlacementID != "" {
+			temp.CompassBidderExt.PlacementID = compassExt.PlacementID
+			temp.CompassBidderExt.Type = "publisher"
+		} else if compassExt.EndpointID != "" {
+			temp.CompassBidderExt.EndpointID = compassExt.EndpointID
+			temp.CompassBidderExt.Type = "network"
+		}
+
+		finalyImpExt, err := json.Marshal(temp)
+		if err != nil {
+			return nil, []error{err}
+		}
+
+		reqCopy.Imp[0].Ext = finalyImpExt
+
+		adapterReq, err := a.makeRequest(&reqCopy)
+		if err != nil {
+			return nil, []error{err}
+		}
+
+		if adapterReq != nil {
+			adapterRequests = append(adapterRequests, adapterReq)
+		}
+	}
+	return adapterRequests, nil
+}
+
+func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) {
+	reqJSON, err := json.Marshal(request)
+	if err != nil {
+		return nil, err
+	}
+
+	headers := http.Header{}
+	headers.Add("Content-Type", "application/json;charset=utf-8")
+	headers.Add("Accept", "application/json")
+	return &adapters.RequestData{
+		Method:  "POST",
+		Uri:     a.endpoint,
+		Body:    reqJSON,
+		Headers: headers,
+	}, err
+}
+
+func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+	if responseData.StatusCode == http.StatusNoContent {
+		return nil, nil
+	}
+
+	if responseData.StatusCode != http.StatusOK {
+		err := &errortypes.BadServerResponse{
+			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
+		}
+		return nil, []error{err}
+	}
+
+	var response openrtb2.BidResponse
+	if err := json.Unmarshal(responseData.Body, &response); err != nil {
+		return nil, []error{err}
+	}
+
+	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
+	bidResponse.Currency = response.Cur
+	for _, seatBid := range response.SeatBid {
+		for i := range seatBid.Bid {
+			bidType, err := getMediaTypeForImp(seatBid.Bid[i].ImpID, request.Imp)
+			if err != nil {
+				return nil, []error{err}
+			}
+
+			b := &adapters.TypedBid{
+				Bid:     &seatBid.Bid[i],
+				BidType: bidType,
+			}
+			bidResponse.Bids = append(bidResponse.Bids, b)
+		}
+	}
+	return bidResponse, nil
+}
+
+func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
+	for _, imp := range imps {
+		if imp.ID == impID {
+			if imp.Banner != nil {
+				return openrtb_ext.BidTypeBanner, nil
+			}
+			if imp.Video != nil {
+				return openrtb_ext.BidTypeVideo, nil
+			}
+			if imp.Native != nil {
+				return openrtb_ext.BidTypeNative, nil
+			}
+		}
+	}
+
+	return "", &errortypes.BadInput{
+		Message: fmt.Sprintf("Failed to find impression \"%s\"", impID),
+	}
+}
diff --git a/adapters/marsmedia/marsmedia.go b/adapters/marsmedia/marsmedia.go
index 0f4fad5a..65ffff25 100644
--- a/adapters/marsmedia/marsmedia.go
+++ b/adapters/marsmedia/marsmedia.go
@@ -83,7 +83,7 @@ func (a *MarsmediaAdapter) MakeRequests(requestIn *openrtb2.BidRequest, reqInfo
 		}}
 	}
 
-	uri := a.URI + "&zone=" + marsmediaExt.ZoneID
+	uri := a.URI + "&zone=" + marsmediaExt.ZoneID.String()
 	headers := http.Header{}
 	headers.Add("Content-Type", "application/json;charset=utf-8")
 	headers.Add("Accept", "application/json")
diff --git a/adapters/openrtb_util.go b/adapters/openrtb_util.go
index 5587cac7..2816e730 100644
--- a/adapters/openrtb_util.go
+++ b/adapters/openrtb_util.go
@@ -4,11 +4,12 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+
 	"github.com/mxmCherry/openrtb/v15/openrtb2"
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-func ExtractAdapterReqBidderParams(bidRequest *openrtb2.BidRequest) (map[string]json.RawMessage, error) {
+func ExtractReqExtBidderParamsMap(bidRequest *openrtb2.BidRequest) (map[string]json.RawMessage, error) {
 	if bidRequest == nil {
 		return nil, errors.New("error bidRequest should not be nil")
 	}
@@ -34,15 +35,14 @@ func ExtractAdapterReqBidderParams(bidRequest *openrtb2.BidRequest) (map[string]
 	return bidderParams, nil
 }
 
-func ExtractReqExtBidderParams(bidReq *openrtb2.BidRequest) (map[string]map[string]json.RawMessage, error) {
-	if bidReq == nil {
+func ExtractReqExtBidderParamsEmbeddedMap(bidRequest *openrtb2.BidRequest) (map[string]map[string]json.RawMessage, error) {
+	if bidRequest == nil {
 		return nil, errors.New("error bidRequest should not be nil")
 	}
 
 	reqExt := &openrtb_ext.ExtRequest{}
-	if len(bidReq.Ext) > 0 {
-		err := json.Unmarshal(bidReq.Ext, &reqExt)
-		if err != nil {
+	if len(bidRequest.Ext) > 0 {
+		if err := json.Unmarshal(bidRequest.Ext, &reqExt); err != nil {
 			return nil, fmt.Errorf("error decoding Request.ext : %s", err.Error())
 		}
 	}
@@ -52,8 +52,7 @@ func ExtractReqExtBidderParams(bidReq *openrtb2.BidRequest) (map[string]map[stri
 	}
 
 	var bidderParams map[string]map[string]json.RawMessage
-	err := json.Unmarshal(reqExt.Prebid.BidderParams, &bidderParams)
-	if err != nil {
+	if err := json.Unmarshal(reqExt.Prebid.BidderParams, &bidderParams); err != nil {
 		return nil, err
 	}
 
diff --git a/adapters/orbidder/orbidder.go b/adapters/orbidder/orbidder.go
index 77985c8d..f2dda85e 100644
--- a/adapters/orbidder/orbidder.go
+++ b/adapters/orbidder/orbidder.go
@@ -3,13 +3,13 @@ package orbidder
 import (
 	"encoding/json"
 	"fmt"
-	"net/http"
-
 	"github.com/mxmCherry/openrtb/v15/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"
+	"net/http"
+	"strings"
 )
 
 type OrbidderAdapter struct {
@@ -18,30 +18,11 @@ type OrbidderAdapter struct {
 
 // MakeRequests makes the HTTP requests which should be made to fetch bids from orbidder.
 func (rcv *OrbidderAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
-	var errs []error
-	var validImps []openrtb2.Imp
-
-	// check if imps exists, if not return error and do send request to orbidder.
-	if len(request.Imp) == 0 {
-		return nil, []error{&errortypes.BadInput{
-			Message: "No impressions in request",
-		}}
-	}
-
-	// validate imps
-	for _, imp := range request.Imp {
-		if err := preprocess(&imp); err != nil {
-			errs = append(errs, err)
-			continue
-		}
-		validImps = append(validImps, imp)
-	}
-
+	validImps, errs := getValidImpressions(request, reqInfo)
 	if len(validImps) == 0 {
 		return nil, errs
 	}
 
-	//set imp array to only valid imps
 	request.Imp = validImps
 
 	requestBodyJSON, err := json.Marshal(request)
@@ -55,14 +36,34 @@ func (rcv *OrbidderAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *
 	headers.Add("Accept", "application/json")
 
 	return []*adapters.RequestData{{
-		Method:  "POST",
+		Method:  http.MethodPost,
 		Uri:     rcv.endpoint,
 		Body:    requestBodyJSON,
 		Headers: headers,
 	}}, errs
 }
 
-func preprocess(imp *openrtb2.Imp) error {
+// getValidImpressions validate imps and check for bid floor currency. Convert to EUR if necessary
+func getValidImpressions(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]openrtb2.Imp, []error) {
+	var errs []error
+	var validImps []openrtb2.Imp
+
+	for _, imp := range request.Imp {
+		if err := preprocessBidFloorCurrency(&imp, reqInfo); err != nil {
+			errs = append(errs, err)
+			continue
+		}
+
+		if err := preprocessExtensions(&imp); err != nil {
+			errs = append(errs, err)
+			continue
+		}
+		validImps = append(validImps, imp)
+	}
+	return validImps, errs
+}
+
+func preprocessExtensions(imp *openrtb2.Imp) error {
 	var bidderExt adapters.ExtImpBidder
 	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
 		return &errortypes.BadInput{
@@ -80,8 +81,21 @@ func preprocess(imp *openrtb2.Imp) error {
 	return nil
 }
 
+func preprocessBidFloorCurrency(imp *openrtb2.Imp, reqInfo *adapters.ExtraRequestInfo) error {
+	// we expect every currency related data to be EUR
+	if imp.BidFloor > 0 && strings.ToUpper(imp.BidFloorCur) != "EUR" && imp.BidFloorCur != "" {
+		if convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "EUR"); err != nil {
+			return err
+		} else {
+			imp.BidFloor = convertedValue
+		}
+	}
+	imp.BidFloorCur = "EUR"
+	return nil
+}
+
 // MakeBids unpacks server response into Bids.
-func (rcv OrbidderAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
+func (rcv OrbidderAdapter) MakeBids(_ *openrtb2.BidRequest, _ *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
 	if response.StatusCode == http.StatusNoContent {
 		return nil, nil
 	}
@@ -125,7 +139,7 @@ func (rcv OrbidderAdapter) MakeBids(internalRequest *openrtb2.BidRequest, extern
 }
 
 // Builder builds a new instance of the Orbidder adapter for the given bidder with the given config.
-func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
+func Builder(_ openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
 	bidder := &OrbidderAdapter{
 		endpoint: config.Endpoint,
 	}
diff --git a/adapters/pubmatic/pubmatic.go b/adapters/pubmatic/pubmatic.go
index 799d3364..f855f917 100644
--- a/adapters/pubmatic/pubmatic.go
+++ b/adapters/pubmatic/pubmatic.go
@@ -305,7 +305,7 @@ func parseImpressionObject(imp *openrtb2.Imp, extractWrapperExtFromImp, extractP
 // extractPubmaticWrapperExtFromRequest parse the imp to get it ready to send to pubmatic
 func extractPubmaticWrapperExtFromRequest(request *openrtb2.BidRequest) (*pubmaticWrapperExt, error) {
 	var wrpExt pubmaticWrapperExt
-	reqExtBidderParams, err := adapters.ExtractAdapterReqBidderParams(request)
+	reqExtBidderParams, err := adapters.ExtractReqExtBidderParamsMap(request)
 	if err != nil {
 		return nil, err
 	}
diff --git a/adapters/valueimpression/valueimpression.go b/adapters/valueimpression/valueimpression.go
deleted file mode 100644
index aac8faab..00000000
--- a/adapters/valueimpression/valueimpression.go
+++ /dev/null
@@ -1,157 +0,0 @@
-package valueimpression
-
-import (
-	"encoding/json"
-	"fmt"
-	"net/http"
-
-	"github.com/mxmCherry/openrtb/v15/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 ValueImpressionAdapter struct {
-	endpoint string
-}
-
-func (a *ValueImpressionAdapter) MakeRequests(request *openrtb2.BidRequest, unused *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
-	var errs []error
-	var adapterRequests []*adapters.RequestData
-
-	if err := preprocess(request); err != nil {
-		errs = append(errs, err)
-		return nil, errs
-	}
-
-	adapterReq, err := a.makeRequest(request)
-	if err != nil {
-		errs = append(errs, err)
-		return nil, errs
-	}
-
-	adapterRequests = append(adapterRequests, adapterReq)
-
-	return adapterRequests, errs
-}
-
-func (a *ValueImpressionAdapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) {
-	var err error
-
-	jsonBody, err := json.Marshal(request)
-	if err != nil {
-		return nil, err
-	}
-
-	headers := http.Header{}
-	headers.Add("Content-Type", "application/json;charset=utf-8")
-
-	return &adapters.RequestData{
-		Method:  "POST",
-		Uri:     a.endpoint,
-		Body:    jsonBody,
-		Headers: headers,
-	}, nil
-}
-
-func preprocess(request *openrtb2.BidRequest) error {
-	if len(request.Imp) == 0 {
-		return &errortypes.BadInput{
-			Message: "No Imps in Bid Request",
-		}
-	}
-	for i := 0; i < len(request.Imp); i++ {
-		var imp = &request.Imp[i]
-		var bidderExt adapters.ExtImpBidder
-
-		if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
-			return &errortypes.BadInput{
-				Message: err.Error(),
-			}
-		}
-
-		var extImp openrtb_ext.ExtImpValueImpression
-		if err := json.Unmarshal(bidderExt.Bidder, &extImp); err != nil {
-			return &errortypes.BadInput{
-				Message: err.Error(),
-			}
-		}
-
-		imp.Ext = bidderExt.Bidder
-	}
-
-	return nil
-}
-
-// MakeBids based on valueimpression server response
-func (a *ValueImpressionAdapter) MakeBids(bidRequest *openrtb2.BidRequest, unused *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
-	if responseData.StatusCode == http.StatusNoContent {
-		return nil, nil
-	}
-
-	if responseData.StatusCode == http.StatusBadRequest {
-		return nil, []error{&errortypes.BadInput{
-			Message: fmt.Sprintf("Bad user input: HTTP status %d", responseData.StatusCode),
-		}}
-	}
-
-	if responseData.StatusCode != http.StatusOK {
-		return nil, []error{&errortypes.BadServerResponse{
-			Message: fmt.Sprintf("Bad server response: HTTP status %d", responseData.StatusCode),
-		}}
-	}
-
-	var bidResponse openrtb2.BidResponse
-
-	if err := json.Unmarshal(responseData.Body, &bidResponse); err != nil {
-		return nil, []error{&errortypes.BadServerResponse{
-			Message: err.Error(),
-		}}
-	}
-
-	if len(bidResponse.SeatBid) == 0 {
-		return nil, nil
-	}
-
-	rv := adapters.NewBidderResponseWithBidsCapacity(len(bidResponse.SeatBid[0].Bid))
-	var errors []error
-
-	for _, seatbid := range bidResponse.SeatBid {
-		for _, bid := range seatbid.Bid {
-			foundMatchingBid := false
-			bidType := openrtb_ext.BidTypeBanner
-			for _, imp := range bidRequest.Imp {
-				if imp.ID == bid.ImpID {
-					foundMatchingBid = true
-					if imp.Banner != nil {
-						bidType = openrtb_ext.BidTypeBanner
-					} else if imp.Video != nil {
-						bidType = openrtb_ext.BidTypeVideo
-					}
-					break
-				}
-			}
-
-			if foundMatchingBid {
-				rv.Bids = append(rv.Bids, &adapters.TypedBid{
-					Bid:     &bid,
-					BidType: bidType,
-				})
-			} else {
-				errors = append(errors, &errortypes.BadServerResponse{
-					Message: fmt.Sprintf("bid id='%s' could not find valid impid='%s'", bid.ID, bid.ImpID),
-				})
-			}
-		}
-	}
-	return rv, errors
-}
-
-// Builder builds a new instance of the Valueimpression adapter for the given bidder with the given config.
-func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) {
-	bidder := &ValueImpressionAdapter{
-		endpoint: config.Endpoint,
-	}
-	return bidder, nil
-}
diff --git a/config/config.go b/config/config.go
index e320f9fc..7c7f721e 100644
--- a/config/config.go
+++ b/config/config.go
@@ -788,8 +788,9 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.adxcg.disabled", true)
 	v.SetDefault("adapters.adyoulike.endpoint", "https://broker.omnitagjs.com/broker/bid?partnerId=19340f4f097d16f41f34fc0274981ca4")
 	v.SetDefault("adapters.aja.endpoint", "https://ad.as.amanad.adtdp.com/v1/bid/4")
-	v.SetDefault("adapters.algorix.endpoint", "https://xyz.svr-algorix.com/rtb/sa?sid={{.SourceId}}&token={{.AccountID}}")
+	v.SetDefault("adapters.algorix.endpoint", "https://{{.Host}}.svr-algorix.com/rtb/sa?sid={{.SourceId}}&token={{.AccountID}}")
 	v.SetDefault("adapters.amx.endpoint", "http://pbs.amxrtb.com/auction/openrtb")
+	v.SetDefault("adapters.apacdex.endpoint", "http://useast.quantumdex.io/auction/pbs")
 	v.SetDefault("adapters.applogy.endpoint", "http://rtb.applogy.com/v1/prebid")
 	v.SetDefault("adapters.appnexus.endpoint", "http://ib.adnxs.com/openrtb2") // Docs: https://wiki.appnexus.com/display/supply/Incoming+Bid+Request+from+SSPs
 	v.SetDefault("adapters.appnexus.platform_id", "5")
@@ -809,6 +810,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.brightroll.endpoint", "http://east-bid.ybp.yahoo.com/bid/appnexuspbs")
 	v.SetDefault("adapters.coinzilla.endpoint", "http://request-global.czilladx.com/serve/prebid-server.php")
 	v.SetDefault("adapters.colossus.endpoint", "http://colossusssp.com/?c=o&m=rtb")
+	v.SetDefault("adapters.compass.endpoint", "http://sa-lb.deliverimp.com/pserver")
 	v.SetDefault("adapters.connectad.endpoint", "http://bidder.connectad.io/API?src=pbs")
 	v.SetDefault("adapters.consumable.endpoint", "https://e.serverbid.com/api/v2")
 	v.SetDefault("adapters.conversant.endpoint", "http://api.hb.ad.cpe.dotomi.com/cvx/server/hb/ortb/25")
@@ -867,6 +869,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.pubmatic.endpoint", "https://hbopenbid.pubmatic.com/translator?source=prebid-server")
 	v.SetDefault("adapters.pubnative.endpoint", "http://dsp.pubnative.net/bid/v1/request")
 	v.SetDefault("adapters.pulsepoint.endpoint", "http://bid.contextweb.com/header/s/ortb/prebid-s2s")
+	v.SetDefault("adapters.quantumdex.endpoint", "http://useast.quantumdex.io/auction/pbs")
 	v.SetDefault("adapters.revcontent.disabled", true)
 	v.SetDefault("adapters.revcontent.endpoint", "https://trends.revcontent.com/rtb")
 	v.SetDefault("adapters.rhythmone.endpoint", "http://tag.1rx.io/rmp")
@@ -896,7 +899,7 @@ func SetupViper(v *viper.Viper, filename string) {
 	v.SetDefault("adapters.ucfunnel.endpoint", "https://pbs.aralego.com/prebid")
 	v.SetDefault("adapters.unicorn.endpoint", "https://ds.uncn.jp/pb/0/bid.json")
 	v.SetDefault("adapters.unruly.endpoint", "https://targeting.unrulymedia.com/unruly_prebid_server")
-	v.SetDefault("adapters.valueimpression.endpoint", "https://rtb.valueimpression.com/endpoint")
+	v.SetDefault("adapters.valueimpression.endpoint", "http://useast.quantumdex.io/auction/pbs")
 	v.SetDefault("adapters.verizonmedia.disabled", true)
 	v.SetDefault("adapters.videobyte.endpoint", "https://x.videobyte.com/ortbhb")
 	v.SetDefault("adapters.viewdeos.endpoint", "http://ghb.sync.viewdeos.com/pbs/ortb")
diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go
index 8e9725f3..07d869dc 100644
--- a/endpoints/openrtb2/auction.go
+++ b/endpoints/openrtb2/auction.go
@@ -332,115 +332,138 @@ func parseTimeout(requestJson []byte, defaultTimeout time.Duration) time.Duratio
 	return defaultTimeout
 }
 
-// mergeBidderParams merges bidder parameters passed at req.ext level with imp[].ext level.
-// Preference is given to parameters at imp[].ext level over req.ext level.
-// Parameters at req.ext level are propagated to adapters as is without any validation.
+// mergeBidderParams merges bidder parameters in req.ext down to the imp[].ext level, with
+// priority given to imp[].ext in case of a conflict. No validation of bidder parameters or
+// of the ext json is performed. Unmarshal errors are not expected since the ext json was
+// validated during the bid request unmarshal. If there is an unmarshal error for some reason,
+// we rely on downstream validation to return the error.
 func mergeBidderParams(req *openrtb_ext.RequestWrapper) error {
-	reqBidderParams, err := adapters.ExtractReqExtBidderParams(req.BidRequest)
-	if err != nil {
-		return err
+	reqBidderParams, err := adapters.ExtractReqExtBidderParamsEmbeddedMap(req.BidRequest)
+	if err != nil || len(reqBidderParams) == 0 {
+		return nil
 	}
 
-	impCpy := make([]openrtb2.Imp, 0, len(req.BidRequest.Imp))
-	for _, imp := range req.BidRequest.Imp {
+	imps := make([]openrtb2.Imp, 0, len(req.BidRequest.Imp))
+	for impIndex, imp := range req.BidRequest.Imp {
 		updatedImp := imp
 
 		if len(imp.Ext) == 0 {
-			impCpy = append(impCpy, updatedImp)
+			imps = append(imps, updatedImp)
 			continue
 		}
 
-		var impExt map[string]map[string]json.RawMessage
-		err := json.Unmarshal(imp.Ext, &impExt)
-		if err != nil {
-			return err
+		var impExt map[string]json.RawMessage
+		if err := json.Unmarshal(imp.Ext, &impExt); err != nil {
+			// imp.ext should be parsable, but we haven't validated yet so there may be another issue. ignore it here
+			// and let the validation catch it later on.
+			imps = append(imps, updatedImp)
+			continue
 		}
 
 		//merges bidder parameters passed at req.ext level with imp[].ext level.
-		err = addMissingReqExtParamsInImpExt(impExt, reqBidderParams)
+		impExtModified, err := addMissingReqExtParamsInImpExt(impExt, reqBidderParams)
 		if err != nil {
-			return err
+			return fmt.Errorf("error processing bidder parameters for imp[%d]: %s", impIndex, err.Error())
 		}
 
 		//merges bidder parameters passed at req.ext level with imp[].ext.prebid.bidder level.
-		err = addMissingReqExtParamsInImpExtPrebid(impExt, reqBidderParams)
+		impExtPrebidModified, err := addMissingReqExtParamsInImpExtPrebid(impExt, reqBidderParams)
 		if err != nil {
-			return err
+			return fmt.Errorf("error processing bidder parameters for imp[%d]: %s", impIndex, err.Error())
 		}
 
-		iExt, err := json.Marshal(impExt)
-		if err != nil {
-			return fmt.Errorf("error marshalling imp[].ext : %s", err.Error())
+		if impExtModified || impExtPrebidModified {
+			updatedImpExt, err := json.Marshal(impExt)
+			if err != nil {
+				return fmt.Errorf("error processing bidder parameters for imp[%d]: error marshalling ext:%s", impIndex, err.Error())
+			}
+			updatedImp.Ext = updatedImpExt
 		}
-		updatedImp.Ext = iExt
-		impCpy = append(impCpy, updatedImp)
+
+		imps = append(imps, updatedImp)
 	}
 
-	req.BidRequest.Imp = impCpy
+	req.BidRequest.Imp = imps
 	return nil
 }
 
 // addMissingReqExtParamsInImpExtPrebid merges bidder parameters passed at req.ext level with imp[].ext.prebid.bidder level.
-func addMissingReqExtParamsInImpExtPrebid(impExtBidder map[string]map[string]json.RawMessage, reqExtParams map[string]map[string]json.RawMessage) error {
-	var bidderParams map[string]json.RawMessage
-	if impExtBidder["prebid"] != nil && impExtBidder["prebid"]["bidder"] != nil {
-		err := json.Unmarshal(impExtBidder["prebid"]["bidder"], &bidderParams)
-		if err != nil {
-			return err
-		}
+func addMissingReqExtParamsInImpExtPrebid(impExtByKey map[string]json.RawMessage, reqExtParams map[string]map[string]json.RawMessage) (bool, error) {
+	if _, prebidSectionExists := impExtByKey["prebid"]; !prebidSectionExists {
+		return false, nil
 	}
 
-	if len(bidderParams) != 0 {
-		for bidder, bidderExt := range bidderParams {
-			if !isBidderToValidate(bidder) {
-				continue
-			}
+	var prebidByKey map[string]json.RawMessage
+	if err := json.Unmarshal(impExtByKey["prebid"], &prebidByKey); err != nil {
+		// prebid should be parsable, but we haven't validated yet so there may be another issue. ignore it here
+		// and let the validation catch it later on.
+		return false, nil
+	}
+
+	if _, prebidBidderSectionExists := prebidByKey["bidder"]; !prebidBidderSectionExists {
+		return false, nil
+	}
 
-			var params map[string]json.RawMessage
-			err := json.Unmarshal(bidderExt, &params)
+	var prebidBidderByBidder map[string]json.RawMessage
+	if err := json.Unmarshal(prebidByKey["bidder"], &prebidBidderByBidder); err != nil {
+		// added for completeness, but not possible. would be caught by the earlier unmarshal call.
+		return false, nil
+	}
 
-			for key, value := range reqExtParams[bidder] {
-				if _, present := params[key]; !present {
-					params[key] = value
-				}
-			}
+	anyModified, err := addMissingReqExtParamsInImpExt(prebidBidderByBidder, reqExtParams)
 
-			paramsJson, err := json.Marshal(params)
-			if err != nil {
-				return err
-			}
-			bidderParams[bidder] = paramsJson
+	if anyModified && err == nil {
+		// marshal imp.ext.prebid.bidder
+		prebidBidderJSON, err := json.Marshal(prebidBidderByBidder)
+		if err != nil {
+			return anyModified, err
 		}
+		prebidByKey["bidder"] = prebidBidderJSON
 
-		bidderParamsJson, err := json.Marshal(bidderParams)
+		// marshal imp.ext.prebid
+		prebidJSON, err := json.Marshal(prebidByKey)
 		if err != nil {
-			return err
+			return anyModified, err
 		}
-		impExtBidder["prebid"]["bidder"] = bidderParamsJson
+		impExtByKey["prebid"] = prebidJSON
 	}
 
-	return nil
+	return anyModified, err
 }
 
 // addMissingReqExtParamsInImpExt merges bidder parameters passed at req.ext level with imp[].ext level.
-func addMissingReqExtParamsInImpExt(impExtBidder map[string]map[string]json.RawMessage, reqExtParams map[string]map[string]json.RawMessage) error {
-	for bidder, bidderExt := range impExtBidder {
+func addMissingReqExtParamsInImpExt(impExtByBidder map[string]json.RawMessage, reqExtParams map[string]map[string]json.RawMessage) (bool, error) {
+	anyModified := false
+	for bidder, bidderExt := range impExtByBidder {
 		if !isBidderToValidate(bidder) {
 			continue
 		}
 
-		wasModified := false
+		var params map[string]json.RawMessage
+		if err := json.Unmarshal(bidderExt, &params); err != nil {
+			// bidder should be parsable, but we haven't validated yet so there may be another issue. ignore it here
+			// and let the validation later on catch it.
+			continue
+		}
+
+		modified := false
 		for key, value := range reqExtParams[bidder] {
-			if _, present := bidderExt[key]; !present {
-				bidderExt[key] = value
-				wasModified = true
+			if _, present := params[key]; !present {
+				params[key] = value
+				modified = true
 			}
 		}
-		if wasModified {
-			impExtBidder[bidder] = bidderExt
+
+		if modified {
+			paramsJson, err := json.Marshal(params)
+			if err != nil {
+				return anyModified, fmt.Errorf("error marshalling ext.prebid.bidder: %s", err.Error())
+			}
+			impExtByBidder[bidder] = paramsJson
+			anyModified = true
 		}
 	}
-	return nil
+	return anyModified, nil
 }
 
 func (deps *endpointDeps) validateRequest(req *openrtb_ext.RequestWrapper, isAmp bool) []error {
@@ -1173,12 +1196,12 @@ func isBidderToValidate(bidder string) bool {
 		return false
 	case openrtb_ext.BidderReservedData:
 		return false
+	case openrtb_ext.BidderReservedGPID:
+		return false
 	case openrtb_ext.BidderReservedPrebid:
 		return false
 	case openrtb_ext.BidderReservedSKAdN:
 		return false
-	case openrtb_ext.BidderReservedBidder:
-		return false
 	default:
 		return true
 	}
diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json
index 5baaa09d..76dc1c2b 100644
--- a/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json
+++ b/endpoints/openrtb2/sample-requests/invalid-whole/cache-nothing.json
@@ -27,5 +27,5 @@
     }
   },
   "expectedReturnCode": 400,
-  "expectedErrorMessage": "Invalid request: error decoding Request.ext : request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n"
+  "expectedErrorMessage": "Invalid request: request.ext is invalid: request.ext.prebid.cache requires one of the \"bids\" or \"vastxml\" properties\n"
 }
diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/imp-ext-invalid-params.json b/endpoints/openrtb2/sample-requests/invalid-whole/imp-ext-invalid-params.json
index b1e9b784..d9ed59c8 100644
--- a/endpoints/openrtb2/sample-requests/invalid-whole/imp-ext-invalid-params.json
+++ b/endpoints/openrtb2/sample-requests/invalid-whole/imp-ext-invalid-params.json
@@ -20,5 +20,5 @@
     }
   },
   "expectedReturnCode": 400,
-  "expectedErrorMessage": "Invalid request: json: cannot unmarshal string into Go value of type map[string]json.RawMessage"
+  "expectedErrorMessage": "Invalid request: request.imp[0].ext.appnexus failed validation.\n(root): Invalid type. Expected: object, given: string\n"
 }
diff --git a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/req-ext-bidder-params-merge-reserved-keyword.json b/endpoints/openrtb2/sample-requests/valid-whole/supplementary/req-ext-bidder-params-merge-reserved-keyword.json
deleted file mode 100644
index 982f86cb..00000000
--- a/endpoints/openrtb2/sample-requests/valid-whole/supplementary/req-ext-bidder-params-merge-reserved-keyword.json
+++ /dev/null
@@ -1,116 +0,0 @@
-{
-  "description": "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder for reserved keyword",
-  "mockBidRequest": {
-    "id": "some-request-id",
-    "site": {
-      "page": "test.somepage.com"
-    },
-    "imp": [
-      {
-        "id": "my-imp-id",
-        "banner": {
-          "format": [
-            {
-              "w": 300,
-              "h": 600
-            }
-          ]
-        },
-        "pmp": {
-          "deals": [
-            {
-              "id": "some-deal-id"
-            }
-          ]
-        },
-        "ext": {
-          "prebid": {
-            "bidder": {
-              "bidder": {
-                "param1": 111111
-              },
-              "appnexus": {
-                "placementId": 111111
-              },
-              "pubmatic": {
-                "publisherId": "1234",
-                "wrapper": {
-                  "profile": 1234
-                }
-              }
-            }
-          }
-        }
-      }
-    ],
-    "ext": {
-      "prebid": {
-        "targeting": {
-          "pricegranularity": "low"
-        },
-        "cache": {
-          "bids": {}
-        },
-        "bidderparams": {
-          "bidder": {
-            "param2": 111111
-          },
-          "appnexus": {
-            "placementId": 222222
-          },
-          "pubmatic": {
-            "publisherId": "5678",
-            "wrapper": {
-              "profile": 5678,
-              "version": 2
-            }
-          }
-        }
-      }
-    }
-  },
-  "expectedReqExt": {
-    "prebid": {
-      "targeting": {
-        "pricegranularity": "low"
-      },
-      "cache": {
-        "bids": {}
-      },
-      "bidderparams": {
-        "bidder": {
-          "param2": 111111
-        },
-        "appnexus": {
-          "placementId": 222222
-        },
-        "pubmatic": {
-          "publisherId": "5678",
-          "wrapper": {
-            "profile": 5678,
-            "version": 2
-          }
-        }
-      }
-    }
-  },
-  "expectedImpExt": {
-    "prebid": {
-      "bidder": {
-        "bidder": {
-          "param1": 111111
-        },
-        "appnexus": {
-          "placementId": 111111
-        },
-        "pubmatic": {
-          "publisherId": "1234",
-          "wrapper": {
-            "profile": 1234
-          }
-        }
-      }
-    }
-  },
-  "expectedReturnCode": 200
-}
\ No newline at end of file
diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go
index 0f14b75c..8075b7f1 100755
--- a/exchange/adapter_builders.go
+++ b/exchange/adapter_builders.go
@@ -28,6 +28,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/aja"
 	"github.com/prebid/prebid-server/adapters/algorix"
 	"github.com/prebid/prebid-server/adapters/amx"
+	"github.com/prebid/prebid-server/adapters/apacdex"
 	"github.com/prebid/prebid-server/adapters/applogy"
 	"github.com/prebid/prebid-server/adapters/appnexus"
 	"github.com/prebid/prebid-server/adapters/audienceNetwork"
@@ -44,6 +45,7 @@ import (
 	"github.com/prebid/prebid-server/adapters/brightroll"
 	"github.com/prebid/prebid-server/adapters/coinzilla"
 	"github.com/prebid/prebid-server/adapters/colossus"
+	"github.com/prebid/prebid-server/adapters/compass"
 	"github.com/prebid/prebid-server/adapters/connectad"
 	"github.com/prebid/prebid-server/adapters/consumable"
 	"github.com/prebid/prebid-server/adapters/conversant"
@@ -122,7 +124,6 @@ import (
 	"github.com/prebid/prebid-server/adapters/ucfunnel"
 	"github.com/prebid/prebid-server/adapters/unicorn"
 	"github.com/prebid/prebid-server/adapters/unruly"
-	"github.com/prebid/prebid-server/adapters/valueimpression"
 	"github.com/prebid/prebid-server/adapters/videobyte"
 	"github.com/prebid/prebid-server/adapters/visx"
 	"github.com/prebid/prebid-server/adapters/vrtcal"
@@ -167,6 +168,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderAJA:               aja.Builder,
 		openrtb_ext.BidderAlgorix:           algorix.Builder,
 		openrtb_ext.BidderAMX:               amx.Builder,
+		openrtb_ext.BidderApacdex:           apacdex.Builder,
 		openrtb_ext.BidderApplogy:           applogy.Builder,
 		openrtb_ext.BidderAppnexus:          appnexus.Builder,
 		openrtb_ext.BidderAudienceNetwork:   audienceNetwork.Builder,
@@ -183,6 +185,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderBrightroll:        brightroll.Builder,
 		openrtb_ext.BidderCoinzilla:         coinzilla.Builder,
 		openrtb_ext.BidderColossus:          colossus.Builder,
+		openrtb_ext.BidderCompass:           compass.Builder,
 		openrtb_ext.BidderConnectAd:         connectad.Builder,
 		openrtb_ext.BidderConsumable:        consumable.Builder,
 		openrtb_ext.BidderConversant:        conversant.Builder,
@@ -239,6 +242,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderPubmatic:          pubmatic.Builder,
 		openrtb_ext.BidderPubnative:         pubnative.Builder,
 		openrtb_ext.BidderPulsepoint:        pulsepoint.Builder,
+		openrtb_ext.BidderQuantumdex:        apacdex.Builder,
 		openrtb_ext.BidderRevcontent:        revcontent.Builder,
 		openrtb_ext.BidderRhythmone:         rhythmone.Builder,
 		openrtb_ext.BidderRichaudience:      richaudience.Builder,
@@ -265,7 +269,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder {
 		openrtb_ext.BidderUcfunnel:          ucfunnel.Builder,
 		openrtb_ext.BidderUnicorn:           unicorn.Builder,
 		openrtb_ext.BidderUnruly:            unruly.Builder,
-		openrtb_ext.BidderValueImpression:   valueimpression.Builder,
+		openrtb_ext.BidderValueImpression:   apacdex.Builder,
 		openrtb_ext.BidderVerizonMedia:      yahoossp.Builder,
 		openrtb_ext.BidderVideoByte:         videobyte.Builder,
 		openrtb_ext.BidderViewdeos:          adtelligent.Builder,
diff --git a/exchange/utils.go b/exchange/utils.go
index 23ffe5e5..48f76b2a 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -223,7 +223,7 @@ func getAuctionBidderRequests(req AuctionRequest,
 		return nil, []error{err}
 	}
 
-	bidderParamsInReqExt, err := adapters.ExtractReqExtBidderParams(req.BidRequest)
+	bidderParamsInReqExt, err := adapters.ExtractReqExtBidderParamsEmbeddedMap(req.BidRequest)
 	if err != nil {
 		return nil, []error{err}
 	}
@@ -464,6 +464,10 @@ func createSanitizedImpExt(impExt, impExtPrebid map[string]json.RawMessage) (map
 		sanitizedImpExt[openrtb_ext.SKAdNExtKey] = v
 	}
 
+	if v, exists := impExt[string(openrtb_ext.GPIDKey)]; exists {
+		sanitizedImpExt[openrtb_ext.GPIDKey] = v
+	}
+
 	return sanitizedImpExt, nil
 }
 
@@ -493,6 +497,7 @@ func isSpecialField(bidder string) bool {
 	return bidder == openrtb_ext.FirstPartyDataContextExtKey ||
 		bidder == openrtb_ext.FirstPartyDataExtKey ||
 		bidder == openrtb_ext.SKAdNExtKey ||
+		bidder == openrtb_ext.GPIDKey ||
 		bidder == openrtb_ext.PrebidExtKey
 }
 
diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go
index fcb52841..941f1a56 100644
--- a/openrtb_ext/bidders.go
+++ b/openrtb_ext/bidders.go
@@ -32,9 +32,9 @@ const (
 	BidderReservedContext BidderName = "context" // Reserved for first party data.
 	BidderReservedData    BidderName = "data"    // Reserved for first party data.
 	BidderReservedGeneral BidderName = "general" // Reserved for non-bidder specific messages when using a map keyed on the bidder name.
+	BidderReservedGPID    BidderName = "gpid"    // Reserved for Global Placement ID (GPID).
 	BidderReservedPrebid  BidderName = "prebid"  // Reserved for Prebid Server configuration.
 	BidderReservedSKAdN   BidderName = "skadn"   // Reserved for Apple's SKAdNetwork OpenRTB extension.
-	BidderReservedBidder  BidderName = "bidder"  // Reserved for passing bidder parameters.
 )
 
 // IsBidderNameReserved returns true if the specified name is a case insensitive match for a reserved bidder name.
@@ -55,15 +55,15 @@ func IsBidderNameReserved(name string) bool {
 		return true
 	}
 
-	if strings.EqualFold(name, string(BidderReservedSKAdN)) {
+	if strings.EqualFold(name, string(BidderReservedGPID)) {
 		return true
 	}
 
-	if strings.EqualFold(name, string(BidderReservedPrebid)) {
+	if strings.EqualFold(name, string(BidderReservedSKAdN)) {
 		return true
 	}
 
-	if strings.EqualFold(name, string(BidderReservedBidder)) {
+	if strings.EqualFold(name, string(BidderReservedPrebid)) {
 		return true
 	}
 
@@ -103,6 +103,7 @@ const (
 	BidderAJA               BidderName = "aja"
 	BidderAlgorix           BidderName = "algorix"
 	BidderAMX               BidderName = "amx"
+	BidderApacdex           BidderName = "apacdex"
 	BidderApplogy           BidderName = "applogy"
 	BidderAppnexus          BidderName = "appnexus"
 	BidderAudienceNetwork   BidderName = "audienceNetwork"
@@ -119,6 +120,7 @@ const (
 	BidderBrightroll        BidderName = "brightroll"
 	BidderCoinzilla         BidderName = "coinzilla"
 	BidderColossus          BidderName = "colossus"
+	BidderCompass           BidderName = "compass"
 	BidderConnectAd         BidderName = "connectad"
 	BidderConsumable        BidderName = "consumable"
 	BidderConversant        BidderName = "conversant"
@@ -175,6 +177,7 @@ const (
 	BidderPubmatic          BidderName = "pubmatic"
 	BidderPubnative         BidderName = "pubnative"
 	BidderPulsepoint        BidderName = "pulsepoint"
+	BidderQuantumdex        BidderName = "quantumdex"
 	BidderRevcontent        BidderName = "revcontent"
 	BidderRhythmone         BidderName = "rhythmone"
 	BidderRichaudience      BidderName = "richaudience"
@@ -246,6 +249,7 @@ func CoreBidderNames() []BidderName {
 		BidderAJA,
 		BidderAlgorix,
 		BidderAMX,
+		BidderApacdex,
 		BidderApplogy,
 		BidderAppnexus,
 		BidderAudienceNetwork,
@@ -262,6 +266,7 @@ func CoreBidderNames() []BidderName {
 		BidderBrightroll,
 		BidderCoinzilla,
 		BidderColossus,
+		BidderCompass,
 		BidderConnectAd,
 		BidderConsumable,
 		BidderConversant,
@@ -318,6 +323,7 @@ func CoreBidderNames() []BidderName {
 		BidderPubmatic,
 		BidderPubnative,
 		BidderPulsepoint,
+		BidderQuantumdex,
 		BidderRevcontent,
 		BidderRhythmone,
 		BidderRichaudience,
diff --git a/openrtb_ext/imp_algorix.go b/openrtb_ext/imp_algorix.go
index 3661018d..d395600c 100644
--- a/openrtb_ext/imp_algorix.go
+++ b/openrtb_ext/imp_algorix.go
@@ -6,4 +6,5 @@ type ExtImpAlgorix struct {
 	Token       string `json:"token"`
 	PlacementId string `json:"placementId"`
 	AppId       string `json:"appId"`
+	Region      string `json:"region"`
 }
diff --git a/openrtb_ext/imp_apacdex.go b/openrtb_ext/imp_apacdex.go
new file mode 100644
index 00000000..dc8fb15b
--- /dev/null
+++ b/openrtb_ext/imp_apacdex.go
@@ -0,0 +1,7 @@
+package openrtb_ext
+
+type ExtImpApacdex struct {
+	PlacementID string  `json:"placementId"`
+	SiteID      string  `json:"siteId"`
+	FloorPrice  float64 `json:"floorPrice"`
+}
diff --git a/openrtb_ext/imp_compass.go b/openrtb_ext/imp_compass.go
new file mode 100644
index 00000000..3a150b9d
--- /dev/null
+++ b/openrtb_ext/imp_compass.go
@@ -0,0 +1,6 @@
+package openrtb_ext
+
+type ImpExtCompass struct {
+	PlacementID string `json:"placementId"`
+	EndpointID  string `json:"endpointId"`
+}
diff --git a/openrtb_ext/imp_marsmedia.go b/openrtb_ext/imp_marsmedia.go
index c27fe2db..e07b6d7c 100644
--- a/openrtb_ext/imp_marsmedia.go
+++ b/openrtb_ext/imp_marsmedia.go
@@ -1,6 +1,8 @@
 package openrtb_ext
 
+import "encoding/json"
+
 // ExtImpMarsmedia defines the contract for bidrequest.imp[i].ext.marsmedia
 type ExtImpMarsmedia struct {
-	ZoneID string `json:"zoneId"`
+	ZoneID json.Number `json:"zoneId"`
 }
diff --git a/openrtb_ext/imp_valueimpression.go b/openrtb_ext/imp_valueimpression.go
deleted file mode 100644
index 7c5c70ee..00000000
--- a/openrtb_ext/imp_valueimpression.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package openrtb_ext
-
-type ExtImpValueImpression struct {
-	SiteId string `json:"siteId"`
-}
diff --git a/openrtb_ext/request.go b/openrtb_ext/request.go
index a65e8d3c..dba30863 100644
--- a/openrtb_ext/request.go
+++ b/openrtb_ext/request.go
@@ -14,6 +14,9 @@ const FirstPartyDataContextExtKey = "context"
 // SKAdNExtKey defines the field name within request.ext reserved for Apple's SKAdNetwork.
 const SKAdNExtKey = "skadn"
 
+// GPIDKey defines the field name within request.ext reserved for the Global Placement ID (GPID),
+const GPIDKey = "gpid"
+
 // NativeExchangeSpecificLowerBound defines the lower threshold of exchange specific types for native ads. There is no upper bound.
 const NativeExchangeSpecificLowerBound = 500
 
diff --git a/static/bidder-info/apacdex.yaml b/static/bidder-info/apacdex.yaml
new file mode 100644
index 00000000..2e8cd08f
--- /dev/null
+++ b/static/bidder-info/apacdex.yaml
@@ -0,0 +1,20 @@
+maintainer:
+  email: "support@apacdex.com"
+modifyingVastXmlAllowed: false
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
+userSync:
+  default: iframe
+  iframe:
+    url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}
+    userMacro: "[UID]"
+  redirect:
+    url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}"
+    userMacro: "[UID]"
diff --git a/static/bidder-info/compass.yaml b/static/bidder-info/compass.yaml
new file mode 100644
index 00000000..5944b27e
--- /dev/null
+++ b/static/bidder-info/compass.yaml
@@ -0,0 +1,19 @@
+maintainer:
+  email: "sa-support@brightcom.com"
+gvlVendorID: 883
+capabilities:
+  site:
+    mediaTypes:
+    - banner
+    - video
+    - native
+    
+  app:
+    mediaTypes:
+    - banner
+    - video
+    - native
+userSync:
+  redirect:
+    url: "https://sa-cs.deliverimp.com/pserver?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir={{.RedirectURL}}"
+    userMacro: "[UID]"
diff --git a/static/bidder-info/quantumdex.yaml b/static/bidder-info/quantumdex.yaml
new file mode 100644
index 00000000..2e8cd08f
--- /dev/null
+++ b/static/bidder-info/quantumdex.yaml
@@ -0,0 +1,20 @@
+maintainer:
+  email: "support@apacdex.com"
+modifyingVastXmlAllowed: false
+capabilities:
+  app:
+    mediaTypes:
+      - banner
+      - video
+  site:
+    mediaTypes:
+      - banner
+      - video
+userSync:
+  default: iframe
+  iframe:
+    url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}
+    userMacro: "[UID]"
+  redirect:
+    url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}"
+    userMacro: "[UID]"
diff --git a/static/bidder-info/valueimpression.yaml b/static/bidder-info/valueimpression.yaml
index 0782f897..2e8cd08f 100644
--- a/static/bidder-info/valueimpression.yaml
+++ b/static/bidder-info/valueimpression.yaml
@@ -1,5 +1,6 @@
 maintainer:
-  email: "info@valueimpression.com"
+  email: "support@apacdex.com"
+modifyingVastXmlAllowed: false
 capabilities:
   app:
     mediaTypes:
@@ -10,6 +11,10 @@ capabilities:
       - banner
       - video
 userSync:
+  default: iframe
+  iframe:
+    url: https://sync.quantumdex.io/usersync/pbs?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}
+    userMacro: "[UID]"
   redirect:
-    url: "https://rtb.valueimpression.com/usersync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}"
-    userMacro: "$UID"
+    url: "https://sync.quantumdex.io/getuid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}}"
+    userMacro: "[UID]"
diff --git a/static/bidder-params/algorix.json b/static/bidder-params/algorix.json
index 675d9793..2fcbd6ec 100644
--- a/static/bidder-params/algorix.json
+++ b/static/bidder-params/algorix.json
@@ -21,6 +21,11 @@
     "appId": {
       "type": "string",
       "description": "An ID which identifies this app of the impression"
+    },
+    "region": {
+      "type": "string",
+      "enum": ["APAC", "USE"],
+      "description": "Server region for PBS request, null for global, APAC for SG Region, USE for US Region"
     }
   },
   "required": ["sid", "token"]
diff --git a/static/bidder-params/apacdex.json b/static/bidder-params/apacdex.json
new file mode 100644
index 00000000..0130fcee
--- /dev/null
+++ b/static/bidder-params/apacdex.json
@@ -0,0 +1,32 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Apacdex Adapter Params",
+  "description": "A schema which validates params accepted by the Apacdex adapter",
+  "type": "object",
+  "properties": {
+    "placementId": {
+      "type": "string",
+      "description": "Placement ID provided by Apacdex"
+    },
+    "siteId": {
+      "type": "string",
+      "description": "Publisher site ID from Apacdex"
+    },
+    "floorPrice": {
+      "type": "number",
+      "description": "CPM bidfloor in USD"
+    }
+  },
+  "oneOf": [
+    {
+      "required": [
+        "placementId"
+      ]
+    },
+    {
+      "required": [
+        "siteId"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/static/bidder-params/compass.json b/static/bidder-params/compass.json
new file mode 100644
index 00000000..11fcbf31
--- /dev/null
+++ b/static/bidder-params/compass.json
@@ -0,0 +1,23 @@
+{
+    "$schema": "http://json-schema.org/draft-04/schema#",
+    "title": "Compass Adapter Params",
+    "description": "A schema which validates params accepted by the Compass adapter",
+    "type": "object",
+  
+    "properties": {
+      "placementId": {
+        "type": "string",
+        "minLength": 1,
+        "description": "Placement ID"
+      },
+      "endpointId": {
+        "type": "string",
+        "minLength": 1,
+        "description": "Endpoint ID"
+      }
+    },
+    "oneOf": [
+      { "required": ["placementId"] },
+      { "required": ["endpointId"] }
+    ]
+  }
\ No newline at end of file
diff --git a/static/bidder-params/marsmedia.json b/static/bidder-params/marsmedia.json
index b812eb89..7555261a 100644
--- a/static/bidder-params/marsmedia.json
+++ b/static/bidder-params/marsmedia.json
@@ -5,8 +5,8 @@
   "type": "object",
   "properties": {
     "zoneId": {
-      "type": "string",
-      "description": "Zone ID to use."
+      "type": ["integer", "string"],
+      "description": "The zone ID from Mars Media Group."
     }
   }
 }
diff --git a/static/bidder-params/quantumdex.json b/static/bidder-params/quantumdex.json
new file mode 100644
index 00000000..3ef9abe3
--- /dev/null
+++ b/static/bidder-params/quantumdex.json
@@ -0,0 +1,32 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Quantumdex Adapter Params",
+  "description": "A schema which validates params accepted by the Quantumdex adapter",
+  "type": "object",
+  "properties": {
+    "placementId": {
+      "type": "string",
+      "description": "Placement ID provided by Quantumdex"
+    },
+    "siteId": {
+      "type": "string",
+      "description": "Publisher site ID from Quantumdex"
+    },
+    "floorPrice": {
+      "type": "number",
+      "description": "CPM bidfloor in USD"
+    }
+  },
+  "oneOf": [
+    {
+      "required": [
+        "placementId"
+      ]
+    },
+    {
+      "required": [
+        "siteId"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/static/bidder-params/valueimpression.json b/static/bidder-params/valueimpression.json
index 5b9c32c5..793e940e 100644
--- a/static/bidder-params/valueimpression.json
+++ b/static/bidder-params/valueimpression.json
@@ -1,15 +1,32 @@
-
 {
-    "$schema": "http://json-schema.org/draft-04/schema#",
-    "title": "ValueImpression Adapter Params",
-    "description": "Schema to validate params accepted by the ValueImpression adapter",
-  
-    "type": "object",
-    "properties": {
-      "siteId": {
-        "type": "string",
-        "description": "Site ID"
-      }
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "title": "Valueimpression Adapter Params",
+  "description": "A schema which validates params accepted by the Valueimpression adapter",
+  "type": "object",
+  "properties": {
+    "placementId": {
+      "type": "string",
+      "description": "Placement ID provided by Valueimpression"
     },
-    "required": ["siteId"]
-  }
+    "siteId": {
+      "type": "string",
+      "description": "Publisher site ID from Valueimpression"
+    },
+    "floorPrice": {
+      "type": "number",
+      "description": "CPM bidfloor in USD"
+    }
+  },
+  "oneOf": [
+    {
+      "required": [
+        "placementId"
+      ]
+    },
+    {
+      "required": [
+        "siteId"
+      ]
+    }
+  ]
+}
\ No newline at end of file


Test patch:
diff --git a/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json
new file mode 100644
index 00000000..96ddff85
--- /dev/null
+++ b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json
@@ -0,0 +1,122 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "user": {
+            "id": "1kjh3429kjh295jkl",
+            "ext": {
+                "consent": "CONSENT_STRING"
+            }
+        },
+        "device": {
+            "ip": "158.174.81.143",
+            "ua": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Mobile Safari/537.36"
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "auId": "123"
+                    }
+                }
+            }
+        ]
+    },
+
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "headers": {
+                    "Content-Type": [
+                        "application/json;charset=utf-8"
+                    ],
+                    "Accept": [
+                        "application/json"
+                    ],
+                    "X-Forwarded-For": [
+                        "158.174.81.143"
+                    ],
+                    "User-Agent": [
+                        "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Mobile Safari/537.36"
+                    ]
+                },
+                "uri": "http://whatever.url?format=json&tzo=0",
+                "body": {
+                    "adUnits": [
+                        {
+                            "auId": "123",
+                            "targetId": "123-test-imp-id"
+                        }
+                    ],
+                    "metaData": {
+                        "usi": "1kjh3429kjh295jkl"
+                    },
+                    "context": "unknown"
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "adUnits": [
+                        {
+                            "auId": "0000000000000123",
+                            "targetId": "123-test-imp-id",
+                            "html": "<ADCODE>",
+                            "responseId": "adn-rsp-900646517",
+                            "ads": [
+                                {
+                                    "destinationUrls": {
+                                        "url": "http://www.google.com"
+                                    },
+                                    "bid": {
+                                        "amount": 20.0,
+                                        "currency": "NOK"
+                                    },
+                                    "adId": "adn-id-1559784094",
+                                    "creativeWidth": "980",
+                                    "creativeHeight": "240",
+                                    "creativeId": "jn9hpzvlsf8cpdmm",
+                                    "lineItemId": "q7y9qm5b0xt9htrv"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "adn-id-1559784094",
+                        "impid": "test-imp-id",
+                        "price": 20000,
+                        "adm": "<ADCODE>",
+                        "adid": "adn-id-1559784094",
+                        "adomain": ["google.com"],
+                        "cid": "q7y9qm5b0xt9htrv",
+                        "crid": "jn9hpzvlsf8cpdmm",
+                        "w": 980,
+                        "h": 240
+                    },
+                    "type": "banner"
+                }
+            ],
+            "currency": "NOK"
+        }
+    ]
+}
diff --git a/adapters/algorix/algorix_test.go b/adapters/algorix/algorix_test.go
index 55c8b9ef..79cf8609 100644
--- a/adapters/algorix/algorix_test.go
+++ b/adapters/algorix/algorix_test.go
@@ -11,7 +11,7 @@ import (
 
 func TestJsonSamples(t *testing.T) {
 	bidder, buildErr := Builder(openrtb_ext.BidderAlgorix, config.Adapter{
-		Endpoint: "https://test.com?sid={{.SourceId}}&token={{.AccountID}}"})
+		Endpoint: "https://{{.Host}}.test.com?sid={{.SourceId}}&token={{.AccountID}}"})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
diff --git a/adapters/algorix/algorixtest/exemplary/sample-banner-with-palcementid.json b/adapters/algorix/algorixtest/exemplary/sample-banner-with-palcementid.json
index 4d1853f0..e50fb3a4 100644
--- a/adapters/algorix/algorixtest/exemplary/sample-banner-with-palcementid.json
+++ b/adapters/algorix/algorixtest/exemplary/sample-banner-with-palcementid.json
@@ -13,7 +13,8 @@
             "sid": "testSid",
             "token": "testToken",
             "placementId": "testPlacementId",
-            "appId": "testAppId"
+            "appId": "testAppId",
+            "region": "USE"
           }
         }
       }
@@ -23,7 +24,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://use.xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
@@ -40,7 +41,8 @@
                   "sid": "testSid",
                   "token": "testToken",
                   "placementId": "testPlacementId",
-                  "appId": "testAppId"
+                  "appId": "testAppId",
+                  "region": "USE"
                 }
               }
             }
diff --git a/adapters/algorix/algorixtest/exemplary/sample-banner.json b/adapters/algorix/algorixtest/exemplary/sample-banner.json
index 118f89c1..d558214a 100644
--- a/adapters/algorix/algorixtest/exemplary/sample-banner.json
+++ b/adapters/algorix/algorixtest/exemplary/sample-banner.json
@@ -10,7 +10,8 @@
         "ext": {
           "bidder": {
             "sid": "testSid",
-            "token": "testToken"
+            "token": "testToken",
+            "region": "APAC"
           }
         }
       }
@@ -20,7 +21,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://apac.xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
@@ -34,7 +35,8 @@
               "ext": {
                 "bidder": {
                   "sid": "testSid",
-                  "token": "testToken"
+                  "token": "testToken",
+                  "region": "APAC"
                 }
               }
             }
diff --git a/adapters/algorix/algorixtest/exemplary/sample-native.json b/adapters/algorix/algorixtest/exemplary/sample-native.json
index 3b24bd3a..36a0d1af 100644
--- a/adapters/algorix/algorixtest/exemplary/sample-native.json
+++ b/adapters/algorix/algorixtest/exemplary/sample-native.json
@@ -22,7 +22,7 @@
   "httpcalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/algorixtest/exemplary/sample-nobid.json b/adapters/algorix/algorixtest/exemplary/sample-nobid.json
index c378ff0d..d4fbd561 100644
--- a/adapters/algorix/algorixtest/exemplary/sample-nobid.json
+++ b/adapters/algorix/algorixtest/exemplary/sample-nobid.json
@@ -22,7 +22,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/algorixtest/exemplary/sample-video.json b/adapters/algorix/algorixtest/exemplary/sample-video.json
index df3f6dcd..edb8fddb 100644
--- a/adapters/algorix/algorixtest/exemplary/sample-video.json
+++ b/adapters/algorix/algorixtest/exemplary/sample-video.json
@@ -26,7 +26,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/algorixtest/supplemental/bad_response.json b/adapters/algorix/algorixtest/supplemental/bad_response.json
index 17d84673..83ed5663 100644
--- a/adapters/algorix/algorixtest/supplemental/bad_response.json
+++ b/adapters/algorix/algorixtest/supplemental/bad_response.json
@@ -20,7 +20,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/algorixtest/supplemental/status_400.json b/adapters/algorix/algorixtest/supplemental/status_400.json
index f384c3b9..2085bf3c 100644
--- a/adapters/algorix/algorixtest/supplemental/status_400.json
+++ b/adapters/algorix/algorixtest/supplemental/status_400.json
@@ -20,7 +20,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/algorixtest/supplemental/status_500.json b/adapters/algorix/algorixtest/supplemental/status_500.json
index ca6cf14b..c7820917 100644
--- a/adapters/algorix/algorixtest/supplemental/status_500.json
+++ b/adapters/algorix/algorixtest/supplemental/status_500.json
@@ -20,7 +20,7 @@
   "httpCalls": [
     {
       "expectedRequest": {
-        "uri": "https://test.com?sid=testSid&token=testToken",
+        "uri": "https://xyz.test.com?sid=testSid&token=testToken",
         "body": {
           "id": "test-request-id",
           "imp": [
diff --git a/adapters/algorix/params_test.go b/adapters/algorix/params_test.go
index 3830b372..c33a3417 100644
--- a/adapters/algorix/params_test.go
+++ b/adapters/algorix/params_test.go
@@ -36,6 +36,8 @@ func TestInvalidParams(t *testing.T) {
 var validParams = []string{
 	`{"sid": "11233", "token": "sin", "placementId": "123", "appId": "abc"}`,
 	`{"sid": "11244", "token": "iad"}`,
+	`{"sid": "11244", "token": "iad", "region": "APAC"}`,
+	`{"sid": "11244", "token": "iad", "region": "USE"}`,
 }
 
 var invalidParams = []string{
@@ -47,4 +49,5 @@ var invalidParams = []string{
 	`{"sid": "11233", "token": "sin", "placementId": 123, "appId": "abc"}`,
 	`{"sid": "11233", "token": "sin", "placementId": "123", "appId": 456}`,
 	`{"sid": "11233", "token": "sin", "placementId": 123, "appId": 456}`,
+	`{"sid": "11233", "token": "sin", "region": 123}`,
 }
diff --git a/adapters/valueimpression/valueimpression_test.go b/adapters/apacdex/apacdex_test.go
similarity index 65%
rename from adapters/valueimpression/valueimpression_test.go
rename to adapters/apacdex/apacdex_test.go
index f4d33864..997302f6 100644
--- a/adapters/valueimpression/valueimpression_test.go
+++ b/adapters/apacdex/apacdex_test.go
@@ -1,4 +1,4 @@
-package valueimpression
+package apacdex
 
 import (
 	"testing"
@@ -9,12 +9,12 @@ import (
 )
 
 func TestJsonSamples(t *testing.T) {
-	bidder, buildErr := Builder(openrtb_ext.BidderValueImpression, config.Adapter{
+	bidder, buildErr := Builder(openrtb_ext.BidderApacdex, config.Adapter{
 		Endpoint: "//host"})
 
 	if buildErr != nil {
 		t.Fatalf("Builder returned unexpected error %v", buildErr)
 	}
 
-	adapterstest.RunJSONBidderTest(t, "valueimpressiontest", bidder)
+	adapterstest.RunJSONBidderTest(t, "apacdextest", bidder)
 }
diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json b/adapters/apacdex/apacdextest/exemplary/banner-and-video.json
similarity index 88%
rename from adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json
rename to adapters/apacdex/apacdextest/exemplary/banner-and-video.json
index fd9d401c..78ce13fd 100644
--- a/adapters/valueimpression/valueimpressiontest/exemplary/banner-and-video.json
+++ b/adapters/apacdex/apacdextest/exemplary/banner-and-video.json
@@ -92,7 +92,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "valueimpression",
+              "seat": "apacdex",
               "bid": [
                 {
                   "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
@@ -101,7 +101,12 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext": {
+                    "prebid": {
+                      "type": "video"
+                    }
+                  }
                 }
               ]
             }
@@ -121,7 +126,12 @@
           "adm": "some-test-ad",
           "crid": "crid_10",
           "w": 300,
-          "h": 250
+          "h": 250,
+          "ext": {
+            "prebid": {
+              "type": "video"
+            }
+          }
         },
         "type": "video"
       }
diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/banner.json b/adapters/apacdex/apacdextest/exemplary/banner.json
similarity index 85%
rename from adapters/valueimpression/valueimpressiontest/exemplary/banner.json
rename to adapters/apacdex/apacdextest/exemplary/banner.json
index 1ef11ade..31b685da 100644
--- a/adapters/valueimpression/valueimpressiontest/exemplary/banner.json
+++ b/adapters/apacdex/apacdextest/exemplary/banner.json
@@ -56,7 +56,7 @@
           "id": "test-request-id",
           "seatbid": [
             {
-              "seat": "valueimpression",
+              "seat": "apacdex",
               "bid": [
                 {
                   "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800",
@@ -65,7 +65,12 @@
                   "adm": "some-test-ad",
                   "crid": "crid_10",
                   "h": 250,
-                  "w": 300
+                  "w": 300,
+                  "ext": {
+                    "prebid": {
+                      "type": "banner"
+                    }
+                  }
                 }
               ]
             }
@@ -87,7 +92,12 @@
             "adm": "some-test-ad",
             "crid": "crid_10",
             "w": 300,
-            "h": 250
+            "h": 250,
+            "ext": {
+              "prebid": {
+                "type": "banner"
+              }
+            }
           },
           "type": "banner"
         }
@@ -95,4 +105,3 @@
     }
   ]
 }
-  
\ No newline at end of file
diff --git a/adapters/valueimpression/valueimpressiontest/exemplary/video.json b/adapters/apacdex/apacdextest/exemplary/video.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/exemplary/video.json
rename to adapters/apacdex/apacdextest/exemplary/video.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/explicit-dimensions.json b/adapters/apacdex/apacdextest/supplemental/explicit-dimensions.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/supplemental/explicit-dimensions.json
rename to adapters/apacdex/apacdextest/supplemental/explicit-dimensions.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-no-bids.json b/adapters/apacdex/apacdextest/supplemental/invalid-response-no-bids.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-no-bids.json
rename to adapters/apacdex/apacdextest/supplemental/invalid-response-no-bids.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-unmarshall-error.json b/adapters/apacdex/apacdextest/supplemental/invalid-response-unmarshall-error.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/supplemental/invalid-response-unmarshall-error.json
rename to adapters/apacdex/apacdextest/supplemental/invalid-response-unmarshall-error.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/no-imps-in-request.json b/adapters/apacdex/apacdextest/supplemental/no-imps-in-request.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/supplemental/no-imps-in-request.json
rename to adapters/apacdex/apacdextest/supplemental/no-imps-in-request.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json b/adapters/apacdex/apacdextest/supplemental/server-error-code.json
similarity index 91%
rename from adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json
rename to adapters/apacdex/apacdextest/supplemental/server-error-code.json
index ea31fdc2..b8656aa7 100644
--- a/adapters/valueimpression/valueimpressiontest/supplemental/server-error-code.json
+++ b/adapters/apacdex/apacdextest/supplemental/server-error-code.json
@@ -46,7 +46,7 @@
 
     "expectedMakeBidsErrors": [
       {
-        "value": "Bad server response: HTTP status 500",
+        "value": "Unexpected status code: 500. Run with request.debug = 1 for more info.",
         "comparison": "literal"
       }
     ]
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/server-no-content.json b/adapters/apacdex/apacdextest/supplemental/server-no-content.json
similarity index 100%
rename from adapters/valueimpression/valueimpressiontest/supplemental/server-no-content.json
rename to adapters/apacdex/apacdextest/supplemental/server-no-content.json
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json b/adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json
similarity index 85%
rename from adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json
rename to adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json
index ef4d3a75..f2842d88 100644
--- a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-mapping.json
+++ b/adapters/apacdex/apacdextest/supplemental/wrong-bid-ext.json
@@ -20,7 +20,6 @@
       }
     ]
   },
-
   "httpCalls": [
     {
       "expectedRequest": {
@@ -29,7 +28,7 @@
           "id": "test-request-id",
           "imp": [
             {
-              "id":"test-imp-id",
+              "id": "test-imp-id",
               "video": {
                 "w": 900,
                 "h": 250,
@@ -54,10 +53,11 @@
               "bid": [
                 {
                   "id": "test-bid-id",
-                  "impid": "BOGUS-IMPID",
+                  "impid": "another-imp-id",
                   "price": 3.5,
                   "w": 900,
-                  "h": 250
+                  "h": 250,
+                  "ext": {}
                 }
               ]
             }
@@ -68,8 +68,8 @@
   ],
   "expectedMakeBidsErrors": [
     {
-      "value": "bid id='test-bid-id' could not find valid impid='BOGUS-IMPID'",
+      "value": "Failed to parse bid mediatype for impression \"another-imp-id\"",
       "comparison": "regex"
     }
-]
+  ]
 }
\ No newline at end of file
diff --git a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json b/adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json
similarity index 89%
rename from adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json
rename to adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json
index 13514ac8..09efa595 100644
--- a/adapters/valueimpression/valueimpressiontest/supplemental/wrong-impression-ext.json
+++ b/adapters/apacdex/apacdextest/supplemental/wrong-impression-ext.json
@@ -19,7 +19,7 @@
 
   "expectedMakeRequestsErrors": [
     {
-      "value": "json: cannot unmarshal number into Go struct field ExtImpValueImpression.siteId of type string",
+      "value": "json: cannot unmarshal number into Go struct field ExtImpApacdex.siteId of type string",
       "comparison": "literal"
     }
   ]
diff --git a/adapters/valueimpression/params_test.go b/adapters/apacdex/params_test.go
similarity index 53%
rename from adapters/valueimpression/params_test.go
rename to adapters/apacdex/params_test.go
index 46471de2..2e5f626e 100644
--- a/adapters/valueimpression/params_test.go
+++ b/adapters/apacdex/params_test.go
@@ -1,4 +1,4 @@
-package valueimpression
+package apacdex
 
 import (
 	"encoding/json"
@@ -7,9 +7,9 @@ import (
 	"github.com/prebid/prebid-server/openrtb_ext"
 )
 
-// This file actually intends to test static/bidder-params/valueimpression.json
-// These also validate the format of the external API: request.imp[i].ext.valueimpression
-// TestValidParams makes sure that the ValueImpression schema accepts all imp.ext fields which we intend to support.
+// This file actually intends to test static/bidder-params/apacdex.json
+// These also validate the format of the external API: request.imp[i].ext.apacdex
+// TestValidParams makes sure that the Apacdex schema accepts all imp.ext fields which we intend to support.
 
 func TestValidParams(t *testing.T) {
 	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
@@ -18,13 +18,13 @@ func TestValidParams(t *testing.T) {
 	}
 
 	for _, validParam := range validParams {
-		if err := validator.Validate(openrtb_ext.BidderValueImpression, json.RawMessage(validParam)); err != nil {
-			t.Errorf("Schema rejected ValueImpression params: %s", validParam)
+		if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(validParam)); err != nil {
+			t.Errorf("Schema rejected Apacdex params: %s", validParam)
 		}
 	}
 }
 
-// TestInvalidParams makes sure that the ValueImpression schema rejects all the imp.ext fields we don't support.
+// TestInvalidParams makes sure that the Apacdex 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 {
@@ -32,7 +32,7 @@ func TestInvalidParams(t *testing.T) {
 	}
 
 	for _, invalidParam := range invalidParams {
-		if err := validator.Validate(openrtb_ext.BidderValueImpression, json.RawMessage(invalidParam)); err == nil {
+		if err := validator.Validate(openrtb_ext.BidderApacdex, json.RawMessage(invalidParam)); err == nil {
 			t.Errorf("Schema allowed unexpected params: %s", invalidParam)
 		}
 	}
@@ -40,6 +40,9 @@ func TestInvalidParams(t *testing.T) {
 
 var validParams = []string{
 	`{"siteId": "123"}`,
+	`{"siteId": "123", "floorPrice": 0.05}`,
+	`{"placementId": "123123"}`,
+	`{"placementId": "123123", "floorPrice": 0.05}`,
 }
 
 var invalidParams = []string{
@@ -47,6 +50,7 @@ var invalidParams = []string{
 	`null`,
 	`true`,
 	`154`,
-	`{"siteId": 123}`, // siteId should be string
+	`{"siteId": 123}`,
 	`{"invalid_param": "123"}`,
+	`{"siteId": "123", "placementId": "123123"}`,
 }
diff --git a/adapters/compass/compass_test.go b/adapters/compass/compass_test.go
new file mode 100644
index 00000000..fce791e5
--- /dev/null
+++ b/adapters/compass/compass_test.go
@@ -0,0 +1,20 @@
+package compass
+
+import (
+	"testing"
+
+	"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.BidderCompass, config.Adapter{
+		Endpoint: "http://sa-lb.deliverimp.com/pserver"})
+
+	if buildErr != nil {
+		t.Fatalf("Builder returned unexpected error %v", buildErr)
+	}
+
+	adapterstest.RunJSONBidderTest(t, "compasstest", bidder)
+}
diff --git a/adapters/compass/compasstest/exemplary/endpointId.json b/adapters/compass/compasstest/exemplary/endpointId.json
new file mode 100644
index 00000000..f02481b3
--- /dev/null
+++ b/adapters/compass/compasstest/exemplary/endpointId.json
@@ -0,0 +1,133 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "iPad"
+        },
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "endpointId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://sa-lb.deliverimp.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "endpointId": "test",
+                                    "type": "network"
+                                }
+                            }
+                        }
+                    ],
+                    "app": {
+                        "id": "1",
+                        "bundle": "com.wls.testwlsapplication"
+                    },
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "iPad"
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250,
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "banner"
+                                        }
+                                    }
+                                }
+                            ],
+                            "seat": "compass"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250,
+                        "ext": {
+                            "prebid": {
+                                "type": "banner"
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/compass/compasstest/exemplary/simple-banner.json b/adapters/compass/compasstest/exemplary/simple-banner.json
new file mode 100644
index 00000000..592570cd
--- /dev/null
+++ b/adapters/compass/compasstest/exemplary/simple-banner.json
@@ -0,0 +1,133 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "iPad"
+        },
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://sa-lb.deliverimp.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "app": {
+                        "id": "1",
+                        "bundle": "com.wls.testwlsapplication"
+                    },
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "iPad"
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250,
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "banner"
+                                        }
+                                    }
+                                }
+                            ],
+                            "seat": "compass"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250,
+                        "ext": {
+                            "prebid": {
+                                "type": "banner"
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/compass/compasstest/exemplary/simple-native.json b/adapters/compass/compasstest/exemplary/simple-native.json
new file mode 100644
index 00000000..0ec8b43c
--- /dev/null
+++ b/adapters/compass/compasstest/exemplary/simple-native.json
@@ -0,0 +1,117 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "iPad"
+        },
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "native": {
+                    "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+                    "ver": "1.1"
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://sa-lb.deliverimp.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "native": {
+                                "request": "{\"ver\":\"1.1\",\"layout\":1,\"adunit\":2,\"plcmtcnt\":6,\"plcmttype\":4,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":75}},{\"id\":2,\"required\":1,\"img\":{\"wmin\":492,\"hmin\":328,\"type\":3,\"mimes\":[\"image/jpeg\",\"image/jpg\",\"image/png\"]}},{\"id\":4,\"required\":0,\"data\":{\"type\":6}},{\"id\":5,\"required\":0,\"data\":{\"type\":7}},{\"id\":6,\"required\":0,\"data\":{\"type\":1,\"len\":20}}]}",
+                                "ver": "1.1"
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "app": {
+                        "id": "1",
+                        "bundle": "com.wls.testwlsapplication"
+                    },
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "iPad"
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 300,
+                                    "h": 250,
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "native"
+                                        }
+                                    }
+                                }
+                            ],
+                            "seat": "compass"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 300,
+                        "h": 250,
+                        "ext": {
+                            "prebid": {
+                                "type": "native"
+                            }
+                        }
+                    },
+                    "type": "native"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/compass/compasstest/exemplary/simple-video.json b/adapters/compass/compasstest/exemplary/simple-video.json
new file mode 100644
index 00000000..0f279496
--- /dev/null
+++ b/adapters/compass/compasstest/exemplary/simple-video.json
@@ -0,0 +1,128 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "iPad"
+        },
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "video": {
+                    "mimes": [
+                        "video/mp4"
+                    ],
+                    "protocols": [
+                        2,
+                        5
+                    ],
+                    "w": 1024,
+                    "h": 576
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ]
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://sa-lb.deliverimp.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "iPad"
+                    },
+                    "app": {
+                        "id": "1",
+                        "bundle": "com.wls.testwlsapplication"
+                    },
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "video": {
+                                "mimes": [
+                                    "video/mp4"
+                                ],
+                                "protocols": [
+                                    2,
+                                    5
+                                ],
+                                "w": 1024,
+                                "h": 576
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ]
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "video"
+                                        }
+                                    }
+                                }
+                            ],
+                            "seat": "compass"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "currency": "USD",
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<VAST version=\"3.0\"><Ad id=\"20001\" sequence=\"1\"><InLine><AdSystem version=\"4.0\"><![CDATA[iabtechlab]]></AdSystem><AdTitle><![CDATA[Inline Simple Ad]]></AdTitle><Impression><![CDATA[]]></Impression><Creatives><Creative id=\"5480\" sequence=\"1\"><Linear><Duration>00:01:00</Duration><MediaFiles><MediaFile id=\"5246\" delivery=\"progressive\" type=\"video/mp4\" bitrate=\"600\" width=\"640\" height=\"360\" minBitrate=\"500\" maxBitrate=\"700\" scalable=\"1\" maintainAspectRatio=\"1\" codec=\"0\"><![CDATA[https://s0.2mdn.net/4253510/google_ddm_animation_480P.mp4]]></MediaFile></MediaFiles><VideoClicks><ClickThrough id=\"blog\"><![CDATA[https://example.com]]></ClickThrough></VideoClicks></Linear></Creative></Creatives></InLine></Ad></VAST>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "ext": {
+                            "prebid": {
+                                "type": "video"
+                            }
+                        }
+                    },
+                    "type": "video"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/compass/compasstest/exemplary/simple-web-banner.json b/adapters/compass/compasstest/exemplary/simple-web-banner.json
new file mode 100644
index 00000000..1896101a
--- /dev/null
+++ b/adapters/compass/compasstest/exemplary/simple-web-banner.json
@@ -0,0 +1,133 @@
+{
+    "mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "tagid": "test",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "site": {
+            "id": "1",
+            "domain": "test.com"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ua": "Ubuntu"
+        }
+    },
+    "httpCalls": [
+        {
+            "expectedRequest": {
+                "uri": "http://sa-lb.deliverimp.com/pserver",
+                "body": {
+                    "id": "test-request-id",
+                    "imp": [
+                        {
+                            "id": "test-imp-id",
+                            "tagid": "test",
+                            "banner": {
+                                "format": [
+                                    {
+                                        "w": 300,
+                                        "h": 250
+                                    },
+                                    {
+                                        "w": 300,
+                                        "h": 600
+                                    }
+                                ]
+                            },
+                            "ext": {
+                                "bidder": {
+                                    "placementId": "test",
+                                    "type": "publisher"
+                                }
+                            }
+                        }
+                    ],
+                    "site": {
+                        "id": "1",
+                        "domain": "test.com"
+                    },
+                    "device": {
+                        "ip": "123.123.123.123",
+                        "ua": "Ubuntu"
+                    }
+                }
+            },
+            "mockResponse": {
+                "status": 200,
+                "body": {
+                    "id": "test-request-id",
+                    "seatbid": [
+                        {
+                            "bid": [
+                                {
+                                    "id": "test_bid_id",
+                                    "impid": "test-imp-id",
+                                    "price": 0.27543,
+                                    "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+                                    "cid": "test_cid",
+                                    "crid": "test_crid",
+                                    "dealid": "test_dealid",
+                                    "w": 468,
+                                    "h": 60,
+                                    "ext": {
+                                        "prebid": {
+                                            "type": "banner"
+                                        }
+                                    }
+                                }
+                            ],
+                            "seat": "compass"
+                        }
+                    ],
+                    "cur": "USD"
+                }
+            }
+        }
+    ],
+    "expectedBidResponses": [
+        {
+            "bids": [
+                {
+                    "bid": {
+                        "id": "test_bid_id",
+                        "impid": "test-imp-id",
+                        "price": 0.27543,
+                        "adm": "<iframe id=\"adm-banner-1\" width=\"468\" height=\"60\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=bc2d316f39931a07d9a8dd249bf85fc0\"></iframe>",
+                        "cid": "test_cid",
+                        "crid": "test_crid",
+                        "dealid": "test_dealid",
+                        "w": 468,
+                        "h": 60,
+                        "ext": {
+                            "prebid": {
+                                "type": "banner"
+                            }
+                        }
+                    },
+                    "type": "banner"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/adapters/compass/compasstest/supplemental/bad_media_type.json b/adapters/compass/compasstest/supplemental/bad_media_type.json
new file mode 100644
index 00000000..0bfaec4f
--- /dev/null
+++ b/adapters/compass/compasstest/supplemental/bad_media_type.json
@@ -0,0 +1,86 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://sa-lb.deliverimp.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 200,
+			"body": {
+                "id": "test-request-id",
+                "seatbid": [
+                    {
+                        "bid": [
+                            {
+                                "id": "test_bid_id",
+                                "impid": "test-imp-id",
+                                "price": 0.27543,
+                                "adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"http://sa-lb.deliverimp.com/pserver&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
+                                "cid": "test_cid",
+                                "crid": "test_crid",
+                                "dealid": "test_dealid",
+                                "w": 300,
+                                "h": 250,
+                                "ext": {
+                                    "prebid": {
+                                        "type": "banner"
+                                    }
+                                }
+                            }
+                        ],
+                        "seat": "compass"
+                    }
+                ],
+                "cur": "USD"
+            }
+        }
+    }],
+    "expectedMakeBidsErrors": [
+        {
+          "value": "Failed to find impression \"test-imp-id\"",
+          "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/compass/compasstest/supplemental/bad_response.json b/adapters/compass/compasstest/supplemental/bad_response.json
new file mode 100644
index 00000000..3c660338
--- /dev/null
+++ b/adapters/compass/compasstest/supplemental/bad_response.json
@@ -0,0 +1,84 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://sa-lb.deliverimp.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 200,
+			"body": ""
+        }
+    }],
+    "expectedMakeBidsErrors": [
+        {
+          "value": "json: cannot unmarshal string into Go value of type openrtb2.BidResponse",
+          "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/compass/compasstest/supplemental/status-204.json b/adapters/compass/compasstest/supplemental/status-204.json
new file mode 100644
index 00000000..1ff5c55a
--- /dev/null
+++ b/adapters/compass/compasstest/supplemental/status-204.json
@@ -0,0 +1,79 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://sa-lb.deliverimp.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 204,
+			"body": {}
+		}
+    }],
+    "expectedBidResponses": []
+}
diff --git a/adapters/compass/compasstest/supplemental/status-not-200.json b/adapters/compass/compasstest/supplemental/status-not-200.json
new file mode 100644
index 00000000..51f648de
--- /dev/null
+++ b/adapters/compass/compasstest/supplemental/status-not-200.json
@@ -0,0 +1,84 @@
+{
+	"mockBidRequest": {
+        "id": "test-request-id",
+        "imp": [
+            {
+                "id": "test-imp-id",
+                "banner": {
+                    "format": [
+                        {
+                            "w": 300,
+                            "h": 250
+                        },
+                        {
+                            "w": 300,
+                            "h": 600
+                        }
+                    ]
+                },
+                "ext": {
+                    "bidder": {
+                        "placementId": "test"
+                    }
+                }
+            }
+        ],
+        "app": {
+            "id": "1",
+            "bundle": "com.wls.testwlsapplication"
+        },
+        "device": {
+            "ip": "123.123.123.123",
+            "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+        }
+    },
+	"httpCalls": [{
+		"expectedRequest": {
+			"uri": "http://sa-lb.deliverimp.com/pserver",
+			"body": {
+                "id": "test-request-id",
+                "imp": [
+                    {
+                        "id": "test-imp-id",
+                        "banner": {
+                            "format": [
+                                {
+                                    "w": 300,
+                                    "h": 250
+                                },
+                                {
+                                    "w": 300,
+                                    "h": 600
+                                }
+                            ]
+                        },
+                        "ext": {
+                            "bidder": {
+                                "placementId": "test",
+                                "type": "publisher"
+                            }
+                        }
+                    }
+                ],
+                "app": {
+                    "id": "1",
+                    "bundle": "com.wls.testwlsapplication"
+                },
+                "device": {
+                    "ip": "123.123.123.123",
+                    "ifa": "sdjfksdf-dfsds-dsdg-dsgg"
+                }
+            }
+		},
+		"mockResponse": {
+			"status": 404,
+			"body": {}
+		}
+    }],
+    "expectedMakeBidsErrors": [
+        {
+          "value": "Unexpected status code: 404. Run with request.debug = 1 for more info.",
+          "comparison": "literal"
+        }
+    ]
+}
diff --git a/adapters/compass/params_test.go b/adapters/compass/params_test.go
new file mode 100644
index 00000000..fca398b0
--- /dev/null
+++ b/adapters/compass/params_test.go
@@ -0,0 +1,47 @@
+package compass
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/prebid/prebid-server/openrtb_ext"
+)
+
+func TestValidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range validParams {
+		if err := validator.Validate(openrtb_ext.BidderCompass, json.RawMessage(p)); err != nil {
+			t.Errorf("Schema rejected valid params: %s", p)
+		}
+	}
+}
+
+func TestInvalidParams(t *testing.T) {
+	validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
+	if err != nil {
+		t.Fatalf("Failed to fetch the json schema. %v", err)
+	}
+
+	for _, p := range invalidParams {
+		if err := validator.Validate(openrtb_ext.BidderCompass, json.RawMessage(p)); err == nil {
+			t.Errorf("Schema allowed invalid params: %s", p)
+		}
+	}
+}
+
+var validParams = []string{
+	`{"placementId": "test"}`,
+	`{"placementId": "1"}`,
+	`{"endpointId": "test"}`,
+	`{"endpointId": "1"}`,
+}
+
+var invalidParams = []string{
+	`{"placementId": 42}`,
+	`{"endpointId": 42}`,
+	`{"placementId": "1", "endpointId": "1"}`,
+}
diff --git a/adapters/marsmedia/marsmediatest/exemplary/simple-banner-int-param.json b/adapters/marsmedia/marsmediatest/exemplary/simple-banner-int-param.json
new file mode 100644
index 00000000..4804a873
--- /dev/null
+++ b/adapters/marsmedia/marsmediatest/exemplary/simple-banner-int-param.json
@@ -0,0 +1,106 @@
+{
+    "mockBidRequest": {
+      "id": "test-request-id",
+      "imp": [
+        {
+          "id": "test-imp-id",
+          "at" : 1,
+          "banner": {
+            "format": [
+              {
+                  "w": 300,
+                  "h": 250
+              }
+            ]
+          },
+          "ext": {
+            "bidder": {
+              "zoneId": 9999
+            }
+          }
+        }
+      ]
+    },
+  
+    "httpCalls": [
+      {
+        "expectedRequest": {
+          "uri": "http://bid306.rtbsrv.com/bidder/?bid=f3xtet&zone=9999",
+          "body": {
+            "id": "test-request-id",
+            "at" : 1,
+            "imp": [
+              {
+                "id": "test-imp-id",
+                "banner": {
+                  "format": [
+                    {
+                        "w": 300,
+                        "h": 250
+                    }
+                  ],
+                  "w": 300,
+                  "h": 250
+                },
+                "ext": {
+                  "bidder": {
+                    "zoneId": 9999
+                  }
+                }
+              }
+            ]
+          }
+        },
+        "mockResponse": {
+          "status": 200,
+          "body": {
+            "id": "test-request-id",
+            "seatbid": [
+              {
+                "seat": "marsmedia",
+                "bid": [{
+                  "id": "1",
+                  "impid": "test-imp-id",
+                  "price": 1.1,
+                  "adid": "17586",
+                  "adm": "some-test-ad",
+                  "nurl" : "some-test-nurl",
+                  "iurl" : "some-test-iurl",
+                  "adomain": ["wooga.com"],
+                  "cid": "17586",
+                  "crid": "17586",
+                  "h": 250,
+                  "w": 300
+                }]
+              }
+            ],
+            "bidid": "5778926625248726496",
+            "cur": "USD"
+          }
+        }
+      }
+    ],
+  
+    "expectedBidResponses": [
+      {
+        "bids": [{
+          "bid": {
+            "id": "1",
+            "impid": "test-imp-id",
+            "price": 1.1,
+            "adm": "some-test-ad",
+            "adid": "17586",
+            "adomain": ["wooga.com"],
+            "cid": "17586",
+            "crid": "17586",
+            "nurl" : "some-test-nurl",
+            "iurl" : "some-test-iurl",
+            "h": 250,
+            "w": 300
+          },
+          "type": "banner"
+        }]
+      }
+    ]
+  }
+  
\ No newline at end of file
diff --git a/adapters/marsmedia/marsmediatest/supplemental/missing-param.json b/adapters/marsmedia/marsmediatest/supplemental/missing-param.json
index b88fba5a..e68b3f52 100644
--- a/adapters/marsmedia/marsmediatest/supplemental/missing-param.json
+++ b/adapters/marsmedia/marsmediatest/supplemental/missing-param.json
@@ -27,7 +27,7 @@
   },
   "expectedMakeRequestsErrors": [
     {
-      "value": "zoneId is empty",
+      "value": "ext.bidder.zoneId not provided",
       "comparison": "literal"
     }
   ]
diff --git a/adapters/marsmedia/params_test.go b/adapters/marsmedia/params_test.go
index 78acd72e..4a91ed6d 100644
--- a/adapters/marsmedia/params_test.go
+++ b/adapters/marsmedia/params_test.go
@@ -41,10 +41,10 @@ func TestInvalidParams(t *testing.T) {
 
 var validParams = []string{
 	`{"zoneId": "9999"}`,
+	`{"zoneId": 9999}`,
 }
 
 var invalidParams = []string{
-	`{"zoneId": 100}`,
 	`{"zoneId": true}`,
 	``,
 	`null`,
diff --git a/adapters/openrtb_util_test.go b/adapters/openrtb_util_test.go
index e09149a7..4a5d33b0 100644
--- a/adapters/openrtb_util_test.go
+++ b/adapters/openrtb_util_test.go
@@ -2,116 +2,100 @@ package adapters
 
 import (
 	"encoding/json"
-	"github.com/mxmCherry/openrtb/v15/openrtb2"
-	"reflect"
+	"errors"
 	"testing"
+
+	"github.com/mxmCherry/openrtb/v15/openrtb2"
+	"github.com/stretchr/testify/assert"
 )
 
-func TestExtractAdapterReqBidderParams(t *testing.T) {
-	type args struct {
-		bidRequest *openrtb2.BidRequest
-	}
+func TestExtractAdapterReqBidderParamsMap(t *testing.T) {
 	tests := []struct {
-		name    string
-		args    args
-		want    map[string]json.RawMessage
-		wantErr bool
+		name            string
+		givenBidRequest *openrtb2.BidRequest
+		want            map[string]json.RawMessage
+		wantErr         error
 	}{
 		{
-			name: "extract bidder params from nil req",
-			args: args{
-				bidRequest: nil,
-			},
-			want:    nil,
-			wantErr: true,
+			name:            "nil req",
+			givenBidRequest: nil,
+			want:            nil,
+			wantErr:         errors.New("error bidRequest should not be nil"),
 		},
 		{
-			name: "extract bidder params from nil req.Ext",
-			args: args{
-				bidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{}}`)},
-			},
-			want:    nil,
-			wantErr: false,
+			name:            "nil req.ext",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{}}`)},
+			want:            nil,
+			wantErr:         nil,
 		},
 		{
-			name: "extract bidder params from req.Ext for input request in adapter code",
-			args: args{
-				bidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"bidderparams": {"profile": 1234, "version": 1}}}`)},
-			},
-			want:    map[string]json.RawMessage{"profile": json.RawMessage(`1234`), "version": json.RawMessage(`1`)},
-			wantErr: false,
+			name:            "malformed req.ext",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage("malformed")},
+			want:            nil,
+			wantErr:         errors.New("error decoding Request.ext : invalid character 'm' looking for beginning of value"),
+		},
+		{
+			name:            "extract bidder params from req.Ext for input request in adapter code",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"bidderparams": {"profile": 1234, "version": 1}}}`)},
+			want:            map[string]json.RawMessage{"profile": json.RawMessage(`1234`), "version": json.RawMessage(`1`)},
+			wantErr:         nil,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, err := ExtractAdapterReqBidderParams(tt.args.bidRequest)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("ExtractReqExtBidderParams() error = %v, wantErr = %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("ExtractReqExtBidderParams() got = %v, want = %v", got, tt.want)
-			}
+			got, err := ExtractReqExtBidderParamsMap(tt.givenBidRequest)
+			assert.Equal(t, tt.wantErr, err, "err")
+			assert.Equal(t, tt.want, got, "result")
 		})
 	}
 }
 
-func TestExtractReqExtBidderParams(t *testing.T) {
-	type args struct {
-		request *openrtb2.BidRequest
-	}
+func TestExtractReqExtBidderParamsMap(t *testing.T) {
 	tests := []struct {
-		name    string
-		args    args
-		want    map[string]map[string]json.RawMessage
-		wantErr bool
+		name            string
+		givenBidRequest *openrtb2.BidRequest
+		want            map[string]map[string]json.RawMessage
+		wantErr         error
 	}{
 		{
-			name: "extract bidder params from nil req",
-			args: args{
-				request: nil,
-			},
-			want:    nil,
-			wantErr: true,
+			name:            "nil req",
+			givenBidRequest: nil,
+			want:            nil,
+			wantErr:         errors.New("error bidRequest should not be nil"),
 		},
 		{
-			name: "extract bidder params from nil req.Ext.prebid",
-			args: args{
-				request: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{}}`)},
-			},
-			want:    nil,
-			wantErr: false,
+			name:            "nil req.ext",
+			givenBidRequest: &openrtb2.BidRequest{Ext: nil},
+			want:            nil,
+			wantErr:         nil,
 		},
 		{
-			name: "extract bidder params from nil req.Ext",
-			args: args{
-				request: &openrtb2.BidRequest{Ext: nil},
-			},
-			want:    nil,
-			wantErr: false,
+			name:            "malformed req.ext",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage("malformed")},
+			want:            nil,
+			wantErr:         errors.New("error decoding Request.ext : invalid character 'm' looking for beginning of value"),
 		},
 		{
-			name: "extract bidder params from req.Ext for input request before adapter code",
-			args: args{
-				request: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"bidderparams": {"pubmatic": {"profile": 1234, "version": 1}, "appnexus": {"key1": 123, "key2": {"innerKey1":"innerValue1"} } }}}`)},
-			},
+			name:            "nil req.ext.prebid",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{}}`)},
+			want:            nil,
+			wantErr:         nil,
+		},
+		{
+			name:            "extract bidder params from req.Ext for input request before adapter code",
+			givenBidRequest: &openrtb2.BidRequest{Ext: json.RawMessage(`{"prebid":{"bidderparams": {"pubmatic": {"profile": 1234, "version": 1}, "appnexus": {"key1": 123, "key2": {"innerKey1":"innerValue1"} } }}}`)},
 			want: map[string]map[string]json.RawMessage{
 				"pubmatic": {"profile": json.RawMessage(`1234`), "version": json.RawMessage(`1`)},
 				"appnexus": {"key1": json.RawMessage(`123`), "key2": json.RawMessage(`{"innerKey1":"innerValue1"}`)},
 			},
-			wantErr: false,
+			wantErr: nil,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, err := ExtractReqExtBidderParams(tt.args.request)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("ExtractReqExtBidderParams() error = %v, wantErr = %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("ExtractReqExtBidderParams() got = %v, want = %v", got, tt.want)
-			}
+			got, err := ExtractReqExtBidderParamsEmbeddedMap(tt.givenBidRequest)
+			assert.Equal(t, tt.wantErr, err, "err")
+			assert.Equal(t, tt.want, got, "result")
 		})
 	}
 }
diff --git a/adapters/orbidder/orbidder_test.go b/adapters/orbidder/orbidder_test.go
index 0eaed23a..bbda1c06 100644
--- a/adapters/orbidder/orbidder_test.go
+++ b/adapters/orbidder/orbidder_test.go
@@ -2,6 +2,10 @@ package orbidder
 
 import (
 	"encoding/json"
+	"errors"
+	"github.com/mxmCherry/openrtb/v15/openrtb2"
+	"github.com/prebid/prebid-server/adapters"
+	"github.com/stretchr/testify/mock"
 	"testing"
 
 	"github.com/prebid/prebid-server/adapters/adapterstest"
@@ -22,6 +26,16 @@ func TestUnmarshalOrbidderExtImp(t *testing.T) {
 	}, impExt)
 }
 
+func TestPreprocessExtensions(t *testing.T) {
+	for name, tc := range testCasesExtension {
+		t.Run(name, func(t *testing.T) {
+			imp := tc.imp
+			err := preprocessExtensions(&imp)
+			tc.assertError(t, err)
+		})
+	}
+}
+
 func TestJsonSamples(t *testing.T) {
 	bidder, buildErr := Builder(openrtb_ext.BidderOrbidder, config.Adapter{
 		Endpoint: "https://orbidder-test"})
@@ -32,3 +46,136 @@ func TestJsonSamples(t *testing.T) {
 
 	adapterstest.RunJSONBidderTest(t, "orbiddertest", bidder)
 }
+
+var testCasesCurrency = map[string]struct {
+	imp         openrtb2.Imp
+	setMock     func(m *mock.Mock)
+	expectedImp openrtb2.Imp
+	assertError func(t assert.TestingT, err error, msgAndArgs ...interface{}) bool
+}{
+	"EUR: no bidfloor, no currency": {
+		imp: openrtb2.Imp{
+			BidFloor:    0,
+			BidFloorCur: "",
+		},
+		setMock: func(m *mock.Mock) {},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    0,
+			BidFloorCur: "EUR",
+		},
+		assertError: assert.NoError,
+	},
+	"EUR: bidfloor, no currency": {
+		imp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "",
+		},
+		setMock: func(m *mock.Mock) {},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "EUR",
+		},
+		assertError: assert.NoError,
+	},
+	"EUR: bidfloor and currency": {
+		imp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "EUR",
+		},
+		setMock: func(m *mock.Mock) {},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "EUR",
+		},
+		assertError: assert.NoError,
+	},
+	"USD: bidfloor with currency": {
+		imp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "USD",
+		},
+		setMock: func(m *mock.Mock) {
+			m.On("GetRate", "USD", "EUR").Return(2.5, nil)
+		},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    2.5,
+			BidFloorCur: "EUR",
+		},
+		assertError: assert.NoError,
+	},
+	"USD: no bidfloor": {
+		imp: openrtb2.Imp{
+			BidFloor:    0,
+			BidFloorCur: "USD",
+		},
+		setMock: func(m *mock.Mock) {},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    0,
+			BidFloorCur: "EUR",
+		},
+		assertError: assert.NoError,
+	},
+	"ABC: invalid currency code": {
+		imp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "ABC",
+		},
+		setMock: func(m *mock.Mock) {
+			m.On("GetRate", "ABC", "EUR").Return(0.0, errors.New("currency conversion error"))
+		},
+		expectedImp: openrtb2.Imp{
+			BidFloor:    1,
+			BidFloorCur: "ABC",
+		},
+		assertError: assert.Error,
+	},
+}
+
+var testCasesExtension = map[string]struct {
+	imp         openrtb2.Imp
+	assertError func(t assert.TestingT, err error, msgAndArgs ...interface{}) bool
+}{
+	"Valid Orbidder Extension": {
+		imp: openrtb2.Imp{
+			Ext: json.RawMessage(`{"bidder":{"accountId":"orbidder-test", "placementId":"center-banner", "bidfloor": 0.1}}`),
+		},
+		assertError: assert.NoError,
+	},
+	"Invalid Orbidder Extension": {
+		imp: openrtb2.Imp{
+			Ext: json.RawMessage(`{"there's'":{"something":"strange", "in the":"neighbourhood", "who you gonna call?": 0.1}}`),
+		},
+		assertError: assert.Error,
+	},
+}
+
+func TestPreprocessBidFloorCurrency(t *testing.T) {
+	for name, tc := range testCasesCurrency {
+		t.Run(name, func(t *testing.T) {
+			imp := tc.imp
+			mockConversions := &mockCurrencyConversion{}
+			tc.setMock(&mockConversions.Mock)
+			extraRequestInfo := adapters.ExtraRequestInfo{
+				CurrencyConversions: mockConversions,
+			}
+			err := preprocessBidFloorCurrency(&imp, &extraRequestInfo)
+			assert.True(t, mockConversions.AssertExpectations(t))
+			tc.assertError(t, err)
+			assert.Equal(t, tc.expectedImp, imp)
+		})
+	}
+}
+
+type mockCurrencyConversion struct {
+	mock.Mock
+}
+
+func (m *mockCurrencyConversion) GetRate(from string, to string) (float64, error) {
+	args := m.Called(from, to)
+	return args.Get(0).(float64), args.Error(1)
+}
+
+func (m *mockCurrencyConversion) GetRates() *map[string]map[string]float64 {
+	args := m.Called()
+	return args.Get(0).(*map[string]map[string]float64)
+}
diff --git a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
index 8697bff3..2315a52c 100644
--- a/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
+++ b/adapters/orbidder/orbiddertest/exemplary/simple-app-banner.json
@@ -51,6 +51,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json
index 69496c4f..dc199d24 100644
--- a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json
+++ b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-request-example.json
@@ -51,6 +51,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json
index d1c57a54..61e70d31 100644
--- a/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json
+++ b/adapters/orbidder/orbiddertest/supplemental/dsp-bad-response-example.json
@@ -51,6 +51,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json
index 20ea36ab..66a766a9 100644
--- a/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json
+++ b/adapters/orbidder/orbiddertest/supplemental/dsp-internal-server-error-example.json
@@ -51,6 +51,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json b/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json
index 6bc0482d..7944db44 100644
--- a/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json
+++ b/adapters/orbidder/orbiddertest/supplemental/dsp-invalid-accountid-example.json
@@ -51,6 +51,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json b/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json
deleted file mode 100644
index 0c5cf6d2..00000000
--- a/adapters/orbidder/orbiddertest/supplemental/empty-imp-request-error.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "mockBidRequest": {
-    "id": "test-request-id",
-    "imp": [
-    ],
-    "app": {
-      "bundle": "com.prebid"
-    },
-    "device": {
-      "ifa":"87857b31-8942-4646-ae80-ab9c95bf3fab"
-    }
-  },
-  "expectedMakeRequestsErrors": [
-    {
-      "value": "No impressions in request",
-      "comparison": "literal"
-    }
-  ]
-}
diff --git a/adapters/orbidder/orbiddertest/supplemental/no-content-response.json b/adapters/orbidder/orbiddertest/supplemental/no-content-response.json
index f3b1b287..0a1e5f0f 100644
--- a/adapters/orbidder/orbiddertest/supplemental/no-content-response.json
+++ b/adapters/orbidder/orbiddertest/supplemental/no-content-response.json
@@ -51,6 +51,7 @@
                                     }
                                 ]
                             },
+                            "bidfloorcur": "EUR",
                             "ext": {
                                 "bidder": {
                                     "accountId": "orbidder-test",
diff --git a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
index b6db9f48..1ea133ab 100644
--- a/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
+++ b/adapters/orbidder/orbiddertest/supplemental/valid-and-invalid-imps.json
@@ -57,6 +57,7 @@
                   }
                 ]
               },
+              "bidfloorcur": "EUR",
               "ext": {
                 "bidder": {
                   "accountId": "orbidder-test",
diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go
index af68d693..a25bb406 100644
--- a/endpoints/openrtb2/auction_test.go
+++ b/endpoints/openrtb2/auction_test.go
@@ -1146,6 +1146,301 @@ func TestStoredRequests(t *testing.T) {
 	}
 }
 
+func TestMergeBidderParams(t *testing.T) {
+	testCases := []struct {
+		description         string
+		givenRequest        openrtb2.BidRequest
+		expectedRequestImps []openrtb2.Imp
+	}{
+		{
+			description: "No Request Params",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+		},
+		{
+			description: "No Request Params - Empty Object",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+		},
+		{
+			description: "Malformed Request Params",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":malformed}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+		},
+		{
+			description: "No Imps",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{},
+		},
+		{
+			description: "One Imp - imp.ext Modified",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1,"b":2}}`)}},
+		},
+		{
+			description: "One Imp - imp.ext.prebid.bidder Modified",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidder1":{"a":1}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"prebid":{"bidder":{"bidder1":{"a":1,"b":2}}}}`)}},
+		},
+		{
+			description: "One Imp - imp.ext + imp.ext.prebid.bidder Modified - Different Bidders",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1},"prebid":{"bidder":{"bidder2":{"a":"one"}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2},"bidder2":{"b":"two"}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1,"b":2},"prebid":{"bidder":{"bidder2":{"a":"one","b":"two"}}}}`)}},
+		},
+		{
+			description: "One Imp - imp.ext + imp.ext.prebid.bidder Modified - Same Bidder",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1},"prebid":{"bidder":{"bidder1":{"a":"one"}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1,"b":2},"prebid":{"bidder":{"bidder1":{"a":"one","b":2}}}}`)}},
+		},
+		{
+			description: "One Imp - No imp.ext",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{{ID: "1"}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{{ID: "1"}},
+		},
+		{
+			description: "Multiple Imps - Modified Mixed",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{
+					{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1},"prebid":{"bidder":{"bidder1":{"a":"one"}}}}`)},
+					{ID: "2", Ext: json.RawMessage(`{"bidder2":{"a":1,"b":"existing"},"prebid":{"bidder":{"bidder2":{"a":"one"}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2},"bidder2":{"b":"two"}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{
+				{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1,"b":2},"prebid":{"bidder":{"bidder1":{"a":"one","b":2}}}}`)},
+				{ID: "2", Ext: json.RawMessage(`{"bidder2":{"a":1,"b":"existing"},"prebid":{"bidder":{"bidder2":{"a":"one","b":"two"}}}}`)}},
+		},
+		{
+			description: "Multiple Imps - None Modified Mixed",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{
+					{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1},"prebid":{"bidder":{"bidder2":{"a":"one"}}}}`)},
+					{ID: "2", Ext: json.RawMessage(`{"bidder1":{"a":2},"prebid":{"bidder":{"bidder2":{"a":"two"}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder3":{"c":3}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{
+				{ID: "1", Ext: json.RawMessage(`{"bidder1":{"a":1},"prebid":{"bidder":{"bidder2":{"a":"one"}}}}`)},
+				{ID: "2", Ext: json.RawMessage(`{"bidder1":{"a":2},"prebid":{"bidder":{"bidder2":{"a":"two"}}}}`)}},
+		},
+		{
+			description: "Multiple Imps - One Malformed",
+			givenRequest: openrtb2.BidRequest{
+				Imp: []openrtb2.Imp{
+					{ID: "1", Ext: json.RawMessage(`malformed`)},
+					{ID: "2", Ext: json.RawMessage(`{"bidder2":{"a":1,"b":"existing"},"prebid":{"bidder":{"bidder2":{"a":"one"}}}}`)}},
+				Ext: json.RawMessage(`{"prebid":{"bidderparams":{"bidder1":{"b":2},"bidder2":{"b":"two"}}}}`),
+			},
+			expectedRequestImps: []openrtb2.Imp{
+				{ID: "1", Ext: json.RawMessage(`malformed`)},
+				{ID: "2", Ext: json.RawMessage(`{"bidder2":{"a":1,"b":"existing"},"prebid":{"bidder":{"bidder2":{"a":"one","b":"two"}}}}`)}},
+		},
+	}
+
+	for _, test := range testCases {
+		actualErr := mergeBidderParams(&openrtb_ext.RequestWrapper{BidRequest: &test.givenRequest})
+
+		// errors are only possible from the marshal operation, which is not testable
+		assert.NoError(t, actualErr, test.description+":err")
+
+		assert.Equal(t, test.givenRequest.Imp, test.expectedRequestImps, test.description+":imps")
+	}
+}
+
+func TestAddMissingReqExtParamsInImpExtPrebid(t *testing.T) {
+	testCases := []struct {
+		description            string
+		givenImpExtByBidder    map[string]json.RawMessage
+		givenReqExtParams      map[string]map[string]json.RawMessage
+		expectedModified       bool
+		expectedImpExtByBidder map[string]json.RawMessage
+	}{
+		{
+			description:            "No Prebid Section",
+			givenImpExtByBidder:    map[string]json.RawMessage{},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{},
+		},
+		{
+			description:            "Malformed Prebid Section",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`malformed`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`malformed`)},
+		},
+		{
+			description:            "No Prebid Bidder Section",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{}`)},
+		},
+		{
+			description:            "Malformed Prebid Bidder Section",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder": malformed}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder": malformed}`)},
+		},
+		{
+			description:            "One Bidder - Modified (no collision)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1}}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       true,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1,"b":2}}}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (imp.ext wins)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1,"b":2}}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`4`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1,"b":2}}}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (reserved bidder ignored)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"gpid":{"a":1}}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"gpid": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"gpid":{"a":1}}}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (reserved bidder ignored - not embedded object)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"gpid":1}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"gpid": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"gpid":1}}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (malformed ignored)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":malformed}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":malformed}}`)},
+		},
+		{
+			description:            "Multiple Bidders - Mixed",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1},"bidder2":{"a":"one","b":"two"}}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}, "bidder2": {"b": json.RawMessage(`"three"`)}},
+			expectedModified:       true,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1,"b":2},"bidder2":{"a":"one","b":"two"}}}`)},
+		},
+		{
+			description:            "Multiple Bidders - None Modified",
+			givenImpExtByBidder:    map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1},"bidder2":{"a":"one","b":"two"}}}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"prebid": json.RawMessage(`{"bidder":{"bidder1":{"a":1},"bidder2":{"a":"one","b":"two"}}}`)},
+		},
+	}
+
+	for _, test := range testCases {
+		actualModified, actualErr := addMissingReqExtParamsInImpExtPrebid(test.givenImpExtByBidder, test.givenReqExtParams)
+
+		// errors are only possible from the marshal operation, which is not testable
+		assert.NoError(t, actualErr, test.description+":err")
+
+		assert.Equal(t, test.expectedModified, actualModified, test.description+":modified")
+		assert.Equal(t, test.expectedImpExtByBidder, test.givenImpExtByBidder, test.description+":imp.ext")
+	}
+}
+
+func TestAddMissingReqExtParamsInImpExt(t *testing.T) {
+	testCases := []struct {
+		description            string
+		givenImpExtByBidder    map[string]json.RawMessage
+		givenReqExtParams      map[string]map[string]json.RawMessage
+		expectedModified       bool
+		expectedImpExtByBidder map[string]json.RawMessage
+	}{
+		{
+			description:            "One Bidder - Modified (no collision)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       true,
+			expectedImpExtByBidder: map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1,"b":2}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (imp.ext wins)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1,"b":2}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`4`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1,"b":2}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (reserved bidder ignored)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"gpid": json.RawMessage(`{"a":1}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"gpid": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"gpid": json.RawMessage(`{"a":1}`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (reserved bidder ignored - not embedded object)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"gpid": json.RawMessage(`1`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"gpid": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"gpid": json.RawMessage(`1`)},
+		},
+		{
+			description:            "One Bidder - Not Modified (malformed ignored)",
+			givenImpExtByBidder:    map[string]json.RawMessage{"bidder1": json.RawMessage(`malformed`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"bidder1": json.RawMessage(`malformed`)},
+		},
+		{
+			description:            "Multiple Bidders - Mixed",
+			givenImpExtByBidder:    map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1}`), "bidder2": json.RawMessage(`{"a":"one","b":"two"}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{"bidder1": {"b": json.RawMessage(`2`)}, "bidder2": {"b": json.RawMessage(`"three"`)}},
+			expectedModified:       true,
+			expectedImpExtByBidder: map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1,"b":2}`), "bidder2": json.RawMessage(`{"a":"one","b":"two"}`)},
+		},
+		{
+			description:            "Multiple Bidders - None Modified",
+			givenImpExtByBidder:    map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1}`), "bidder2": json.RawMessage(`{"a":"one","b":"two"}`)},
+			givenReqExtParams:      map[string]map[string]json.RawMessage{},
+			expectedModified:       false,
+			expectedImpExtByBidder: map[string]json.RawMessage{"bidder1": json.RawMessage(`{"a":1}`), "bidder2": json.RawMessage(`{"a":"one","b":"two"}`)},
+		},
+	}
+
+	for _, test := range testCases {
+		actualModified, actualErr := addMissingReqExtParamsInImpExt(test.givenImpExtByBidder, test.givenReqExtParams)
+
+		// errors are only possible from the marshal operation, which is not testable
+		assert.NoError(t, actualErr, test.description+":err")
+
+		assert.Equal(t, test.expectedModified, actualModified, test.description+":modified")
+		assert.Equal(t, test.expectedImpExtByBidder, test.givenImpExtByBidder, test.description+":imp.ext")
+	}
+}
+
+//impExtByBidder map[string]json.RawMessage, reqExtParams map[string]map[string]json.RawMessage) (bool, error) {
+
 func TestValidateRequest(t *testing.T) {
 	deps := &endpointDeps{
 		fakeUUIDGenerator{},
@@ -4048,51 +4343,33 @@ func TestValidateBanner(t *testing.T) {
 }
 
 func TestParseRequestMergeBidderParams(t *testing.T) {
-	type args struct {
-		reqBody string
-	}
 	tests := []struct {
-		name           string
-		args           args
-		expectedImpExt json.RawMessage
-		expectedReqExt json.RawMessage
-		errL           int
+		name               string
+		givenRequestBody   string
+		expectedImpExt     json.RawMessage
+		expectedReqExt     json.RawMessage
+		expectedErrorCount int
 	}{
 		{
-			name: "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder",
-			args: args{
-				reqBody: validRequest(t, "req-ext-bidder-params.json"),
-			},
-			expectedImpExt: getObject(t, "req-ext-bidder-params.json", "expectedImpExt"),
-			expectedReqExt: getObject(t, "req-ext-bidder-params.json", "expectedReqExt"),
-			errL:           0,
+			name:               "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder",
+			givenRequestBody:   validRequest(t, "req-ext-bidder-params.json"),
+			expectedImpExt:     getObject(t, "req-ext-bidder-params.json", "expectedImpExt"),
+			expectedReqExt:     getObject(t, "req-ext-bidder-params.json", "expectedReqExt"),
+			expectedErrorCount: 0,
 		},
 		{
-			name: "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder with preference for imp[].ext.prebid.bidder params",
-			args: args{
-				reqBody: validRequest(t, "req-ext-bidder-params-merge.json"),
-			},
-			expectedImpExt: getObject(t, "req-ext-bidder-params-merge.json", "expectedImpExt"),
-			expectedReqExt: getObject(t, "req-ext-bidder-params-merge.json", "expectedReqExt"),
-			errL:           0,
+			name:               "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder with preference for imp[].ext.prebid.bidder params",
+			givenRequestBody:   validRequest(t, "req-ext-bidder-params-merge.json"),
+			expectedImpExt:     getObject(t, "req-ext-bidder-params-merge.json", "expectedImpExt"),
+			expectedReqExt:     getObject(t, "req-ext-bidder-params-merge.json", "expectedReqExt"),
+			expectedErrorCount: 0,
 		},
 		{
-			name: "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext for backward compatibility",
-			args: args{
-				reqBody: validRequest(t, "req-ext-bidder-params-backward-compatible-merge.json"),
-			},
-			expectedImpExt: getObject(t, "req-ext-bidder-params-backward-compatible-merge.json", "expectedImpExt"),
-			expectedReqExt: getObject(t, "req-ext-bidder-params-backward-compatible-merge.json", "expectedReqExt"),
-			errL:           0,
-		},
-		{
-			name: "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext.prebid.bidder for reserved keyword",
-			args: args{
-				reqBody: validRequest(t, "req-ext-bidder-params-merge-reserved-keyword.json"),
-			},
-			expectedImpExt: getObject(t, "req-ext-bidder-params-merge-reserved-keyword.json", "expectedImpExt"),
-			expectedReqExt: getObject(t, "req-ext-bidder-params-merge-reserved-keyword.json", "expectedReqExt"),
-			errL:           0,
+			name:               "add missing bidder-params from req.ext.prebid.bidderparams to imp[].ext for backward compatibility",
+			givenRequestBody:   validRequest(t, "req-ext-bidder-params-backward-compatible-merge.json"),
+			expectedImpExt:     getObject(t, "req-ext-bidder-params-backward-compatible-merge.json", "expectedImpExt"),
+			expectedReqExt:     getObject(t, "req-ext-bidder-params-backward-compatible-merge.json", "expectedReqExt"),
+			expectedErrorCount: 0,
 		},
 	}
 	for _, tt := range tests {
@@ -4105,7 +4382,7 @@ func TestParseRequestMergeBidderParams(t *testing.T) {
 				&mockStoredReqFetcher{},
 				empty_fetcher.EmptyFetcher{},
 				empty_fetcher.EmptyFetcher{},
-				&config.Configuration{MaxRequestSize: int64(len(tt.args.reqBody))},
+				&config.Configuration{MaxRequestSize: int64(len(tt.givenRequestBody))},
 				&metricsConfig.NilMetricsEngine{},
 				analyticsConf.NewPBSAnalytics(&config.Analytics{}),
 				map[string]string{},
@@ -4117,7 +4394,7 @@ func TestParseRequestMergeBidderParams(t *testing.T) {
 				hardcodedResponseIPValidator{response: true},
 			}
 
-			req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(tt.args.reqBody))
+			req := httptest.NewRequest("POST", "/openrtb2/auction", strings.NewReader(tt.givenRequestBody))
 
 			resReq, _, errL := deps.parseRequest(req)
 
@@ -4140,7 +4417,7 @@ func TestParseRequestMergeBidderParams(t *testing.T) {
 
 			assert.Equal(t, eReqE, reqE, "req.Ext should match")
 
-			assert.Len(t, errL, tt.errL, "error length should match")
+			assert.Len(t, errL, tt.expectedErrorCount, "error length should match")
 		})
 	}
 }
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index d0b4006d..c10e294f 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -249,6 +249,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder": json.RawMessage(`"anyBidder"`),
@@ -257,6 +258,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			expectedError: "",
 		},
@@ -267,6 +269,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder":    json.RawMessage(`"anyBidder"`),
@@ -277,6 +280,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			expectedError: "",
 		},
@@ -287,12 +291,14 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":      json.RawMessage(`"anyData"`),
 				"context":   json.RawMessage(`"anyContext"`),
 				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":      json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{},
 			expected: map[string]json.RawMessage{
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			expectedError: "",
 		},
@@ -304,6 +310,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":      json.RawMessage(`"anyData"`),
 				"context":   json.RawMessage(`"anyContext"`),
 				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":      json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder": json.RawMessage(`"anyBidder"`),
@@ -312,6 +319,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			expectedError: "",
 		},
@@ -323,6 +331,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":      json.RawMessage(`"anyData"`),
 				"context":   json.RawMessage(`"anyContext"`),
 				"skadn":     json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":      json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"bidder":    json.RawMessage(`"anyBidder"`),
@@ -333,6 +342,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			expectedError: "",
 		},
@@ -343,6 +353,7 @@ func TestCreateSanitizedImpExt(t *testing.T) {
 				"data":    json.RawMessage(`"anyData"`),
 				"context": json.RawMessage(`"anyContext"`),
 				"skadn":   json.RawMessage(`"anySKAdNetwork"`),
+				"gpid":    json.RawMessage(`"anyGPID"`),
 			},
 			givenImpExtPrebid: map[string]json.RawMessage{
 				"malformed": json.RawMessage(`json`), // String value without quotes.
@@ -401,7 +412,7 @@ func TestExtractBidderExts(t *testing.T) {
 		},
 		{
 			description:              "Special Names Ignored - imp.ext.BIDDER",
-			givenImpExt:              map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
+			givenImpExt:              map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`), "gpid": json.RawMessage(`{"gpid":"value4"}}`)},
 			givenImpExtPrebidBidders: map[string]json.RawMessage{},
 			expected:                 map[string]json.RawMessage{},
 		},
@@ -420,8 +431,8 @@ func TestExtractBidderExts(t *testing.T) {
 		{
 			description:              "Special Names Not Treated Differently - imp.ext.prebid.bidder.BIDDER",
 			givenImpExt:              map[string]json.RawMessage{},
-			givenImpExtPrebidBidders: map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
-			expected:                 map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`)},
+			givenImpExtPrebidBidders: map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`), "gpid": json.RawMessage(`{"gpid":"value4"}}`)},
+			expected:                 map[string]json.RawMessage{"prebid": json.RawMessage(`{"prebid":"value1"}}`), "context": json.RawMessage(`{"firstPartyData":"value2"}}`), "skadn": json.RawMessage(`{"skAdNetwork":"value3"}}`), "gpid": json.RawMessage(`{"gpid":"value4"}}`)},
 		},
 		{
 			description:              "Mixed - Both - imp.ext.BIDDER + imp.ext.prebid.bidder.BIDDER",
diff --git a/openrtb_ext/bidders_test.go b/openrtb_ext/bidders_test.go
index 8bd25d9e..cde79f70 100644
--- a/openrtb_ext/bidders_test.go
+++ b/openrtb_ext/bidders_test.go
@@ -104,15 +104,15 @@ func TestIsBidderNameReserved(t *testing.T) {
 		{"general", true},
 		{"gEnErAl", true},
 		{"GENERAL", true},
-		{"skadn", true},
-		{"skADN", true},
-		{"SKADN", true},
+		{"gpid", true},
+		{"GPID", true},
+		{"GPid", true},
 		{"prebid", true},
 		{"PREbid", true},
 		{"PREBID", true},
-		{"bidder", true},
-		{"BIDDER", true},
-		{"BidDer", true},
+		{"skadn", true},
+		{"skADN", true},
+		{"SKADN", true},
 		{"notreserved", false},
 	}